From cca134623f95bb2f4778b19a436454d937fb1e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 22 Aug 2024 09:16:21 -0700 Subject: [PATCH 1/4] add util command to debug transaction --- cmd/util/cmd/debug-tx/cmd.go | 143 +++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 cmd/util/cmd/debug-tx/cmd.go diff --git a/cmd/util/cmd/debug-tx/cmd.go b/cmd/util/cmd/debug-tx/cmd.go new file mode 100644 index 00000000000..029eb5ae6db --- /dev/null +++ b/cmd/util/cmd/debug-tx/cmd.go @@ -0,0 +1,143 @@ +package debug_tx + +import ( + "context" + + sdk "github.com/onflow/flow-go-sdk" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" + + "github.com/onflow/flow-go/model/flow" + "github.com/onflow/flow-go/module/grpcclient" + "github.com/onflow/flow-go/utils/debug" +) + +var ( + flagAccessAddress string + flagExecutionAddress string + flagChain string + flagTx string + flagComputeLimit uint64 + flagAtLatestBlock bool + flagProposalKeySeq uint64 +) + +var Cmd = &cobra.Command{ + Use: "debug-tx", + Short: "debug a transaction", + Run: run, +} + +func init() { + + Cmd.Flags().StringVar( + &flagChain, + "chain", + "", + "Chain name", + ) + _ = Cmd.MarkFlagRequired("chain") + + Cmd.Flags().StringVar(&flagAccessAddress, "access-address", "", "address of the access node") + _ = Cmd.MarkFlagRequired("access-address") + + Cmd.Flags().StringVar(&flagExecutionAddress, "execution-address", "", "address of the execution node") + _ = Cmd.MarkFlagRequired("execution-address") + + Cmd.Flags().StringVar(&flagTx, "tx", "", "transaction ID") + _ = Cmd.MarkFlagRequired("tx") + + Cmd.Flags().Uint64Var(&flagComputeLimit, "compute-limit", 9999, "transaction compute limit") + + Cmd.Flags().BoolVar(&flagAtLatestBlock, "at-latest-block", false, "run at latest block") + + Cmd.Flags().Uint64Var(&flagProposalKeySeq, "proposal-key-seq", 0, "proposal key sequence number") +} + +func run(*cobra.Command, []string) { + + chainID := flow.ChainID(flagChain) + chain := chainID.Chain() + + txID, err := flow.HexStringToIdentifier(flagTx) + if err != nil { + log.Fatal().Err(err).Msg("failed to parse transaction ID") + } + + config, err := grpcclient.NewFlowClientConfig(flagAccessAddress, "", flow.ZeroID, true) + if err != nil { + log.Fatal().Err(err).Msg("failed to create flow client config") + } + + flowClient, err := grpcclient.FlowClient(config) + if err != nil { + log.Fatal().Err(err).Msg("failed to create flow client") + } + + log.Info().Msg("Fetching transaction ...") + + tx, err := flowClient.GetTransaction(context.Background(), sdk.Identifier(txID)) + if err != nil { + log.Fatal().Err(err).Msg("failed to fetch transaction") + } + + log.Info().Msgf("Fetched transaction: %s", tx.ID()) + + log.Info().Msg("Fetching transaction result ...") + + txResult, err := flowClient.GetTransactionResult(context.Background(), sdk.Identifier(txID)) + if err != nil { + log.Fatal().Err(err).Msg("failed to fetch transaction result") + } + + log.Info().Msgf("Fetched transaction result: %s at block %s", txResult.Status, txResult.BlockID) + + log.Info().Msg("Debugging transaction ...") + + debugger := debug.NewRemoteDebugger( + flagExecutionAddress, + chain, + log.Logger, + ) + + txBody := flow.NewTransactionBody(). + SetScript(tx.Script). + SetComputeLimit(flagComputeLimit). + SetPayer(flow.Address(tx.Payer)) + + for _, argument := range tx.Arguments { + txBody.AddArgument(argument) + } + + for _, authorizer := range tx.Authorizers { + txBody.AddAuthorizer(flow.Address(authorizer)) + } + + proposalKeySequenceNumber := tx.ProposalKey.SequenceNumber + if flagProposalKeySeq != 0 { + proposalKeySequenceNumber = flagProposalKeySeq + } + + txBody.SetProposalKey( + flow.Address(tx.ProposalKey.Address), + tx.ProposalKey.KeyIndex, + proposalKeySequenceNumber, + ) + + var txErr, processErr error + if flagAtLatestBlock { + txErr, processErr = debugger.RunTransaction(txBody) + } else { + txErr, processErr = debugger.RunTransactionAtBlockID( + txBody, + flow.Identifier(txResult.BlockID), + "", + ) + } + if txErr != nil { + log.Fatal().Err(txErr).Msg("transaction error") + } + if processErr != nil { + log.Fatal().Err(processErr).Msg("process error") + } +} From 0fc02ef0bbb00e9942848a6bac0904167887df0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 22 Aug 2024 10:54:03 -0700 Subject: [PATCH 2/4] lint --- cmd/util/cmd/debug-tx/cmd.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/util/cmd/debug-tx/cmd.go b/cmd/util/cmd/debug-tx/cmd.go index 029eb5ae6db..cb1a7291017 100644 --- a/cmd/util/cmd/debug-tx/cmd.go +++ b/cmd/util/cmd/debug-tx/cmd.go @@ -3,10 +3,11 @@ package debug_tx import ( "context" - sdk "github.com/onflow/flow-go-sdk" "github.com/rs/zerolog/log" "github.com/spf13/cobra" + sdk "github.com/onflow/flow-go-sdk" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/grpcclient" "github.com/onflow/flow-go/utils/debug" From c864ad7624625eff8434a6ac87fad75ac114b2b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 23 Aug 2024 08:43:40 -0700 Subject: [PATCH 3/4] add comment on how to forward port from EN --- cmd/util/cmd/debug-tx/cmd.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/util/cmd/debug-tx/cmd.go b/cmd/util/cmd/debug-tx/cmd.go index cb1a7291017..a7f955549e5 100644 --- a/cmd/util/cmd/debug-tx/cmd.go +++ b/cmd/util/cmd/debug-tx/cmd.go @@ -13,6 +13,9 @@ import ( "github.com/onflow/flow-go/utils/debug" ) +// use the following command to forward port 9000 from the EN to localhost:9001 +// `gcloud compute ssh '--ssh-flag=-A' --no-user-output-enabled --tunnel-through-iap migrationmainnet1-execution-001 --project flow-multi-region -- -NL 9001:localhost:9000` + var ( flagAccessAddress string flagExecutionAddress string From 23dd517e00adfffc961b826c92d93ea11654f5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Wed, 22 Jan 2025 17:24:22 -0800 Subject: [PATCH 4/4] add command to root --- cmd/util/cmd/root.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/util/cmd/root.go b/cmd/util/cmd/root.go index cbb35b4c8f1..4f00a706364 100644 --- a/cmd/util/cmd/root.go +++ b/cmd/util/cmd/root.go @@ -17,6 +17,7 @@ import ( checkpoint_collect_stats "github.com/onflow/flow-go/cmd/util/cmd/checkpoint-collect-stats" checkpoint_list_tries "github.com/onflow/flow-go/cmd/util/cmd/checkpoint-list-tries" checkpoint_trie_stats "github.com/onflow/flow-go/cmd/util/cmd/checkpoint-trie-stats" + debug_transaction "github.com/onflow/flow-go/cmd/util/cmd/debug-tx" diff_states "github.com/onflow/flow-go/cmd/util/cmd/diff-states" epochs "github.com/onflow/flow-go/cmd/util/cmd/epochs/cmd" export "github.com/onflow/flow-go/cmd/util/cmd/exec-data-json-export" @@ -122,6 +123,7 @@ func addCommands() { rootCmd.AddCommand(check_storage.Cmd) rootCmd.AddCommand(generate_authorization_fixes.Cmd) rootCmd.AddCommand(verify_execution_result.Cmd) + rootCmd.AddCommand(debug_transaction.Cmd) } func initConfig() {