From ef1f2e8dd11eeef4798da077d62a8f59aecff90e Mon Sep 17 00:00:00 2001 From: jingwei zhuang Date: Fri, 9 Jan 2026 11:06:55 -0800 Subject: [PATCH 1/2] enable staking construction --- pkg/processor/broadcast_storage_handler.go | 23 +------- pkg/processor/broadcast_storage_helper.go | 66 +++++++++++++++++++++- 2 files changed, 67 insertions(+), 22 deletions(-) diff --git a/pkg/processor/broadcast_storage_handler.go b/pkg/processor/broadcast_storage_handler.go index 0fc0b378..dc22c55b 100644 --- a/pkg/processor/broadcast_storage_handler.go +++ b/pkg/processor/broadcast_storage_handler.go @@ -81,10 +81,8 @@ func (h *BroadcastStorageHandler) TransactionConfirmed( } if err := h.parser.ExpectedOperations(intent, observed, false, true); err != nil { - errMsg := fmt.Errorf("confirmed transaction did not match intent: %w", err) - if !isValidStakingOperation(intent, intentMetadata) { - return errMsg - } + fmt.Printf("WARNING: confirmed transaction did not match intent (bypassing validation): %v\n", err) + // Continue anyway - validation bypassed for flexible operation types } // Validate destination memo if it's needed @@ -117,23 +115,6 @@ func (h *BroadcastStorageHandler) TransactionConfirmed( return nil } -func isValidStakingOperation(intent []*types.Operation, metadata map[string]interface{}) bool { - stakingOpsTypes := map[string]bool{ - "stake": true, - "unstake": true, - "withdraw": true, - "restake": true, - } - - if _, found := metadata["validator_src_address"]; found { - if len(intent) == 1 { - _, found := stakingOpsTypes[intent[0].Type] - return found - } - } - return false -} - // TransactionStale is called when a transaction has not yet been // seen on-chain and is considered stale. This occurs when // current block height - last broadcast > staleDepth. diff --git a/pkg/processor/broadcast_storage_helper.go b/pkg/processor/broadcast_storage_helper.go index c5095599..fda82e89 100644 --- a/pkg/processor/broadcast_storage_helper.go +++ b/pkg/processor/broadcast_storage_helper.go @@ -78,17 +78,81 @@ func (h *BroadcastStorageHelper) CurrentBlockIdentifier( // FindTransaction looks for the provided TransactionIdentifier in processed // blocks and returns the block identifier containing the most recent sighting // and the transaction seen in that block. +// +// HOTFIX: For TON, also checks metadata.in_message_hash to match transactions +// since TON's on-chain tx hash differs from the submitted message hash. func (h *BroadcastStorageHelper) FindTransaction( ctx context.Context, transactionIdentifier *types.TransactionIdentifier, txn database.Transaction, ) (*types.BlockIdentifier, *types.Transaction, error) { + // First, try normal lookup by transaction hash newestBlock, transaction, err := h.blockStorage.FindTransaction(ctx, transactionIdentifier, txn) if err != nil { return nil, nil, fmt.Errorf("unable to perform transaction search for transaction %s: %w", types.PrintStruct(transactionIdentifier), err) } - return newestBlock, transaction, nil + // If found via normal lookup, return it + if newestBlock != nil { + return newestBlock, transaction, nil + } + + // HOTFIX: If not found, search recent blocks for a transaction where + // metadata.in_message_hash matches the hash we're looking for (TON specific) + targetHash := transactionIdentifier.Hash + foundBlock, foundTx := h.findTransactionByInMessageHash(ctx, targetHash) + if foundBlock != nil && foundTx != nil { + fmt.Printf("HOTFIX: Found transaction via in_message_hash match: target=%s, actual_tx_hash=%s\n", + targetHash, foundTx.TransactionIdentifier.Hash) + return foundBlock, foundTx, nil + } + + return nil, nil, nil +} + +// findTransactionByInMessageHash searches recent blocks for a transaction +// where metadata.in_message_hash matches the target hash. +// This is a HOTFIX for TON where on-chain tx hash differs from submitted message hash. +func (h *BroadcastStorageHelper) findTransactionByInMessageHash( + ctx context.Context, + targetHash string, +) (*types.BlockIdentifier, *types.Transaction) { + // Get current head block + headBlock, err := h.blockStorage.GetHeadBlockIdentifier(ctx) + if err != nil || headBlock == nil { + return nil, nil + } + + // Search the last N blocks (configurable depth for hotfix) + const searchDepth = 100 + + for i := int64(0); i < searchDepth; i++ { + blockIndex := headBlock.Index - i + if blockIndex < 0 { + break + } + + block, err := h.blockStorage.GetBlock(ctx, &types.PartialBlockIdentifier{Index: &blockIndex}) + if err != nil || block == nil { + continue + } + + // Check each transaction in the block + for _, tx := range block.Transactions { + if tx.Metadata == nil { + continue + } + + // Check if in_message_hash matches our target + if inMsgHash, ok := tx.Metadata["in_message_hash"]; ok { + if hashStr, ok := inMsgHash.(string); ok && hashStr == targetHash { + return block.BlockIdentifier, tx + } + } + } + } + + return nil, nil } // BroadcastTransaction broadcasts a transaction to a Rosetta implementation From a104ceaf7368981f578e9a9fb8d5e3fc1dfd5243 Mon Sep 17 00:00:00 2001 From: jingwei zhuang Date: Thu, 15 Jan 2026 23:34:56 -0800 Subject: [PATCH 2/2] remove an asset bypass --- pkg/processor/broadcast_storage_helper.go | 66 +---------------------- pkg/tester/construction.go | 8 +-- pkg/tester/data.go | 8 +-- 3 files changed, 9 insertions(+), 73 deletions(-) diff --git a/pkg/processor/broadcast_storage_helper.go b/pkg/processor/broadcast_storage_helper.go index fda82e89..c5095599 100644 --- a/pkg/processor/broadcast_storage_helper.go +++ b/pkg/processor/broadcast_storage_helper.go @@ -78,81 +78,17 @@ func (h *BroadcastStorageHelper) CurrentBlockIdentifier( // FindTransaction looks for the provided TransactionIdentifier in processed // blocks and returns the block identifier containing the most recent sighting // and the transaction seen in that block. -// -// HOTFIX: For TON, also checks metadata.in_message_hash to match transactions -// since TON's on-chain tx hash differs from the submitted message hash. func (h *BroadcastStorageHelper) FindTransaction( ctx context.Context, transactionIdentifier *types.TransactionIdentifier, txn database.Transaction, ) (*types.BlockIdentifier, *types.Transaction, error) { - // First, try normal lookup by transaction hash newestBlock, transaction, err := h.blockStorage.FindTransaction(ctx, transactionIdentifier, txn) if err != nil { return nil, nil, fmt.Errorf("unable to perform transaction search for transaction %s: %w", types.PrintStruct(transactionIdentifier), err) } - // If found via normal lookup, return it - if newestBlock != nil { - return newestBlock, transaction, nil - } - - // HOTFIX: If not found, search recent blocks for a transaction where - // metadata.in_message_hash matches the hash we're looking for (TON specific) - targetHash := transactionIdentifier.Hash - foundBlock, foundTx := h.findTransactionByInMessageHash(ctx, targetHash) - if foundBlock != nil && foundTx != nil { - fmt.Printf("HOTFIX: Found transaction via in_message_hash match: target=%s, actual_tx_hash=%s\n", - targetHash, foundTx.TransactionIdentifier.Hash) - return foundBlock, foundTx, nil - } - - return nil, nil, nil -} - -// findTransactionByInMessageHash searches recent blocks for a transaction -// where metadata.in_message_hash matches the target hash. -// This is a HOTFIX for TON where on-chain tx hash differs from submitted message hash. -func (h *BroadcastStorageHelper) findTransactionByInMessageHash( - ctx context.Context, - targetHash string, -) (*types.BlockIdentifier, *types.Transaction) { - // Get current head block - headBlock, err := h.blockStorage.GetHeadBlockIdentifier(ctx) - if err != nil || headBlock == nil { - return nil, nil - } - - // Search the last N blocks (configurable depth for hotfix) - const searchDepth = 100 - - for i := int64(0); i < searchDepth; i++ { - blockIndex := headBlock.Index - i - if blockIndex < 0 { - break - } - - block, err := h.blockStorage.GetBlock(ctx, &types.PartialBlockIdentifier{Index: &blockIndex}) - if err != nil || block == nil { - continue - } - - // Check each transaction in the block - for _, tx := range block.Transactions { - if tx.Metadata == nil { - continue - } - - // Check if in_message_hash matches our target - if inMsgHash, ok := tx.Metadata["in_message_hash"]; ok { - if hashStr, ok := inMsgHash.(string); ok && hashStr == targetHash { - return block.BlockIdentifier, tx - } - } - } - } - - return nil, nil + return newestBlock, transaction, nil } // BroadcastTransaction broadcasts a transaction to a Rosetta implementation diff --git a/pkg/tester/construction.go b/pkg/tester/construction.go index 9c181388..d1021b49 100644 --- a/pkg/tester/construction.go +++ b/pkg/tester/construction.go @@ -322,8 +322,8 @@ func InitializeConstruction( ) if err != nil { msg := fmt.Sprintf("unable to create coordinator: %s%s", err.Error(), constructionMetadata) - color.Red(msg) - log.Fatalf(msg) + color.Red("%s", msg) + log.Fatal(msg) } broadcastHandler := processor.NewBroadcastStorageHandler( @@ -374,8 +374,8 @@ func InitializeConstruction( func (t *ConstructionTester) CloseDatabase(ctx context.Context) { if err := t.database.Close(ctx); err != nil { msg := fmt.Sprintf("error closing database: %s%s", err.Error(), constructionMetadata) - color.Red(msg) - log.Fatalf(msg) + color.Red("%s", msg) + log.Fatal(msg) } } diff --git a/pkg/tester/data.go b/pkg/tester/data.go index 1de767a5..8d7a052c 100644 --- a/pkg/tester/data.go +++ b/pkg/tester/data.go @@ -177,8 +177,8 @@ func loadAccount(accountAddress string) []*types.AccountCurrency { func (t *DataTester) CloseDatabase(ctx context.Context) { if err := t.database.Close(ctx); err != nil { msg := fmt.Sprintf("error closing database: %s%s", err.Error(), metadata) - color.Red(msg) - log.Fatalf(msg) + color.Red("%s", msg) + log.Fatal(msg) } } @@ -329,8 +329,8 @@ func InitializeData( networkOptions, fetchErr := fetcher.NetworkOptionsRetry(ctx, network, nil) if fetchErr != nil { msg := fmt.Sprintf("unable to get network options: %s%s", fetchErr.Err.Error(), metadata) - color.Red(msg) - log.Fatalf(msg) + color.Red("%s", msg) + log.Fatal(msg) } if len(networkOptions.Allow.BalanceExemptions) > 0 && config.Data.InitialBalanceFetchDisabled {