From dbc8cf50e2f5fc81d1b68a963de69b810b38e5ba Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 6 Sep 2026 16:40:55 +0000 Subject: [PATCH 1/2] Fix account_transactions silently dropping BlockEpilogue write-sets BlockEpilogue (and other non-User/Genesis/BlockMetadata/Validator types) returned an empty account set before walking transaction_info.changes. Epilogues write resources such as 0x1::block::BlockResource, so those accounts were never indexed. Walk write-set resource accounts for every txn type; only events and signatures remain type-specific. Co-authored-by: Young Yang Liauw --- .../account_transactions_model.rs | 82 +++++++++++++++++-- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/processor/src/processors/account_transactions/account_transactions_model.rs b/processor/src/processors/account_transactions/account_transactions_model.rs index 8ffb731e..3b1a3fd0 100644 --- a/processor/src/processors/account_transactions/account_transactions_model.rs +++ b/processor/src/processors/account_transactions/account_transactions_model.rs @@ -63,9 +63,13 @@ impl AccountTransaction { .as_ref() .unwrap_or_else(|| panic!("Transaction info doesn't exist for version {txn_version}")); let wscs = &transaction_info.changes; + // Events/signatures are type-specific. Write-set resource accounts are not: + // BlockEpilogue (and StateCheckpoint) still carry WriteResource changes + // (e.g. 0x1::block::BlockResource). Returning here used to drop those + // accounts from account_transactions entirely. let (events, signatures) = match txn_data { TxnData::User(inner) => ( - &inner.events, + inner.events.as_slice(), UserTransaction::get_signatures( inner.request.as_ref().unwrap_or_else(|| { panic!("User request doesn't exist for version {txn_version}") @@ -76,12 +80,10 @@ impl AccountTransaction { .naive_utc(), ), ), - TxnData::Genesis(inner) => (&inner.events, vec![]), - TxnData::BlockMetadata(inner) => (&inner.events, vec![]), - TxnData::Validator(inner) => (&inner.events, vec![]), - _ => { - return AHashSet::new(); - }, + TxnData::Genesis(inner) => (inner.events.as_slice(), vec![]), + TxnData::BlockMetadata(inner) => (inner.events.as_slice(), vec![]), + TxnData::Validator(inner) => (inner.events.as_slice(), vec![]), + _ => (&[] as &[_], vec![]), }; let mut accounts = AHashSet::new(); for sig in signatures { @@ -167,3 +169,69 @@ impl From for PostgresAccountTransaction { } } } + +#[cfg(test)] +mod tests { + use super::*; + use aptos_indexer_processor_sdk::aptos_protos::{ + transaction::v1::{ + transaction::TransactionType, write_set_change::Change, BlockEpilogueTransaction, + MoveStructTag, TransactionInfo, WriteResource, WriteSetChange, + }, + util::timestamp::Timestamp, + }; + + fn epilogue_txn_with_write_resource(address: &str) -> Transaction { + Transaction { + timestamp: Some(Timestamp { + seconds: 1_700_000_000, + nanos: 0, + }), + version: 7_250_088_688, + info: Some(TransactionInfo { + hash: vec![0u8; 32], + state_change_hash: vec![0u8; 32], + event_root_hash: vec![0u8; 32], + state_checkpoint_hash: None, + gas_used: 0, + success: true, + vm_status: String::new(), + accumulator_root_hash: vec![0u8; 32], + changes: vec![WriteSetChange { + r#type: 0, + change: Some(Change::WriteResource(WriteResource { + address: address.to_string(), + state_key_hash: vec![0u8; 32], + r#type: Some(MoveStructTag { + address: "0x1".to_string(), + module: "block".to_string(), + name: "BlockResource".to_string(), + generic_type_params: vec![], + }), + type_str: "0x1::block::BlockResource".to_string(), + data: r#"{"epoch_interval":"1","height":"1"}"#.to_string(), + })), + }], + }), + epoch: 1, + block_height: 1, + r#type: TransactionType::BlockEpilogue as i32, + size_info: None, + txn_data: Some(TxnData::BlockEpilogue(BlockEpilogueTransaction { + block_end_info: None, + })), + } + } + + #[test] + fn block_epilogue_indexes_write_set_accounts() { + let txn = epilogue_txn_with_write_resource("0x1"); + let accounts = AccountTransaction::get_accounts(&txn); + + assert!( + accounts.contains("0x0000000000000000000000000000000000000000000000000000000000000001"), + "BlockEpilogue WriteResource accounts must be indexed; got {accounts:?}" + ); + assert_eq!(accounts.len(), 1); + } +} From bfc1ff3fd56ba264eb2c5fc59ad33c5285ed366a Mon Sep 17 00:00:00 2001 From: Young Yang Liauw <7528420+sausagee@users.noreply.github.com> Date: Mon, 7 Sep 2026 15:34:42 -0700 Subject: [PATCH 2/2] ci: apply #70 unblocker files (stable xclippy + bookworm docker) Stack the CI unblocker files from PR #70 (stable cargo xclippy, bookworm Dockerfiles with make) onto this bugfix branch so CI can go green while #70 awaits review. Merge target remains main; this does not merge #70. --- Dockerfile | 22 +++++++++++++++++----- Dockerfile.address-reputation-api | 22 +++++++++++++++++----- scripts/rust_lint.sh | 5 ++++- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index a7e266e6..57df1080 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,13 +2,25 @@ # Stage 1: Build the binary -FROM rust:slim-bullseye as builder +FROM rust:slim-bookworm AS builder WORKDIR /app COPY --link . /app -RUN for i in 1 2 3; do apt-get update && apt-get install --fix-missing -y cmake curl clang git pkg-config libssl-dev libdw-dev libpq-dev lld && break || sleep 10; done +RUN apt-get update \ + && apt-get install --no-install-recommends --fix-missing -y \ + cmake \ + curl \ + clang \ + make \ + git \ + pkg-config \ + libssl-dev \ + libdw-dev \ + libpq-dev \ + lld \ + && rm -rf /var/lib/apt/lists/* ENV CARGO_NET_GIT_FETCH_WITH_CLI true # TODO: Fix this with real processors. RUN cargo build --locked --release -p processor && ls -lah target/release/ @@ -24,19 +36,19 @@ ENV GIT_SHA ${GIT_SHA} # Stage 2: Create the final image -FROM debian:bullseye-slim +FROM debian:bookworm-slim COPY --from=builder /usr/local/bin/processor /usr/local/bin RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update && apt-get install --no-install-recommends --fix-missing -y \ - libssl1.1 \ + libssl3 \ ca-certificates \ net-tools \ tcpdump \ iproute2 \ - netcat \ + netcat-openbsd \ libdw-dev \ libpq-dev \ curl diff --git a/Dockerfile.address-reputation-api b/Dockerfile.address-reputation-api index 5be4c111..488d8ed5 100644 --- a/Dockerfile.address-reputation-api +++ b/Dockerfile.address-reputation-api @@ -2,13 +2,25 @@ # Stage 1: Build the binary -FROM rust:slim-bullseye as builder +FROM rust:slim-bookworm AS builder WORKDIR /app COPY --link . /app -RUN for i in 1 2 3; do apt-get update && apt-get install --fix-missing -y cmake curl clang git pkg-config libssl-dev libdw-dev libpq-dev lld && break || sleep 10; done +RUN apt-get update \ + && apt-get install --no-install-recommends --fix-missing -y \ + cmake \ + curl \ + clang \ + make \ + git \ + pkg-config \ + libssl-dev \ + libdw-dev \ + libpq-dev \ + lld \ + && rm -rf /var/lib/apt/lists/* ENV CARGO_NET_GIT_FETCH_WITH_CLI true RUN cargo build --locked --release -p address-reputation-api && ls -lah target/release/ RUN cp target/release/address-reputation-api /usr/local/bin @@ -23,19 +35,19 @@ ENV GIT_SHA ${GIT_SHA} # Stage 2: Create the final image -FROM debian:bullseye-slim +FROM debian:bookworm-slim COPY --from=builder /usr/local/bin/address-reputation-api /usr/local/bin RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ apt-get update && apt-get install --no-install-recommends --fix-missing -y \ - libssl1.1 \ + libssl3 \ ca-certificates \ net-tools \ tcpdump \ iproute2 \ - netcat \ + netcat-openbsd \ libdw-dev \ libpq-dev \ curl diff --git a/scripts/rust_lint.sh b/scripts/rust_lint.sh index 261c1aa9..32a48f2b 100755 --- a/scripts/rust_lint.sh +++ b/scripts/rust_lint.sh @@ -25,7 +25,10 @@ fi set -e set -x -cargo +nightly xclippy +# Run clippy on the pinned STABLE toolchain (from rust-toolchain.toml), NOT +# nightly. Latest nightly makes Infallible an alias of !, which breaks +# allocative (impl Allocative for both). Stable clippy matches the build toolchain. +cargo xclippy # We require the nightly build of cargo fmt # to provide stricter rust formatting.