From 9d2a41a231bc36d496643fa00d515f3e7149e076 Mon Sep 17 00:00:00 2001 From: georgehao Date: Fri, 26 May 2023 12:23:29 +0800 Subject: [PATCH] refactor(bridge): update bridge orm and layout (#496) Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> --- bridge/abi/bridge_abi_test.go | 48 +- bridge/{scripts => abi}/build_abi.sh | 0 bridge/cmd/event_watcher/app/app.go | 29 +- bridge/cmd/gas_oracle/app/app.go | 35 +- bridge/cmd/mock_app.go | 2 +- bridge/cmd/msg_relayer/app/app.go | 31 +- bridge/cmd/rollup_relayer/app/app.go | 35 +- bridge/{ => conf}/config.json | 0 bridge/go.mod | 18 +- bridge/go.sum | 83 +- bridge/{ => internal}/config/config.go | 8 +- bridge/{ => internal}/config/config_test.go | 2 +- bridge/internal/config/db.go | 33 + .../l1_config.go => internal/config/l1.go} | 0 .../l2_config.go => internal/config/l2.go} | 2 +- .../config/relayer.go} | 0 bridge/internal/controller/relayer/common.go | 20 + .../controller}/relayer/l1_relayer.go | 72 +- .../controller}/relayer/l1_relayer_test.go | 135 +- .../controller}/relayer/l2_relayer.go | 146 +- .../controller}/relayer/l2_relayer_test.go | 311 +- .../controller}/relayer/relayer_test.go | 37 +- .../controller}/sender/account_pool.go | 0 .../controller}/sender/estimategas.go | 0 .../controller}/sender/sender.go | 4 +- .../controller}/sender/sender_test.go | 7 +- .../controller}/watcher/batch_proposer.go | 200 +- .../controller/watcher/batch_proposer_test.go | 206 + .../controller}/watcher/common.go | 0 .../controller}/watcher/l1_watcher.go | 104 +- .../controller}/watcher/l1_watcher_test.go | 102 +- .../controller}/watcher/l2_watcher.go | 117 +- .../controller}/watcher/l2_watcher_test.go | 151 +- .../controller}/watcher/watcher_test.go | 37 +- bridge/internal/orm/block_batch.go | 292 + bridge/internal/orm/block_trace.go | 155 + bridge/internal/orm/common.go | 38 + bridge/internal/orm/l1_block.go | 87 + bridge/internal/orm/l1_message.go | 124 + bridge/internal/orm/l2_message.go | 127 + bridge/internal/orm/migrate/migrate.go | 61 + bridge/internal/orm/migrate/migrate_test.go | 86 + .../migrate/migrations/00001_block_trace.sql | 38 + .../migrate/migrations/00002_l1_message.sql | 50 + .../migrate/migrations/00003_l2_message.sql | 50 + .../migrate/migrations/00004_block_batch.sql | 50 + .../orm/migrate/migrations/00005_l1_block.sql | 33 + bridge/internal/types/batch.go | 236 + bridge/internal/types/batch_test.go | 90 + bridge/internal/types/block.go | 21 + bridge/internal/utils/confirmation.go | 56 + bridge/internal/utils/confirmation_test.go | 134 + bridge/internal/utils/db.go | 43 + bridge/internal/utils/utils.go | 65 + bridge/internal/utils/utils_test.go | 49 + bridge/relayer/params.go | 11 - bridge/testdata/blockTrace_02.json | 545 + bridge/testdata/blockTrace_03.json | 12877 ++++++++++++++++ bridge/tests/bridge_test.go | 27 +- bridge/tests/gas_oracle_test.go | 88 +- bridge/tests/l1_message_relay_test.go | 37 +- bridge/tests/l2_message_relay_test.go | 130 +- bridge/tests/rollup_test.go | 122 +- bridge/watcher/batch_proposer_test.go | 199 - common/go.mod | 4 +- common/go.sum | 7 +- common/version/version.go | 2 +- coordinator/go.mod | 2 + coordinator/go.sum | 6 +- go.work.sum | 12 +- roller/go.mod | 11 +- roller/go.sum | 25 +- tests/integration-test/go.mod | 2 + tests/integration-test/go.sum | 4 +- tests/integration-test/integration_test.go | 2 +- 75 files changed, 16737 insertions(+), 1236 deletions(-) rename bridge/{scripts => abi}/build_abi.sh (100%) rename bridge/{ => conf}/config.json (100%) rename bridge/{ => internal}/config/config.go (71%) rename bridge/{ => internal}/config/config_test.go (96%) create mode 100644 bridge/internal/config/db.go rename bridge/{config/l1_config.go => internal/config/l1.go} (100%) rename bridge/{config/l2_config.go => internal/config/l2.go} (98%) rename bridge/{config/relayer_config.go => internal/config/relayer.go} (100%) create mode 100644 bridge/internal/controller/relayer/common.go rename bridge/{ => internal/controller}/relayer/l1_relayer.go (72%) rename bridge/{ => internal/controller}/relayer/l1_relayer_test.go (60%) rename bridge/{ => internal/controller}/relayer/l2_relayer.go (75%) rename bridge/{ => internal/controller}/relayer/l2_relayer_test.go (61%) rename bridge/{ => internal/controller}/relayer/relayer_test.go (72%) rename bridge/{ => internal/controller}/sender/account_pool.go (100%) rename bridge/{ => internal/controller}/sender/estimategas.go (100%) rename bridge/{ => internal/controller}/sender/sender.go (99%) rename bridge/{ => internal/controller}/sender/sender_test.go (98%) rename bridge/{ => internal/controller}/watcher/batch_proposer.go (59%) create mode 100644 bridge/internal/controller/watcher/batch_proposer_test.go rename bridge/{ => internal/controller}/watcher/common.go (100%) rename bridge/{ => internal/controller}/watcher/l1_watcher.go (75%) rename bridge/{ => internal/controller}/watcher/l1_watcher_test.go (82%) rename bridge/{ => internal/controller}/watcher/l2_watcher.go (74%) rename bridge/{ => internal/controller}/watcher/l2_watcher_test.go (76%) rename bridge/{ => internal/controller}/watcher/watcher_test.go (76%) create mode 100644 bridge/internal/orm/block_batch.go create mode 100644 bridge/internal/orm/block_trace.go create mode 100644 bridge/internal/orm/common.go create mode 100644 bridge/internal/orm/l1_block.go create mode 100644 bridge/internal/orm/l1_message.go create mode 100644 bridge/internal/orm/l2_message.go create mode 100644 bridge/internal/orm/migrate/migrate.go create mode 100644 bridge/internal/orm/migrate/migrate_test.go create mode 100644 bridge/internal/orm/migrate/migrations/00001_block_trace.sql create mode 100644 bridge/internal/orm/migrate/migrations/00002_l1_message.sql create mode 100644 bridge/internal/orm/migrate/migrations/00003_l2_message.sql create mode 100644 bridge/internal/orm/migrate/migrations/00004_block_batch.sql create mode 100644 bridge/internal/orm/migrate/migrations/00005_l1_block.sql create mode 100644 bridge/internal/types/batch.go create mode 100644 bridge/internal/types/batch_test.go create mode 100644 bridge/internal/types/block.go create mode 100644 bridge/internal/utils/confirmation.go create mode 100644 bridge/internal/utils/confirmation_test.go create mode 100644 bridge/internal/utils/db.go create mode 100644 bridge/internal/utils/utils.go create mode 100644 bridge/internal/utils/utils_test.go delete mode 100644 bridge/relayer/params.go create mode 100644 bridge/testdata/blockTrace_02.json create mode 100644 bridge/testdata/blockTrace_03.json delete mode 100644 bridge/watcher/batch_proposer_test.go diff --git a/bridge/abi/bridge_abi_test.go b/bridge/abi/bridge_abi_test.go index e1341d436..bef3bdb48 100644 --- a/bridge/abi/bridge_abi_test.go +++ b/bridge/abi/bridge_abi_test.go @@ -1,4 +1,4 @@ -package bridgeabi_test +package bridgeabi import ( "math/big" @@ -6,37 +6,35 @@ import ( "github.com/scroll-tech/go-ethereum/common" "github.com/stretchr/testify/assert" - - bridge_abi "scroll-tech/bridge/abi" ) func TestEventSignature(t *testing.T) { assert := assert.New(t) - assert.Equal(bridge_abi.L1SentMessageEventSignature, common.HexToHash("104371f3b442861a2a7b82a070afbbaab748bb13757bf47769e170e37809ec1e")) - assert.Equal(bridge_abi.L1RelayedMessageEventSignature, common.HexToHash("4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c")) - assert.Equal(bridge_abi.L1FailedRelayedMessageEventSignature, common.HexToHash("99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f")) + assert.Equal(L1SentMessageEventSignature, common.HexToHash("104371f3b442861a2a7b82a070afbbaab748bb13757bf47769e170e37809ec1e")) + assert.Equal(L1RelayedMessageEventSignature, common.HexToHash("4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c")) + assert.Equal(L1FailedRelayedMessageEventSignature, common.HexToHash("99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f")) - assert.Equal(bridge_abi.L1CommitBatchEventSignature, common.HexToHash("2cdc615c74452778c0fb6184735e014c13aad2b62774fe0b09bd1dcc2cc14a62")) - assert.Equal(bridge_abi.L1FinalizeBatchEventSignature, common.HexToHash("6be443154c959a7a1645b4392b6fa97d8e8ab6e8fd853d7085e8867083737d79")) + assert.Equal(L1CommitBatchEventSignature, common.HexToHash("2cdc615c74452778c0fb6184735e014c13aad2b62774fe0b09bd1dcc2cc14a62")) + assert.Equal(L1FinalizeBatchEventSignature, common.HexToHash("6be443154c959a7a1645b4392b6fa97d8e8ab6e8fd853d7085e8867083737d79")) - assert.Equal(bridge_abi.L1QueueTransactionEventSignature, common.HexToHash("bdcc7517f8fe3db6506dfd910942d0bbecaf3d6a506dadea65b0d988e75b9439")) + assert.Equal(L1QueueTransactionEventSignature, common.HexToHash("bdcc7517f8fe3db6506dfd910942d0bbecaf3d6a506dadea65b0d988e75b9439")) - assert.Equal(bridge_abi.L2SentMessageEventSignature, common.HexToHash("104371f3b442861a2a7b82a070afbbaab748bb13757bf47769e170e37809ec1e")) - assert.Equal(bridge_abi.L2RelayedMessageEventSignature, common.HexToHash("4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c")) - assert.Equal(bridge_abi.L2FailedRelayedMessageEventSignature, common.HexToHash("99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f")) + assert.Equal(L2SentMessageEventSignature, common.HexToHash("104371f3b442861a2a7b82a070afbbaab748bb13757bf47769e170e37809ec1e")) + assert.Equal(L2RelayedMessageEventSignature, common.HexToHash("4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c")) + assert.Equal(L2FailedRelayedMessageEventSignature, common.HexToHash("99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f")) - assert.Equal(bridge_abi.L2ImportBlockEventSignature, common.HexToHash("a7823f45e1ee21f9530b77959b57507ad515a14fa9fa24d262ee80e79b2b5745")) + assert.Equal(L2ImportBlockEventSignature, common.HexToHash("a7823f45e1ee21f9530b77959b57507ad515a14fa9fa24d262ee80e79b2b5745")) - assert.Equal(bridge_abi.L2AppendMessageEventSignature, common.HexToHash("faa617c2d8ce12c62637dbce76efcc18dae60574aa95709bdcedce7e76071693")) + assert.Equal(L2AppendMessageEventSignature, common.HexToHash("faa617c2d8ce12c62637dbce76efcc18dae60574aa95709bdcedce7e76071693")) } func TestPackRelayL2MessageWithProof(t *testing.T) { assert := assert.New(t) - l1MessengerABI, err := bridge_abi.L1ScrollMessengerMetaData.GetAbi() + l1MessengerABI, err := L1ScrollMessengerMetaData.GetAbi() assert.NoError(err) - proof := bridge_abi.IL1ScrollMessengerL2MessageProof{ + proof := IL1ScrollMessengerL2MessageProof{ BatchHash: common.Hash{}, MerkleProof: make([]byte, 0), } @@ -47,10 +45,10 @@ func TestPackRelayL2MessageWithProof(t *testing.T) { func TestPackCommitBatch(t *testing.T) { assert := assert.New(t) - scrollChainABI, err := bridge_abi.ScrollChainMetaData.GetAbi() + scrollChainABI, err := ScrollChainMetaData.GetAbi() assert.NoError(err) - header := bridge_abi.IScrollChainBlockContext{ + header := IScrollChainBlockContext{ BlockHash: common.Hash{}, ParentHash: common.Hash{}, BlockNumber: 0, @@ -61,8 +59,8 @@ func TestPackCommitBatch(t *testing.T) { NumL1Messages: 0, } - batch := bridge_abi.IScrollChainBatch{ - Blocks: []bridge_abi.IScrollChainBlockContext{header}, + batch := IScrollChainBatch{ + Blocks: []IScrollChainBlockContext{header}, PrevStateRoot: common.Hash{}, NewStateRoot: common.Hash{}, WithdrawTrieRoot: common.Hash{}, @@ -77,7 +75,7 @@ func TestPackCommitBatch(t *testing.T) { func TestPackFinalizeBatchWithProof(t *testing.T) { assert := assert.New(t) - l1RollupABI, err := bridge_abi.ScrollChainMetaData.GetAbi() + l1RollupABI, err := ScrollChainMetaData.GetAbi() assert.NoError(err) proof := make([]*big.Int, 10) @@ -94,7 +92,7 @@ func TestPackFinalizeBatchWithProof(t *testing.T) { func TestPackRelayL1Message(t *testing.T) { assert := assert.New(t) - l2MessengerABI, err := bridge_abi.L2ScrollMessengerMetaData.GetAbi() + l2MessengerABI, err := L2ScrollMessengerMetaData.GetAbi() assert.NoError(err) _, err = l2MessengerABI.Pack("relayMessage", common.Address{}, common.Address{}, big.NewInt(0), big.NewInt(0), make([]byte, 0)) @@ -104,7 +102,7 @@ func TestPackRelayL1Message(t *testing.T) { func TestPackSetL1BaseFee(t *testing.T) { assert := assert.New(t) - l1GasOracleABI, err := bridge_abi.L1GasPriceOracleMetaData.GetAbi() + l1GasOracleABI, err := L1GasPriceOracleMetaData.GetAbi() assert.NoError(err) baseFee := big.NewInt(2333) @@ -115,7 +113,7 @@ func TestPackSetL1BaseFee(t *testing.T) { func TestPackSetL2BaseFee(t *testing.T) { assert := assert.New(t) - l2GasOracleABI, err := bridge_abi.L2GasPriceOracleMetaData.GetAbi() + l2GasOracleABI, err := L2GasPriceOracleMetaData.GetAbi() assert.NoError(err) baseFee := big.NewInt(2333) @@ -126,7 +124,7 @@ func TestPackSetL2BaseFee(t *testing.T) { func TestPackImportBlock(t *testing.T) { assert := assert.New(t) - l1BlockContainerABI := bridge_abi.L1BlockContainerABI + l1BlockContainerABI := L1BlockContainerABI _, err := l1BlockContainerABI.Pack("importBlockHeader", common.Hash{}, make([]byte, 0), false) assert.NoError(err) diff --git a/bridge/scripts/build_abi.sh b/bridge/abi/build_abi.sh similarity index 100% rename from bridge/scripts/build_abi.sh rename to bridge/abi/build_abi.sh diff --git a/bridge/cmd/event_watcher/app/app.go b/bridge/cmd/event_watcher/app/app.go index cfb4db455..9256b9eae 100644 --- a/bridge/cmd/event_watcher/app/app.go +++ b/bridge/cmd/event_watcher/app/app.go @@ -11,36 +11,29 @@ import ( "github.com/scroll-tech/go-ethereum/log" "github.com/urfave/cli/v2" - "scroll-tech/database" - "scroll-tech/common/metrics" + cutils "scroll-tech/common/utils" "scroll-tech/common/version" - "scroll-tech/bridge/config" - "scroll-tech/bridge/watcher" - - cutils "scroll-tech/common/utils" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/controller/watcher" + "scroll-tech/bridge/internal/utils" ) -var ( - app *cli.App -) +var app *cli.App func init() { // Set up event-watcher app info. app = cli.NewApp() - app.Action = action app.Name = "event-watcher" app.Usage = "The Scroll Event Watcher" app.Version = version.Version app.Flags = append(app.Flags, cutils.CommonFlags...) app.Commands = []*cli.Command{} - app.Before = func(ctx *cli.Context) error { return cutils.LogSetup(ctx) } - // Register `event-watcher-test` app for integration-test. cutils.RegisterSimulation(app, cutils.EventWatcherApp) } @@ -55,15 +48,13 @@ func action(ctx *cli.Context) error { subCtx, cancel := context.WithCancel(ctx.Context) // Init db connection - var ormFactory database.OrmFactory - if ormFactory, err = database.NewOrmFactory(cfg.DBConfig); err != nil { + db, err := utils.InitDB(cfg.DBConfig) + if err != nil { log.Crit("failed to init db connection", "err", err) } - defer func() { cancel() - err = ormFactory.Close() - if err != nil { + if err = utils.CloseDB(db); err != nil { log.Error("can not close ormFactory", "error", err) } }() @@ -81,8 +72,8 @@ func action(ctx *cli.Context) error { log.Error("failed to connect l2 geth", "config file", cfgFile, "error", err) return err } - l1watcher := watcher.NewL1WatcherClient(ctx.Context, l1client, cfg.L1Config.StartHeight, cfg.L1Config.Confirmations, cfg.L1Config.L1MessengerAddress, cfg.L1Config.L1MessageQueueAddress, cfg.L1Config.ScrollChainContractAddress, ormFactory) - l2watcher := watcher.NewL2WatcherClient(ctx.Context, l2client, cfg.L2Config.Confirmations, cfg.L2Config.L2MessengerAddress, cfg.L2Config.L2MessageQueueAddress, cfg.L2Config.WithdrawTrieRootSlot, ormFactory) + l1watcher := watcher.NewL1WatcherClient(ctx.Context, l1client, cfg.L1Config.StartHeight, cfg.L1Config.Confirmations, cfg.L1Config.L1MessengerAddress, cfg.L1Config.L1MessageQueueAddress, cfg.L1Config.ScrollChainContractAddress, db) + l2watcher := watcher.NewL2WatcherClient(ctx.Context, l2client, cfg.L2Config.Confirmations, cfg.L2Config.L2MessengerAddress, cfg.L2Config.L2MessageQueueAddress, cfg.L2Config.WithdrawTrieRootSlot, db) go cutils.Loop(subCtx, 10*time.Second, func() { if loopErr := l1watcher.FetchContractEvent(); loopErr != nil { diff --git a/bridge/cmd/gas_oracle/app/app.go b/bridge/cmd/gas_oracle/app/app.go index b7a45bcc8..a13b59348 100644 --- a/bridge/cmd/gas_oracle/app/app.go +++ b/bridge/cmd/gas_oracle/app/app.go @@ -11,27 +11,21 @@ import ( "github.com/scroll-tech/go-ethereum/log" "github.com/urfave/cli/v2" - "scroll-tech/database" - "scroll-tech/common/metrics" + cutils "scroll-tech/common/utils" "scroll-tech/common/version" - "scroll-tech/bridge/config" - "scroll-tech/bridge/relayer" - "scroll-tech/bridge/utils" - "scroll-tech/bridge/watcher" - - cutils "scroll-tech/common/utils" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/controller/watcher" + "scroll-tech/bridge/internal/utils" ) -var ( - app *cli.App -) +var app *cli.App func init() { // Set up gas-oracle app info. app = cli.NewApp() - app.Action = action app.Name = "gas-oracle" app.Usage = "The Scroll Gas Oracle" @@ -39,11 +33,9 @@ func init() { app.Version = version.Version app.Flags = append(app.Flags, cutils.CommonFlags...) app.Commands = []*cli.Command{} - app.Before = func(ctx *cli.Context) error { return cutils.LogSetup(ctx) } - // Register `gas-oracle-test` app for integration-test. cutils.RegisterSimulation(app, cutils.GasOracleApp) } @@ -57,18 +49,17 @@ func action(ctx *cli.Context) error { } subCtx, cancel := context.WithCancel(ctx.Context) // Init db connection - var ormFactory database.OrmFactory - if ormFactory, err = database.NewOrmFactory(cfg.DBConfig); err != nil { + db, err := utils.InitDB(cfg.DBConfig) + if err != nil { log.Crit("failed to init db connection", "err", err) } - defer func() { cancel() - err = ormFactory.Close() - if err != nil { + if err = utils.CloseDB(db); err != nil { log.Error("can not close ormFactory", "error", err) } }() + // Start metrics server. metrics.Serve(subCtx, ctx) @@ -85,14 +76,14 @@ func action(ctx *cli.Context) error { return err } - l1watcher := watcher.NewL1WatcherClient(ctx.Context, l1client, cfg.L1Config.StartHeight, cfg.L1Config.Confirmations, cfg.L1Config.L1MessengerAddress, cfg.L1Config.L1MessageQueueAddress, cfg.L1Config.ScrollChainContractAddress, ormFactory) + l1watcher := watcher.NewL1WatcherClient(ctx.Context, l1client, cfg.L1Config.StartHeight, cfg.L1Config.Confirmations, cfg.L1Config.L1MessengerAddress, cfg.L1Config.L1MessageQueueAddress, cfg.L1Config.ScrollChainContractAddress, db) - l1relayer, err := relayer.NewLayer1Relayer(ctx.Context, ormFactory, cfg.L1Config.RelayerConfig) + l1relayer, err := relayer.NewLayer1Relayer(ctx.Context, db, cfg.L1Config.RelayerConfig) if err != nil { log.Error("failed to create new l1 relayer", "config file", cfgFile, "error", err) return err } - l2relayer, err := relayer.NewLayer2Relayer(ctx.Context, l2client, ormFactory, cfg.L2Config.RelayerConfig) + l2relayer, err := relayer.NewLayer2Relayer(ctx.Context, l2client, db, cfg.L2Config.RelayerConfig) if err != nil { log.Error("failed to create new l2 relayer", "config file", cfgFile, "error", err) return err diff --git a/bridge/cmd/mock_app.go b/bridge/cmd/mock_app.go index 96ee072b2..e0fb2ac51 100644 --- a/bridge/cmd/mock_app.go +++ b/bridge/cmd/mock_app.go @@ -11,7 +11,7 @@ import ( "scroll-tech/common/docker" "scroll-tech/common/utils" - "scroll-tech/bridge/config" + "scroll-tech/bridge/internal/config" ) // MockApp mockApp-test client manager. diff --git a/bridge/cmd/msg_relayer/app/app.go b/bridge/cmd/msg_relayer/app/app.go index f2e2d40b0..962f6445c 100644 --- a/bridge/cmd/msg_relayer/app/app.go +++ b/bridge/cmd/msg_relayer/app/app.go @@ -11,25 +11,20 @@ import ( "github.com/scroll-tech/go-ethereum/log" "github.com/urfave/cli/v2" - "scroll-tech/database" - "scroll-tech/common/metrics" + cutils "scroll-tech/common/utils" "scroll-tech/common/version" - "scroll-tech/bridge/config" - "scroll-tech/bridge/relayer" - - cutils "scroll-tech/common/utils" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/utils" ) -var ( - app *cli.App -) +var app *cli.App func init() { // Set up message-relayer app info. app = cli.NewApp() - app.Action = action app.Name = "message-relayer" app.Usage = "The Scroll Message Relayer" @@ -37,11 +32,9 @@ func init() { app.Version = version.Version app.Flags = append(app.Flags, cutils.CommonFlags...) app.Commands = []*cli.Command{} - app.Before = func(ctx *cli.Context) error { return cutils.LogSetup(ctx) } - // Register `message-relayer-test` app for integration-test. cutils.RegisterSimulation(app, cutils.MessageRelayerApp) } @@ -53,18 +46,16 @@ func action(ctx *cli.Context) error { if err != nil { log.Crit("failed to load config file", "config file", cfgFile, "error", err) } - subCtx, cancel := context.WithCancel(ctx.Context) + subCtx, cancel := context.WithCancel(ctx.Context) // Init db connection - var ormFactory database.OrmFactory - if ormFactory, err = database.NewOrmFactory(cfg.DBConfig); err != nil { + db, err := utils.InitDB(cfg.DBConfig) + if err != nil { log.Crit("failed to init db connection", "err", err) } - defer func() { cancel() - err = ormFactory.Close() - if err != nil { + if err = utils.CloseDB(db); err != nil { log.Error("can not close ormFactory", "error", err) } }() @@ -79,12 +70,12 @@ func action(ctx *cli.Context) error { return err } - l1relayer, err := relayer.NewLayer1Relayer(ctx.Context, ormFactory, cfg.L1Config.RelayerConfig) + l1relayer, err := relayer.NewLayer1Relayer(ctx.Context, db, cfg.L1Config.RelayerConfig) if err != nil { log.Error("failed to create new l1 relayer", "config file", cfgFile, "error", err) return err } - l2relayer, err := relayer.NewLayer2Relayer(ctx.Context, l2client, ormFactory, cfg.L2Config.RelayerConfig) + l2relayer, err := relayer.NewLayer2Relayer(ctx.Context, l2client, db, cfg.L2Config.RelayerConfig) if err != nil { log.Error("failed to create new l2 relayer", "config file", cfgFile, "error", err) return err diff --git a/bridge/cmd/rollup_relayer/app/app.go b/bridge/cmd/rollup_relayer/app/app.go index f08cc659a..62e148d70 100644 --- a/bridge/cmd/rollup_relayer/app/app.go +++ b/bridge/cmd/rollup_relayer/app/app.go @@ -11,34 +11,27 @@ import ( "github.com/scroll-tech/go-ethereum/log" "github.com/urfave/cli/v2" - "scroll-tech/database" - "scroll-tech/common/metrics" + cutils "scroll-tech/common/utils" "scroll-tech/common/version" - "scroll-tech/bridge/config" - "scroll-tech/bridge/relayer" - "scroll-tech/bridge/utils" - "scroll-tech/bridge/watcher" - - cutils "scroll-tech/common/utils" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/controller/watcher" + "scroll-tech/bridge/internal/utils" ) -var ( - app *cli.App -) +var app *cli.App func init() { // Set up rollup-relayer app info. app = cli.NewApp() - app.Action = action app.Name = "rollup-relayer" app.Usage = "The Scroll Rollup Relayer" app.Version = version.Version app.Flags = append(app.Flags, cutils.CommonFlags...) app.Commands = []*cli.Command{} - app.Before = func(ctx *cli.Context) error { return cutils.LogSetup(ctx) } @@ -55,16 +48,14 @@ func action(ctx *cli.Context) error { } subCtx, cancel := context.WithCancel(ctx.Context) - - // init db connection - var ormFactory database.OrmFactory - if ormFactory, err = database.NewOrmFactory(cfg.DBConfig); err != nil { + // Init db connection + db, err := utils.InitDB(cfg.DBConfig) + if err != nil { log.Crit("failed to init db connection", "err", err) } defer func() { cancel() - err = ormFactory.Close() - if err != nil { + if err = utils.CloseDB(db); err != nil { log.Error("can not close ormFactory", "error", err) } }() @@ -79,19 +70,19 @@ func action(ctx *cli.Context) error { return err } - l2relayer, err := relayer.NewLayer2Relayer(ctx.Context, l2client, ormFactory, cfg.L2Config.RelayerConfig) + l2relayer, err := relayer.NewLayer2Relayer(ctx.Context, l2client, db, cfg.L2Config.RelayerConfig) if err != nil { log.Error("failed to create l2 relayer", "config file", cfgFile, "error", err) return err } - batchProposer := watcher.NewBatchProposer(subCtx, cfg.L2Config.BatchProposerConfig, l2relayer, ormFactory) + batchProposer := watcher.NewBatchProposer(subCtx, cfg.L2Config.BatchProposerConfig, l2relayer, db) if err != nil { log.Error("failed to create batchProposer", "config file", cfgFile, "error", err) return err } - l2watcher := watcher.NewL2WatcherClient(subCtx, l2client, cfg.L2Config.Confirmations, cfg.L2Config.L2MessengerAddress, cfg.L2Config.L2MessageQueueAddress, cfg.L2Config.WithdrawTrieRootSlot, ormFactory) + l2watcher := watcher.NewL2WatcherClient(subCtx, l2client, cfg.L2Config.Confirmations, cfg.L2Config.L2MessengerAddress, cfg.L2Config.L2MessageQueueAddress, cfg.L2Config.WithdrawTrieRootSlot, db) // Watcher loop to fetch missing blocks go cutils.LoopWithContext(subCtx, 2*time.Second, func(ctx context.Context) { diff --git a/bridge/config.json b/bridge/conf/config.json similarity index 100% rename from bridge/config.json rename to bridge/conf/config.json diff --git a/bridge/go.mod b/bridge/go.mod index 51a5fe483..308300f6b 100644 --- a/bridge/go.mod +++ b/bridge/go.mod @@ -4,13 +4,18 @@ go 1.18 require ( github.com/agiledragon/gomonkey/v2 v2.9.0 + github.com/jmoiron/sqlx v1.3.5 + github.com/lib/pq v1.10.7 github.com/orcaman/concurrent-map v1.0.0 github.com/orcaman/concurrent-map/v2 v2.0.1 + github.com/pressly/goose/v3 v3.7.0 github.com/scroll-tech/go-ethereum v1.10.14-0.20230508165858-27a3830afa61 github.com/smartystreets/goconvey v1.8.0 github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa golang.org/x/sync v0.1.0 + gorm.io/driver/postgres v1.5.0 + gorm.io/gorm v1.25.1 modernc.org/mathutil v1.4.1 ) @@ -21,19 +26,27 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/uuid v1.3.0 // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/holiman/uint256 v1.2.2 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/iden3/go-iden3-crypto v0.0.15 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx/v5 v5.3.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mattn/go-sqlite3 v1.14.14 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rivo/uniseg v0.4.4 // indirect @@ -51,8 +64,9 @@ require ( github.com/yusufpapurcu/wmi v1.2.2 // indirect golang.org/x/crypto v0.9.0 // indirect golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.3.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + golang.org/x/tools v0.8.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/bridge/go.sum b/bridge/go.sum index 2400570e0..8180eef41 100644 --- a/bridge/go.sum +++ b/bridge/go.sum @@ -29,10 +29,14 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -43,21 +47,38 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= +github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.3.0 h1:/NQi8KHMpKWHInxXesC8yD4DhkXPrVhmnwYkjp9AmBA= +github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= +github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -65,6 +86,9 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -72,8 +96,10 @@ github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp9 github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -87,6 +113,8 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pressly/goose/v3 v3.7.0 h1:jblaZul15uCIEKHRu5KUdA+5wDA7E60JC0TOthdrtf8= +github.com/pressly/goose/v3 v3.7.0/go.mod h1:N5gqPdIzdxf3BiPWdmoPreIwHStkxsvKWE5xjUvfYNk= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -95,6 +123,7 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= @@ -118,8 +147,11 @@ github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -133,37 +165,68 @@ github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bC github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= @@ -173,5 +236,19 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= +gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= +gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64= +gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +modernc.org/cc/v3 v3.36.1 h1:CICrjwr/1M4+6OQ4HJZ/AHxjcwe67r5vPUF518MkO8A= +modernc.org/ccgo/v3 v3.16.8 h1:G0QNlTqI5uVgczBWfGKs7B++EPwCfXPWGD2MdeKloDs= +modernc.org/libc v1.16.19 h1:S8flPn5ZeXx6iw/8yNa986hwTQDrY8RXU7tObZuAozo= modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/sqlite v1.18.1 h1:ko32eKt3jf7eqIkCgPAeHMBXw3riNSLhl2f3loEF7o8= +modernc.org/strutil v1.1.2 h1:iFBDH6j1Z0bN/Q9udJnnFoFpENA4252qe/7/5woE5MI= +modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= diff --git a/bridge/config/config.go b/bridge/internal/config/config.go similarity index 71% rename from bridge/config/config.go rename to bridge/internal/config/config.go index 8561dbb1e..3de7af940 100644 --- a/bridge/config/config.go +++ b/bridge/internal/config/config.go @@ -4,15 +4,13 @@ import ( "encoding/json" "os" "path/filepath" - - "scroll-tech/database" ) // Config load configuration items. type Config struct { - L1Config *L1Config `json:"l1_config"` - L2Config *L2Config `json:"l2_config"` - DBConfig *database.DBConfig `json:"db_config"` + L1Config *L1Config `json:"l1_config"` + L2Config *L2Config `json:"l2_config"` + DBConfig *DBConfig `json:"db_config"` } // NewConfig returns a new instance of Config. diff --git a/bridge/config/config_test.go b/bridge/internal/config/config_test.go similarity index 96% rename from bridge/config/config_test.go rename to bridge/internal/config/config_test.go index b21560dfe..43d466fc9 100644 --- a/bridge/config/config_test.go +++ b/bridge/internal/config/config_test.go @@ -12,7 +12,7 @@ import ( func TestConfig(t *testing.T) { t.Run("Success Case", func(t *testing.T) { - cfg, err := NewConfig("../config.json") + cfg, err := NewConfig("../../conf/config.json") assert.NoError(t, err) assert.Len(t, cfg.L1Config.RelayerConfig.MessageSenderPrivateKeys, 1) diff --git a/bridge/internal/config/db.go b/bridge/internal/config/db.go new file mode 100644 index 000000000..af116d172 --- /dev/null +++ b/bridge/internal/config/db.go @@ -0,0 +1,33 @@ +package config + +import ( + "encoding/json" + "os" + "path/filepath" +) + +// DBConfig db config +type DBConfig struct { + // data source name + DSN string `json:"dsn"` + DriverName string `json:"driver_name"` + + MaxOpenNum int `json:"maxOpenNum"` + MaxIdleNum int `json:"maxIdleNum"` +} + +// NewDBConfig returns a new instance of Config. +func NewDBConfig(file string) (*DBConfig, error) { + buf, err := os.ReadFile(filepath.Clean(file)) + if err != nil { + return nil, err + } + + cfg := &DBConfig{} + err = json.Unmarshal(buf, cfg) + if err != nil { + return nil, err + } + + return cfg, nil +} diff --git a/bridge/config/l1_config.go b/bridge/internal/config/l1.go similarity index 100% rename from bridge/config/l1_config.go rename to bridge/internal/config/l1.go diff --git a/bridge/config/l2_config.go b/bridge/internal/config/l2.go similarity index 98% rename from bridge/config/l2_config.go rename to bridge/internal/config/l2.go index e63f089dc..c0cdec0af 100644 --- a/bridge/config/l2_config.go +++ b/bridge/internal/config/l2.go @@ -5,7 +5,7 @@ import ( "github.com/scroll-tech/go-ethereum/common" - "scroll-tech/common/types" + "scroll-tech/bridge/internal/types" ) // L2Config loads l2geth configuration items. diff --git a/bridge/config/relayer_config.go b/bridge/internal/config/relayer.go similarity index 100% rename from bridge/config/relayer_config.go rename to bridge/internal/config/relayer.go diff --git a/bridge/internal/controller/relayer/common.go b/bridge/internal/controller/relayer/common.go new file mode 100644 index 000000000..ff8ba675d --- /dev/null +++ b/bridge/internal/controller/relayer/common.go @@ -0,0 +1,20 @@ +package relayer + +import "errors" + +const ( + gasPriceDiffPrecision = 1000000 + + defaultGasPriceDiff = 50000 // 5% + + defaultL1MessageRelayMinGasLimit = 130000 // should be enough for both ERC20 and ETH relay + + defaultL2MessageRelayMinGasLimit = 200000 +) + +var ( + // ErrExecutionRevertedMessageExpired error of Message expired + ErrExecutionRevertedMessageExpired = errors.New("execution reverted: Message expired") + // ErrExecutionRevertedAlreadySuccessExecuted error of Message was already successfully executed + ErrExecutionRevertedAlreadySuccessExecuted = errors.New("execution reverted: Message was already successfully executed") +) diff --git a/bridge/relayer/l1_relayer.go b/bridge/internal/controller/relayer/l1_relayer.go similarity index 72% rename from bridge/relayer/l1_relayer.go rename to bridge/internal/controller/relayer/l1_relayer.go index e4ecf13ae..8d70a183c 100644 --- a/bridge/relayer/l1_relayer.go +++ b/bridge/internal/controller/relayer/l1_relayer.go @@ -6,27 +6,25 @@ import ( "math/big" // not sure if this will make problems when relay with l1geth - "github.com/scroll-tech/go-ethereum/accounts/abi" "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/log" - geth_metrics "github.com/scroll-tech/go-ethereum/metrics" - - "scroll-tech/common/types" - - "scroll-tech/database" + gethMetrics "github.com/scroll-tech/go-ethereum/metrics" + "gorm.io/gorm" "scroll-tech/common/metrics" + "scroll-tech/common/types" - bridge_abi "scroll-tech/bridge/abi" - "scroll-tech/bridge/config" - "scroll-tech/bridge/sender" + bridgeAbi "scroll-tech/bridge/abi" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/controller/sender" + "scroll-tech/bridge/internal/orm" ) var ( - bridgeL1MsgsRelayedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l1/msgs/relayed/total", metrics.ScrollRegistry) - bridgeL1MsgsRelayedConfirmedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l1/msgs/relayed/confirmed/total", metrics.ScrollRegistry) + bridgeL1MsgsRelayedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l1/msgs/relayed/total", metrics.ScrollRegistry) + bridgeL1MsgsRelayedConfirmedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l1/msgs/relayed/confirmed/total", metrics.ScrollRegistry) ) // Layer1Relayer is responsible for @@ -38,7 +36,6 @@ var ( type Layer1Relayer struct { ctx context.Context - db database.OrmFactory cfg *config.RelayerConfig // channel used to communicate with transaction sender @@ -53,10 +50,13 @@ type Layer1Relayer struct { lastGasPrice uint64 minGasPrice uint64 gasPriceDiff uint64 + + l1MessageOrm *orm.L1Message + l1Block *orm.L1Block } // NewLayer1Relayer will return a new instance of Layer1RelayerClient -func NewLayer1Relayer(ctx context.Context, db database.OrmFactory, cfg *config.RelayerConfig) (*Layer1Relayer, error) { +func NewLayer1Relayer(ctx context.Context, db *gorm.DB, cfg *config.RelayerConfig) (*Layer1Relayer, error) { messageSender, err := sender.NewSender(ctx, cfg.SenderConfig, cfg.MessageSenderPrivateKeys) if err != nil { addr := crypto.PubkeyToAddress(cfg.MessageSenderPrivateKeys[0].PublicKey) @@ -88,14 +88,15 @@ func NewLayer1Relayer(ctx context.Context, db database.OrmFactory, cfg *config.R } l1Relayer := &Layer1Relayer{ - ctx: ctx, - db: db, + ctx: ctx, + l1MessageOrm: orm.NewL1Message(db), + l1Block: orm.NewL1Block(db), messageSender: messageSender, - l2MessengerABI: bridge_abi.L2ScrollMessengerABI, + l2MessengerABI: bridgeAbi.L2ScrollMessengerABI, gasOracleSender: gasOracleSender, - l1GasOracleABI: bridge_abi.L1GasPriceOracleABI, + l1GasOracleABI: bridgeAbi.L1GasPriceOracleABI, minGasLimitForMessageRelay: minGasLimitForMessageRelay, @@ -112,7 +113,7 @@ func NewLayer1Relayer(ctx context.Context, db database.OrmFactory, cfg *config.R // ProcessSavedEvents relays saved un-processed cross-domain transactions to desired blockchain func (r *Layer1Relayer) ProcessSavedEvents() { // msgs are sorted by nonce in increasing order - msgs, err := r.db.GetL1MessagesByStatus(types.MsgPending, 100) + msgs, err := r.l1MessageOrm.GetL1MessagesByStatus(types.MsgPending, 100) if err != nil { log.Error("Failed to fetch unprocessed L1 messages", "err", err) return @@ -123,7 +124,8 @@ func (r *Layer1Relayer) ProcessSavedEvents() { } for _, msg := range msgs { - if err = r.processSavedEvent(msg); err != nil { + tmpMsg := msg + if err = r.processSavedEvent(&tmpMsg); err != nil { if !errors.Is(err, sender.ErrNoAvailableAccount) && !errors.Is(err, sender.ErrFullPending) { log.Error("failed to process event", "msg.msgHash", msg.MsgHash, "err", err) } @@ -132,15 +134,15 @@ func (r *Layer1Relayer) ProcessSavedEvents() { } } -func (r *Layer1Relayer) processSavedEvent(msg *types.L1Message) error { +func (r *Layer1Relayer) processSavedEvent(msg *orm.L1Message) error { calldata := common.Hex2Bytes(msg.Calldata) - hash, err := r.messageSender.SendTransaction(msg.MsgHash, &r.cfg.MessengerContractAddress, big.NewInt(0), calldata, r.minGasLimitForMessageRelay) - if err != nil && err.Error() == "execution reverted: Message expired" { - return r.db.UpdateLayer1Status(r.ctx, msg.MsgHash, types.MsgExpired) + if err != nil && errors.Is(err, ErrExecutionRevertedMessageExpired) { + return r.l1MessageOrm.UpdateLayer1Status(r.ctx, msg.MsgHash, types.MsgExpired) } - if err != nil && err.Error() == "execution reverted: Message was already successfully executed" { - return r.db.UpdateLayer1Status(r.ctx, msg.MsgHash, types.MsgConfirmed) + + if err != nil && errors.Is(err, ErrExecutionRevertedAlreadySuccessExecuted) { + return r.l1MessageOrm.UpdateLayer1Status(r.ctx, msg.MsgHash, types.MsgConfirmed) } if err != nil { return err @@ -148,7 +150,7 @@ func (r *Layer1Relayer) processSavedEvent(msg *types.L1Message) error { bridgeL1MsgsRelayedTotalCounter.Inc(1) log.Info("relayMessage to layer2", "msg hash", msg.MsgHash, "tx hash", hash) - err = r.db.UpdateLayer1StatusAndLayer2Hash(r.ctx, msg.MsgHash, types.MsgSubmitted, hash.String()) + err = r.l1MessageOrm.UpdateLayer1StatusAndLayer2Hash(r.ctx, msg.MsgHash, types.MsgSubmitted, hash.String()) if err != nil { log.Error("UpdateLayer1StatusAndLayer2Hash failed", "msg.msgHash", msg.MsgHash, "msg.height", msg.Height, "err", err) } @@ -157,17 +159,17 @@ func (r *Layer1Relayer) processSavedEvent(msg *types.L1Message) error { // ProcessGasPriceOracle imports gas price to layer2 func (r *Layer1Relayer) ProcessGasPriceOracle() { - latestBlockHeight, err := r.db.GetLatestL1BlockHeight() + latestBlockHeight, err := r.l1Block.GetLatestL1BlockHeight() if err != nil { log.Warn("Failed to fetch latest L1 block height from db", "err", err) return } - blocks, err := r.db.GetL1BlockInfos(map[string]interface{}{ + blocks, err := r.l1Block.GetL1Blocks(map[string]interface{}{ "number": latestBlockHeight, }) if err != nil { - log.Error("Failed to GetL1BlockInfos from db", "height", latestBlockHeight, "err", err) + log.Error("Failed to GetL1Blocks from db", "height", latestBlockHeight, "err", err) return } if len(blocks) != 1 { @@ -176,7 +178,7 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() { } block := blocks[0] - if block.GasOracleStatus == types.GasOraclePending { + if types.GasOracleStatus(block.GasOracleStatus) == types.GasOraclePending { expectedDelta := r.lastGasPrice * r.gasPriceDiff / gasPriceDiffPrecision // last is undefine or (block.BaseFee >= minGasPrice && exceed diff) if r.lastGasPrice == 0 || (block.BaseFee >= r.minGasPrice && (block.BaseFee >= r.lastGasPrice+expectedDelta || block.BaseFee <= r.lastGasPrice-expectedDelta)) { @@ -195,7 +197,7 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() { return } - err = r.db.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, block.Hash, types.GasOracleImporting, hash.String()) + err = r.l1Block.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, block.Hash, types.GasOracleImporting, hash.String()) if err != nil { log.Error("UpdateGasOracleStatusAndOracleTxHash failed", "block.Hash", block.Hash, "block.Height", block.Number, "err", err) return @@ -214,14 +216,14 @@ func (r *Layer1Relayer) handleConfirmLoop(ctx context.Context) { case cfm := <-r.messageSender.ConfirmChan(): bridgeL1MsgsRelayedConfirmedTotalCounter.Inc(1) if !cfm.IsSuccessful { - err := r.db.UpdateLayer1StatusAndLayer2Hash(r.ctx, cfm.ID, types.MsgRelayFailed, cfm.TxHash.String()) + err := r.l1MessageOrm.UpdateLayer1StatusAndLayer2Hash(r.ctx, cfm.ID, types.MsgRelayFailed, cfm.TxHash.String()) if err != nil { log.Warn("UpdateLayer1StatusAndLayer2Hash failed", "err", err) } log.Warn("transaction confirmed but failed in layer2", "confirmation", cfm) } else { // @todo handle db error - err := r.db.UpdateLayer1StatusAndLayer2Hash(r.ctx, cfm.ID, types.MsgConfirmed, cfm.TxHash.String()) + err := r.l1MessageOrm.UpdateLayer1StatusAndLayer2Hash(r.ctx, cfm.ID, types.MsgConfirmed, cfm.TxHash.String()) if err != nil { log.Warn("UpdateLayer1StatusAndLayer2Hash failed", "err", err) } @@ -230,14 +232,14 @@ func (r *Layer1Relayer) handleConfirmLoop(ctx context.Context) { case cfm := <-r.gasOracleSender.ConfirmChan(): if !cfm.IsSuccessful { // @discuss: maybe make it pending again? - err := r.db.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleFailed, cfm.TxHash.String()) + err := r.l1Block.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleFailed, cfm.TxHash.String()) if err != nil { log.Warn("UpdateL1GasOracleStatusAndOracleTxHash failed", "err", err) } log.Warn("transaction confirmed but failed in layer2", "confirmation", cfm) } else { // @todo handle db error - err := r.db.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleImported, cfm.TxHash.String()) + err := r.l1Block.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleImported, cfm.TxHash.String()) if err != nil { log.Warn("UpdateGasOracleStatusAndOracleTxHash failed", "err", err) } diff --git a/bridge/relayer/l1_relayer_test.go b/bridge/internal/controller/relayer/l1_relayer_test.go similarity index 60% rename from bridge/relayer/l1_relayer_test.go rename to bridge/internal/controller/relayer/l1_relayer_test.go index 41a1a1e04..1f4b3c036 100644 --- a/bridge/relayer/l1_relayer_test.go +++ b/bridge/internal/controller/relayer/l1_relayer_test.go @@ -9,20 +9,20 @@ import ( "github.com/agiledragon/gomonkey/v2" "github.com/scroll-tech/go-ethereum/common" "github.com/smartystreets/goconvey/convey" - "github.com/stretchr/testify/assert" - - "scroll-tech/database" - "scroll-tech/database/migrate" + "gorm.io/gorm" "scroll-tech/common/types" "scroll-tech/common/utils" - "scroll-tech/bridge/sender" + "scroll-tech/bridge/internal/controller/sender" + "scroll-tech/bridge/internal/orm" + "scroll-tech/bridge/internal/orm/migrate" + bridgeUtils "scroll-tech/bridge/internal/utils" ) var ( - templateL1Message = []*types.L1Message{ + templateL1Message = []*orm.L1Message{ { QueueIndex: 1, MsgHash: "msg_hash1", @@ -48,59 +48,58 @@ var ( } ) +func setupL1RelayerDB(t *testing.T) *gorm.DB { + db, err := bridgeUtils.InitDB(cfg.DBConfig) + assert.NoError(t, err) + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, migrate.ResetDB(sqlDB)) + return db +} + // testCreateNewRelayer test create new relayer instance and stop func testCreateNewL1Relayer(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() - + db := setupL1RelayerDB(t) + defer bridgeUtils.CloseDB(db) relayer, err := NewLayer1Relayer(context.Background(), db, cfg.L2Config.RelayerConfig) assert.NoError(t, err) assert.NotNil(t, relayer) } func testL1RelayerProcessSaveEvents(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL1RelayerDB(t) + defer bridgeUtils.CloseDB(db) + l1MessageOrm := orm.NewL1Message(db) l1Cfg := cfg.L1Config relayer, err := NewLayer1Relayer(context.Background(), db, l1Cfg.RelayerConfig) assert.NoError(t, err) - assert.NoError(t, db.SaveL1Messages(context.Background(), templateL1Message)) + assert.NotNil(t, relayer) + assert.NoError(t, l1MessageOrm.SaveL1Messages(context.Background(), templateL1Message)) relayer.ProcessSavedEvents() - msg1, err := db.GetL1MessageByQueueIndex(1) + msg1, err := l1MessageOrm.GetL1MessageByQueueIndex(1) assert.NoError(t, err) - assert.Equal(t, msg1.Status, types.MsgSubmitted) - msg2, err := db.GetL1MessageByQueueIndex(2) + assert.Equal(t, types.MsgStatus(msg1.Status), types.MsgSubmitted) + msg2, err := l1MessageOrm.GetL1MessageByQueueIndex(2) assert.NoError(t, err) - assert.Equal(t, msg2.Status, types.MsgSubmitted) + assert.Equal(t, types.MsgStatus(msg2.Status), types.MsgSubmitted) } func testL1RelayerMsgConfirm(t *testing.T) { - // Set up the database and defer closing it. - db, err := database.NewOrmFactory(cfg.DBConfig) + db := setupL1RelayerDB(t) + defer bridgeUtils.CloseDB(db) + l1MessageOrm := orm.NewL1Message(db) + l1Messages := []*orm.L1Message{ + {MsgHash: "msg-1", QueueIndex: 0}, + {MsgHash: "msg-2", QueueIndex: 1}, + } + err := l1MessageOrm.SaveL1Messages(context.Background(), l1Messages) assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() - - // Insert test data. - assert.NoError(t, db.SaveL1Messages(context.Background(), - []*types.L1Message{ - {MsgHash: "msg-1", QueueIndex: 0}, - {MsgHash: "msg-2", QueueIndex: 1}, - })) - // Create and set up the Layer1 Relayer. l1Cfg := cfg.L1Config ctx, cancel := context.WithCancel(context.Background()) defer cancel() l1Relayer, err := NewLayer1Relayer(ctx, db, l1Cfg.RelayerConfig) assert.NoError(t, err) - assert.NotNil(t, l1Relayer) // Simulate message confirmations. l1Relayer.messageSender.SendConfirmation(&sender.Confirmation{ @@ -114,27 +113,25 @@ func testL1RelayerMsgConfirm(t *testing.T) { // Check the database for the updated status using TryTimes. ok := utils.TryTimes(5, func() bool { - msg1, err1 := db.GetL1MessageByMsgHash("msg-1") - msg2, err2 := db.GetL1MessageByMsgHash("msg-2") - return err1 == nil && msg1.Status == types.MsgConfirmed && - err2 == nil && msg2.Status == types.MsgRelayFailed + msg1, err1 := l1MessageOrm.GetL1MessageByMsgHash("msg-1") + msg2, err2 := l1MessageOrm.GetL1MessageByMsgHash("msg-2") + return err1 == nil && types.MsgStatus(msg1.Status) == types.MsgConfirmed && + err2 == nil && types.MsgStatus(msg2.Status) == types.MsgRelayFailed }) assert.True(t, ok) } func testL1RelayerGasOracleConfirm(t *testing.T) { - // Set up the database and defer closing it. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL1RelayerDB(t) + defer bridgeUtils.CloseDB(db) + l1BlockOrm := orm.NewL1Block(db) + l1Block := []orm.L1Block{ + {Hash: "gas-oracle-1", Number: 0}, + {Hash: "gas-oracle-2", Number: 1}, + } // Insert test data. - assert.NoError(t, db.InsertL1Blocks(context.Background(), - []*types.L1BlockInfo{ - {Hash: "gas-oracle-1", Number: 0}, - {Hash: "gas-oracle-2", Number: 1}, - })) + assert.NoError(t, l1BlockOrm.InsertL1Blocks(context.Background(), l1Block)) // Create and set up the Layer2 Relayer. l1Cfg := cfg.L1Config @@ -142,7 +139,6 @@ func testL1RelayerGasOracleConfirm(t *testing.T) { defer cancel() l1Relayer, err := NewLayer1Relayer(ctx, db, l1Cfg.RelayerConfig) assert.NoError(t, err) - assert.NotNil(t, l1Relayer) // Simulate message confirmations. l1Relayer.gasOracleSender.SendConfirmation(&sender.Confirmation{ @@ -156,19 +152,17 @@ func testL1RelayerGasOracleConfirm(t *testing.T) { // Check the database for the updated status using TryTimes. ok := utils.TryTimes(5, func() bool { - msg1, err1 := db.GetL1BlockInfos(map[string]interface{}{"hash": "gas-oracle-1"}) - msg2, err2 := db.GetL1BlockInfos(map[string]interface{}{"hash": "gas-oracle-2"}) - return err1 == nil && len(msg1) == 1 && msg1[0].GasOracleStatus == types.GasOracleImported && - err2 == nil && len(msg2) == 1 && msg2[0].GasOracleStatus == types.GasOracleFailed + msg1, err1 := l1BlockOrm.GetL1Blocks(map[string]interface{}{"hash": "gas-oracle-1"}) + msg2, err2 := l1BlockOrm.GetL1Blocks(map[string]interface{}{"hash": "gas-oracle-2"}) + return err1 == nil && len(msg1) == 1 && types.GasOracleStatus(msg1[0].GasOracleStatus) == types.GasOracleImported && + err2 == nil && len(msg2) == 1 && types.GasOracleStatus(msg2[0].GasOracleStatus) == types.GasOracleFailed }) assert.True(t, ok) } func testL1RelayerProcessGasPriceOracle(t *testing.T) { - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL1RelayerDB(t) + defer bridgeUtils.CloseDB(db) l1Cfg := cfg.L1Config ctx, cancel := context.WithCancel(context.Background()) @@ -177,31 +171,32 @@ func testL1RelayerProcessGasPriceOracle(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, l1Relayer) + var l1BlockOrm *orm.L1Block convey.Convey("GetLatestL1BlockHeight failure", t, func() { targetErr := errors.New("GetLatestL1BlockHeight error") - patchGuard := gomonkey.ApplyMethodFunc(db, "GetLatestL1BlockHeight", func() (uint64, error) { + patchGuard := gomonkey.ApplyMethodFunc(l1BlockOrm, "GetLatestL1BlockHeight", func() (uint64, error) { return 0, targetErr }) defer patchGuard.Reset() l1Relayer.ProcessGasPriceOracle() }) - patchGuard := gomonkey.ApplyMethodFunc(db, "GetLatestL1BlockHeight", func() (uint64, error) { + patchGuard := gomonkey.ApplyMethodFunc(l1BlockOrm, "GetLatestL1BlockHeight", func() (uint64, error) { return 100, nil }) defer patchGuard.Reset() - convey.Convey("GetL1BlockInfos failure", t, func() { - targetErr := errors.New("GetL1BlockInfos error") - patchGuard.ApplyMethodFunc(db, "GetL1BlockInfos", func(fields map[string]interface{}, args ...string) ([]*types.L1BlockInfo, error) { + convey.Convey("GetL1Blocks failure", t, func() { + targetErr := errors.New("GetL1Blocks error") + patchGuard.ApplyMethodFunc(l1BlockOrm, "GetL1Blocks", func(fields map[string]interface{}) ([]orm.L1Block, error) { return nil, targetErr }) l1Relayer.ProcessGasPriceOracle() }) convey.Convey("Block not exist", t, func() { - patchGuard.ApplyMethodFunc(db, "GetL1BlockInfos", func(fields map[string]interface{}, args ...string) ([]*types.L1BlockInfo, error) { - tmpInfo := []*types.L1BlockInfo{ + patchGuard.ApplyMethodFunc(l1BlockOrm, "GetL1Blocks", func(fields map[string]interface{}) ([]orm.L1Block, error) { + tmpInfo := []orm.L1Block{ {Hash: "gas-oracle-1", Number: 0}, {Hash: "gas-oracle-2", Number: 1}, } @@ -210,12 +205,12 @@ func testL1RelayerProcessGasPriceOracle(t *testing.T) { l1Relayer.ProcessGasPriceOracle() }) - patchGuard.ApplyMethodFunc(db, "GetL1BlockInfos", func(fields map[string]interface{}, args ...string) ([]*types.L1BlockInfo, error) { - tmpInfo := []*types.L1BlockInfo{ + patchGuard.ApplyMethodFunc(l1BlockOrm, "GetL1Blocks", func(fields map[string]interface{}) ([]orm.L1Block, error) { + tmpInfo := []orm.L1Block{ { Hash: "gas-oracle-1", Number: 0, - GasOracleStatus: types.GasOraclePending, + GasOracleStatus: int(types.GasOraclePending), }, } return tmpInfo, nil @@ -247,13 +242,13 @@ func testL1RelayerProcessGasPriceOracle(t *testing.T) { convey.Convey("UpdateL1GasOracleStatusAndOracleTxHash failure", t, func() { targetErr := errors.New("UpdateL1GasOracleStatusAndOracleTxHash failure") - patchGuard.ApplyMethodFunc(db, "UpdateL1GasOracleStatusAndOracleTxHash", func(context.Context, string, types.GasOracleStatus, string) error { + patchGuard.ApplyMethodFunc(l1BlockOrm, "UpdateL1GasOracleStatusAndOracleTxHash", func(context.Context, string, types.GasOracleStatus, string) error { return targetErr }) l1Relayer.ProcessGasPriceOracle() }) - patchGuard.ApplyMethodFunc(db, "UpdateL1GasOracleStatusAndOracleTxHash", func(context.Context, string, types.GasOracleStatus, string) error { + patchGuard.ApplyMethodFunc(l1BlockOrm, "UpdateL1GasOracleStatusAndOracleTxHash", func(context.Context, string, types.GasOracleStatus, string) error { return nil }) diff --git a/bridge/relayer/l2_relayer.go b/bridge/internal/controller/relayer/l2_relayer.go similarity index 75% rename from bridge/relayer/l2_relayer.go rename to bridge/internal/controller/relayer/l2_relayer.go index 59ff4138e..f3d71c53a 100644 --- a/bridge/relayer/l2_relayer.go +++ b/bridge/internal/controller/relayer/l2_relayer.go @@ -3,7 +3,6 @@ package relayer import ( "context" "errors" - "fmt" "math/big" "runtime" "sync" @@ -13,29 +12,30 @@ import ( "github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/log" - geth_metrics "github.com/scroll-tech/go-ethereum/metrics" + gethMetrics "github.com/scroll-tech/go-ethereum/metrics" "golang.org/x/sync/errgroup" + "gorm.io/gorm" "modernc.org/mathutil" "scroll-tech/common/metrics" "scroll-tech/common/types" - "scroll-tech/database" - - bridge_abi "scroll-tech/bridge/abi" - "scroll-tech/bridge/config" - "scroll-tech/bridge/sender" - "scroll-tech/bridge/utils" + bridgeAbi "scroll-tech/bridge/abi" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/controller/sender" + "scroll-tech/bridge/internal/orm" + bridgeTypes "scroll-tech/bridge/internal/types" + "scroll-tech/bridge/internal/utils" ) var ( - bridgeL2MsgsRelayedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/msgs/relayed/total", metrics.ScrollRegistry) - bridgeL2BatchesFinalizedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/finalized/total", metrics.ScrollRegistry) - bridgeL2BatchesCommittedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/committed/total", metrics.ScrollRegistry) - bridgeL2MsgsRelayedConfirmedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/msgs/relayed/confirmed/total", metrics.ScrollRegistry) - bridgeL2BatchesFinalizedConfirmedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/finalized/confirmed/total", metrics.ScrollRegistry) - bridgeL2BatchesCommittedConfirmedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/committed/confirmed/total", metrics.ScrollRegistry) - bridgeL2BatchesSkippedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/skipped/total", metrics.ScrollRegistry) + bridgeL2MsgsRelayedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/msgs/relayed/total", metrics.ScrollRegistry) + bridgeL2BatchesFinalizedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/finalized/total", metrics.ScrollRegistry) + bridgeL2BatchesCommittedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/committed/total", metrics.ScrollRegistry) + bridgeL2MsgsRelayedConfirmedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/msgs/relayed/confirmed/total", metrics.ScrollRegistry) + bridgeL2BatchesFinalizedConfirmedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/finalized/confirmed/total", metrics.ScrollRegistry) + bridgeL2BatchesCommittedConfirmedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/committed/confirmed/total", metrics.ScrollRegistry) + bridgeL2BatchesSkippedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/skipped/total", metrics.ScrollRegistry) ) // Layer2Relayer is responsible for @@ -49,7 +49,10 @@ type Layer2Relayer struct { l2Client *ethclient.Client - db database.OrmFactory + blockBatchOrm *orm.BlockBatch + blockTraceOrm *orm.BlockTrace + l2MessageOrm *orm.L2Message + cfg *config.RelayerConfig messageSender *sender.Sender @@ -81,7 +84,7 @@ type Layer2Relayer struct { } // NewLayer2Relayer will return a new instance of Layer2RelayerClient -func NewLayer2Relayer(ctx context.Context, l2Client *ethclient.Client, db database.OrmFactory, cfg *config.RelayerConfig) (*Layer2Relayer, error) { +func NewLayer2Relayer(ctx context.Context, l2Client *ethclient.Client, db *gorm.DB, cfg *config.RelayerConfig) (*Layer2Relayer, error) { // @todo use different sender for relayer, block commit and proof finalize messageSender, err := sender.NewSender(ctx, cfg.SenderConfig, cfg.MessageSenderPrivateKeys) if err != nil { @@ -118,18 +121,21 @@ func NewLayer2Relayer(ctx context.Context, l2Client *ethclient.Client, db databa layer2Relayer := &Layer2Relayer{ ctx: ctx, - db: db, + + blockBatchOrm: orm.NewBlockBatch(db), + l2MessageOrm: orm.NewL2Message(db), + blockTraceOrm: orm.NewBlockTrace(db), l2Client: l2Client, messageSender: messageSender, - l1MessengerABI: bridge_abi.L1ScrollMessengerABI, + l1MessengerABI: bridgeAbi.L1ScrollMessengerABI, rollupSender: rollupSender, - l1RollupABI: bridge_abi.ScrollChainABI, + l1RollupABI: bridgeAbi.ScrollChainABI, gasOracleSender: gasOracleSender, - l2GasOracleABI: bridge_abi.L2GasPriceOracleABI, + l2GasOracleABI: bridgeAbi.L2GasPriceOracleABI, minGasLimitForMessageRelay: minGasLimitForMessageRelay, @@ -149,19 +155,23 @@ const processMsgLimit = 100 // ProcessSavedEvents relays saved un-processed cross-domain transactions to desired blockchain func (r *Layer2Relayer) ProcessSavedEvents() { - batch, err := r.db.GetLatestFinalizedBatch() + batch, err := r.blockBatchOrm.GetLatestBatchByRollupStatus([]types.RollupStatus{types.RollupFinalized}) if err != nil { log.Error("GetLatestFinalizedBatch failed", "err", err) return } // msgs are sorted by nonce in increasing order - msgs, err := r.db.GetL2Messages( - map[string]interface{}{"status": types.MsgPending}, - fmt.Sprintf("AND height<=%d", batch.EndBlockNumber), - fmt.Sprintf("ORDER BY nonce ASC LIMIT %d", processMsgLimit), - ) + fields := map[string]interface{}{ + "status": int(types.MsgPending), + "height <= (?)": batch.EndBlockNumber, + } + orderByList := []string{ + "nonce ASC", + } + limit := processMsgLimit + msgs, err := r.l2MessageOrm.GetL2Messages(fields, orderByList, limit) if err != nil { log.Error("Failed to fetch unprocessed L2 messages", "err", err) return @@ -177,7 +187,7 @@ func (r *Layer2Relayer) ProcessSavedEvents() { for _, msg := range msgs[:size] { msg := msg g.Go(func() error { - return r.processSavedEvent(msg) + return r.processSavedEvent(&msg) }) } if err := g.Wait(); err != nil { @@ -189,24 +199,28 @@ func (r *Layer2Relayer) ProcessSavedEvents() { } } -func (r *Layer2Relayer) processSavedEvent(msg *types.L2Message) error { +func (r *Layer2Relayer) processSavedEvent(msg *orm.L2Message) error { // @todo fetch merkle proof from l2geth log.Info("Processing L2 Message", "msg.nonce", msg.Nonce, "msg.height", msg.Height) // Get the block info that contains the message - blockInfos, err := r.db.GetL2BlockInfos(map[string]interface{}{"number": msg.Height}) + blockInfos, err := r.blockTraceOrm.GetL2BlockInfos(map[string]interface{}{"number": msg.Height}, nil, 0) if err != nil { log.Error("Failed to GetL2BlockInfos from DB", "number", msg.Height) } + if len(blockInfos) == 0 { + return errors.New("get block trace len is 0, exit") + } + blockInfo := blockInfos[0] - if !blockInfo.BatchHash.Valid { + if blockInfo.BatchHash == "" { log.Error("Block has not been batched yet", "number", blockInfo.Number, "msg.nonce", msg.Nonce) return nil } // TODO: rebuild the withdraw trie to generate the merkle proof - proof := bridge_abi.IL1ScrollMessengerL2MessageProof{ - BatchHash: common.HexToHash(blockInfo.BatchHash.String), + proof := bridgeAbi.IL1ScrollMessengerL2MessageProof{ + BatchHash: common.HexToHash(blockInfo.BatchHash), MerkleProof: make([]byte, 0), } from := common.HexToAddress(msg.Sender) @@ -227,11 +241,11 @@ func (r *Layer2Relayer) processSavedEvent(msg *types.L2Message) error { } hash, err := r.messageSender.SendTransaction(msg.MsgHash, &r.cfg.MessengerContractAddress, big.NewInt(0), data, r.minGasLimitForMessageRelay) - if err != nil && err.Error() == "execution reverted: Message expired" { - return r.db.UpdateLayer2Status(r.ctx, msg.MsgHash, types.MsgExpired) + if err != nil && errors.Is(err, ErrExecutionRevertedMessageExpired) { + return r.l2MessageOrm.UpdateLayer2Status(r.ctx, msg.MsgHash, types.MsgExpired) } - if err != nil && err.Error() == "execution reverted: Message was already successfully executed" { - return r.db.UpdateLayer2Status(r.ctx, msg.MsgHash, types.MsgConfirmed) + if err != nil && errors.Is(err, ErrExecutionRevertedAlreadySuccessExecuted) { + return r.l2MessageOrm.UpdateLayer2Status(r.ctx, msg.MsgHash, types.MsgConfirmed) } if err != nil { if !errors.Is(err, sender.ErrNoAvailableAccount) && !errors.Is(err, sender.ErrFullPending) { @@ -244,7 +258,7 @@ func (r *Layer2Relayer) processSavedEvent(msg *types.L2Message) error { // save status in db // @todo handle db error - err = r.db.UpdateLayer2StatusAndLayer1Hash(r.ctx, msg.MsgHash, types.MsgSubmitted, hash.String()) + err = r.l2MessageOrm.UpdateLayer2StatusAndLayer1Hash(r.ctx, msg.MsgHash, types.MsgSubmitted, hash.String()) if err != nil { log.Error("UpdateLayer2StatusAndLayer1Hash failed", "msgHash", msg.MsgHash, "err", err) return err @@ -255,13 +269,13 @@ func (r *Layer2Relayer) processSavedEvent(msg *types.L2Message) error { // ProcessGasPriceOracle imports gas price to layer1 func (r *Layer2Relayer) ProcessGasPriceOracle() { - batch, err := r.db.GetLatestBatch() + batch, err := r.blockBatchOrm.GetLatestBatch() if err != nil { log.Error("Failed to GetLatestBatch", "err", err) return } - if batch.OracleStatus == types.GasOraclePending { + if types.GasOracleStatus(batch.OracleStatus) == types.GasOraclePending { suggestGasPrice, err := r.l2Client.SuggestGasPrice(r.ctx) if err != nil { log.Error("Failed to fetch SuggestGasPrice from l2geth", "err", err) @@ -286,7 +300,7 @@ func (r *Layer2Relayer) ProcessGasPriceOracle() { return } - err = r.db.UpdateL2GasOracleStatusAndOracleTxHash(r.ctx, batch.Hash, types.GasOracleImporting, hash.String()) + err = r.blockBatchOrm.UpdateL2GasOracleStatusAndOracleTxHash(r.ctx, batch.Hash, types.GasOracleImporting, hash.String()) if err != nil { log.Error("UpdateGasOracleStatusAndOracleTxHash failed", "batch.Hash", batch.Hash, "err", err) return @@ -298,14 +312,14 @@ func (r *Layer2Relayer) ProcessGasPriceOracle() { } // SendCommitTx sends commitBatches tx to L1. -func (r *Layer2Relayer) SendCommitTx(batchData []*types.BatchData) error { +func (r *Layer2Relayer) SendCommitTx(batchData []*bridgeTypes.BatchData) error { if len(batchData) == 0 { log.Error("SendCommitTx receives empty batch") return nil } // pack calldata - commitBatches := make([]bridge_abi.IScrollChainBatch, len(batchData)) + commitBatches := make([]bridgeAbi.IScrollChainBatch, len(batchData)) for i, batch := range batchData { commitBatches[i] = batch.Batch } @@ -341,7 +355,7 @@ func (r *Layer2Relayer) SendCommitTx(batchData []*types.BatchData) error { batchHashes := make([]string, len(batchData)) for i, batch := range batchData { batchHashes[i] = batch.Hash().Hex() - err = r.db.UpdateCommitTxHashAndRollupStatus(r.ctx, batchHashes[i], txHash.String(), types.RollupCommitting) + err = r.blockBatchOrm.UpdateCommitTxHashAndRollupStatus(r.ctx, batchHashes[i], txHash.String(), types.RollupCommitting) if err != nil { log.Error("UpdateCommitTxHashAndRollupStatus failed", "hash", batchHashes[i], "index", batch.Batch.BatchIndex, "err", err) } @@ -353,7 +367,7 @@ func (r *Layer2Relayer) SendCommitTx(batchData []*types.BatchData) error { // ProcessCommittedBatches submit proof to layer 1 rollup contract func (r *Layer2Relayer) ProcessCommittedBatches() { // set skipped batches in a single db operation - if count, err := r.db.UpdateSkippedBatches(); err != nil { + if count, err := r.blockBatchOrm.UpdateSkippedBatches(); err != nil { log.Error("UpdateSkippedBatches failed", "err", err) // continue anyway } else if count > 0 { @@ -362,7 +376,7 @@ func (r *Layer2Relayer) ProcessCommittedBatches() { } // batches are sorted by batch index in increasing order - batchHashes, err := r.db.GetCommittedBatches(1) + batchHashes, err := r.blockBatchOrm.GetBlockBatchesHashByRollupStatus(types.RollupCommitted, 1) if err != nil { log.Error("Failed to fetch committed L2 batches", "err", err) return @@ -373,7 +387,7 @@ func (r *Layer2Relayer) ProcessCommittedBatches() { hash := batchHashes[0] // @todo add support to relay multiple batches - batches, err := r.db.GetBlockBatches(map[string]interface{}{"hash": hash}, "LIMIT 1") + batches, err := r.blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": hash}, nil, 1) if err != nil { log.Error("Failed to fetch committed L2 batch", "hash", hash, "err", err) return @@ -384,33 +398,31 @@ func (r *Layer2Relayer) ProcessCommittedBatches() { } batch := batches[0] - status := batch.ProvingStatus - + status := types.ProvingStatus(batch.ProvingStatus) switch status { case types.ProvingTaskUnassigned, types.ProvingTaskAssigned: // The proof for this block is not ready yet. return - case types.ProvingTaskProved: // It's an intermediate state. The roller manager received the proof but has not verified // the proof yet. We don't roll up the proof until it's verified. return - case types.ProvingTaskFailed, types.ProvingTaskSkipped: // note: this is covered by UpdateSkippedBatches, but we keep it for completeness's sake - - if err = r.db.UpdateRollupStatus(r.ctx, hash, types.RollupFinalizationSkipped); err != nil { + if err = r.blockBatchOrm.UpdateRollupStatus(r.ctx, hash, types.RollupFinalizationSkipped); err != nil { log.Warn("UpdateRollupStatus failed", "hash", hash, "err", err) } - case types.ProvingTaskVerified: log.Info("Start to roll up zk proof", "hash", hash) success := false - previousBatch, err := r.db.GetLatestFinalizingOrFinalizedBatch() - + rollupStatues := []types.RollupStatus{ + types.RollupFinalizing, + types.RollupFinalized, + } + previousBatch, err := r.blockBatchOrm.GetLatestBatchByRollupStatus(rollupStatues) // skip submitting proof - if err == nil && uint64(batch.CreatedAt.Sub(*previousBatch.CreatedAt).Seconds()) < r.cfg.FinalizeBatchIntervalSec { + if err == nil && uint64(batch.CreatedAt.Sub(previousBatch.CreatedAt).Seconds()) < r.cfg.FinalizeBatchIntervalSec { log.Info( "Not enough time passed, skipping", "hash", hash, @@ -420,7 +432,7 @@ func (r *Layer2Relayer) ProcessCommittedBatches() { "lastFinalizingCreatedAt", previousBatch.CreatedAt, ) - if err = r.db.UpdateRollupStatus(r.ctx, hash, types.RollupFinalizationSkipped); err != nil { + if err = r.blockBatchOrm.UpdateRollupStatus(r.ctx, hash, types.RollupFinalizationSkipped); err != nil { log.Warn("UpdateRollupStatus failed", "hash", hash, "err", err) } else { success = true @@ -430,7 +442,7 @@ func (r *Layer2Relayer) ProcessCommittedBatches() { } // handle unexpected db error - if err != nil && err.Error() != "sql: no rows in result set" { + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { log.Error("Failed to get latest finalized batch", "err", err) return } @@ -439,13 +451,13 @@ func (r *Layer2Relayer) ProcessCommittedBatches() { // TODO: need to revisit this and have a more fine-grained error handling if !success { log.Info("Failed to upload the proof, change rollup status to FinalizationSkipped", "hash", hash) - if err = r.db.UpdateRollupStatus(r.ctx, hash, types.RollupFinalizationSkipped); err != nil { + if err = r.blockBatchOrm.UpdateRollupStatus(r.ctx, hash, types.RollupFinalizationSkipped); err != nil { log.Warn("UpdateRollupStatus failed", "hash", hash, "err", err) } } }() - proofBuffer, icBuffer, err := r.db.GetVerifiedProofAndInstanceCommitmentsByHash(hash) + proofBuffer, icBuffer, err := r.blockBatchOrm.GetVerifiedProofAndInstanceCommitmentsByHash(hash) if err != nil { log.Warn("fetch get proof by hash failed", "hash", hash, "err", err) return @@ -485,7 +497,7 @@ func (r *Layer2Relayer) ProcessCommittedBatches() { log.Info("finalizeBatchWithProof in layer1", "batch_hash", hash, "tx_hash", hash) // record and sync with db, @todo handle db error - err = r.db.UpdateFinalizeTxHashAndRollupStatus(r.ctx, hash, finalizeTxHash.String(), types.RollupFinalizing) + err = r.blockBatchOrm.UpdateFinalizeTxHashAndRollupStatus(r.ctx, hash, finalizeTxHash.String(), types.RollupFinalizing) if err != nil { log.Warn("UpdateFinalizeTxHashAndRollupStatus failed", "batch_hash", hash, "err", err) } @@ -512,7 +524,7 @@ func (r *Layer2Relayer) handleConfirmation(confirmation *sender.Confirmation) { log.Warn("transaction confirmed but failed in layer1", "confirmation", confirmation) } // @todo handle db error - err := r.db.UpdateLayer2StatusAndLayer1Hash(r.ctx, msgHash.(string), status, confirmation.TxHash.String()) + err := r.l2MessageOrm.UpdateLayer2StatusAndLayer1Hash(r.ctx, msgHash.(string), status, confirmation.TxHash.String()) if err != nil { log.Warn("UpdateLayer2StatusAndLayer1Hash failed", "msgHash", msgHash.(string), "err", err) } @@ -533,7 +545,7 @@ func (r *Layer2Relayer) handleConfirmation(confirmation *sender.Confirmation) { } for _, batchHash := range batchHashes { // @todo handle db error - err := r.db.UpdateCommitTxHashAndRollupStatus(r.ctx, batchHash, confirmation.TxHash.String(), status) + err := r.blockBatchOrm.UpdateCommitTxHashAndRollupStatus(r.ctx, batchHash, confirmation.TxHash.String(), status) if err != nil { log.Warn("UpdateCommitTxHashAndRollupStatus failed", "batch_hash", batchHash, "err", err) } @@ -553,7 +565,7 @@ func (r *Layer2Relayer) handleConfirmation(confirmation *sender.Confirmation) { log.Warn("transaction confirmed but failed in layer1", "confirmation", confirmation) } // @todo handle db error - err := r.db.UpdateFinalizeTxHashAndRollupStatus(r.ctx, batchHash.(string), confirmation.TxHash.String(), status) + err := r.blockBatchOrm.UpdateFinalizeTxHashAndRollupStatus(r.ctx, batchHash.(string), confirmation.TxHash.String(), status) if err != nil { log.Warn("UpdateFinalizeTxHashAndRollupStatus failed", "batch_hash", batchHash.(string), "err", err) } @@ -575,14 +587,14 @@ func (r *Layer2Relayer) handleConfirmLoop(ctx context.Context) { case cfm := <-r.gasOracleSender.ConfirmChan(): if !cfm.IsSuccessful { // @discuss: maybe make it pending again? - err := r.db.UpdateL2GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleFailed, cfm.TxHash.String()) + err := r.blockBatchOrm.UpdateL2GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleFailed, cfm.TxHash.String()) if err != nil { log.Warn("UpdateL2GasOracleStatusAndOracleTxHash failed", "err", err) } log.Warn("transaction confirmed but failed in layer1", "confirmation", cfm) } else { // @todo handle db error - err := r.db.UpdateL2GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleImported, cfm.TxHash.String()) + err := r.blockBatchOrm.UpdateL2GasOracleStatusAndOracleTxHash(r.ctx, cfm.ID, types.GasOracleImported, cfm.TxHash.String()) if err != nil { log.Warn("UpdateL2GasOracleStatusAndOracleTxHash failed", "err", err) } diff --git a/bridge/relayer/l2_relayer_test.go b/bridge/internal/controller/relayer/l2_relayer_test.go similarity index 61% rename from bridge/relayer/l2_relayer_test.go rename to bridge/internal/controller/relayer/l2_relayer_test.go index 1d1f9767e..15e2a7e61 100644 --- a/bridge/relayer/l2_relayer_test.go +++ b/bridge/internal/controller/relayer/l2_relayer_test.go @@ -12,21 +12,23 @@ import ( "github.com/agiledragon/gomonkey/v2" "github.com/scroll-tech/go-ethereum/accounts/abi" "github.com/scroll-tech/go-ethereum/common" - geth_types "github.com/scroll-tech/go-ethereum/core/types" + gethTypes "github.com/scroll-tech/go-ethereum/core/types" "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/assert" + "gorm.io/gorm" "scroll-tech/common/types" "scroll-tech/common/utils" - "scroll-tech/bridge/sender" - - "scroll-tech/database" - "scroll-tech/database/migrate" + "scroll-tech/bridge/internal/controller/sender" + "scroll-tech/bridge/internal/orm" + "scroll-tech/bridge/internal/orm/migrate" + bridgeTypes "scroll-tech/bridge/internal/types" + bridgeUtils "scroll-tech/bridge/internal/utils" ) var ( - templateL2Message = []*types.L2Message{ + templateL2Message = []orm.L2Message{ { Nonce: 1, Height: 1, @@ -39,144 +41,170 @@ var ( } ) -func testCreateNewRelayer(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) +func setupL2RelayerDB(t *testing.T) *gorm.DB { + db, err := bridgeUtils.InitDB(cfg.DBConfig) assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, migrate.ResetDB(sqlDB)) + return db +} +func testCreateNewRelayer(t *testing.T) { + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) relayer, err := NewLayer2Relayer(context.Background(), l2Cli, db, cfg.L2Config.RelayerConfig) assert.NoError(t, err) assert.NotNil(t, relayer) } func testL2RelayerProcessSaveEvents(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() - + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) l2Cfg := cfg.L2Config relayer, err := NewLayer2Relayer(context.Background(), l2Cli, db, l2Cfg.RelayerConfig) assert.NoError(t, err) - err = db.SaveL2Messages(context.Background(), templateL2Message) + l2MessageOrm := orm.NewL2Message(db) + err = l2MessageOrm.SaveL2Messages(context.Background(), templateL2Message) assert.NoError(t, err) - traces := []*types.WrappedBlock{ + traces := []*bridgeTypes.WrappedBlock{ { - Header: &geth_types.Header{ + Header: &gethTypes.Header{ Number: big.NewInt(int64(templateL2Message[0].Height)), }, Transactions: nil, WithdrawTrieRoot: common.Hash{}, }, { - Header: &geth_types.Header{ + Header: &gethTypes.Header{ Number: big.NewInt(int64(templateL2Message[0].Height + 1)), }, Transactions: nil, WithdrawTrieRoot: common.Hash{}, }, } - assert.NoError(t, db.InsertWrappedBlocks(traces)) - parentBatch1 := &types.BlockBatch{ + blockTraceOrm := orm.NewBlockTrace(db) + assert.NoError(t, blockTraceOrm.InsertWrappedBlocks(traces)) + blockBatchOrm := orm.NewBlockBatch(db) + parentBatch1 := &bridgeTypes.BatchInfo{ Index: 0, Hash: common.Hash{}.Hex(), StateRoot: common.Hash{}.Hex(), } - batchData1 := types.NewBatchData(parentBatch1, []*types.WrappedBlock{wrappedBlock1}, nil) - dbTx, err := db.Beginx() - assert.NoError(t, err) - assert.NoError(t, db.NewBatchInDBTx(dbTx, batchData1)) + batchData1 := bridgeTypes.NewBatchData(parentBatch1, []*bridgeTypes.WrappedBlock{wrappedBlock1}, nil) batchHash := batchData1.Hash().Hex() - assert.NoError(t, db.SetBatchHashForL2BlocksInDBTx(dbTx, []uint64{1}, batchHash)) - assert.NoError(t, dbTx.Commit()) + err = db.Transaction(func(tx *gorm.DB) error { + rowsAffected, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batchData1) + if dbTxErr != nil { + return dbTxErr + } + if rowsAffected != 1 { + dbTxErr = errors.New("the InsertBlockBatchByBatchData affected row is not 1") + return dbTxErr + } + dbTxErr = blockTraceOrm.UpdateBatchHashForL2Blocks(tx, []uint64{1}, batchHash) + if dbTxErr != nil { + return dbTxErr + } + return nil + }) + assert.NoError(t, err) - err = db.UpdateRollupStatus(context.Background(), batchHash, types.RollupFinalized) + err = blockBatchOrm.UpdateRollupStatus(context.Background(), batchHash, types.RollupFinalized) assert.NoError(t, err) relayer.ProcessSavedEvents() - msg, err := db.GetL2MessageByNonce(templateL2Message[0].Nonce) + msg, err := l2MessageOrm.GetL2MessageByNonce(templateL2Message[0].Nonce) assert.NoError(t, err) - assert.Equal(t, types.MsgSubmitted, msg.Status) + assert.Equal(t, types.MsgSubmitted, types.MsgStatus(msg.Status)) } func testL2RelayerProcessCommittedBatches(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) l2Cfg := cfg.L2Config relayer, err := NewLayer2Relayer(context.Background(), l2Cli, db, l2Cfg.RelayerConfig) assert.NoError(t, err) - parentBatch1 := &types.BlockBatch{ + parentBatch1 := &bridgeTypes.BatchInfo{ Index: 0, Hash: common.Hash{}.Hex(), StateRoot: common.Hash{}.Hex(), } - batchData1 := types.NewBatchData(parentBatch1, []*types.WrappedBlock{wrappedBlock1}, nil) - dbTx, err := db.Beginx() - assert.NoError(t, err) - assert.NoError(t, db.NewBatchInDBTx(dbTx, batchData1)) + + blockBatchOrm := orm.NewBlockBatch(db) + batchData1 := bridgeTypes.NewBatchData(parentBatch1, []*bridgeTypes.WrappedBlock{wrappedBlock1}, nil) batchHash := batchData1.Hash().Hex() - err = dbTx.Commit() + err = db.Transaction(func(tx *gorm.DB) error { + rowsAffected, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batchData1) + if dbTxErr != nil { + return dbTxErr + } + if rowsAffected != 1 { + dbTxErr = errors.New("the InsertBlockBatchByBatchData affected row is not 1") + return dbTxErr + } + return nil + }) assert.NoError(t, err) - err = db.UpdateRollupStatus(context.Background(), batchHash, types.RollupCommitted) + err = blockBatchOrm.UpdateRollupStatus(context.Background(), batchHash, types.RollupCommitted) assert.NoError(t, err) tProof := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} tInstanceCommitments := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} - err = db.UpdateProofByHash(context.Background(), batchHash, tProof, tInstanceCommitments, 100) + err = blockBatchOrm.UpdateProofByHash(context.Background(), batchHash, tProof, tInstanceCommitments, 100) assert.NoError(t, err) - err = db.UpdateProvingStatus(batchHash, types.ProvingTaskVerified) + err = blockBatchOrm.UpdateProvingStatus(batchHash, types.ProvingTaskVerified) assert.NoError(t, err) relayer.ProcessCommittedBatches() - status, err := db.GetRollupStatus(batchHash) + statuses, err := blockBatchOrm.GetRollupStatusByHashList([]string{batchHash}) assert.NoError(t, err) - assert.Equal(t, types.RollupFinalizing, status) + assert.Equal(t, 1, len(statuses)) + assert.Equal(t, types.RollupFinalizing, statuses[0]) } func testL2RelayerSkipBatches(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) l2Cfg := cfg.L2Config relayer, err := NewLayer2Relayer(context.Background(), l2Cli, db, l2Cfg.RelayerConfig) assert.NoError(t, err) + blockBatchOrm := orm.NewBlockBatch(db) createBatch := func(rollupStatus types.RollupStatus, provingStatus types.ProvingStatus, index uint64) string { - dbTx, err := db.Beginx() - assert.NoError(t, err) batchData := genBatchData(t, index) - assert.NoError(t, db.NewBatchInDBTx(dbTx, batchData)) - batchHash := batchData.Hash().Hex() - err = dbTx.Commit() + err = db.Transaction(func(tx *gorm.DB) error { + rowsAffected, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batchData) + if dbTxErr != nil { + return dbTxErr + } + if rowsAffected != 1 { + dbTxErr = errors.New("the InsertBlockBatchByBatchData affected row is not 1") + return dbTxErr + } + return nil + }) assert.NoError(t, err) - err = db.UpdateRollupStatus(context.Background(), batchHash, rollupStatus) + batchHash := batchData.Hash().Hex() + err = blockBatchOrm.UpdateRollupStatus(context.Background(), batchHash, rollupStatus) assert.NoError(t, err) tProof := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} tInstanceCommitments := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} - err = db.UpdateProofByHash(context.Background(), batchHash, tProof, tInstanceCommitments, 100) + err = blockBatchOrm.UpdateProofByHash(context.Background(), batchHash, tProof, tInstanceCommitments, 100) assert.NoError(t, err) - err = db.UpdateProvingStatus(batchHash, provingStatus) + err = blockBatchOrm.UpdateProvingStatus(batchHash, provingStatus) assert.NoError(t, err) - return batchHash } @@ -200,29 +228,30 @@ func testL2RelayerSkipBatches(t *testing.T) { relayer.ProcessCommittedBatches() for _, id := range skipped { - status, err := db.GetRollupStatus(id) + statuses, err := blockBatchOrm.GetRollupStatusByHashList([]string{id}) assert.NoError(t, err) - assert.Equal(t, types.RollupFinalizationSkipped, status) + assert.Equal(t, 1, len(statuses)) + assert.Equal(t, types.RollupFinalizationSkipped, statuses[0]) } for _, id := range notSkipped { - status, err := db.GetRollupStatus(id) + statuses, err := blockBatchOrm.GetRollupStatusByHashList([]string{id}) assert.NoError(t, err) - assert.NotEqual(t, types.RollupFinalizationSkipped, status) + assert.Equal(t, 1, len(statuses)) + assert.NotEqual(t, types.RollupFinalizationSkipped, statuses[0]) } } func testL2RelayerMsgConfirm(t *testing.T) { - // Set up the database and defer closing it. - db, err := database.NewOrmFactory(cfg.DBConfig) + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) + l2MessageOrm := orm.NewL2Message(db) + insertL2Messages := []orm.L2Message{ + {MsgHash: "msg-1", Nonce: 0}, + {MsgHash: "msg-2", Nonce: 1}, + } + err := l2MessageOrm.SaveL2Messages(context.Background(), insertL2Messages) assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() - - // Insert test data. - assert.NoError(t, db.SaveL2Messages(context.Background(), []*types.L2Message{ - {MsgHash: "msg-1", Nonce: 0}, {MsgHash: "msg-2", Nonce: 1}, - })) // Create and set up the Layer2 Relayer. l2Cfg := cfg.L2Config @@ -245,32 +274,46 @@ func testL2RelayerMsgConfirm(t *testing.T) { // Check the database for the updated status using TryTimes. assert.True(t, utils.TryTimes(5, func() bool { - msg1, err1 := db.GetL2MessageByMsgHash("msg-1") - msg2, err2 := db.GetL2MessageByMsgHash("msg-2") - return err1 == nil && msg1.Status == types.MsgConfirmed && - err2 == nil && msg2.Status == types.MsgRelayFailed + fields1 := map[string]interface{}{"msg_hash": "msg-1"} + msg1, err1 := l2MessageOrm.GetL2Messages(fields1, nil, 0) + if len(msg1) != 1 { + return false + } + fields2 := map[string]interface{}{"msg_hash": "msg-2"} + msg2, err2 := l2MessageOrm.GetL2Messages(fields2, nil, 0) + if len(msg2) != 1 { + return false + } + return err1 == nil && types.MsgStatus(msg1[0].Status) == types.MsgConfirmed && + err2 == nil && types.MsgStatus(msg2[0].Status) == types.MsgRelayFailed })) } func testL2RelayerRollupConfirm(t *testing.T) { - // Set up the database and defer closing it. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) // Insert test data. - batches := make([]*types.BatchData, 6) + batches := make([]*bridgeTypes.BatchData, 6) for i := 0; i < 6; i++ { batches[i] = genBatchData(t, uint64(i)) } - dbTx, err := db.Beginx() + blockBatchOrm := orm.NewBlockBatch(db) + err := db.Transaction(func(tx *gorm.DB) error { + for _, batch := range batches { + rowsAffected, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batch) + if dbTxErr != nil { + return dbTxErr + } + if rowsAffected != 1 { + dbTxErr = errors.New("the InsertBlockBatchByBatchData affected row is not 1") + return dbTxErr + } + } + return nil + }) assert.NoError(t, err) - for _, batch := range batches { - assert.NoError(t, db.NewBatchInDBTx(dbTx, batch)) - } - assert.NoError(t, dbTx.Commit()) // Create and set up the Layer2 Relayer. l2Cfg := cfg.L2Config @@ -314,8 +357,8 @@ func testL2RelayerRollupConfirm(t *testing.T) { } for i, batch := range batches[:6] { - batchInDB, err := db.GetBlockBatches(map[string]interface{}{"hash": batch.Hash().Hex()}) - if err != nil || len(batchInDB) != 1 || batchInDB[0].RollupStatus != expectedStatuses[i] { + batchInDB, err := blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batch.Hash().Hex()}, nil, 0) + if err != nil || len(batchInDB) != 1 || types.RollupStatus(batchInDB[0].RollupStatus) != expectedStatuses[i] { return false } } @@ -325,24 +368,30 @@ func testL2RelayerRollupConfirm(t *testing.T) { } func testL2RelayerGasOracleConfirm(t *testing.T) { - // Set up the database and defer closing it. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) // Insert test data. - batches := make([]*types.BatchData, 2) + batches := make([]*bridgeTypes.BatchData, 2) for i := 0; i < 2; i++ { batches[i] = genBatchData(t, uint64(i)) } - dbTx, err := db.Beginx() + blockBatchOrm := orm.NewBlockBatch(db) + err := db.Transaction(func(tx *gorm.DB) error { + for _, batch := range batches { + rowsAffected, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batch) + if dbTxErr != nil { + return dbTxErr + } + if rowsAffected != 1 { + dbTxErr = errors.New("the InsertBlockBatchByBatchData affected row is not 1") + return dbTxErr + } + } + return nil + }) assert.NoError(t, err) - for _, batch := range batches { - assert.NoError(t, db.NewBatchInDBTx(dbTx, batch)) - } - assert.NoError(t, dbTx.Commit()) // Create and set up the Layer2 Relayer. l2Cfg := cfg.L2Config @@ -364,8 +413,8 @@ func testL2RelayerGasOracleConfirm(t *testing.T) { ok := utils.TryTimes(5, func() bool { expectedStatuses := []types.GasOracleStatus{types.GasOracleImported, types.GasOracleFailed} for i, batch := range batches { - gasOracle, err := db.GetBlockBatches(map[string]interface{}{"hash": batch.Hash().Hex()}) - if err != nil || len(gasOracle) != 1 || gasOracle[0].OracleStatus != expectedStatuses[i] { + gasOracle, err := blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batch.Hash().Hex()}, nil, 0) + if err != nil || len(gasOracle) != 1 || types.GasOracleStatus(gasOracle[0].OracleStatus) != expectedStatuses[i] { return false } } @@ -374,43 +423,42 @@ func testL2RelayerGasOracleConfirm(t *testing.T) { assert.True(t, ok) } -func genBatchData(t *testing.T, index uint64) *types.BatchData { - templateBlockTrace, err := os.ReadFile("../../common/testdata/blockTrace_02.json") +func genBatchData(t *testing.T, index uint64) *bridgeTypes.BatchData { + templateBlockTrace, err := os.ReadFile("../../../testdata/blockTrace_02.json") assert.NoError(t, err) // unmarshal blockTrace - wrappedBlock := &types.WrappedBlock{} + wrappedBlock := &bridgeTypes.WrappedBlock{} err = json.Unmarshal(templateBlockTrace, wrappedBlock) assert.NoError(t, err) wrappedBlock.Header.ParentHash = common.HexToHash("0x" + strconv.FormatUint(index+1, 16)) - parentBatch := &types.BlockBatch{ + parentBatch := &bridgeTypes.BatchInfo{ Index: index, Hash: "0x0000000000000000000000000000000000000000", } - return types.NewBatchData(parentBatch, []*types.WrappedBlock{wrappedBlock}, nil) + return bridgeTypes.NewBatchData(parentBatch, []*bridgeTypes.WrappedBlock{wrappedBlock}, nil) } func testLayer2RelayerProcessGasPriceOracle(t *testing.T) { - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) relayer, err := NewLayer2Relayer(context.Background(), l2Cli, db, cfg.L2Config.RelayerConfig) assert.NoError(t, err) assert.NotNil(t, relayer) + var blockBatchOrm *orm.BlockBatch convey.Convey("Failed to GetLatestBatch", t, func() { targetErr := errors.New("GetLatestBatch error") - patchGuard := gomonkey.ApplyMethodFunc(db, "GetLatestBatch", func() (*types.BlockBatch, error) { + patchGuard := gomonkey.ApplyMethodFunc(blockBatchOrm, "GetLatestBatch", func() (*orm.BlockBatch, error) { return nil, targetErr }) defer patchGuard.Reset() relayer.ProcessGasPriceOracle() }) - patchGuard := gomonkey.ApplyMethodFunc(db, "GetLatestBatch", func() (*types.BlockBatch, error) { - batch := types.BlockBatch{ - OracleStatus: types.GasOraclePending, + patchGuard := gomonkey.ApplyMethodFunc(blockBatchOrm, "GetLatestBatch", func() (*orm.BlockBatch, error) { + batch := orm.BlockBatch{ + OracleStatus: int(types.GasOraclePending), Hash: "0x0000000000000000000000000000000000000000", } return &batch, nil @@ -455,42 +503,40 @@ func testLayer2RelayerProcessGasPriceOracle(t *testing.T) { convey.Convey("UpdateGasOracleStatusAndOracleTxHash failed", t, func() { targetErr := errors.New("UpdateL2GasOracleStatusAndOracleTxHash error") - patchGuard.ApplyMethodFunc(db, "UpdateL2GasOracleStatusAndOracleTxHash", func(ctx context.Context, hash string, status types.GasOracleStatus, txHash string) error { + patchGuard.ApplyMethodFunc(blockBatchOrm, "UpdateL2GasOracleStatusAndOracleTxHash", func(ctx context.Context, hash string, status types.GasOracleStatus, txHash string) error { return targetErr }) relayer.ProcessGasPriceOracle() }) - patchGuard.ApplyMethodFunc(db, "UpdateL2GasOracleStatusAndOracleTxHash", func(ctx context.Context, hash string, status types.GasOracleStatus, txHash string) error { + patchGuard.ApplyMethodFunc(blockBatchOrm, "UpdateL2GasOracleStatusAndOracleTxHash", func(ctx context.Context, hash string, status types.GasOracleStatus, txHash string) error { return nil }) relayer.ProcessGasPriceOracle() } func testLayer2RelayerSendCommitTx(t *testing.T) { - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupL2RelayerDB(t) + defer bridgeUtils.CloseDB(db) relayer, err := NewLayer2Relayer(context.Background(), l2Cli, db, cfg.L2Config.RelayerConfig) assert.NoError(t, err) assert.NotNil(t, relayer) - var batchDataList []*types.BatchData + var batchDataList []*bridgeTypes.BatchData convey.Convey("SendCommitTx receives empty batch", t, func() { err = relayer.SendCommitTx(batchDataList) assert.NoError(t, err) }) - parentBatch := &types.BlockBatch{ + parentBatch := &bridgeTypes.BatchInfo{ Index: 0, Hash: "0x0000000000000000000000000000000000000000", } - traces := []*types.WrappedBlock{ + traces := []*bridgeTypes.WrappedBlock{ { - Header: &geth_types.Header{ + Header: &gethTypes.Header{ Number: big.NewInt(1000), ParentHash: common.Hash{}, Difficulty: big.NewInt(0), @@ -501,8 +547,8 @@ func testLayer2RelayerSendCommitTx(t *testing.T) { }, } - blocks := []*types.WrappedBlock{traces[0]} - tmpBatchData := types.NewBatchData(parentBatch, blocks, cfg.L2Config.BatchProposerConfig.PublicInputConfig) + blocks := []*bridgeTypes.WrappedBlock{traces[0]} + tmpBatchData := bridgeTypes.NewBatchData(parentBatch, blocks, cfg.L2Config.BatchProposerConfig.PublicInputConfig) batchDataList = append(batchDataList, tmpBatchData) var s abi.ABI @@ -535,16 +581,17 @@ func testLayer2RelayerSendCommitTx(t *testing.T) { return common.HexToHash("0x56789abcdef1234"), nil }) + var blockBatchOrm *orm.BlockBatch convey.Convey("UpdateCommitTxHashAndRollupStatus failed", t, func() { targetErr := errors.New("UpdateCommitTxHashAndRollupStatus failure") - patchGuard.ApplyMethodFunc(db, "UpdateCommitTxHashAndRollupStatus", func(ctx context.Context, hash string, commitTxHash string, status types.RollupStatus) error { + patchGuard.ApplyMethodFunc(blockBatchOrm, "UpdateCommitTxHashAndRollupStatus", func(ctx context.Context, hash string, commitTxHash string, status types.RollupStatus) error { return targetErr }) err = relayer.SendCommitTx(batchDataList) assert.NoError(t, err) }) - patchGuard.ApplyMethodFunc(db, "UpdateCommitTxHashAndRollupStatus", func(ctx context.Context, hash string, commitTxHash string, status types.RollupStatus) error { + patchGuard.ApplyMethodFunc(blockBatchOrm, "UpdateCommitTxHashAndRollupStatus", func(ctx context.Context, hash string, commitTxHash string, status types.RollupStatus) error { return nil }) err = relayer.SendCommitTx(batchDataList) diff --git a/bridge/relayer/relayer_test.go b/bridge/internal/controller/relayer/relayer_test.go similarity index 72% rename from bridge/relayer/relayer_test.go rename to bridge/internal/controller/relayer/relayer_test.go index ee0db4af8..0f00adc59 100644 --- a/bridge/relayer/relayer_test.go +++ b/bridge/internal/controller/relayer/relayer_test.go @@ -10,9 +10,9 @@ import ( "github.com/stretchr/testify/assert" "scroll-tech/common/docker" - "scroll-tech/common/types" - "scroll-tech/bridge/config" + "scroll-tech/bridge/internal/config" + bridgeTypes "scroll-tech/bridge/internal/types" ) var ( @@ -25,60 +25,65 @@ var ( l2Cli *ethclient.Client // block trace - wrappedBlock1 *types.WrappedBlock - wrappedBlock2 *types.WrappedBlock + wrappedBlock1 *bridgeTypes.WrappedBlock + wrappedBlock2 *bridgeTypes.WrappedBlock // batch data - batchData1 *types.BatchData - batchData2 *types.BatchData + batchData1 *bridgeTypes.BatchData + batchData2 *bridgeTypes.BatchData ) func setupEnv(t *testing.T) (err error) { // Load config. - cfg, err = config.NewConfig("../config.json") + cfg, err = config.NewConfig("../../../conf/config.json") assert.NoError(t, err) base.RunImages(t) cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1gethImg.Endpoint() cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2gethImg.Endpoint() - cfg.DBConfig = base.DBConfig + cfg.DBConfig = &config.DBConfig{ + DSN: base.DBConfig.DSN, + DriverName: base.DBConfig.DriverName, + MaxOpenNum: base.DBConfig.MaxOpenNum, + MaxIdleNum: base.DBConfig.MaxIdleNum, + } // Create l2geth client. l2Cli, err = base.L2Client() assert.NoError(t, err) - templateBlockTrace1, err := os.ReadFile("../../common/testdata/blockTrace_02.json") + templateBlockTrace1, err := os.ReadFile("../../../testdata/blockTrace_02.json") if err != nil { return err } // unmarshal blockTrace - wrappedBlock1 = &types.WrappedBlock{} + wrappedBlock1 = &bridgeTypes.WrappedBlock{} if err = json.Unmarshal(templateBlockTrace1, wrappedBlock1); err != nil { return err } - parentBatch1 := &types.BlockBatch{ + parentBatch1 := &bridgeTypes.BatchInfo{ Index: 0, Hash: "0x0cc6b102c2924402c14b2e3a19baccc316252bfdc44d9ec62e942d34e39ec729", StateRoot: "0x2579122e8f9ec1e862e7d415cef2fb495d7698a8e5f0dddc5651ba4236336e7d", } - batchData1 = types.NewBatchData(parentBatch1, []*types.WrappedBlock{wrappedBlock1}, nil) + batchData1 = bridgeTypes.NewBatchData(parentBatch1, []*bridgeTypes.WrappedBlock{wrappedBlock1}, nil) - templateBlockTrace2, err := os.ReadFile("../../common/testdata/blockTrace_03.json") + templateBlockTrace2, err := os.ReadFile("../../../testdata/blockTrace_03.json") if err != nil { return err } // unmarshal blockTrace - wrappedBlock2 = &types.WrappedBlock{} + wrappedBlock2 = &bridgeTypes.WrappedBlock{} if err = json.Unmarshal(templateBlockTrace2, wrappedBlock2); err != nil { return err } - parentBatch2 := &types.BlockBatch{ + parentBatch2 := &bridgeTypes.BatchInfo{ Index: batchData1.Batch.BatchIndex, Hash: batchData1.Hash().Hex(), StateRoot: batchData1.Batch.NewStateRoot.String(), } - batchData2 = types.NewBatchData(parentBatch2, []*types.WrappedBlock{wrappedBlock2}, nil) + batchData2 = bridgeTypes.NewBatchData(parentBatch2, []*bridgeTypes.WrappedBlock{wrappedBlock2}, nil) log.Info("batchHash", "batchhash1", batchData1.Hash().Hex(), "batchhash2", batchData2.Hash().Hex()) diff --git a/bridge/sender/account_pool.go b/bridge/internal/controller/sender/account_pool.go similarity index 100% rename from bridge/sender/account_pool.go rename to bridge/internal/controller/sender/account_pool.go diff --git a/bridge/sender/estimategas.go b/bridge/internal/controller/sender/estimategas.go similarity index 100% rename from bridge/sender/estimategas.go rename to bridge/internal/controller/sender/estimategas.go diff --git a/bridge/sender/sender.go b/bridge/internal/controller/sender/sender.go similarity index 99% rename from bridge/sender/sender.go rename to bridge/internal/controller/sender/sender.go index 6c633aa46..8d6b05d59 100644 --- a/bridge/sender/sender.go +++ b/bridge/internal/controller/sender/sender.go @@ -17,8 +17,8 @@ import ( "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/log" - "scroll-tech/bridge/config" - "scroll-tech/bridge/utils" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/utils" ) const ( diff --git a/bridge/sender/sender_test.go b/bridge/internal/controller/sender/sender_test.go similarity index 98% rename from bridge/sender/sender_test.go rename to bridge/internal/controller/sender/sender_test.go index 147590815..799b6ddf6 100644 --- a/bridge/sender/sender_test.go +++ b/bridge/internal/controller/sender/sender_test.go @@ -9,8 +9,6 @@ import ( "testing" "time" - "golang.org/x/sync/errgroup" - "github.com/agiledragon/gomonkey/v2" cmap "github.com/orcaman/concurrent-map" "github.com/scroll-tech/go-ethereum/accounts/abi/bind" @@ -20,10 +18,11 @@ import ( "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/rpc" "github.com/stretchr/testify/assert" + "golang.org/x/sync/errgroup" "scroll-tech/common/docker" - "scroll-tech/bridge/config" + "scroll-tech/bridge/internal/config" ) const TXBatch = 50 @@ -45,7 +44,7 @@ func TestMain(m *testing.M) { func setupEnv(t *testing.T) { var err error - cfg, err = config.NewConfig("../config.json") + cfg, err = config.NewConfig("../../../conf/config.json") assert.NoError(t, err) base.RunImages(t) priv, err := crypto.HexToECDSA("1212121212121212121212121212121212121212121212121212121212121212") diff --git a/bridge/watcher/batch_proposer.go b/bridge/internal/controller/watcher/batch_proposer.go similarity index 59% rename from bridge/watcher/batch_proposer.go rename to bridge/internal/controller/watcher/batch_proposer.go index cf59ef095..352644876 100644 --- a/bridge/watcher/batch_proposer.go +++ b/bridge/internal/controller/watcher/batch_proposer.go @@ -8,70 +8,35 @@ import ( "time" "github.com/scroll-tech/go-ethereum/log" - geth_metrics "github.com/scroll-tech/go-ethereum/metrics" + gethMetrics "github.com/scroll-tech/go-ethereum/metrics" + "gorm.io/gorm" "scroll-tech/common/metrics" "scroll-tech/common/types" - "scroll-tech/database" - - bridgeabi "scroll-tech/bridge/abi" - "scroll-tech/bridge/config" - "scroll-tech/bridge/relayer" + bridgeAbi "scroll-tech/bridge/abi" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/orm" + bridgeTypes "scroll-tech/bridge/internal/types" ) var ( - bridgeL2BatchesGasOverThresholdTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/gas/over/threshold/total", metrics.ScrollRegistry) - bridgeL2BatchesTxsOverThresholdTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/txs/over/threshold/total", metrics.ScrollRegistry) - bridgeL2BatchesBlocksCreatedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/blocks/created/total", metrics.ScrollRegistry) - bridgeL2BatchesCommitsSentTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/commits/sent/total", metrics.ScrollRegistry) - bridgeL2BatchesOversizedTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/batches/oversized/total", metrics.ScrollRegistry) - - bridgeL2BatchesTxsCreatedPerBatchGauge = geth_metrics.NewRegisteredGauge("bridge/l2/batches/txs/created/per/batch", metrics.ScrollRegistry) - bridgeL2BatchesGasCreatedPerBatchGauge = geth_metrics.NewRegisteredGauge("bridge/l2/batches/gas/created/per/batch", metrics.ScrollRegistry) - bridgeL2BatchesPayloadSizePerBatchGauge = geth_metrics.NewRegisteredGauge("bridge/l2/batches/payload/size/per/batch", metrics.ScrollRegistry) + bridgeL2BatchesGasOverThresholdTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/gas/over/threshold/total", metrics.ScrollRegistry) + bridgeL2BatchesTxsOverThresholdTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/txs/over/threshold/total", metrics.ScrollRegistry) + bridgeL2BatchesBlocksCreatedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/blocks/created/total", metrics.ScrollRegistry) + bridgeL2BatchesCommitsSentTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/commits/sent/total", metrics.ScrollRegistry) + bridgeL2BatchesOversizedTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/batches/oversized/total", metrics.ScrollRegistry) + bridgeL2BatchesTxsCreatedPerBatchGauge = gethMetrics.NewRegisteredGauge("bridge/l2/batches/txs/created/per/batch", metrics.ScrollRegistry) + bridgeL2BatchesGasCreatedPerBatchGauge = gethMetrics.NewRegisteredGauge("bridge/l2/batches/gas/created/per/batch", metrics.ScrollRegistry) + bridgeL2BatchesPayloadSizePerBatchGauge = gethMetrics.NewRegisteredGauge("bridge/l2/batches/payload/size/per/batch", metrics.ScrollRegistry) ) -// AddBatchInfoToDB inserts the batch information to the BlockBatch table and updates the batch_hash -// in all blocks included in the batch. -func AddBatchInfoToDB(db database.OrmFactory, batchData *types.BatchData) error { - dbTx, err := db.Beginx() - if err != nil { - return err - } - - var dbTxErr error - defer func() { - if dbTxErr != nil { - if err := dbTx.Rollback(); err != nil { - log.Error("dbTx.Rollback()", "err", err) - } - } - }() - - if dbTxErr = db.NewBatchInDBTx(dbTx, batchData); dbTxErr != nil { - return dbTxErr - } - - var blockIDs = make([]uint64, len(batchData.Batch.Blocks)) - for i, block := range batchData.Batch.Blocks { - blockIDs[i] = block.BlockNumber - } - - if dbTxErr = db.SetBatchHashForL2BlocksInDBTx(dbTx, blockIDs, batchData.Hash().Hex()); dbTxErr != nil { - return dbTxErr - } - - dbTxErr = dbTx.Commit() - return dbTxErr -} - // BatchProposer sends batches commit transactions to relayer. type BatchProposer struct { mutex sync.Mutex - - ctx context.Context - orm database.OrmFactory + ctx context.Context + db *gorm.DB batchTimeSec uint64 batchGasThreshold uint64 @@ -83,18 +48,23 @@ type BatchProposer struct { commitCalldataMinSize uint64 proofGenerationFreq uint64 - batchDataBuffer []*types.BatchData + batchDataBuffer []*bridgeTypes.BatchData relayer *relayer.Layer2Relayer - piCfg *types.PublicInputHashConfig + blockBatchOrm *orm.BlockBatch + blockTraceOrm *orm.BlockTrace + + piCfg *bridgeTypes.PublicInputHashConfig } // NewBatchProposer will return a new instance of BatchProposer. -func NewBatchProposer(ctx context.Context, cfg *config.BatchProposerConfig, relayer *relayer.Layer2Relayer, orm database.OrmFactory) *BatchProposer { +func NewBatchProposer(ctx context.Context, cfg *config.BatchProposerConfig, relayer *relayer.Layer2Relayer, db *gorm.DB) *BatchProposer { p := &BatchProposer{ mutex: sync.Mutex{}, ctx: ctx, - orm: orm, + db: db, + blockBatchOrm: orm.NewBlockBatch(db), + blockTraceOrm: orm.NewBlockTrace(db), batchTimeSec: cfg.BatchTimeSec, batchGasThreshold: cfg.BatchGasThreshold, batchTxNumThreshold: cfg.BatchTxNumThreshold, @@ -119,7 +89,7 @@ func NewBatchProposer(ctx context.Context, cfg *config.BatchProposerConfig, rela func (p *BatchProposer) recoverBatchDataBuffer() { // batches are sorted by batch index in increasing order - batchHashes, err := p.orm.GetPendingBatches(math.MaxInt32) + batchHashes, err := p.blockBatchOrm.GetBlockBatchesHashByRollupStatus(types.RollupPending, math.MaxInt32) if err != nil { log.Crit("Failed to fetch pending L2 batches", "err", err) } @@ -129,17 +99,17 @@ func (p *BatchProposer) recoverBatchDataBuffer() { log.Info("Load pending batches into batchDataBuffer") // helper function to cache and get BlockBatch from DB - blockBatchCache := make(map[string]*types.BlockBatch) - getBlockBatch := func(batchHash string) (*types.BlockBatch, error) { + blockBatchCache := make(map[string]orm.BlockBatch) + getBlockBatch := func(batchHash string) (*orm.BlockBatch, error) { if blockBatch, ok := blockBatchCache[batchHash]; ok { - return blockBatch, nil + return &blockBatch, nil } - blockBatches, err := p.orm.GetBlockBatches(map[string]interface{}{"hash": batchHash}) + blockBatches, err := p.blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batchHash}, nil, 0) if err != nil || len(blockBatches) == 0 { return nil, err } blockBatchCache[batchHash] = blockBatches[0] - return blockBatches[0], nil + return &blockBatches[0], nil } // recover the in-memory batchData from DB @@ -157,23 +127,26 @@ func (p *BatchProposer) recoverBatchDataBuffer() { continue } - blockInfos, err := p.orm.GetL2BlockInfos( - map[string]interface{}{"batch_hash": batchHash}, - "order by number ASC", - ) + whereFileds := map[string]interface{}{ + "batch_hash": batchHash, + } + orderByList := []string{ + "number ASC", + } + blockTraces, err := p.blockTraceOrm.GetL2BlockInfos(whereFileds, orderByList, 0) if err != nil { log.Error("could not GetL2BlockInfos", "batch_hash", batchHash, "error", err) continue } - if len(blockInfos) != int(blockBatch.EndBlockNumber-blockBatch.StartBlockNumber+1) { + if len(blockTraces) != int(blockBatch.EndBlockNumber-blockBatch.StartBlockNumber+1) { log.Error("the number of block info retrieved from DB mistmatches the batch info in the DB", - "len(blockInfos)", len(blockInfos), + "len(blockInfos)", len(blockTraces), "expected", blockBatch.EndBlockNumber-blockBatch.StartBlockNumber+1) continue } - batchData, err := p.generateBatchData(parentBatch, blockInfos) + batchData, err := p.generateBatchData(parentBatch, blockTraces) if err != nil { continue } @@ -194,16 +167,14 @@ func (p *BatchProposer) TryProposeBatch() { defer p.mutex.Unlock() for p.getBatchDataBufferSize() < p.batchDataBufferSizeLimit { - blocks, err := p.orm.GetUnbatchedL2Blocks( - map[string]interface{}{}, - fmt.Sprintf("order by number ASC LIMIT %d", p.batchBlocksLimit), - ) + orderBy := []string{"number ASC"} + blockTraces, err := p.blockTraceOrm.GetUnbatchedL2Blocks(map[string]interface{}{}, orderBy, int(p.batchBlocksLimit)) if err != nil { log.Error("failed to get unbatched blocks", "err", err) return } - batchCreated := p.proposeBatch(blocks) + batchCreated := p.proposeBatch(blockTraces) // while size of batchDataBuffer < commitCalldataMinSize, // proposer keeps fetching and porposing batches. @@ -232,7 +203,7 @@ func (p *BatchProposer) TryCommitBatches() { commit := false calldataByteLen := uint64(0) for ; index < len(p.batchDataBuffer); index++ { - calldataByteLen += bridgeabi.GetBatchCalldataLength(&p.batchDataBuffer[index].Batch) + calldataByteLen += bridgeAbi.GetBatchCalldataLength(&p.batchDataBuffer[index].Batch) if calldataByteLen > p.commitCalldataSizeLimit { commit = true if index == 0 { @@ -264,13 +235,13 @@ func (p *BatchProposer) TryCommitBatches() { } } -func (p *BatchProposer) proposeBatch(blocks []*types.BlockInfo) bool { - if len(blocks) == 0 { +func (p *BatchProposer) proposeBatch(blockTraces []orm.BlockTrace) bool { + if len(blockTraces) == 0 { return false } approximatePayloadSize := func(hash string) (uint64, error) { - traces, err := p.orm.GetL2WrappedBlocks(map[string]interface{}{"hash": hash}) + traces, err := p.blockTraceOrm.GetL2WrappedBlocks(map[string]interface{}{"hash": hash}) if err != nil { return 0, err } @@ -284,49 +255,49 @@ func (p *BatchProposer) proposeBatch(blocks []*types.BlockInfo) bool { return uint64(size), nil } - firstSize, err := approximatePayloadSize(blocks[0].Hash) + firstSize, err := approximatePayloadSize(blockTraces[0].Hash) if err != nil { - log.Error("failed to create batch", "number", blocks[0].Number, "err", err) + log.Error("failed to create batch", "number", blockTraces[0].Number, "err", err) return false } if firstSize > p.commitCalldataSizeLimit { - log.Warn("oversized payload even for only 1 block", "height", blocks[0].Number, "size", firstSize) + log.Warn("oversized payload even for only 1 block", "height", blockTraces[0].Number, "size", firstSize) // note: we should probably fail here once we can ensure this will not happen - if err := p.createBatchForBlocks(blocks[:1]); err != nil { - log.Error("failed to create batch", "number", blocks[0].Number, "err", err) + if err := p.createBatchForBlocks(blockTraces[:1]); err != nil { + log.Error("failed to create batch", "number", blockTraces[0].Number, "err", err) return false } - bridgeL2BatchesTxsCreatedPerBatchGauge.Update(int64(blocks[0].TxNum)) - bridgeL2BatchesGasCreatedPerBatchGauge.Update(int64(blocks[0].GasUsed)) + bridgeL2BatchesTxsCreatedPerBatchGauge.Update(int64(blockTraces[0].TxNum)) + bridgeL2BatchesGasCreatedPerBatchGauge.Update(int64(blockTraces[0].GasUsed)) bridgeL2BatchesPayloadSizePerBatchGauge.Update(int64(firstSize)) bridgeL2BatchesBlocksCreatedTotalCounter.Inc(1) bridgeL2BatchesOversizedTotalCounter.Inc(1) return true } - if blocks[0].GasUsed > p.batchGasThreshold { + if blockTraces[0].GasUsed > p.batchGasThreshold { bridgeL2BatchesGasOverThresholdTotalCounter.Inc(1) - log.Warn("gas overflow even for only 1 block", "height", blocks[0].Number, "gas", blocks[0].GasUsed) - if err := p.createBatchForBlocks(blocks[:1]); err != nil { - log.Error("failed to create batch", "number", blocks[0].Number, "err", err) + log.Warn("gas overflow even for only 1 block", "height", blockTraces[0].Number, "gas", blockTraces[0].GasUsed) + if err := p.createBatchForBlocks(blockTraces[:1]); err != nil { + log.Error("failed to create batch", "number", blockTraces[0].Number, "err", err) } else { - bridgeL2BatchesTxsCreatedPerBatchGauge.Update(int64(blocks[0].TxNum)) - bridgeL2BatchesGasCreatedPerBatchGauge.Update(int64(blocks[0].GasUsed)) + bridgeL2BatchesTxsCreatedPerBatchGauge.Update(int64(blockTraces[0].TxNum)) + bridgeL2BatchesGasCreatedPerBatchGauge.Update(int64(blockTraces[0].GasUsed)) bridgeL2BatchesPayloadSizePerBatchGauge.Update(int64(firstSize)) bridgeL2BatchesBlocksCreatedTotalCounter.Inc(1) } return true } - if blocks[0].TxNum > p.batchTxNumThreshold { + if blockTraces[0].TxNum > p.batchTxNumThreshold { bridgeL2BatchesTxsOverThresholdTotalCounter.Inc(1) - log.Warn("too many txs even for only 1 block", "height", blocks[0].Number, "tx_num", blocks[0].TxNum) - if err := p.createBatchForBlocks(blocks[:1]); err != nil { - log.Error("failed to create batch", "number", blocks[0].Number, "err", err) + log.Warn("too many txs even for only 1 block", "height", blockTraces[0].Number, "tx_num", blockTraces[0].TxNum) + if err := p.createBatchForBlocks(blockTraces[:1]); err != nil { + log.Error("failed to create batch", "number", blockTraces[0].Number, "err", err) } else { - bridgeL2BatchesTxsCreatedPerBatchGauge.Update(int64(blocks[0].TxNum)) - bridgeL2BatchesGasCreatedPerBatchGauge.Update(int64(blocks[0].GasUsed)) + bridgeL2BatchesTxsCreatedPerBatchGauge.Update(int64(blockTraces[0].TxNum)) + bridgeL2BatchesGasCreatedPerBatchGauge.Update(int64(blockTraces[0].GasUsed)) bridgeL2BatchesPayloadSizePerBatchGauge.Update(int64(firstSize)) bridgeL2BatchesBlocksCreatedTotalCounter.Inc(1) } @@ -336,7 +307,7 @@ func (p *BatchProposer) proposeBatch(blocks []*types.BlockInfo) bool { var gasUsed, txNum, payloadSize uint64 reachThreshold := false // add blocks into batch until reach batchGasThreshold - for i, block := range blocks { + for i, block := range blockTraces { size, err := approximatePayloadSize(block.Hash) if err != nil { log.Error("failed to create batch", "number", block.Number, "err", err) @@ -344,7 +315,7 @@ func (p *BatchProposer) proposeBatch(blocks []*types.BlockInfo) bool { } if (gasUsed+block.GasUsed > p.batchGasThreshold) || (txNum+block.TxNum > p.batchTxNumThreshold) || (payloadSize+size > p.commitCalldataSizeLimit) { - blocks = blocks[:i] + blockTraces = blockTraces[:i] reachThreshold = true break } @@ -356,24 +327,24 @@ func (p *BatchProposer) proposeBatch(blocks []*types.BlockInfo) bool { // if too few gas gathered, but we don't want to halt, we then check the first block in the batch: // if it's not old enough we will skip proposing the batch, // otherwise we will still propose a batch - if !reachThreshold && blocks[0].BlockTimestamp+p.batchTimeSec > uint64(time.Now().Unix()) { + if !reachThreshold && blockTraces[0].BlockTimestamp+p.batchTimeSec > uint64(time.Now().Unix()) { return false } - if err := p.createBatchForBlocks(blocks); err != nil { - log.Error("failed to create batch", "from", blocks[0].Number, "to", blocks[len(blocks)-1].Number, "err", err) + if err := p.createBatchForBlocks(blockTraces); err != nil { + log.Error("failed to create batch", "from", blockTraces[0].Number, "to", blockTraces[len(blockTraces)-1].Number, "err", err) } else { bridgeL2BatchesTxsCreatedPerBatchGauge.Update(int64(txNum)) bridgeL2BatchesGasCreatedPerBatchGauge.Update(int64(gasUsed)) bridgeL2BatchesPayloadSizePerBatchGauge.Update(int64(payloadSize)) - bridgeL2BatchesBlocksCreatedTotalCounter.Inc(int64(len(blocks))) + bridgeL2BatchesBlocksCreatedTotalCounter.Inc(int64(len(blockTraces))) } return true } -func (p *BatchProposer) createBatchForBlocks(blocks []*types.BlockInfo) error { - lastBatch, err := p.orm.GetLatestBatch() +func (p *BatchProposer) createBatchForBlocks(blocks []orm.BlockTrace) error { + lastBatch, err := p.blockBatchOrm.GetLatestBatch() if err != nil { // We should not receive sql.ErrNoRows error. The DB should have the batch entry that contains the genesis block. return err @@ -385,7 +356,7 @@ func (p *BatchProposer) createBatchForBlocks(blocks []*types.BlockInfo) error { return err } - if err := AddBatchInfoToDB(p.orm, batchData); err != nil { + if err := orm.AddBatchInfoToDB(p.db, batchData); err != nil { log.Error("addBatchInfoToDB failed", "BatchHash", batchData.Hash(), "error", err) return err } @@ -394,22 +365,29 @@ func (p *BatchProposer) createBatchForBlocks(blocks []*types.BlockInfo) error { return nil } -func (p *BatchProposer) generateBatchData(parentBatch *types.BlockBatch, blocks []*types.BlockInfo) (*types.BatchData, error) { - var wrappedBlocks []*types.WrappedBlock +func (p *BatchProposer) generateBatchData(parentBatch *orm.BlockBatch, blocks []orm.BlockTrace) (*bridgeTypes.BatchData, error) { + var wrappedBlocks []*bridgeTypes.WrappedBlock for _, block := range blocks { - trs, err := p.orm.GetL2WrappedBlocks(map[string]interface{}{"hash": block.Hash}) + trs, err := p.blockTraceOrm.GetL2WrappedBlocks(map[string]interface{}{"hash": block.Hash}) if err != nil || len(trs) != 1 { log.Error("Failed to GetBlockTraces", "hash", block.Hash, "err", err) return nil, err } + wrappedBlocks = append(wrappedBlocks, trs[0]) } - return types.NewBatchData(parentBatch, wrappedBlocks, p.piCfg), nil + + parentBatchInfo := bridgeTypes.BatchInfo{ + Index: parentBatch.Index, + Hash: parentBatch.Hash, + StateRoot: parentBatch.StateRoot, + } + return bridgeTypes.NewBatchData(&parentBatchInfo, wrappedBlocks, p.piCfg), nil } func (p *BatchProposer) getBatchDataBufferSize() (size uint64) { for _, batchData := range p.batchDataBuffer { - size += bridgeabi.GetBatchCalldataLength(&batchData.Batch) + size += bridgeAbi.GetBatchCalldataLength(&batchData.Batch) } return } diff --git a/bridge/internal/controller/watcher/batch_proposer_test.go b/bridge/internal/controller/watcher/batch_proposer_test.go new file mode 100644 index 000000000..3d75b2093 --- /dev/null +++ b/bridge/internal/controller/watcher/batch_proposer_test.go @@ -0,0 +1,206 @@ +package watcher + +import ( + "context" + "math" + "strings" + "testing" + "time" + + "github.com/agiledragon/gomonkey/v2" + "github.com/scroll-tech/go-ethereum/common" + gethTtypes "github.com/scroll-tech/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + "gorm.io/gorm" + + "scroll-tech/common/types" + + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/orm" + bridgeTypes "scroll-tech/bridge/internal/types" + bridgeUtils "scroll-tech/bridge/internal/utils" +) + +func testBatchProposerProposeBatch(t *testing.T) { + db := setupDB(t) + defer bridgeUtils.CloseDB(db) + + p := &BatchProposer{ + batchGasThreshold: 1000, + batchTxNumThreshold: 10, + batchTimeSec: 300, + commitCalldataSizeLimit: 500, + } + + var blockTrace *orm.BlockTrace + patchGuard := gomonkey.ApplyMethodFunc(blockTrace, "GetL2WrappedBlocks", func(fields map[string]interface{}) ([]*bridgeTypes.WrappedBlock, error) { + hash, _ := fields["hash"].(string) + if hash == "blockWithLongData" { + longData := strings.Repeat("0", 1000) + return []*bridgeTypes.WrappedBlock{{ + Transactions: []*gethTtypes.TransactionData{{ + Data: longData, + }}, + }}, nil + } + return []*bridgeTypes.WrappedBlock{{ + Transactions: []*gethTtypes.TransactionData{{ + Data: "short", + }}, + }}, nil + }) + defer patchGuard.Reset() + patchGuard.ApplyPrivateMethod(p, "createBatchForBlocks", func(*BatchProposer, []*types.BlockInfo) error { + return nil + }) + + block1 := orm.BlockTrace{Number: 1, GasUsed: 100, TxNum: 1, BlockTimestamp: uint64(time.Now().Unix()) - 200} + block2 := orm.BlockTrace{Number: 2, GasUsed: 200, TxNum: 2, BlockTimestamp: uint64(time.Now().Unix())} + block3 := orm.BlockTrace{Number: 3, GasUsed: 300, TxNum: 11, BlockTimestamp: uint64(time.Now().Unix())} + block4 := orm.BlockTrace{Number: 4, GasUsed: 1001, TxNum: 3, BlockTimestamp: uint64(time.Now().Unix())} + blockOutdated := orm.BlockTrace{Number: 1, GasUsed: 100, TxNum: 1, BlockTimestamp: uint64(time.Now().Add(-400 * time.Second).Unix())} + blockWithLongData := orm.BlockTrace{Hash: "blockWithLongData", Number: 5, GasUsed: 500, TxNum: 1, BlockTimestamp: uint64(time.Now().Unix())} + + testCases := []struct { + description string + blocks []orm.BlockTrace + expectedRes bool + }{ + {"Empty block list", []orm.BlockTrace{}, false}, + {"Single block exceeding gas threshold", []orm.BlockTrace{block4}, true}, + {"Single block exceeding transaction number threshold", []orm.BlockTrace{block3}, true}, + {"Multiple blocks meeting thresholds", []orm.BlockTrace{block1, block2, block3}, true}, + {"Multiple blocks not meeting thresholds", []orm.BlockTrace{block1, block2}, false}, + {"Outdated and valid block", []orm.BlockTrace{blockOutdated, block2}, true}, + {"Single block with long data", []orm.BlockTrace{blockWithLongData}, true}, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + assert.Equal(t, tc.expectedRes, p.proposeBatch(tc.blocks), "Failed on: %s", tc.description) + }) + } +} + +func testBatchProposerBatchGeneration(t *testing.T) { + db := setupDB(t) + subCtx, cancel := context.WithCancel(context.Background()) + defer func() { + bridgeUtils.CloseDB(db) + cancel() + }() + blockTraceOrm := orm.NewBlockTrace(db) + // Insert traces into db. + assert.NoError(t, blockTraceOrm.InsertWrappedBlocks([]*bridgeTypes.WrappedBlock{wrappedBlock1})) + + l2cfg := cfg.L2Config + wc := NewL2WatcherClient(context.Background(), l2Cli, l2cfg.Confirmations, l2cfg.L2MessengerAddress, l2cfg.L2MessageQueueAddress, l2cfg.WithdrawTrieRootSlot, db) + loopToFetchEvent(subCtx, wc) + + blockBatchOrm := orm.NewBlockBatch(db) + batch, err := blockBatchOrm.GetLatestBatch() + assert.NoError(t, err) + + // Create a new batch. + batchData := bridgeTypes.NewBatchData(&bridgeTypes.BatchInfo{ + Index: 0, + Hash: batch.Hash, + StateRoot: batch.StateRoot, + }, []*bridgeTypes.WrappedBlock{wrappedBlock1}, nil) + + relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Cli, db, cfg.L2Config.RelayerConfig) + assert.NoError(t, err) + + proposer := NewBatchProposer(context.Background(), &config.BatchProposerConfig{ + ProofGenerationFreq: 1, + BatchGasThreshold: 3000000, + BatchTxNumThreshold: 135, + BatchTimeSec: 1, + BatchBlocksLimit: 100, + }, relayer, db) + proposer.TryProposeBatch() + + infos, err := blockTraceOrm.GetUnbatchedL2Blocks(map[string]interface{}{}, []string{"number ASC"}, 100) + assert.NoError(t, err) + assert.Equal(t, 0, len(infos)) + + batches, err := blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batchData.Hash().Hex()}, nil, 1) + assert.NoError(t, err) + assert.Equal(t, 1, len(batches)) +} + +func testBatchProposerGracefulRestart(t *testing.T) { + db := setupDB(t) + defer bridgeUtils.CloseDB(db) + + relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Cli, db, cfg.L2Config.RelayerConfig) + assert.NoError(t, err) + + blockTraceOrm := orm.NewBlockTrace(db) + // Insert traces into db. + assert.NoError(t, blockTraceOrm.InsertWrappedBlocks([]*bridgeTypes.WrappedBlock{wrappedBlock2})) + + // Insert block batch into db. + parentBatch1 := &bridgeTypes.BatchInfo{ + Index: 0, + Hash: common.Hash{}.String(), + StateRoot: common.Hash{}.String(), + } + batchData1 := bridgeTypes.NewBatchData(parentBatch1, []*bridgeTypes.WrappedBlock{wrappedBlock1}, nil) + + parentBatch2 := &bridgeTypes.BatchInfo{ + Index: batchData1.Batch.BatchIndex, + Hash: batchData1.Hash().Hex(), + StateRoot: batchData1.Batch.NewStateRoot.String(), + } + batchData2 := bridgeTypes.NewBatchData(parentBatch2, []*bridgeTypes.WrappedBlock{wrappedBlock2}, nil) + + blockBatchOrm := orm.NewBlockBatch(db) + err = db.Transaction(func(tx *gorm.DB) error { + _, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batchData1) + if dbTxErr != nil { + return dbTxErr + } + _, dbTxErr = blockBatchOrm.InsertBlockBatchByBatchData(tx, batchData2) + if dbTxErr != nil { + return dbTxErr + } + numbers1 := []uint64{batchData1.Batch.Blocks[0].BlockNumber} + hash1 := batchData1.Hash().Hex() + dbTxErr = blockTraceOrm.UpdateBatchHashForL2Blocks(tx, numbers1, hash1) + if dbTxErr != nil { + return dbTxErr + } + numbers2 := []uint64{batchData2.Batch.Blocks[0].BlockNumber} + hash2 := batchData2.Hash().Hex() + dbTxErr = blockTraceOrm.UpdateBatchHashForL2Blocks(tx, numbers2, hash2) + if dbTxErr != nil { + return dbTxErr + } + return nil + }) + assert.NoError(t, err) + err = blockBatchOrm.UpdateRollupStatus(context.Background(), batchData1.Hash().Hex(), types.RollupFinalized) + assert.NoError(t, err) + batchHashes, err := blockBatchOrm.GetBlockBatchesHashByRollupStatus(types.RollupPending, math.MaxInt32) + assert.NoError(t, err) + assert.Equal(t, 1, len(batchHashes)) + assert.Equal(t, batchData2.Hash().Hex(), batchHashes[0]) + // test p.recoverBatchDataBuffer(). + _ = NewBatchProposer(context.Background(), &config.BatchProposerConfig{ + ProofGenerationFreq: 1, + BatchGasThreshold: 3000000, + BatchTxNumThreshold: 135, + BatchTimeSec: 1, + BatchBlocksLimit: 100, + }, relayer, db) + + batchHashes, err = blockBatchOrm.GetBlockBatchesHashByRollupStatus(types.RollupPending, math.MaxInt32) + assert.NoError(t, err) + assert.Equal(t, 0, len(batchHashes)) + + batches, err := blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batchData2.Hash().Hex()}, nil, 1) + assert.NoError(t, err) + assert.Equal(t, 1, len(batches)) +} diff --git a/bridge/watcher/common.go b/bridge/internal/controller/watcher/common.go similarity index 100% rename from bridge/watcher/common.go rename to bridge/internal/controller/watcher/common.go diff --git a/bridge/watcher/l1_watcher.go b/bridge/internal/controller/watcher/l1_watcher.go similarity index 75% rename from bridge/watcher/l1_watcher.go rename to bridge/internal/controller/watcher/l1_watcher.go index 75115f34c..9e906ed2c 100644 --- a/bridge/watcher/l1_watcher.go +++ b/bridge/internal/controller/watcher/l1_watcher.go @@ -7,28 +7,27 @@ import ( geth "github.com/scroll-tech/go-ethereum" "github.com/scroll-tech/go-ethereum/accounts/abi" "github.com/scroll-tech/go-ethereum/common" - geth_types "github.com/scroll-tech/go-ethereum/core/types" + gethTypes "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/log" - geth_metrics "github.com/scroll-tech/go-ethereum/metrics" + gethMetrics "github.com/scroll-tech/go-ethereum/metrics" "github.com/scroll-tech/go-ethereum/rpc" + "gorm.io/gorm" "scroll-tech/common/metrics" "scroll-tech/common/types" - "scroll-tech/database" - - bridge_abi "scroll-tech/bridge/abi" - "scroll-tech/bridge/utils" + bridgeAbi "scroll-tech/bridge/abi" + "scroll-tech/bridge/internal/orm" + "scroll-tech/bridge/internal/utils" ) var ( - bridgeL1MsgsSyncHeightGauge = geth_metrics.NewRegisteredGauge("bridge/l1/msgs/sync/height", metrics.ScrollRegistry) - - bridgeL1MsgsSentEventsTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l1/msgs/sent/events/total", metrics.ScrollRegistry) - bridgeL1MsgsRelayedEventsTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l1/msgs/relayed/events/total", metrics.ScrollRegistry) - bridgeL1MsgsRollupEventsTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l1/msgs/rollup/events/total", metrics.ScrollRegistry) + bridgeL1MsgsSyncHeightGauge = gethMetrics.NewRegisteredGauge("bridge/l1/msgs/sync/height", metrics.ScrollRegistry) + bridgeL1MsgsSentEventsTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l1/msgs/sent/events/total", metrics.ScrollRegistry) + bridgeL1MsgsRelayedEventsTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l1/msgs/relayed/events/total", metrics.ScrollRegistry) + bridgeL1MsgsRollupEventsTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l1/msgs/rollup/events/total", metrics.ScrollRegistry) ) type rollupEvent struct { @@ -39,9 +38,12 @@ type rollupEvent struct { // L1WatcherClient will listen for smart contract events from Eth L1. type L1WatcherClient struct { - ctx context.Context - client *ethclient.Client - db database.OrmFactory + ctx context.Context + client *ethclient.Client + l1MessageOrm *orm.L1Message + l2MessageOrm *orm.L2Message + l1BlockOrm *orm.L1Block + l1BatchOrm *orm.BlockBatch // The number of new blocks to wait for a block to be confirmed confirmations rpc.BlockNumber @@ -62,8 +64,9 @@ type L1WatcherClient struct { } // NewL1WatcherClient returns a new instance of L1WatcherClient. -func NewL1WatcherClient(ctx context.Context, client *ethclient.Client, startHeight uint64, confirmations rpc.BlockNumber, messengerAddress, messageQueueAddress, scrollChainAddress common.Address, db database.OrmFactory) *L1WatcherClient { - savedHeight, err := db.GetLayer1LatestWatchedHeight() +func NewL1WatcherClient(ctx context.Context, client *ethclient.Client, startHeight uint64, confirmations rpc.BlockNumber, messengerAddress, messageQueueAddress, scrollChainAddress common.Address, db *gorm.DB) *L1WatcherClient { + l1MessageOrm := orm.NewL1Message(db) + savedHeight, err := l1MessageOrm.GetLayer1LatestWatchedHeight() if err != nil { log.Warn("Failed to fetch height from db", "err", err) savedHeight = 0 @@ -72,7 +75,8 @@ func NewL1WatcherClient(ctx context.Context, client *ethclient.Client, startHeig savedHeight = int64(startHeight) } - savedL1BlockHeight, err := db.GetLatestL1BlockHeight() + l1BlockOrm := orm.NewL1Block(db) + savedL1BlockHeight, err := l1BlockOrm.GetLatestL1BlockHeight() if err != nil { log.Warn("Failed to fetch latest L1 block height from db", "err", err) savedL1BlockHeight = 0 @@ -84,17 +88,20 @@ func NewL1WatcherClient(ctx context.Context, client *ethclient.Client, startHeig return &L1WatcherClient{ ctx: ctx, client: client, - db: db, + l1MessageOrm: l1MessageOrm, + l1BlockOrm: l1BlockOrm, + l1BatchOrm: orm.NewBlockBatch(db), + l2MessageOrm: orm.NewL2Message(db), confirmations: confirmations, messengerAddress: messengerAddress, - messengerABI: bridge_abi.L1ScrollMessengerABI, + messengerABI: bridgeAbi.L1ScrollMessengerABI, messageQueueAddress: messageQueueAddress, - messageQueueABI: bridge_abi.L1MessageQueueABI, + messageQueueABI: bridgeAbi.L1MessageQueueABI, scrollChainAddress: scrollChainAddress, - scrollChainABI: bridge_abi.ScrollChainABI, + scrollChainABI: bridgeAbi.ScrollChainABI, processedMsgHeight: uint64(savedHeight), processedBlockHeight: savedL1BlockHeight, @@ -130,11 +137,11 @@ func (w *L1WatcherClient) FetchBlockHeader(blockHeight uint64) error { toBlock = fromBlock + contractEventsBlocksFetchLimit - 1 } - var blocks []*types.L1BlockInfo + var blocks []orm.L1Block var err error height := fromBlock for ; height <= toBlock; height++ { - var block *geth_types.Header + var block *gethTypes.Header block, err = w.client.HeaderByNumber(w.ctx, big.NewInt(height)) if err != nil { log.Warn("Failed to get block", "height", height, "err", err) @@ -144,7 +151,7 @@ func (w *L1WatcherClient) FetchBlockHeader(blockHeight uint64) error { if block.BaseFee != nil { baseFee = block.BaseFee.Uint64() } - blocks = append(blocks, &types.L1BlockInfo{ + blocks = append(blocks, orm.L1Block{ Number: uint64(height), Hash: block.Hash().String(), BaseFee: baseFee, @@ -158,7 +165,7 @@ func (w *L1WatcherClient) FetchBlockHeader(blockHeight uint64) error { toBlock = height - 1 // insert succeed blocks - err = w.db.InsertL1Blocks(w.ctx, blocks) + err = w.l1BlockOrm.InsertL1Blocks(w.ctx, blocks) if err != nil { log.Warn("Failed to insert L1 block to db", "fromBlock", fromBlock, "toBlock", toBlock, "err", err) return err @@ -202,11 +209,11 @@ func (w *L1WatcherClient) FetchContractEvent() error { Topics: make([][]common.Hash, 1), } query.Topics[0] = make([]common.Hash, 5) - query.Topics[0][0] = bridge_abi.L1QueueTransactionEventSignature - query.Topics[0][1] = bridge_abi.L1RelayedMessageEventSignature - query.Topics[0][2] = bridge_abi.L1FailedRelayedMessageEventSignature - query.Topics[0][3] = bridge_abi.L1CommitBatchEventSignature - query.Topics[0][4] = bridge_abi.L1FinalizeBatchEventSignature + query.Topics[0][0] = bridgeAbi.L1QueueTransactionEventSignature + query.Topics[0][1] = bridgeAbi.L1RelayedMessageEventSignature + query.Topics[0][2] = bridgeAbi.L1FailedRelayedMessageEventSignature + query.Topics[0][3] = bridgeAbi.L1CommitBatchEventSignature + query.Topics[0][4] = bridgeAbi.L1FinalizeBatchEventSignature logs, err := w.client.FilterLogs(w.ctx, query) if err != nil { @@ -238,7 +245,7 @@ func (w *L1WatcherClient) FetchContractEvent() error { for _, event := range rollupEvents { batchHashes = append(batchHashes, event.batchHash.String()) } - statuses, err := w.db.GetRollupStatusByHashList(batchHashes) + statuses, err := w.l1BatchOrm.GetRollupStatusByHashList(batchHashes) if err != nil { log.Error("Failed to GetRollupStatusByHashList", "err", err) return err @@ -254,9 +261,9 @@ func (w *L1WatcherClient) FetchContractEvent() error { // only update when db status is before event status if event.status > status { if event.status == types.RollupFinalized { - err = w.db.UpdateFinalizeTxHashAndRollupStatus(w.ctx, batchHash, event.txHash.String(), event.status) + err = w.l1BatchOrm.UpdateFinalizeTxHashAndRollupStatus(w.ctx, batchHash, event.txHash.String(), event.status) } else if event.status == types.RollupCommitted { - err = w.db.UpdateCommitTxHashAndRollupStatus(w.ctx, batchHash, event.txHash.String(), event.status) + err = w.l1BatchOrm.UpdateCommitTxHashAndRollupStatus(w.ctx, batchHash, event.txHash.String(), event.status) } if err != nil { log.Error("Failed to update Rollup/Finalize TxHash and Status", "err", err) @@ -274,13 +281,13 @@ func (w *L1WatcherClient) FetchContractEvent() error { } else { msgStatus = types.MsgFailed } - if err = w.db.UpdateLayer2StatusAndLayer1Hash(w.ctx, msg.msgHash.String(), msgStatus, msg.txHash.String()); err != nil { + if err = w.l2MessageOrm.UpdateLayer2StatusAndLayer1Hash(w.ctx, msg.msgHash.String(), msgStatus, msg.txHash.String()); err != nil { log.Error("Failed to update layer1 status and layer2 hash", "err", err) return err } } - if err = w.db.SaveL1Messages(w.ctx, sentMessageEvents); err != nil { + if err = w.l1MessageOrm.SaveL1Messages(w.ctx, sentMessageEvents); err != nil { return err } @@ -291,17 +298,16 @@ func (w *L1WatcherClient) FetchContractEvent() error { return nil } -func (w *L1WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types.L1Message, []relayedMessage, []rollupEvent, error) { +func (w *L1WatcherClient) parseBridgeEventLogs(logs []gethTypes.Log) ([]*orm.L1Message, []relayedMessage, []rollupEvent, error) { // Need use contract abi to parse event Log // Can only be tested after we have our contracts set up - - var l1Messages []*types.L1Message + var l1Messages []*orm.L1Message var relayedMessages []relayedMessage var rollupEvents []rollupEvent for _, vLog := range logs { switch vLog.Topics[0] { - case bridge_abi.L1QueueTransactionEventSignature: - event := bridge_abi.L1QueueTransactionEvent{} + case bridgeAbi.L1QueueTransactionEventSignature: + event := bridgeAbi.L1QueueTransactionEvent{} err := utils.UnpackLog(w.messageQueueABI, &event, "QueueTransaction", vLog) if err != nil { log.Warn("Failed to unpack layer1 QueueTransaction event", "err", err) @@ -310,7 +316,7 @@ func (w *L1WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. msgHash := common.BytesToHash(crypto.Keccak256(event.Data)) - l1Messages = append(l1Messages, &types.L1Message{ + l1Messages = append(l1Messages, &orm.L1Message{ QueueIndex: event.QueueIndex.Uint64(), MsgHash: msgHash.String(), Height: vLog.BlockNumber, @@ -321,8 +327,8 @@ func (w *L1WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. GasLimit: event.GasLimit.Uint64(), Layer1Hash: vLog.TxHash.Hex(), }) - case bridge_abi.L1RelayedMessageEventSignature: - event := bridge_abi.L1RelayedMessageEvent{} + case bridgeAbi.L1RelayedMessageEventSignature: + event := bridgeAbi.L1RelayedMessageEvent{} err := utils.UnpackLog(w.messengerABI, &event, "RelayedMessage", vLog) if err != nil { log.Warn("Failed to unpack layer1 RelayedMessage event", "err", err) @@ -334,8 +340,8 @@ func (w *L1WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. txHash: vLog.TxHash, isSuccessful: true, }) - case bridge_abi.L1FailedRelayedMessageEventSignature: - event := bridge_abi.L1FailedRelayedMessageEvent{} + case bridgeAbi.L1FailedRelayedMessageEventSignature: + event := bridgeAbi.L1FailedRelayedMessageEvent{} err := utils.UnpackLog(w.messengerABI, &event, "FailedRelayedMessage", vLog) if err != nil { log.Warn("Failed to unpack layer1 FailedRelayedMessage event", "err", err) @@ -347,8 +353,8 @@ func (w *L1WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. txHash: vLog.TxHash, isSuccessful: false, }) - case bridge_abi.L1CommitBatchEventSignature: - event := bridge_abi.L1CommitBatchEvent{} + case bridgeAbi.L1CommitBatchEventSignature: + event := bridgeAbi.L1CommitBatchEvent{} err := utils.UnpackLog(w.scrollChainABI, &event, "CommitBatch", vLog) if err != nil { log.Warn("Failed to unpack layer1 CommitBatch event", "err", err) @@ -360,8 +366,8 @@ func (w *L1WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. txHash: vLog.TxHash, status: types.RollupCommitted, }) - case bridge_abi.L1FinalizeBatchEventSignature: - event := bridge_abi.L1FinalizeBatchEvent{} + case bridgeAbi.L1FinalizeBatchEventSignature: + event := bridgeAbi.L1FinalizeBatchEvent{} err := utils.UnpackLog(w.scrollChainABI, &event, "FinalizeBatch", vLog) if err != nil { log.Warn("Failed to unpack layer1 FinalizeBatch event", "err", err) diff --git a/bridge/watcher/l1_watcher_test.go b/bridge/internal/controller/watcher/l1_watcher_test.go similarity index 82% rename from bridge/watcher/l1_watcher_test.go rename to bridge/internal/controller/watcher/l1_watcher_test.go index 6fcad69d4..875360173 100644 --- a/bridge/watcher/l1_watcher_test.go +++ b/bridge/internal/controller/watcher/l1_watcher_test.go @@ -11,31 +11,24 @@ import ( "github.com/scroll-tech/go-ethereum/accounts/abi" "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/core/types" - geth_types "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/rpc" "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/assert" - - bridge_abi "scroll-tech/bridge/abi" - "scroll-tech/bridge/utils" + "gorm.io/gorm" commonTypes "scroll-tech/common/types" - "scroll-tech/database" - "scroll-tech/database/migrate" + bridgeAbi "scroll-tech/bridge/abi" + "scroll-tech/bridge/internal/orm" + "scroll-tech/bridge/internal/utils" ) -func setupL1Watcher(t *testing.T) (*L1WatcherClient, database.OrmFactory) { - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - +func setupL1Watcher(t *testing.T) (*L1WatcherClient, *gorm.DB) { + db := setupDB(t) client, err := ethclient.Dial(base.L1gethImg.Endpoint()) assert.NoError(t, err) - l1Cfg := cfg.L1Config - watcher := NewL1WatcherClient(context.Background(), client, l1Cfg.StartHeight, l1Cfg.Confirmations, l1Cfg.L1MessengerAddress, l1Cfg.L1MessageQueueAddress, l1Cfg.RelayerConfig.RollupContractAddress, db) assert.NoError(t, watcher.FetchContractEvent()) return watcher, db @@ -43,13 +36,13 @@ func setupL1Watcher(t *testing.T) (*L1WatcherClient, database.OrmFactory) { func testFetchContractEvent(t *testing.T) { watcher, db := setupL1Watcher(t) - defer db.Close() + defer utils.CloseDB(db) assert.NoError(t, watcher.FetchContractEvent()) } func testL1WatcherClientFetchBlockHeader(t *testing.T) { watcher, db := setupL1Watcher(t) - defer db.Close() + defer utils.CloseDB(db) convey.Convey("test toBlock < fromBlock", t, func() { var blockHeight uint64 if watcher.ProcessedBlockHeight() <= 0 { @@ -73,6 +66,7 @@ func testL1WatcherClientFetchBlockHeader(t *testing.T) { assert.Error(t, err) }) + var l1BlockOrm *orm.L1Block convey.Convey("insert l1 block error", t, func() { var c *ethclient.Client patchGuard := gomonkey.ApplyMethodFunc(c, "HeaderByNumber", func(ctx context.Context, height *big.Int) (*types.Header, error) { @@ -86,7 +80,7 @@ func testL1WatcherClientFetchBlockHeader(t *testing.T) { }) defer patchGuard.Reset() - patchGuard.ApplyMethodFunc(db, "InsertL1Blocks", func(ctx context.Context, blocks []*commonTypes.L1BlockInfo) error { + patchGuard.ApplyMethodFunc(l1BlockOrm, "InsertL1Blocks", func(ctx context.Context, blocks []orm.L1Block) error { return errors.New("insert failed") }) @@ -108,7 +102,7 @@ func testL1WatcherClientFetchBlockHeader(t *testing.T) { }) defer patchGuard.Reset() - patchGuard.ApplyMethodFunc(db, "InsertL1Blocks", func(ctx context.Context, blocks []*commonTypes.L1BlockInfo) error { + patchGuard.ApplyMethodFunc(l1BlockOrm, "InsertL1Blocks", func(ctx context.Context, blocks []orm.L1Block) error { return nil }) @@ -120,7 +114,7 @@ func testL1WatcherClientFetchBlockHeader(t *testing.T) { func testL1WatcherClientFetchContractEvent(t *testing.T) { watcher, db := setupL1Watcher(t) - defer db.Close() + defer utils.CloseDB(db) watcher.SetConfirmations(rpc.SafeBlockNumber) convey.Convey("get latest confirmed block number failure", t, func() { @@ -165,14 +159,14 @@ func testL1WatcherClientFetchContractEvent(t *testing.T) { convey.Convey("parse bridge event logs failure", t, func() { targetErr := errors.New("parse log failure") - patchGuard.ApplyPrivateMethod(watcher, "parseBridgeEventLogs", func(*L1WatcherClient, []geth_types.Log) ([]*commonTypes.L1Message, []relayedMessage, []rollupEvent, error) { + patchGuard.ApplyPrivateMethod(watcher, "parseBridgeEventLogs", func(*L1WatcherClient, []types.Log) ([]*orm.L1Message, []relayedMessage, []rollupEvent, error) { return nil, nil, nil, targetErr }) err := watcher.FetchContractEvent() assert.Equal(t, err.Error(), targetErr.Error()) }) - patchGuard.ApplyPrivateMethod(watcher, "parseBridgeEventLogs", func(*L1WatcherClient, []geth_types.Log) ([]*commonTypes.L1Message, []relayedMessage, []rollupEvent, error) { + patchGuard.ApplyPrivateMethod(watcher, "parseBridgeEventLogs", func(*L1WatcherClient, []types.Log) ([]*orm.L1Message, []relayedMessage, []rollupEvent, error) { rollupEvents := []rollupEvent{ { batchHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), @@ -201,9 +195,10 @@ func testL1WatcherClientFetchContractEvent(t *testing.T) { return nil, relayedMessageEvents, rollupEvents, nil }) + var blockBatchOrm *orm.BlockBatch convey.Convey("db get rollup status by hash list failure", t, func() { targetErr := errors.New("get db failure") - patchGuard.ApplyMethodFunc(db, "GetRollupStatusByHashList", func(hashes []string) ([]commonTypes.RollupStatus, error) { + patchGuard.ApplyMethodFunc(blockBatchOrm, "GetRollupStatusByHashList", func(hashes []string) ([]commonTypes.RollupStatus, error) { return nil, targetErr }) err := watcher.FetchContractEvent() @@ -211,7 +206,7 @@ func testL1WatcherClientFetchContractEvent(t *testing.T) { }) convey.Convey("rollup status mismatch batch hashes length", t, func() { - patchGuard.ApplyMethodFunc(db, "GetRollupStatusByHashList", func(hashes []string) ([]commonTypes.RollupStatus, error) { + patchGuard.ApplyMethodFunc(blockBatchOrm, "GetRollupStatusByHashList", func(hashes []string) ([]commonTypes.RollupStatus, error) { s := []commonTypes.RollupStatus{ commonTypes.RollupFinalized, } @@ -221,7 +216,7 @@ func testL1WatcherClientFetchContractEvent(t *testing.T) { assert.NoError(t, err) }) - patchGuard.ApplyMethodFunc(db, "GetRollupStatusByHashList", func(hashes []string) ([]commonTypes.RollupStatus, error) { + patchGuard.ApplyMethodFunc(blockBatchOrm, "GetRollupStatusByHashList", func(hashes []string) ([]commonTypes.RollupStatus, error) { s := []commonTypes.RollupStatus{ commonTypes.RollupPending, commonTypes.RollupCommitting, @@ -231,53 +226,55 @@ func testL1WatcherClientFetchContractEvent(t *testing.T) { convey.Convey("db update RollupFinalized status failure", t, func() { targetErr := errors.New("UpdateFinalizeTxHashAndRollupStatus RollupFinalized failure") - patchGuard.ApplyMethodFunc(db, "UpdateFinalizeTxHashAndRollupStatus", func(context.Context, string, string, commonTypes.RollupStatus) error { + patchGuard.ApplyMethodFunc(blockBatchOrm, "UpdateFinalizeTxHashAndRollupStatus", func(context.Context, string, string, commonTypes.RollupStatus) error { return targetErr }) err := watcher.FetchContractEvent() assert.Equal(t, targetErr.Error(), err.Error()) }) - patchGuard.ApplyMethodFunc(db, "UpdateFinalizeTxHashAndRollupStatus", func(context.Context, string, string, commonTypes.RollupStatus) error { + patchGuard.ApplyMethodFunc(blockBatchOrm, "UpdateFinalizeTxHashAndRollupStatus", func(context.Context, string, string, commonTypes.RollupStatus) error { return nil }) convey.Convey("db update RollupCommitted status failure", t, func() { targetErr := errors.New("UpdateCommitTxHashAndRollupStatus RollupCommitted failure") - patchGuard.ApplyMethodFunc(db, "UpdateCommitTxHashAndRollupStatus", func(context.Context, string, string, commonTypes.RollupStatus) error { + patchGuard.ApplyMethodFunc(blockBatchOrm, "UpdateCommitTxHashAndRollupStatus", func(context.Context, string, string, commonTypes.RollupStatus) error { return targetErr }) err := watcher.FetchContractEvent() assert.Equal(t, targetErr.Error(), err.Error()) }) - patchGuard.ApplyMethodFunc(db, "UpdateCommitTxHashAndRollupStatus", func(context.Context, string, string, commonTypes.RollupStatus) error { + patchGuard.ApplyMethodFunc(blockBatchOrm, "UpdateCommitTxHashAndRollupStatus", func(context.Context, string, string, commonTypes.RollupStatus) error { return nil }) + var l2MessageOrm *orm.L2Message convey.Convey("db update layer2 status and layer1 hash failure", t, func() { targetErr := errors.New("UpdateLayer2StatusAndLayer1Hash failure") - patchGuard.ApplyMethodFunc(db, "UpdateLayer2StatusAndLayer1Hash", func(context.Context, string, commonTypes.MsgStatus, string) error { + patchGuard.ApplyMethodFunc(l2MessageOrm, "UpdateLayer2StatusAndLayer1Hash", func(context.Context, string, commonTypes.MsgStatus, string) error { return targetErr }) err := watcher.FetchContractEvent() assert.Equal(t, targetErr.Error(), err.Error()) }) - patchGuard.ApplyMethodFunc(db, "UpdateLayer2StatusAndLayer1Hash", func(context.Context, string, commonTypes.MsgStatus, string) error { + patchGuard.ApplyMethodFunc(l2MessageOrm, "UpdateLayer2StatusAndLayer1Hash", func(context.Context, string, commonTypes.MsgStatus, string) error { return nil }) + var l1MessageOrm *orm.L1Message convey.Convey("db save l1 message failure", t, func() { targetErr := errors.New("SaveL1Messages failure") - patchGuard.ApplyMethodFunc(db, "SaveL1Messages", func(context.Context, []*commonTypes.L1Message) error { + patchGuard.ApplyMethodFunc(l1MessageOrm, "SaveL1Messages", func(context.Context, []*orm.L1Message) error { return targetErr }) err := watcher.FetchContractEvent() assert.Equal(t, targetErr.Error(), err.Error()) }) - patchGuard.ApplyMethodFunc(db, "SaveL1Messages", func(context.Context, []*commonTypes.L1Message) error { + patchGuard.ApplyMethodFunc(l1MessageOrm, "SaveL1Messages", func(context.Context, []*orm.L1Message) error { return nil }) @@ -289,11 +286,11 @@ func testL1WatcherClientFetchContractEvent(t *testing.T) { func testParseBridgeEventLogsL1QueueTransactionEventSignature(t *testing.T) { watcher, db := setupL1Watcher(t) - defer db.Close() + defer utils.CloseDB(db) - logs := []geth_types.Log{ + logs := []types.Log{ { - Topics: []common.Hash{bridge_abi.L1QueueTransactionEventSignature}, + Topics: []common.Hash{bridgeAbi.L1QueueTransactionEventSignature}, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), }, @@ -315,7 +312,7 @@ func testParseBridgeEventLogsL1QueueTransactionEventSignature(t *testing.T) { convey.Convey("L1QueueTransactionEventSignature success", t, func() { patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log types.Log) error { - tmpOut := out.(*bridge_abi.L1QueueTransactionEvent) + tmpOut := out.(*bridgeAbi.L1QueueTransactionEvent) tmpOut.QueueIndex = big.NewInt(100) tmpOut.Data = []byte("test data") tmpOut.Sender = common.HexToAddress("0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30") @@ -337,11 +334,11 @@ func testParseBridgeEventLogsL1QueueTransactionEventSignature(t *testing.T) { func testParseBridgeEventLogsL1RelayedMessageEventSignature(t *testing.T) { watcher, db := setupL1Watcher(t) - defer db.Close() + defer utils.CloseDB(db) - logs := []geth_types.Log{ + logs := []types.Log{ { - Topics: []common.Hash{bridge_abi.L1RelayedMessageEventSignature}, + Topics: []common.Hash{bridgeAbi.L1RelayedMessageEventSignature}, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), }, @@ -364,7 +361,7 @@ func testParseBridgeEventLogsL1RelayedMessageEventSignature(t *testing.T) { convey.Convey("L1RelayedMessageEventSignature success", t, func() { msgHash := common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5") patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log types.Log) error { - tmpOut := out.(*bridge_abi.L1RelayedMessageEvent) + tmpOut := out.(*bridgeAbi.L1RelayedMessageEvent) tmpOut.MessageHash = msgHash return nil }) @@ -381,11 +378,10 @@ func testParseBridgeEventLogsL1RelayedMessageEventSignature(t *testing.T) { func testParseBridgeEventLogsL1FailedRelayedMessageEventSignature(t *testing.T) { watcher, db := setupL1Watcher(t) - defer db.Close() - - logs := []geth_types.Log{ + defer utils.CloseDB(db) + logs := []types.Log{ { - Topics: []common.Hash{bridge_abi.L1FailedRelayedMessageEventSignature}, + Topics: []common.Hash{bridgeAbi.L1FailedRelayedMessageEventSignature}, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), }, @@ -408,7 +404,7 @@ func testParseBridgeEventLogsL1FailedRelayedMessageEventSignature(t *testing.T) convey.Convey("L1FailedRelayedMessageEventSignature success", t, func() { msgHash := common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5") patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log types.Log) error { - tmpOut := out.(*bridge_abi.L1FailedRelayedMessageEvent) + tmpOut := out.(*bridgeAbi.L1FailedRelayedMessageEvent) tmpOut.MessageHash = msgHash return nil }) @@ -425,11 +421,10 @@ func testParseBridgeEventLogsL1FailedRelayedMessageEventSignature(t *testing.T) func testParseBridgeEventLogsL1CommitBatchEventSignature(t *testing.T) { watcher, db := setupL1Watcher(t) - defer db.Close() - - logs := []geth_types.Log{ + defer utils.CloseDB(db) + logs := []types.Log{ { - Topics: []common.Hash{bridge_abi.L1CommitBatchEventSignature}, + Topics: []common.Hash{bridgeAbi.L1CommitBatchEventSignature}, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), }, @@ -452,7 +447,7 @@ func testParseBridgeEventLogsL1CommitBatchEventSignature(t *testing.T) { convey.Convey("L1CommitBatchEventSignature success", t, func() { msgHash := common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5") patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log types.Log) error { - tmpOut := out.(*bridge_abi.L1CommitBatchEvent) + tmpOut := out.(*bridgeAbi.L1CommitBatchEvent) tmpOut.BatchHash = msgHash return nil }) @@ -470,11 +465,10 @@ func testParseBridgeEventLogsL1CommitBatchEventSignature(t *testing.T) { func testParseBridgeEventLogsL1FinalizeBatchEventSignature(t *testing.T) { watcher, db := setupL1Watcher(t) - defer db.Close() - - logs := []geth_types.Log{ + defer utils.CloseDB(db) + logs := []types.Log{ { - Topics: []common.Hash{bridge_abi.L1FinalizeBatchEventSignature}, + Topics: []common.Hash{bridgeAbi.L1FinalizeBatchEventSignature}, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), }, @@ -497,7 +491,7 @@ func testParseBridgeEventLogsL1FinalizeBatchEventSignature(t *testing.T) { convey.Convey("L1FinalizeBatchEventSignature success", t, func() { msgHash := common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5") patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log types.Log) error { - tmpOut := out.(*bridge_abi.L1FinalizeBatchEvent) + tmpOut := out.(*bridgeAbi.L1FinalizeBatchEvent) tmpOut.BatchHash = msgHash return nil }) diff --git a/bridge/watcher/l2_watcher.go b/bridge/internal/controller/watcher/l2_watcher.go similarity index 74% rename from bridge/watcher/l2_watcher.go rename to bridge/internal/controller/watcher/l2_watcher.go index 3d1b162e5..1ba655848 100644 --- a/bridge/watcher/l2_watcher.go +++ b/bridge/internal/controller/watcher/l2_watcher.go @@ -10,31 +10,31 @@ import ( "github.com/scroll-tech/go-ethereum/accounts/abi" "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common/hexutil" - geth_types "github.com/scroll-tech/go-ethereum/core/types" + gethTypes "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/event" "github.com/scroll-tech/go-ethereum/log" - geth_metrics "github.com/scroll-tech/go-ethereum/metrics" + gethMetrics "github.com/scroll-tech/go-ethereum/metrics" "github.com/scroll-tech/go-ethereum/rpc" + "gorm.io/gorm" "scroll-tech/common/metrics" "scroll-tech/common/types" - "scroll-tech/database" - - bridge_abi "scroll-tech/bridge/abi" - "scroll-tech/bridge/utils" + bridgeAbi "scroll-tech/bridge/abi" + "scroll-tech/bridge/internal/orm" + bridgeTypes "scroll-tech/bridge/internal/types" + "scroll-tech/bridge/internal/utils" ) // Metrics var ( - bridgeL2MsgsSyncHeightGauge = geth_metrics.NewRegisteredGauge("bridge/l2/msgs/sync/height", metrics.ScrollRegistry) - bridgeL2BlocksFetchedHeightGauge = geth_metrics.NewRegisteredGauge("bridge/l2/blocks/fetched/height", metrics.ScrollRegistry) - bridgeL2BlocksFetchedGapGauge = geth_metrics.NewRegisteredGauge("bridge/l2/blocks/fetched/gap", metrics.ScrollRegistry) - - bridgeL2MsgsSentEventsTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/msgs/sent/events/total", metrics.ScrollRegistry) - bridgeL2MsgsAppendEventsTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/msgs/append/events/total", metrics.ScrollRegistry) - bridgeL2MsgsRelayedEventsTotalCounter = geth_metrics.NewRegisteredCounter("bridge/l2/msgs/relayed/events/total", metrics.ScrollRegistry) + bridgeL2MsgsSyncHeightGauge = gethMetrics.NewRegisteredGauge("bridge/l2/msgs/sync/height", metrics.ScrollRegistry) + bridgeL2BlocksFetchedHeightGauge = gethMetrics.NewRegisteredGauge("bridge/l2/blocks/fetched/height", metrics.ScrollRegistry) + bridgeL2BlocksFetchedGapGauge = gethMetrics.NewRegisteredGauge("bridge/l2/blocks/fetched/gap", metrics.ScrollRegistry) + bridgeL2MsgsSentEventsTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/msgs/sent/events/total", metrics.ScrollRegistry) + bridgeL2MsgsAppendEventsTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/msgs/append/events/total", metrics.ScrollRegistry) + bridgeL2MsgsRelayedEventsTotalCounter = gethMetrics.NewRegisteredCounter("bridge/l2/msgs/relayed/events/total", metrics.ScrollRegistry) ) // L2WatcherClient provide APIs which support others to subscribe to various event from l2geth @@ -44,7 +44,11 @@ type L2WatcherClient struct { *ethclient.Client - orm database.OrmFactory + db *gorm.DB + blockBatchOrm *orm.BlockBatch + blockTraceOrm *orm.BlockTrace + l1MessageOrm *orm.L1Message + l2MessageOrm *orm.L2Message confirmations rpc.BlockNumber @@ -62,25 +66,31 @@ type L2WatcherClient struct { } // NewL2WatcherClient take a l2geth instance to generate a l2watcherclient instance -func NewL2WatcherClient(ctx context.Context, client *ethclient.Client, confirmations rpc.BlockNumber, messengerAddress, messageQueueAddress common.Address, withdrawTrieRootSlot common.Hash, orm database.OrmFactory) *L2WatcherClient { - savedHeight, err := orm.GetLayer2LatestWatchedHeight() +func NewL2WatcherClient(ctx context.Context, client *ethclient.Client, confirmations rpc.BlockNumber, messengerAddress, messageQueueAddress common.Address, withdrawTrieRootSlot common.Hash, db *gorm.DB) *L2WatcherClient { + l2MessageOrm := orm.NewL2Message(db) + savedHeight, err := l2MessageOrm.GetLayer2LatestWatchedHeight() if err != nil { log.Warn("fetch height from db failed", "err", err) savedHeight = 0 } w := L2WatcherClient{ - ctx: ctx, - Client: client, - orm: orm, + ctx: ctx, + db: db, + Client: client, + + blockBatchOrm: orm.NewBlockBatch(db), + blockTraceOrm: orm.NewBlockTrace(db), + l1MessageOrm: orm.NewL1Message(db), + l2MessageOrm: l2MessageOrm, processedMsgHeight: uint64(savedHeight), confirmations: confirmations, messengerAddress: messengerAddress, - messengerABI: bridge_abi.L2ScrollMessengerABI, + messengerABI: bridgeAbi.L2ScrollMessengerABI, messageQueueAddress: messageQueueAddress, - messageQueueABI: bridge_abi.L2MessageQueueABI, + messageQueueABI: bridgeAbi.L2MessageQueueABI, withdrawTrieRootSlot: withdrawTrieRootSlot, stopped: 0, @@ -95,7 +105,7 @@ func NewL2WatcherClient(ctx context.Context, client *ethclient.Client, confirmat } func (w *L2WatcherClient) initializeGenesis() error { - if count, err := w.orm.GetBatchCount(); err != nil { + if count, err := w.blockBatchOrm.GetBatchCount(); err != nil { return fmt.Errorf("failed to get batch count: %v", err) } else if count > 0 { log.Info("genesis already imported") @@ -109,21 +119,25 @@ func (w *L2WatcherClient) initializeGenesis() error { log.Info("retrieved L2 genesis header", "hash", genesis.Hash().String()) - blockTrace := &types.WrappedBlock{Header: genesis, Transactions: nil, WithdrawTrieRoot: common.Hash{}} - batchData := types.NewGenesisBatchData(blockTrace) + blockTrace := &bridgeTypes.WrappedBlock{ + Header: genesis, + Transactions: nil, + WithdrawTrieRoot: common.Hash{}, + } + batchData := bridgeTypes.NewGenesisBatchData(blockTrace) - if err = AddBatchInfoToDB(w.orm, batchData); err != nil { + if err = orm.AddBatchInfoToDB(w.db, batchData); err != nil { log.Error("failed to add batch info to DB", "BatchHash", batchData.Hash(), "error", err) return err } batchHash := batchData.Hash().Hex() - if err = w.orm.UpdateProvingStatus(batchHash, types.ProvingTaskProved); err != nil { + if err = w.blockBatchOrm.UpdateProvingStatus(batchHash, types.ProvingTaskProved); err != nil { return fmt.Errorf("failed to update genesis batch proving status: %v", err) } - if err = w.orm.UpdateRollupStatus(w.ctx, batchHash, types.RollupFinalized); err != nil { + if err = w.blockBatchOrm.UpdateRollupStatus(w.ctx, batchHash, types.RollupFinalized); err != nil { return fmt.Errorf("failed to update genesis batch rollup status: %v", err) } @@ -139,7 +153,7 @@ func (w *L2WatcherClient) TryFetchRunningMissingBlocks(ctx context.Context, bloc // Get newest block in DB. must have blocks at that time. // Don't use "block_trace" table "trace" column's BlockTrace.Number, // because it might be empty if the corresponding rollup_result is finalized/finalization_skipped - heightInDB, err := w.orm.GetL2BlocksLatestHeight() + heightInDB, err := w.blockTraceOrm.GetL2BlocksLatestHeight() if err != nil { log.Error("failed to GetL2BlocksLatestHeight", "err", err) return @@ -168,11 +182,11 @@ func (w *L2WatcherClient) TryFetchRunningMissingBlocks(ctx context.Context, bloc } } -func txsToTxsData(txs geth_types.Transactions) []*geth_types.TransactionData { - txsData := make([]*geth_types.TransactionData, len(txs)) +func txsToTxsData(txs gethTypes.Transactions) []*gethTypes.TransactionData { + txsData := make([]*gethTypes.TransactionData, len(txs)) for i, tx := range txs { v, r, s := tx.RawSignatureValues() - txsData[i] = &geth_types.TransactionData{ + txsData[i] = &gethTypes.TransactionData{ Type: tx.Type(), TxHash: tx.Hash().String(), Nonce: tx.Nonce(), @@ -192,8 +206,7 @@ func txsToTxsData(txs geth_types.Transactions) []*geth_types.TransactionData { } func (w *L2WatcherClient) getAndStoreBlockTraces(ctx context.Context, from, to uint64) error { - var blocks []*types.WrappedBlock - + var blocks []*bridgeTypes.WrappedBlock for number := from; number <= to; number++ { log.Debug("retrieving block", "height", number) block, err2 := w.BlockByNumber(ctx, big.NewInt(int64(number))) @@ -208,7 +221,7 @@ func (w *L2WatcherClient) getAndStoreBlockTraces(ctx context.Context, from, to u return fmt.Errorf("failed to get withdrawTrieRoot: %v. number: %v", err3, number) } - blocks = append(blocks, &types.WrappedBlock{ + blocks = append(blocks, &bridgeTypes.WrappedBlock{ Header: block.Header(), Transactions: txsToTxsData(block.Transactions()), WithdrawTrieRoot: common.BytesToHash(withdrawTrieRoot), @@ -216,7 +229,7 @@ func (w *L2WatcherClient) getAndStoreBlockTraces(ctx context.Context, from, to u } if len(blocks) > 0 { - if err := w.orm.InsertWrappedBlocks(blocks); err != nil { + if err := w.blockTraceOrm.InsertWrappedBlocks(blocks); err != nil { return fmt.Errorf("failed to batch insert BlockTraces: %v", err) } } @@ -257,10 +270,10 @@ func (w *L2WatcherClient) FetchContractEvent() { Topics: make([][]common.Hash, 1), } query.Topics[0] = make([]common.Hash, 4) - query.Topics[0][0] = bridge_abi.L2SentMessageEventSignature - query.Topics[0][1] = bridge_abi.L2RelayedMessageEventSignature - query.Topics[0][2] = bridge_abi.L2FailedRelayedMessageEventSignature - query.Topics[0][3] = bridge_abi.L2AppendMessageEventSignature + query.Topics[0][0] = bridgeAbi.L2SentMessageEventSignature + query.Topics[0][1] = bridgeAbi.L2RelayedMessageEventSignature + query.Topics[0][2] = bridgeAbi.L2FailedRelayedMessageEventSignature + query.Topics[0][3] = bridgeAbi.L2AppendMessageEventSignature logs, err := w.FilterLogs(w.ctx, query) if err != nil { @@ -295,13 +308,13 @@ func (w *L2WatcherClient) FetchContractEvent() { } else { msgStatus = types.MsgFailed } - if err = w.orm.UpdateLayer1StatusAndLayer2Hash(w.ctx, msg.msgHash.String(), msgStatus, msg.txHash.String()); err != nil { + if err = w.l1MessageOrm.UpdateLayer1StatusAndLayer2Hash(w.ctx, msg.msgHash.String(), msgStatus, msg.txHash.String()); err != nil { log.Error("Failed to update layer1 status and layer2 hash", "err", err) return } } - if err = w.orm.SaveL2Messages(w.ctx, sentMessageEvents); err != nil { + if err = w.l2MessageOrm.SaveL2Messages(w.ctx, sentMessageEvents); err != nil { log.Error("failed to save l2 messages", "err", err) return } @@ -311,18 +324,18 @@ func (w *L2WatcherClient) FetchContractEvent() { } } -func (w *L2WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types.L2Message, []relayedMessage, error) { +func (w *L2WatcherClient) parseBridgeEventLogs(logs []gethTypes.Log) ([]orm.L2Message, []relayedMessage, error) { // Need use contract abi to parse event Log // Can only be tested after we have our contracts set up - var l2Messages []*types.L2Message + var l2Messages []orm.L2Message var relayedMessages []relayedMessage var lastAppendMsgHash common.Hash var lastAppendMsgNonce uint64 for _, vLog := range logs { switch vLog.Topics[0] { - case bridge_abi.L2SentMessageEventSignature: - event := bridge_abi.L2SentMessageEvent{} + case bridgeAbi.L2SentMessageEventSignature: + event := bridgeAbi.L2SentMessageEvent{} err := utils.UnpackLog(w.messengerABI, &event, "SentMessage", vLog) if err != nil { log.Error("failed to unpack layer2 SentMessage event", "err", err) @@ -350,7 +363,7 @@ func (w *L2WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. return l2Messages, relayedMessages, errors.New(errMsg) } - l2Messages = append(l2Messages, &types.L2Message{ + l2Messages = append(l2Messages, orm.L2Message{ Nonce: event.MessageNonce.Uint64(), MsgHash: computedMsgHash.String(), Height: vLog.BlockNumber, @@ -360,8 +373,8 @@ func (w *L2WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. Calldata: common.Bytes2Hex(event.Message), Layer2Hash: vLog.TxHash.Hex(), }) - case bridge_abi.L2RelayedMessageEventSignature: - event := bridge_abi.L2RelayedMessageEvent{} + case bridgeAbi.L2RelayedMessageEventSignature: + event := bridgeAbi.L2RelayedMessageEvent{} err := utils.UnpackLog(w.messengerABI, &event, "RelayedMessage", vLog) if err != nil { log.Warn("Failed to unpack layer2 RelayedMessage event", "err", err) @@ -373,8 +386,8 @@ func (w *L2WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. txHash: vLog.TxHash, isSuccessful: true, }) - case bridge_abi.L2FailedRelayedMessageEventSignature: - event := bridge_abi.L2FailedRelayedMessageEvent{} + case bridgeAbi.L2FailedRelayedMessageEventSignature: + event := bridgeAbi.L2FailedRelayedMessageEvent{} err := utils.UnpackLog(w.messengerABI, &event, "FailedRelayedMessage", vLog) if err != nil { log.Warn("Failed to unpack layer2 FailedRelayedMessage event", "err", err) @@ -386,8 +399,8 @@ func (w *L2WatcherClient) parseBridgeEventLogs(logs []geth_types.Log) ([]*types. txHash: vLog.TxHash, isSuccessful: false, }) - case bridge_abi.L2AppendMessageEventSignature: - event := bridge_abi.L2AppendMessageEvent{} + case bridgeAbi.L2AppendMessageEventSignature: + event := bridgeAbi.L2AppendMessageEvent{} err := utils.UnpackLog(w.messageQueueABI, &event, "AppendMessage", vLog) if err != nil { log.Warn("Failed to unpack layer2 AppendMessage event", "err", err) diff --git a/bridge/watcher/l2_watcher_test.go b/bridge/internal/controller/watcher/l2_watcher_test.go similarity index 76% rename from bridge/watcher/l2_watcher_test.go rename to bridge/internal/controller/watcher/l2_watcher_test.go index b4891ac0c..916b27bdf 100644 --- a/bridge/watcher/l2_watcher_test.go +++ b/bridge/internal/controller/watcher/l2_watcher_test.go @@ -9,54 +9,43 @@ import ( "testing" "time" + "gorm.io/gorm" + "github.com/agiledragon/gomonkey/v2" "github.com/scroll-tech/go-ethereum/accounts/abi" "github.com/scroll-tech/go-ethereum/accounts/abi/bind" "github.com/scroll-tech/go-ethereum/common" - geth_types "github.com/scroll-tech/go-ethereum/core/types" + gethTypes "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/rpc" "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/assert" "scroll-tech/common/types" - - bridge_abi "scroll-tech/bridge/abi" - "scroll-tech/bridge/mock_bridge" - "scroll-tech/bridge/sender" - "scroll-tech/bridge/utils" - cutils "scroll-tech/common/utils" - "scroll-tech/database" - "scroll-tech/database/migrate" + bridgeAbi "scroll-tech/bridge/abi" + "scroll-tech/bridge/internal/controller/sender" + "scroll-tech/bridge/internal/orm" + "scroll-tech/bridge/internal/utils" + "scroll-tech/bridge/mock_bridge" ) -func setupL2Watcher(t *testing.T) *L2WatcherClient { - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() - +func setupL2Watcher(t *testing.T) (*L2WatcherClient, *gorm.DB) { + db := setupDB(t) l2cfg := cfg.L2Config watcher := NewL2WatcherClient(context.Background(), l2Cli, l2cfg.Confirmations, l2cfg.L2MessengerAddress, l2cfg.L2MessageQueueAddress, l2cfg.WithdrawTrieRootSlot, db) - return watcher + return watcher, db } func testCreateNewWatcherAndStop(t *testing.T) { - // Create db handler and reset db. - l2db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(l2db.GetDB().DB)) - ctx := context.Background() - subCtx, cancel := context.WithCancel(ctx) + wc, db := setupL2Watcher(t) + subCtx, cancel := context.WithCancel(context.Background()) defer func() { cancel() - l2db.Close() + defer utils.CloseDB(db) }() - l2cfg := cfg.L2Config - wc := NewL2WatcherClient(context.Background(), l2Cli, l2cfg.Confirmations, l2cfg.L2MessengerAddress, l2cfg.L2MessageQueueAddress, l2cfg.WithdrawTrieRootSlot, l2db) loopToFetchEvent(subCtx, wc) l1cfg := cfg.L1Config @@ -79,20 +68,13 @@ func testCreateNewWatcherAndStop(t *testing.T) { } func testMonitorBridgeContract(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - ctx := context.Background() - subCtx, cancel := context.WithCancel(ctx) - + wc, db := setupL2Watcher(t) + subCtx, cancel := context.WithCancel(context.Background()) defer func() { cancel() - db.Close() + defer utils.CloseDB(db) }() - l2cfg := cfg.L2Config - wc := NewL2WatcherClient(context.Background(), l2Cli, l2cfg.Confirmations, l2cfg.L2MessengerAddress, l2cfg.L2MessageQueueAddress, l2cfg.WithdrawTrieRootSlot, db) loopToFetchEvent(subCtx, wc) previousHeight, err := l2Cli.BlockNumber(context.Background()) @@ -117,7 +99,7 @@ func testMonitorBridgeContract(t *testing.T) { tx, err = instance.SendMessage(auth, toAddress, fee, message, gasLimit) assert.NoError(t, err) receipt, err := bind.WaitMined(context.Background(), l2Cli, tx) - if receipt.Status != geth_types.ReceiptStatusSuccessful || err != nil { + if receipt.Status != gethTypes.ReceiptStatusSuccessful || err != nil { t.Fatalf("Call failed") } @@ -127,34 +109,30 @@ func testMonitorBridgeContract(t *testing.T) { tx, err = instance.SendMessage(auth, toAddress, fee, message, gasLimit) assert.NoError(t, err) receipt, err = bind.WaitMined(context.Background(), l2Cli, tx) - if receipt.Status != geth_types.ReceiptStatusSuccessful || err != nil { + if receipt.Status != gethTypes.ReceiptStatusSuccessful || err != nil { t.Fatalf("Call failed") } + l2MessageOrm := orm.NewL2Message(db) // check if we successfully stored events assert.True(t, cutils.TryTimes(10, func() bool { - height, err := db.GetLayer2LatestWatchedHeight() + height, err := l2MessageOrm.GetLayer2LatestWatchedHeight() return err == nil && height > int64(previousHeight) })) // check l1 messages. assert.True(t, cutils.TryTimes(10, func() bool { - msgs, err := db.GetL2Messages(map[string]interface{}{"status": types.MsgPending}) + msgs, err := l2MessageOrm.GetL2Messages(map[string]interface{}{"status": types.MsgPending}, nil, 0) return err == nil && len(msgs) == 2 })) } func testFetchMultipleSentMessageInOneBlock(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - ctx := context.Background() - subCtx, cancel := context.WithCancel(ctx) - + _, db := setupL2Watcher(t) + subCtx, cancel := context.WithCancel(context.Background()) defer func() { cancel() - db.Close() + defer utils.CloseDB(db) }() previousHeight, err := l2Cli.BlockNumber(context.Background()) // shallow the global previousHeight @@ -172,8 +150,7 @@ func testFetchMultipleSentMessageInOneBlock(t *testing.T) { // Call mock_bridge instance sendMessage to trigger emit events multiple times numTransactions := 4 - var tx *geth_types.Transaction - + var tx *gethTypes.Transaction for i := 0; i < numTransactions; i++ { addr := common.HexToAddress("0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63") nonce, nounceErr := l2Cli.PendingNonceAt(context.Background(), addr) @@ -188,7 +165,7 @@ func testFetchMultipleSentMessageInOneBlock(t *testing.T) { } receipt, err := bind.WaitMined(context.Background(), l2Cli, tx) - if receipt.Status != geth_types.ReceiptStatusSuccessful || err != nil { + if receipt.Status != gethTypes.ReceiptStatusSuccessful || err != nil { t.Fatalf("Call failed") } @@ -204,28 +181,26 @@ func testFetchMultipleSentMessageInOneBlock(t *testing.T) { tx, err = instance.SendMessage(auth, toAddress, fee, message, gasLimit) assert.NoError(t, err) receipt, err = bind.WaitMined(context.Background(), l2Cli, tx) - if receipt.Status != geth_types.ReceiptStatusSuccessful || err != nil { + if receipt.Status != gethTypes.ReceiptStatusSuccessful || err != nil { t.Fatalf("Call failed") } + l2MessageOrm := orm.NewL2Message(db) // check if we successfully stored events assert.True(t, cutils.TryTimes(10, func() bool { - height, err := db.GetLayer2LatestWatchedHeight() + height, err := l2MessageOrm.GetLayer2LatestWatchedHeight() return err == nil && height > int64(previousHeight) })) assert.True(t, cutils.TryTimes(10, func() bool { - msgs, err := db.GetL2Messages(map[string]interface{}{"status": types.MsgPending}) + msgs, err := l2MessageOrm.GetL2Messages(map[string]interface{}{"status": types.MsgPending}, nil, 0) return err == nil && len(msgs) == 5 })) } func testFetchRunningMissingBlocks(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + _, db := setupL2Watcher(t) + defer utils.CloseDB(db) auth := prepareAuth(t, l2Cli, cfg.L2Config.RelayerConfig.MessageSenderPrivateKeys[0]) @@ -235,6 +210,7 @@ func testFetchRunningMissingBlocks(t *testing.T) { address, err := bind.WaitDeployed(context.Background(), l2Cli, tx) assert.NoError(t, err) + blockTraceOrm := orm.NewBlockTrace(db) ok := cutils.TryTimes(10, func() bool { latestHeight, err := l2Cli.BlockNumber(context.Background()) if err != nil { @@ -242,13 +218,13 @@ func testFetchRunningMissingBlocks(t *testing.T) { } wc := prepareWatcherClient(l2Cli, db, address) wc.TryFetchRunningMissingBlocks(context.Background(), latestHeight) - fetchedHeight, err := db.GetL2BlocksLatestHeight() + fetchedHeight, err := blockTraceOrm.GetL2BlocksLatestHeight() return err == nil && uint64(fetchedHeight) == latestHeight }) assert.True(t, ok) } -func prepareWatcherClient(l2Cli *ethclient.Client, db database.OrmFactory, contractAddr common.Address) *L2WatcherClient { +func prepareWatcherClient(l2Cli *ethclient.Client, db *gorm.DB, contractAddr common.Address) *L2WatcherClient { confirmations := rpc.LatestBlockNumber return NewL2WatcherClient(context.Background(), l2Cli, confirmations, contractAddr, contractAddr, common.Hash{}, db) } @@ -268,11 +244,13 @@ func loopToFetchEvent(subCtx context.Context, watcher *L2WatcherClient) { } func testParseBridgeEventLogsL2SentMessageEventSignature(t *testing.T) { - watcher := setupL2Watcher(t) - logs := []geth_types.Log{ + watcher, db := setupL2Watcher(t) + defer utils.CloseDB(db) + + logs := []gethTypes.Log{ { Topics: []common.Hash{ - bridge_abi.L2SentMessageEventSignature, + bridgeAbi.L2SentMessageEventSignature, }, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), @@ -281,7 +259,7 @@ func testParseBridgeEventLogsL2SentMessageEventSignature(t *testing.T) { convey.Convey("unpack SentMessage log failure", t, func() { targetErr := errors.New("UnpackLog SentMessage failure") - patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log geth_types.Log) error { + patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log gethTypes.Log) error { return targetErr }) defer patchGuard.Reset() @@ -298,8 +276,8 @@ func testParseBridgeEventLogsL2SentMessageEventSignature(t *testing.T) { tmpValue := big.NewInt(1000) tmpMessageNonce := big.NewInt(100) tmpMessage := []byte("test for L2SentMessageEventSignature") - patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log geth_types.Log) error { - tmpOut := out.(*bridge_abi.L2SentMessageEvent) + patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log gethTypes.Log) error { + tmpOut := out.(*bridgeAbi.L2SentMessageEvent) tmpOut.Sender = tmpSendAddr tmpOut.Value = tmpValue tmpOut.Target = tmpTargetAddr @@ -317,10 +295,12 @@ func testParseBridgeEventLogsL2SentMessageEventSignature(t *testing.T) { } func testParseBridgeEventLogsL2RelayedMessageEventSignature(t *testing.T) { - watcher := setupL2Watcher(t) - logs := []geth_types.Log{ + watcher, db := setupL2Watcher(t) + defer utils.CloseDB(db) + + logs := []gethTypes.Log{ { - Topics: []common.Hash{bridge_abi.L2RelayedMessageEventSignature}, + Topics: []common.Hash{bridgeAbi.L2RelayedMessageEventSignature}, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), }, @@ -328,7 +308,7 @@ func testParseBridgeEventLogsL2RelayedMessageEventSignature(t *testing.T) { convey.Convey("unpack RelayedMessage log failure", t, func() { targetErr := errors.New("UnpackLog RelayedMessage failure") - patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log geth_types.Log) error { + patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log gethTypes.Log) error { return targetErr }) defer patchGuard.Reset() @@ -341,8 +321,8 @@ func testParseBridgeEventLogsL2RelayedMessageEventSignature(t *testing.T) { convey.Convey("L2RelayedMessageEventSignature success", t, func() { msgHash := common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5") - patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log geth_types.Log) error { - tmpOut := out.(*bridge_abi.L2RelayedMessageEvent) + patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log gethTypes.Log) error { + tmpOut := out.(*bridgeAbi.L2RelayedMessageEvent) tmpOut.MessageHash = msgHash return nil }) @@ -357,10 +337,12 @@ func testParseBridgeEventLogsL2RelayedMessageEventSignature(t *testing.T) { } func testParseBridgeEventLogsL2FailedRelayedMessageEventSignature(t *testing.T) { - watcher := setupL2Watcher(t) - logs := []geth_types.Log{ + watcher, db := setupL2Watcher(t) + defer utils.CloseDB(db) + + logs := []gethTypes.Log{ { - Topics: []common.Hash{bridge_abi.L2FailedRelayedMessageEventSignature}, + Topics: []common.Hash{bridgeAbi.L2FailedRelayedMessageEventSignature}, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), }, @@ -368,7 +350,7 @@ func testParseBridgeEventLogsL2FailedRelayedMessageEventSignature(t *testing.T) convey.Convey("unpack FailedRelayedMessage log failure", t, func() { targetErr := errors.New("UnpackLog FailedRelayedMessage failure") - patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log geth_types.Log) error { + patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log gethTypes.Log) error { return targetErr }) defer patchGuard.Reset() @@ -381,8 +363,8 @@ func testParseBridgeEventLogsL2FailedRelayedMessageEventSignature(t *testing.T) convey.Convey("L2FailedRelayedMessageEventSignature success", t, func() { msgHash := common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5") - patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log geth_types.Log) error { - tmpOut := out.(*bridge_abi.L2FailedRelayedMessageEvent) + patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log gethTypes.Log) error { + tmpOut := out.(*bridgeAbi.L2FailedRelayedMessageEvent) tmpOut.MessageHash = msgHash return nil }) @@ -397,10 +379,11 @@ func testParseBridgeEventLogsL2FailedRelayedMessageEventSignature(t *testing.T) } func testParseBridgeEventLogsL2AppendMessageEventSignature(t *testing.T) { - watcher := setupL2Watcher(t) - logs := []geth_types.Log{ + watcher, db := setupL2Watcher(t) + defer utils.CloseDB(db) + logs := []gethTypes.Log{ { - Topics: []common.Hash{bridge_abi.L2AppendMessageEventSignature}, + Topics: []common.Hash{bridgeAbi.L2AppendMessageEventSignature}, BlockNumber: 100, TxHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), }, @@ -408,7 +391,7 @@ func testParseBridgeEventLogsL2AppendMessageEventSignature(t *testing.T) { convey.Convey("unpack AppendMessage log failure", t, func() { targetErr := errors.New("UnpackLog AppendMessage failure") - patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log geth_types.Log) error { + patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log gethTypes.Log) error { return targetErr }) defer patchGuard.Reset() @@ -421,8 +404,8 @@ func testParseBridgeEventLogsL2AppendMessageEventSignature(t *testing.T) { convey.Convey("L2AppendMessageEventSignature success", t, func() { msgHash := common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5") - patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log geth_types.Log) error { - tmpOut := out.(*bridge_abi.L2AppendMessageEvent) + patchGuard := gomonkey.ApplyFunc(utils.UnpackLog, func(c *abi.ABI, out interface{}, event string, log gethTypes.Log) error { + tmpOut := out.(*bridgeAbi.L2AppendMessageEvent) tmpOut.MessageHash = msgHash tmpOut.Index = big.NewInt(100) return nil diff --git a/bridge/watcher/watcher_test.go b/bridge/internal/controller/watcher/watcher_test.go similarity index 76% rename from bridge/watcher/watcher_test.go rename to bridge/internal/controller/watcher/watcher_test.go index 2d49a01ae..1d97a2ca6 100644 --- a/bridge/watcher/watcher_test.go +++ b/bridge/internal/controller/watcher/watcher_test.go @@ -7,11 +7,14 @@ import ( "github.com/scroll-tech/go-ethereum/ethclient" "github.com/stretchr/testify/assert" + "gorm.io/gorm" "scroll-tech/common/docker" - "scroll-tech/common/types" - "scroll-tech/bridge/config" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/orm/migrate" + bridgeTypes "scroll-tech/bridge/internal/types" + "scroll-tech/bridge/internal/utils" ) var ( @@ -24,47 +27,61 @@ var ( l2Cli *ethclient.Client // block trace - wrappedBlock1 *types.WrappedBlock - wrappedBlock2 *types.WrappedBlock + wrappedBlock1 *bridgeTypes.WrappedBlock + wrappedBlock2 *bridgeTypes.WrappedBlock ) func setupEnv(t *testing.T) (err error) { // Load config. - cfg, err = config.NewConfig("../config.json") + cfg, err = config.NewConfig("../../../conf/config.json") assert.NoError(t, err) base.RunImages(t) cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = base.L1gethImg.Endpoint() cfg.L1Config.RelayerConfig.SenderConfig.Endpoint = base.L2gethImg.Endpoint() - cfg.DBConfig = base.DBConfig + cfg.DBConfig = &config.DBConfig{ + DSN: base.DBConfig.DSN, + DriverName: base.DBConfig.DriverName, + MaxOpenNum: base.DBConfig.MaxOpenNum, + MaxIdleNum: base.DBConfig.MaxIdleNum, + } // Create l2geth client. l2Cli, err = base.L2Client() assert.NoError(t, err) - templateBlockTrace1, err := os.ReadFile("../../common/testdata/blockTrace_02.json") + templateBlockTrace1, err := os.ReadFile("../../../testdata/blockTrace_02.json") if err != nil { return err } // unmarshal blockTrace - wrappedBlock1 = &types.WrappedBlock{} + wrappedBlock1 = &bridgeTypes.WrappedBlock{} if err = json.Unmarshal(templateBlockTrace1, wrappedBlock1); err != nil { return err } - templateBlockTrace2, err := os.ReadFile("../../common/testdata/blockTrace_03.json") + templateBlockTrace2, err := os.ReadFile("../../../testdata/blockTrace_03.json") if err != nil { return err } // unmarshal blockTrace - wrappedBlock2 = &types.WrappedBlock{} + wrappedBlock2 = &bridgeTypes.WrappedBlock{} if err = json.Unmarshal(templateBlockTrace2, wrappedBlock2); err != nil { return err } return err } +func setupDB(t *testing.T) *gorm.DB { + db, err := utils.InitDB(cfg.DBConfig) + assert.NoError(t, err) + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, migrate.ResetDB(sqlDB)) + return db +} + func TestMain(m *testing.M) { base = docker.NewDockerApp() diff --git a/bridge/internal/orm/block_batch.go b/bridge/internal/orm/block_batch.go new file mode 100644 index 000000000..c788df076 --- /dev/null +++ b/bridge/internal/orm/block_batch.go @@ -0,0 +1,292 @@ +package orm + +import ( + "context" + "errors" + "time" + + "github.com/scroll-tech/go-ethereum/log" + "gorm.io/gorm" + + "scroll-tech/common/types" + + bridgeTypes "scroll-tech/bridge/internal/types" +) + +// BlockBatch is structure of stored block batch message +type BlockBatch struct { + db *gorm.DB `gorm:"column:-"` + + Hash string `json:"hash" gorm:"column:hash"` + Index uint64 `json:"index" gorm:"column:index"` + StartBlockNumber uint64 `json:"start_block_number" gorm:"column:start_block_number"` + StartBlockHash string `json:"start_block_hash" gorm:"column:start_block_hash"` + EndBlockNumber uint64 `json:"end_block_number" gorm:"column:end_block_number"` + EndBlockHash string `json:"end_block_hash" gorm:"column:end_block_hash"` + ParentHash string `json:"parent_hash" gorm:"column:parent_hash"` + StateRoot string `json:"state_root" gorm:"column:state_root"` + TotalTxNum uint64 `json:"total_tx_num" gorm:"column:total_tx_num"` + TotalL1TxNum uint64 `json:"total_l1_tx_num" gorm:"column:total_l1_tx_num"` + TotalL2Gas uint64 `json:"total_l2_gas" gorm:"column:total_l2_gas"` + ProvingStatus int `json:"proving_status" gorm:"column:proving_status;default:1"` + Proof []byte `json:"proof" gorm:"column:proof"` + InstanceCommitments []byte `json:"instance_commitments" gorm:"column:instance_commitments"` + ProofTimeSec uint64 `json:"proof_time_sec" gorm:"column:proof_time_sec;default:0"` + RollupStatus int `json:"rollup_status" gorm:"column:rollup_status;default:1"` + CommitTxHash string `json:"commit_tx_hash" gorm:"column:commit_tx_hash;default:NULL"` + OracleStatus int `json:"oracle_status" gorm:"column:oracle_status;default:1"` + OracleTxHash string `json:"oracle_tx_hash" gorm:"column:oracle_tx_hash;default:NULL"` + FinalizeTxHash string `json:"finalize_tx_hash" gorm:"column:finalize_tx_hash;default:NULL"` + CreatedAt time.Time `json:"created_at" gorm:"column:created_at;default:CURRENT_TIMESTAMP()"` + ProverAssignedAt *time.Time `json:"prover_assigned_at" gorm:"column:prover_assigned_at;default:NULL"` + ProvedAt *time.Time `json:"proved_at" gorm:"column:proved_at;default:NULL"` + CommittedAt *time.Time `json:"committed_at" gorm:"column:committed_at;default:NULL"` + FinalizedAt *time.Time `json:"finalized_at" gorm:"column:finalized_at;default:NULL"` +} + +// NewBlockBatch create an blockBatchOrm instance +func NewBlockBatch(db *gorm.DB) *BlockBatch { + return &BlockBatch{db: db} +} + +// TableName define the BlockBatch table name +func (*BlockBatch) TableName() string { + return "block_batch" +} + +// GetBatchCount get the batch count +func (o *BlockBatch) GetBatchCount() (int64, error) { + var count int64 + if err := o.db.Model(&BlockBatch{}).Count(&count).Error; err != nil { + return 0, err + } + return count, nil +} + +// GetBlockBatches get the select block batches +func (o *BlockBatch) GetBlockBatches(fields map[string]interface{}, orderByList []string, limit int) ([]BlockBatch, error) { + var blockBatches []BlockBatch + db := o.db + for key, value := range fields { + db = db.Where(key, value) + } + + for _, orderBy := range orderByList { + db = db.Order(orderBy) + } + + if limit != 0 { + db = db.Limit(limit) + } + + if err := db.Find(&blockBatches).Error; err != nil { + return nil, err + } + return blockBatches, nil +} + +// GetBlockBatchesHashByRollupStatus get the block batches by rollup status +func (o *BlockBatch) GetBlockBatchesHashByRollupStatus(status types.RollupStatus, limit int) ([]string, error) { + var blockBatches []BlockBatch + err := o.db.Select("hash").Where("rollup_status", int(status)).Order("index ASC").Limit(limit).Find(&blockBatches).Error + if err != nil { + return nil, err + } + + var hashes []string + for _, v := range blockBatches { + hashes = append(hashes, v.Hash) + } + return hashes, nil +} + +// GetVerifiedProofAndInstanceCommitmentsByHash get verified proof and instance comments by hash +func (o *BlockBatch) GetVerifiedProofAndInstanceCommitmentsByHash(hash string) ([]byte, []byte, error) { + var blockBatch BlockBatch + err := o.db.Select("proof, instance_commitments").Where("hash", hash).Where("proving_status", int(types.ProvingTaskVerified)).Find(&blockBatch).Error + if err != nil { + return nil, nil, err + } + return blockBatch.Proof, blockBatch.InstanceCommitments, nil +} + +// GetLatestBatch get the latest batch +// because we will `initializeGenesis()` when we start the `L2Watcher`, so a batch must exist. +func (o *BlockBatch) GetLatestBatch() (*BlockBatch, error) { + var blockBatch BlockBatch + err := o.db.Order("index DESC").Limit(1).First(&blockBatch).Error + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + return &blockBatch, nil +} + +// GetLatestBatchByRollupStatus get the latest block batch by rollup status +func (o *BlockBatch) GetLatestBatchByRollupStatus(rollupStatuses []types.RollupStatus) (*BlockBatch, error) { + var tmpRollupStatus []int + for _, v := range rollupStatuses { + tmpRollupStatus = append(tmpRollupStatus, int(v)) + } + var blockBatch BlockBatch + err := o.db.Where("rollup_status IN (?)", tmpRollupStatus).Order("index DESC").Limit(1).First(&blockBatch).Error + if err != nil { + return nil, err + } + return &blockBatch, nil +} + +// GetRollupStatusByHashList get rollup status by hash list +func (o *BlockBatch) GetRollupStatusByHashList(hashes []string) ([]types.RollupStatus, error) { + if len(hashes) == 0 { + return nil, nil + } + + var blockBatches []BlockBatch + err := o.db.Select("hash, rollup_status").Where("hash IN (?)", hashes).Find(&blockBatches).Error + if err != nil { + return nil, err + } + + var statuses []types.RollupStatus + for _, v := range blockBatches { + statuses = append(statuses, types.RollupStatus(v.RollupStatus)) + } + return statuses, nil +} + +// InsertBlockBatchByBatchData insert a block batch data by the BatchData +func (o *BlockBatch) InsertBlockBatchByBatchData(tx *gorm.DB, batchData *bridgeTypes.BatchData) (int64, error) { + var db *gorm.DB + if tx != nil { + db = tx + } else { + db = o.db + } + + numBlocks := len(batchData.Batch.Blocks) + insertBlockBatch := BlockBatch{ + Hash: batchData.Hash().Hex(), + Index: batchData.Batch.BatchIndex, + StartBlockNumber: batchData.Batch.Blocks[0].BlockNumber, + StartBlockHash: batchData.Batch.Blocks[0].BlockHash.Hex(), + EndBlockNumber: batchData.Batch.Blocks[numBlocks-1].BlockNumber, + EndBlockHash: batchData.Batch.Blocks[numBlocks-1].BlockHash.Hex(), + ParentHash: batchData.Batch.ParentBatchHash.Hex(), + StateRoot: batchData.Batch.NewStateRoot.Hex(), + TotalTxNum: batchData.TotalTxNum, + TotalL1TxNum: batchData.TotalL1TxNum, + TotalL2Gas: batchData.TotalL2Gas, + CreatedAt: time.Now(), + } + result := db.Create(&insertBlockBatch) + if result.Error != nil { + log.Error("failed to insert block batch by batchData", "err", result.Error) + return 0, result.Error + } + return result.RowsAffected, nil +} + +// UpdateProvingStatus update the proving status +func (o *BlockBatch) UpdateProvingStatus(hash string, status types.ProvingStatus) error { + updateFields := make(map[string]interface{}) + updateFields["proving_status"] = int(status) + + switch status { + case types.ProvingTaskAssigned: + updateFields["prover_assigned_at"] = time.Now() + case types.ProvingTaskUnassigned: + updateFields["prover_assigned_at"] = nil + case types.ProvingTaskProved, types.ProvingTaskVerified: + updateFields["proved_at"] = time.Now() + default: + } + + if err := o.db.Model(&BlockBatch{}).Where("hash", hash).Updates(updateFields).Error; err != nil { + return err + } + return nil +} + +// UpdateRollupStatus update the rollup status +func (o *BlockBatch) UpdateRollupStatus(ctx context.Context, hash string, status types.RollupStatus) error { + updateFields := make(map[string]interface{}) + updateFields["rollup_status"] = int(status) + + switch status { + case types.RollupCommitted: + updateFields["committed_at"] = time.Now() + case types.RollupFinalized: + updateFields["finalized_at"] = time.Now() + } + if err := o.db.Model(&BlockBatch{}).WithContext(ctx).Where("hash", hash).Updates(updateFields).Error; err != nil { + return err + } + return nil +} + +// UpdateSkippedBatches update the skipped batches +func (o *BlockBatch) UpdateSkippedBatches() (int64, error) { + provingStatusList := []interface{}{ + int(types.ProvingTaskSkipped), + int(types.ProvingTaskFailed), + } + result := o.db.Model(&BlockBatch{}).Where("rollup_status", int(types.RollupCommitted)). + Where("proving_status IN (?)", provingStatusList).Update("rollup_status", int(types.RollupFinalizationSkipped)) + if result.Error != nil { + return 0, result.Error + } + return result.RowsAffected, nil +} + +// UpdateCommitTxHashAndRollupStatus update the commit tx hash and rollup status +func (o *BlockBatch) UpdateCommitTxHashAndRollupStatus(ctx context.Context, hash string, commitTxHash string, status types.RollupStatus) error { + updateFields := make(map[string]interface{}) + updateFields["commit_tx_hash"] = commitTxHash + updateFields["rollup_status"] = int(status) + if status == types.RollupCommitted { + updateFields["committed_at"] = time.Now() + } + if err := o.db.WithContext(ctx).Model(&BlockBatch{}).Where("hash", hash).Updates(updateFields).Error; err != nil { + return err + } + return nil +} + +// UpdateFinalizeTxHashAndRollupStatus update the finalize tx hash and rollup status +func (o *BlockBatch) UpdateFinalizeTxHashAndRollupStatus(ctx context.Context, hash string, finalizeTxHash string, status types.RollupStatus) error { + updateFields := make(map[string]interface{}) + updateFields["finalize_tx_hash"] = finalizeTxHash + updateFields["rollup_status"] = int(status) + if status == types.RollupFinalized { + updateFields["finalized_at"] = time.Now() + } + if err := o.db.WithContext(ctx).Model(&BlockBatch{}).Where("hash", hash).Updates(updateFields).Error; err != nil { + return err + } + return nil +} + +// UpdateL2GasOracleStatusAndOracleTxHash update the l2 gas oracle status and oracle tx hash +func (o *BlockBatch) UpdateL2GasOracleStatusAndOracleTxHash(ctx context.Context, hash string, status types.GasOracleStatus, txHash string) error { + updateFields := make(map[string]interface{}) + updateFields["oracle_status"] = int(status) + updateFields["oracle_tx_hash"] = txHash + if err := o.db.WithContext(ctx).Model(&BlockBatch{}).Where("hash", hash).Updates(updateFields).Error; err != nil { + return err + } + return nil +} + +// UpdateProofByHash update the block batch proof by hash +// for unit test +func (o *BlockBatch) UpdateProofByHash(ctx context.Context, hash string, proof, instanceCommitments []byte, proofTimeSec uint64) error { + updateFields := make(map[string]interface{}) + updateFields["proof"] = proof + updateFields["instance_commitments"] = instanceCommitments + updateFields["proof_time_sec"] = proofTimeSec + err := o.db.WithContext(ctx).Model(&BlockBatch{}).Where("hash", hash).Updates(updateFields).Error + if err != nil { + log.Error("failed to update proof", "err", err) + } + return err +} diff --git a/bridge/internal/orm/block_trace.go b/bridge/internal/orm/block_trace.go new file mode 100644 index 000000000..f95c0236a --- /dev/null +++ b/bridge/internal/orm/block_trace.go @@ -0,0 +1,155 @@ +package orm + +import ( + "encoding/json" + + "github.com/scroll-tech/go-ethereum/log" + "gorm.io/gorm" + + "scroll-tech/bridge/internal/types" +) + +// BlockTrace is structure of stored block trace message +type BlockTrace struct { + db *gorm.DB `gorm:"column:-"` + + Number uint64 `json:"number" gorm:"number"` + Hash string `json:"hash" gorm:"hash"` + ParentHash string `json:"parent_hash" gorm:"parent_hash"` + Trace string `json:"trace" gorm:"column:trace"` + BatchHash string `json:"batch_hash" gorm:"batch_hash;default:NULL"` + TxNum uint64 `json:"tx_num" gorm:"tx_num"` + GasUsed uint64 `json:"gas_used" gorm:"gas_used"` + BlockTimestamp uint64 `json:"block_timestamp" gorm:"block_timestamp"` +} + +// NewBlockTrace create an blockTraceOrm instance +func NewBlockTrace(db *gorm.DB) *BlockTrace { + return &BlockTrace{db: db} +} + +// TableName define the BlockTrace table name +func (*BlockTrace) TableName() string { + return "block_trace" +} + +// GetL2BlocksLatestHeight get the l2 blocks latest height +func (o *BlockTrace) GetL2BlocksLatestHeight() (int64, error) { + result := o.db.Model(&BlockTrace{}).Select("COALESCE(MAX(number), -1)").Row() + if result.Err() != nil { + return -1, result.Err() + } + var maxNumber int64 + if err := result.Scan(&maxNumber); err != nil { + return -1, err + } + return maxNumber, nil +} + +// GetL2WrappedBlocks get the l2 wrapped blocks +func (o *BlockTrace) GetL2WrappedBlocks(fields map[string]interface{}) ([]*types.WrappedBlock, error) { + var blockTraces []BlockTrace + db := o.db.Select("trace") + for key, value := range fields { + db = db.Where(key, value) + } + if err := db.Find(&blockTraces).Error; err != nil { + return nil, err + } + + var wrappedBlocks []*types.WrappedBlock + for _, v := range blockTraces { + var wrappedBlock types.WrappedBlock + if err := json.Unmarshal([]byte(v.Trace), &wrappedBlock); err != nil { + break + } + wrappedBlocks = append(wrappedBlocks, &wrappedBlock) + } + return wrappedBlocks, nil +} + +// GetL2BlockInfos get l2 block infos +func (o *BlockTrace) GetL2BlockInfos(fields map[string]interface{}, orderByList []string, limit int) ([]BlockTrace, error) { + var blockTraces []BlockTrace + db := o.db.Select("number, hash, parent_hash, batch_hash, tx_num, gas_used, block_timestamp") + for key, value := range fields { + db = db.Where(key, value) + } + + for _, orderBy := range orderByList { + db = db.Order(orderBy) + } + + if limit != 0 { + db = db.Limit(limit) + } + + if err := db.Find(&blockTraces).Error; err != nil { + return nil, err + } + return blockTraces, nil +} + +// GetUnbatchedL2Blocks get unbatched l2 blocks +func (o *BlockTrace) GetUnbatchedL2Blocks(fields map[string]interface{}, orderByList []string, limit int) ([]BlockTrace, error) { + var unbatchedBlockTraces []BlockTrace + db := o.db.Select("number, hash, parent_hash, batch_hash, tx_num, gas_used, block_timestamp").Where("batch_hash is NULL") + for key, value := range fields { + db = db.Where(key, value) + } + if err := db.Find(&unbatchedBlockTraces).Error; err != nil { + return nil, err + } + return unbatchedBlockTraces, nil +} + +// InsertWrappedBlocks insert block to block trace +func (o *BlockTrace) InsertWrappedBlocks(blocks []*types.WrappedBlock) error { + var blockTraces []BlockTrace + for _, block := range blocks { + number := block.Header.Number.Uint64() + hash := block.Header.Hash().String() + txNum := len(block.Transactions) + mtime := block.Header.Time + gasCost := block.Header.GasUsed + + data, err := json.Marshal(block) + if err != nil { + log.Error("failed to marshal block", "hash", hash, "err", err) + return err + } + + tmpBlockTrace := BlockTrace{ + Number: number, + Hash: hash, + ParentHash: block.Header.ParentHash.String(), + Trace: string(data), + TxNum: uint64(txNum), + GasUsed: gasCost, + BlockTimestamp: mtime, + } + blockTraces = append(blockTraces, tmpBlockTrace) + } + + if err := o.db.Create(&blockTraces).Error; err != nil { + log.Error("failed to insert blockTraces", "err", err) + return err + } + return nil +} + +// UpdateBatchHashForL2Blocks update the batch_hash of block trace +func (o *BlockTrace) UpdateBatchHashForL2Blocks(tx *gorm.DB, numbers []uint64, batchHash string) error { + var db *gorm.DB + if tx != nil { + db = tx + } else { + db = o.db + } + + err := db.Model(&BlockTrace{}).Where("number IN (?)", numbers).Update("batch_hash", batchHash).Error + if err != nil { + return err + } + return nil +} diff --git a/bridge/internal/orm/common.go b/bridge/internal/orm/common.go new file mode 100644 index 000000000..92f5ebdfb --- /dev/null +++ b/bridge/internal/orm/common.go @@ -0,0 +1,38 @@ +package orm + +import ( + "errors" + + "gorm.io/gorm" + + bridgeTypes "scroll-tech/bridge/internal/types" +) + +// AddBatchInfoToDB inserts the batch information to the BlockBatch table and updates the batch_hash +// in all blocks included in the batch. +func AddBatchInfoToDB(db *gorm.DB, batchData *bridgeTypes.BatchData) error { + blockBatch := NewBlockBatch(db) + blockTrace := NewBlockTrace(db) + err := db.Transaction(func(tx *gorm.DB) error { + rowsAffected, dbTxErr := blockBatch.InsertBlockBatchByBatchData(tx, batchData) + if dbTxErr != nil { + return dbTxErr + } + if rowsAffected != 1 { + dbTxErr = errors.New("the InsertBlockBatchByBatchData affected row is not 1") + return dbTxErr + } + + var blockIDs = make([]uint64, len(batchData.Batch.Blocks)) + for i, block := range batchData.Batch.Blocks { + blockIDs[i] = block.BlockNumber + } + + dbTxErr = blockTrace.UpdateBatchHashForL2Blocks(tx, blockIDs, batchData.Hash().Hex()) + if dbTxErr != nil { + return dbTxErr + } + return nil + }) + return err +} diff --git a/bridge/internal/orm/l1_block.go b/bridge/internal/orm/l1_block.go new file mode 100644 index 000000000..5a2e9b28a --- /dev/null +++ b/bridge/internal/orm/l1_block.go @@ -0,0 +1,87 @@ +package orm + +import ( + "context" + + "github.com/scroll-tech/go-ethereum/log" + "gorm.io/gorm" + + "scroll-tech/common/types" +) + +// L1Block is structure of stored l1 block message +type L1Block struct { + db *gorm.DB `gorm:"column:-"` + + Number uint64 `json:"number" gorm:"column:number"` + Hash string `json:"hash" gorm:"column:hash"` + HeaderRLP string `json:"header_rlp" gorm:"column:header_rlp"` + BaseFee uint64 `json:"base_fee" gorm:"column:base_fee"` + BlockStatus int `json:"block_status" gorm:"column:block_status;default:1"` + ImportTxHash string `json:"import_tx_hash" gorm:"column:import_tx_hash;default:NULL"` + GasOracleStatus int `json:"oracle_status" gorm:"column:oracle_status;default:1"` + OracleTxHash string `json:"oracle_tx_hash" gorm:"column:oracle_tx_hash;default:NULL"` +} + +// NewL1Block create an l1Block instance +func NewL1Block(db *gorm.DB) *L1Block { + return &L1Block{db: db} +} + +// TableName define the L1Block table name +func (*L1Block) TableName() string { + return "l1_block" +} + +// GetLatestL1BlockHeight get the latest l1 block height +func (l *L1Block) GetLatestL1BlockHeight() (uint64, error) { + result := l.db.Model(&L1Block{}).Select("COALESCE(MAX(number), 0)").Row() + if result.Err() != nil { + return 0, result.Err() + } + + var maxNumber uint64 + if err := result.Scan(&maxNumber); err != nil { + return 0, err + } + return maxNumber, nil +} + +// GetL1Blocks get the l1 blocks +func (l *L1Block) GetL1Blocks(fields map[string]interface{}) ([]L1Block, error) { + var l1Blocks []L1Block + db := l.db + for key, value := range fields { + db = db.Where(key, value) + } + db = db.Order("number ASC") + if err := db.Find(&l1Blocks).Error; err != nil { + return nil, err + } + return l1Blocks, nil +} + +// InsertL1Blocks batch insert l1 blocks +func (l *L1Block) InsertL1Blocks(ctx context.Context, blocks []L1Block) error { + if len(blocks) == 0 { + return nil + } + + err := l.db.WithContext(ctx).Create(&blocks).Error + if err != nil { + log.Error("failed to insert L1 Blocks", "err", err) + } + return err +} + +// UpdateL1GasOracleStatusAndOracleTxHash update l1 gas oracle status and oracle tx hash +func (l *L1Block) UpdateL1GasOracleStatusAndOracleTxHash(ctx context.Context, blockHash string, status types.GasOracleStatus, txHash string) error { + updateFields := map[string]interface{}{ + "oracle_status": int(status), + "oracle_tx_hash": txHash, + } + if err := l.db.WithContext(ctx).Model(&L1Block{}).Where("hash", blockHash).Updates(updateFields).Error; err != nil { + return err + } + return nil +} diff --git a/bridge/internal/orm/l1_message.go b/bridge/internal/orm/l1_message.go new file mode 100644 index 000000000..b40e23467 --- /dev/null +++ b/bridge/internal/orm/l1_message.go @@ -0,0 +1,124 @@ +package orm + +import ( + "context" + "database/sql" + + "github.com/scroll-tech/go-ethereum/log" + "gorm.io/gorm" + + "scroll-tech/common/types" +) + +// L1Message is structure of stored layer1 bridge message +type L1Message struct { + db *gorm.DB `gorm:"column:-"` + + QueueIndex uint64 `json:"queue_index" gorm:"column:queue_index"` + MsgHash string `json:"msg_hash" gorm:"column:msg_hash"` + Height uint64 `json:"height" gorm:"column:height"` + GasLimit uint64 `json:"gas_limit" gorm:"column:gas_limit"` + Sender string `json:"sender" gorm:"column:sender"` + Target string `json:"target" gorm:"column:target"` + Value string `json:"value" gorm:"column:value"` + Calldata string `json:"calldata" gorm:"column:calldata"` + Layer1Hash string `json:"layer1_hash" gorm:"column:layer1_hash"` + Layer2Hash string `json:"layer2_hash" gorm:"column:layer2_hash;default:NULL"` + Status int `json:"status" gorm:"column:status;default:1"` +} + +// NewL1Message create an L1MessageOrm instance +func NewL1Message(db *gorm.DB) *L1Message { + return &L1Message{db: db} +} + +// TableName define the L1Message table name +func (*L1Message) TableName() string { + return "l1_message" +} + +// GetLayer1LatestWatchedHeight returns latest height stored in the table +func (m *L1Message) GetLayer1LatestWatchedHeight() (int64, error) { + // @note It's not correct, since we may don't have message in some blocks. + // But it will only be called at start, some redundancy is acceptable. + var maxHeight sql.NullInt64 + result := m.db.Model(&L1Message{}).Select("MAX(height)").Scan(&maxHeight) + if result.Error != nil { + return -1, result.Error + } + if maxHeight.Valid { + return maxHeight.Int64, nil + } + return -1, nil +} + +// GetL1MessagesByStatus fetch list of unprocessed messages given msg status +func (m *L1Message) GetL1MessagesByStatus(status types.MsgStatus, limit uint64) ([]L1Message, error) { + var msgs []L1Message + err := m.db.Where("status", int(status)).Order("queue_index ASC").Limit(int(limit)).Find(&msgs).Error + if err != nil { + return nil, err + } + return msgs, nil +} + +// GetL1MessageByQueueIndex fetch message by queue_index +// for unit test +func (m *L1Message) GetL1MessageByQueueIndex(queueIndex uint64) (*L1Message, error) { + var msg L1Message + err := m.db.Where("queue_index", queueIndex).First(&msg).Error + if err != nil { + return nil, err + } + return &msg, nil +} + +// GetL1MessageByMsgHash fetch message by queue_index +// for unit test +func (m *L1Message) GetL1MessageByMsgHash(msgHash string) (*L1Message, error) { + var msg L1Message + err := m.db.Where("msg_hash", msgHash).First(&msg).Error + if err != nil { + return nil, err + } + return &msg, nil +} + +// SaveL1Messages batch save a list of layer1 messages +func (m *L1Message) SaveL1Messages(ctx context.Context, messages []*L1Message) error { + if len(messages) == 0 { + return nil + } + + err := m.db.WithContext(ctx).Create(&messages).Error + if err != nil { + queueIndices := make([]uint64, 0, len(messages)) + heights := make([]uint64, 0, len(messages)) + for _, msg := range messages { + queueIndices = append(queueIndices, msg.QueueIndex) + heights = append(heights, msg.Height) + } + log.Error("failed to insert l1Messages", "queueIndices", queueIndices, "heights", heights, "err", err) + } + return err +} + +// UpdateLayer1Status updates message stauts, given message hash +func (m *L1Message) UpdateLayer1Status(ctx context.Context, msgHash string, status types.MsgStatus) error { + if err := m.db.Model(&L1Message{}).WithContext(ctx).Where("msg_hash", msgHash).Update("status", int(status)).Error; err != nil { + return err + } + return nil +} + +// UpdateLayer1StatusAndLayer2Hash updates message status and layer2 transaction hash, given message hash +func (m *L1Message) UpdateLayer1StatusAndLayer2Hash(ctx context.Context, msgHash string, status types.MsgStatus, layer2Hash string) error { + updateFields := map[string]interface{}{ + "status": int(status), + "layer2_hash": layer2Hash, + } + if err := m.db.Model(&L1Message{}).WithContext(ctx).Where("msg_hash", msgHash).Updates(updateFields).Error; err != nil { + return err + } + return nil +} diff --git a/bridge/internal/orm/l2_message.go b/bridge/internal/orm/l2_message.go new file mode 100644 index 000000000..592426a45 --- /dev/null +++ b/bridge/internal/orm/l2_message.go @@ -0,0 +1,127 @@ +package orm + +import ( + "context" + + "github.com/scroll-tech/go-ethereum/log" + "gorm.io/gorm" + + "scroll-tech/common/types" +) + +// L2Message is structure of stored layer2 bridge message +type L2Message struct { + db *gorm.DB `gorm:"column:-"` + + Nonce uint64 `json:"nonce" gorm:"column:nonce"` + MsgHash string `json:"msg_hash" gorm:"column:msg_hash"` + Height uint64 `json:"height" gorm:"column:height"` + Sender string `json:"sender" gorm:"column:sender"` + Value string `json:"value" gorm:"column:value"` + Target string `json:"target" gorm:"column:target"` + Calldata string `json:"calldata" gorm:"column:calldata"` + Layer2Hash string `json:"layer2_hash" gorm:"column:layer2_hash"` + Layer1Hash string `json:"layer1_hash" gorm:"column:layer1_hash;default:NULL"` + Proof string `json:"proof" gorm:"column:proof;default:NULL"` + Status int `json:"status" gorm:"column:status;default:1"` +} + +// NewL2Message create an L2Message instance +func NewL2Message(db *gorm.DB) *L2Message { + return &L2Message{db: db} +} + +// TableName define the L2Message table name +func (*L2Message) TableName() string { + return "l2_message" +} + +// GetL2Messages fetch list of messages given msg status +func (m *L2Message) GetL2Messages(fields map[string]interface{}, orderByList []string, limit int) ([]L2Message, error) { + var l2MsgList []L2Message + db := m.db + for key, value := range fields { + db = db.Where(key, value) + } + + for _, orderBy := range orderByList { + db = db.Order(orderBy) + } + + if limit != 0 { + db = db.Limit(limit) + } + + if err := db.Find(&l2MsgList).Error; err != nil { + return nil, err + } + return l2MsgList, nil +} + +// GetLayer2LatestWatchedHeight returns latest height stored in the table +func (m *L2Message) GetLayer2LatestWatchedHeight() (int64, error) { + // @note It's not correct, since we may don't have message in some blocks. + // But it will only be called at start, some redundancy is acceptable. + result := m.db.Model(&L2Message{}).Select("COALESCE(MAX(height), -1)").Row() + if result.Err() != nil { + return -1, result.Err() + } + + var maxNumber int64 + if err := result.Scan(&maxNumber); err != nil { + return 0, err + } + return maxNumber, nil +} + +// GetL2MessageByNonce fetch message by nonce +// for unit test +func (m *L2Message) GetL2MessageByNonce(nonce uint64) (*L2Message, error) { + var msg L2Message + err := m.db.Where("nonce", nonce).First(&msg).Error + if err != nil { + return nil, err + } + return &msg, nil +} + +// SaveL2Messages batch save a list of layer2 messages +func (m *L2Message) SaveL2Messages(ctx context.Context, messages []L2Message) error { + if len(messages) == 0 { + return nil + } + + err := m.db.WithContext(ctx).Create(&messages).Error + if err != nil { + nonces := make([]uint64, 0, len(messages)) + heights := make([]uint64, 0, len(messages)) + for _, msg := range messages { + nonces = append(nonces, msg.Nonce) + heights = append(heights, msg.Height) + } + log.Error("failed to insert layer2Messages", "nonces", nonces, "heights", heights, "err", err) + } + return err +} + +// UpdateLayer2Status updates message stauts, given message hash +func (m *L2Message) UpdateLayer2Status(ctx context.Context, msgHash string, status types.MsgStatus) error { + err := m.db.Model(&L2Message{}).WithContext(ctx).Where("msg_hash", msgHash).Update("status", int(status)).Error + if err != nil { + return err + } + return nil +} + +// UpdateLayer2StatusAndLayer1Hash updates message stauts and layer1 transaction hash, given message hash +func (m *L2Message) UpdateLayer2StatusAndLayer1Hash(ctx context.Context, msgHash string, status types.MsgStatus, layer1Hash string) error { + updateFields := map[string]interface{}{ + "status": int(status), + "layer1_hash": layer1Hash, + } + err := m.db.Model(&L2Message{}).WithContext(ctx).Where("msg_hash", msgHash).Updates(updateFields).Error + if err != nil { + return err + } + return nil +} diff --git a/bridge/internal/orm/migrate/migrate.go b/bridge/internal/orm/migrate/migrate.go new file mode 100644 index 000000000..87d025593 --- /dev/null +++ b/bridge/internal/orm/migrate/migrate.go @@ -0,0 +1,61 @@ +package migrate + +import ( + "database/sql" + "embed" + "os" + "strconv" + + "github.com/pressly/goose/v3" +) + +//go:embed migrations/*.sql +var embedMigrations embed.FS + +// MigrationsDir migration dir +const MigrationsDir string = "migrations" + +func init() { + goose.SetBaseFS(embedMigrations) + goose.SetSequential(true) + goose.SetTableName("scroll_migrations") + + verbose, _ := strconv.ParseBool(os.Getenv("LOG_SQL_MIGRATIONS")) + goose.SetVerbose(verbose) +} + +// Migrate migrate db +func Migrate(db *sql.DB) error { + return goose.Up(db, MigrationsDir, goose.WithAllowMissing()) +} + +// Rollback rollback to the given version +func Rollback(db *sql.DB, version *int64) error { + if version != nil { + return goose.DownTo(db, MigrationsDir, *version) + } + return goose.Down(db, MigrationsDir) +} + +// ResetDB clean and migrate db. +func ResetDB(db *sql.DB) error { + if err := Rollback(db, new(int64)); err != nil { + return err + } + return Migrate(db) +} + +// Current get current version +func Current(db *sql.DB) (int64, error) { + return goose.GetDBVersion(db) +} + +// Status is normal or not +func Status(db *sql.DB) error { + return goose.Version(db, MigrationsDir) +} + +// Create a new migration folder +func Create(db *sql.DB, name, migrationType string) error { + return goose.Create(db, MigrationsDir, name, migrationType) +} diff --git a/bridge/internal/orm/migrate/migrate_test.go b/bridge/internal/orm/migrate/migrate_test.go new file mode 100644 index 000000000..8d40c92ec --- /dev/null +++ b/bridge/internal/orm/migrate/migrate_test.go @@ -0,0 +1,86 @@ +package migrate + +import ( + "testing" + + "github.com/jmoiron/sqlx" + _ "github.com/lib/pq" + "github.com/stretchr/testify/assert" + + "scroll-tech/common/docker" + + "scroll-tech/database" +) + +var ( + base *docker.App + pgDB *sqlx.DB +) + +func initEnv(t *testing.T) error { + // Start db container. + base.RunDBImage(t) + + // Create db orm handler. + factory, err := database.NewOrmFactory(base.DBConfig) + if err != nil { + return err + } + pgDB = factory.GetDB() + return nil +} + +func TestMigrate(t *testing.T) { + base = docker.NewDockerApp() + if err := initEnv(t); err != nil { + t.Fatal(err) + } + + t.Run("testCurrent", testCurrent) + t.Run("testStatus", testStatus) + t.Run("testResetDB", testResetDB) + t.Run("testMigrate", testMigrate) + t.Run("testRollback", testRollback) + + t.Cleanup(func() { + base.Free() + }) +} + +func testCurrent(t *testing.T) { + cur, err := Current(pgDB.DB) + assert.NoError(t, err) + assert.Equal(t, 0, int(cur)) +} + +func testStatus(t *testing.T) { + status := Status(pgDB.DB) + assert.NoError(t, status) +} + +func testResetDB(t *testing.T) { + assert.NoError(t, ResetDB(pgDB.DB)) + cur, err := Current(pgDB.DB) + assert.NoError(t, err) + // total number of tables. + assert.Equal(t, 5, int(cur)) +} + +func testMigrate(t *testing.T) { + assert.NoError(t, Migrate(pgDB.DB)) + cur, err := Current(pgDB.DB) + assert.NoError(t, err) + assert.Equal(t, true, cur > 0) +} + +func testRollback(t *testing.T) { + version, err := Current(pgDB.DB) + assert.NoError(t, err) + assert.Equal(t, true, version > 0) + + assert.NoError(t, Rollback(pgDB.DB, nil)) + + cur, err := Current(pgDB.DB) + assert.NoError(t, err) + assert.Equal(t, true, cur+1 == version) +} diff --git a/bridge/internal/orm/migrate/migrations/00001_block_trace.sql b/bridge/internal/orm/migrate/migrations/00001_block_trace.sql new file mode 100644 index 000000000..2b8fc4454 --- /dev/null +++ b/bridge/internal/orm/migrate/migrations/00001_block_trace.sql @@ -0,0 +1,38 @@ +-- +goose Up +-- +goose StatementBegin + +-- TODO: use foreign key for batch_id? +-- TODO: why tx_num is bigint? +create table block_trace +( + number BIGINT NOT NULL, + hash VARCHAR NOT NULL, + parent_hash VARCHAR NOT NULL, + trace JSON NOT NULL, + batch_hash VARCHAR DEFAULT NULL, + tx_num INTEGER NOT NULL, + gas_used BIGINT NOT NULL, + block_timestamp NUMERIC NOT NULL +); + +create unique index block_trace_hash_uindex + on block_trace (hash); + +create unique index block_trace_number_uindex + on block_trace (number); + +create unique index block_trace_parent_uindex + on block_trace (number, parent_hash); + +create unique index block_trace_parent_hash_uindex + on block_trace (hash, parent_hash); + +create index block_trace_batch_hash_index + on block_trace (batch_hash); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +drop table if exists block_trace; +-- +goose StatementEnd diff --git a/bridge/internal/orm/migrate/migrations/00002_l1_message.sql b/bridge/internal/orm/migrate/migrations/00002_l1_message.sql new file mode 100644 index 000000000..46e35a641 --- /dev/null +++ b/bridge/internal/orm/migrate/migrations/00002_l1_message.sql @@ -0,0 +1,50 @@ +-- +goose Up +-- +goose StatementBegin +create table l1_message +( + queue_index BIGINT NOT NULL, + msg_hash VARCHAR NOT NULL, + height BIGINT NOT NULL, + gas_limit BIGINT NOT NULL, + sender VARCHAR NOT NULL, + target VARCHAR NOT NULL, + value VARCHAR NOT NULL, + calldata TEXT NOT NULL, + layer1_hash VARCHAR NOT NULL, + layer2_hash VARCHAR DEFAULT NULL, + status INTEGER DEFAULT 1, + created_time TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_time TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +comment +on column l1_message.status is 'undefined, pending, submitted, confirmed, failed, expired, relay_failed'; + +create unique index l1_message_hash_uindex +on l1_message (msg_hash); + +create unique index l1_message_nonce_uindex +on l1_message (queue_index); + +create index l1_message_height_index + on l1_message (height); + +CREATE OR REPLACE FUNCTION update_timestamp() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_time = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ language 'plpgsql'; + +CREATE TRIGGER update_timestamp BEFORE UPDATE +ON l1_message FOR EACH ROW EXECUTE PROCEDURE +update_timestamp(); + + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +drop table if exists l1_message; +-- +goose StatementEnd \ No newline at end of file diff --git a/bridge/internal/orm/migrate/migrations/00003_l2_message.sql b/bridge/internal/orm/migrate/migrations/00003_l2_message.sql new file mode 100644 index 000000000..d1cedbff3 --- /dev/null +++ b/bridge/internal/orm/migrate/migrations/00003_l2_message.sql @@ -0,0 +1,50 @@ +-- +goose Up +-- +goose StatementBegin +create table l2_message +( + nonce BIGINT NOT NULL, + msg_hash VARCHAR NOT NULL, + height BIGINT NOT NULL, + sender VARCHAR NOT NULL, + target VARCHAR NOT NULL, + value VARCHAR NOT NULL, + calldata TEXT NOT NULL, + layer2_hash VARCHAR NOT NULL, + layer1_hash VARCHAR DEFAULT NULL, + proof TEXT DEFAULT NULL, + status INTEGER DEFAULT 1, + created_time TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_time TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +comment +on column l2_message.status is 'undefined, pending, submitted, confirmed, failed, expired, relay_failed'; + +create unique index l2_message_hash_uindex +on l2_message (msg_hash); + +create unique index l2_message_nonce_uindex +on l2_message (nonce); + +create index l2_message_height_index + on l2_message (height); + +CREATE OR REPLACE FUNCTION update_timestamp() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_time = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ language 'plpgsql'; + +CREATE TRIGGER update_timestamp BEFORE UPDATE +ON l2_message FOR EACH ROW EXECUTE PROCEDURE +update_timestamp(); + + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +drop table if exists l2_message; +-- +goose StatementEnd \ No newline at end of file diff --git a/bridge/internal/orm/migrate/migrations/00004_block_batch.sql b/bridge/internal/orm/migrate/migrations/00004_block_batch.sql new file mode 100644 index 000000000..bbc709489 --- /dev/null +++ b/bridge/internal/orm/migrate/migrations/00004_block_batch.sql @@ -0,0 +1,50 @@ +-- +goose Up +-- +goose StatementBegin + +create table block_batch +( + hash VARCHAR NOT NULL, + index BIGINT NOT NULL, + start_block_number BIGINT NOT NULL, + start_block_hash VARCHAR NOT NULL, + end_block_number BIGINT NOT NULL, + end_block_hash VARCHAR NOT NULL, + parent_hash VARCHAR NOT NULL, + state_root VARCHAR NOT NULL, + total_tx_num BIGINT NOT NULL, + total_l1_tx_num BIGINT NOT NULL, + total_l2_gas BIGINT NOT NULL, + proving_status INTEGER DEFAULT 1, + proof BYTEA DEFAULT NULL, + instance_commitments BYTEA DEFAULT NULL, + proof_time_sec INTEGER DEFAULT 0, + rollup_status INTEGER DEFAULT 1, + commit_tx_hash VARCHAR DEFAULT NULL, + finalize_tx_hash VARCHAR DEFAULT NULL, + oracle_status INTEGER DEFAULT 1, + oracle_tx_hash VARCHAR DEFAULT NULL, + created_at TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + prover_assigned_at TIMESTAMP(0) DEFAULT NULL, + proved_at TIMESTAMP(0) DEFAULT NULL, + committed_at TIMESTAMP(0) DEFAULT NULL, + finalized_at TIMESTAMP(0) DEFAULT NULL +); + +comment +on column block_batch.proving_status is 'undefined, unassigned, skipped, assigned, proved, verified, failed'; +comment +on column block_batch.rollup_status is 'undefined, pending, committing, committed, finalizing, finalized, finalization_skipped, commit_failed, finalize_failed'; +comment +on column block_batch.oracle_status is 'undefined, pending, importing, imported, failed'; + +create unique index block_batch_hash_uindex + on block_batch (hash); +create unique index block_batch_index_uindex + on block_batch (index); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +drop table if exists block_batch; +-- +goose StatementEnd diff --git a/bridge/internal/orm/migrate/migrations/00005_l1_block.sql b/bridge/internal/orm/migrate/migrations/00005_l1_block.sql new file mode 100644 index 000000000..a9a32f59e --- /dev/null +++ b/bridge/internal/orm/migrate/migrations/00005_l1_block.sql @@ -0,0 +1,33 @@ +-- +goose Up +-- +goose StatementBegin + +create table l1_block +( + number BIGINT NOT NULL, + hash VARCHAR NOT NULL, + header_rlp TEXT NOT NULL, + base_fee BIGINT NOT NULL, + block_status INTEGER DEFAULT 1, + import_tx_hash VARCHAR DEFAULT NULL, + oracle_status INTEGER DEFAULT 1, + oracle_tx_hash VARCHAR DEFAULT NULL +); + +comment +on column l1_block.block_status is 'undefined, pending, importing, imported, failed'; + +comment +on column l1_block.oracle_status is 'undefined, pending, importing, imported, failed'; + +create unique index l1_block_hash_uindex +on l1_block (hash); + +create unique index l1_block_number_uindex +on l1_block (number); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +drop table if exists l1_block; +-- +goose StatementEnd \ No newline at end of file diff --git a/bridge/internal/types/batch.go b/bridge/internal/types/batch.go new file mode 100644 index 000000000..d41300a0e --- /dev/null +++ b/bridge/internal/types/batch.go @@ -0,0 +1,236 @@ +package types + +import ( + "bufio" + "bytes" + "encoding/binary" + "math/big" + + "github.com/scroll-tech/go-ethereum/common" + "github.com/scroll-tech/go-ethereum/common/hexutil" + "github.com/scroll-tech/go-ethereum/core/types" + "github.com/scroll-tech/go-ethereum/crypto" + + abi "scroll-tech/bridge/abi" +) + +// PublicInputHashConfig is the configuration of how to compute the public input hash. +type PublicInputHashConfig struct { + MaxTxNum int `json:"max_tx_num"` + PaddingTxHash common.Hash `json:"padding_tx_hash"` +} + +const defaultMaxTxNum = 44 + +var defaultPaddingTxHash = [32]byte{} + +// BatchData contains info of batch to be committed. +type BatchData struct { + Batch abi.IScrollChainBatch + TxHashes []common.Hash + TotalTxNum uint64 + TotalL1TxNum uint64 + TotalL2Gas uint64 + + // cache for the BatchHash + hash *common.Hash + // The config to compute the public input hash, or the block hash. + // If it is nil, the hash calculation will use `defaultMaxTxNum` and `defaultPaddingTxHash`. + piCfg *PublicInputHashConfig +} + +// Timestamp returns the timestamp of the first block in the BlockData. +func (b *BatchData) Timestamp() uint64 { + if len(b.Batch.Blocks) == 0 { + return 0 + } + return b.Batch.Blocks[0].Timestamp +} + +// Hash calculates the hash of this batch. +func (b *BatchData) Hash() *common.Hash { + if b.hash != nil { + return b.hash + } + + buf := make([]byte, 8) + hasher := crypto.NewKeccakState() + + // 1. hash PrevStateRoot, NewStateRoot, WithdrawTrieRoot + // @todo: panic on error here. + _, _ = hasher.Write(b.Batch.PrevStateRoot[:]) + _, _ = hasher.Write(b.Batch.NewStateRoot[:]) + _, _ = hasher.Write(b.Batch.WithdrawTrieRoot[:]) + + // 2. hash all block contexts + for _, block := range b.Batch.Blocks { + // write BlockHash & ParentHash + _, _ = hasher.Write(block.BlockHash[:]) + _, _ = hasher.Write(block.ParentHash[:]) + // write BlockNumber + binary.BigEndian.PutUint64(buf, block.BlockNumber) + _, _ = hasher.Write(buf) + // write Timestamp + binary.BigEndian.PutUint64(buf, block.Timestamp) + _, _ = hasher.Write(buf) + // write BaseFee + var baseFee [32]byte + if block.BaseFee != nil { + baseFee = newByte32FromBytes(block.BaseFee.Bytes()) + } + _, _ = hasher.Write(baseFee[:]) + // write GasLimit + binary.BigEndian.PutUint64(buf, block.GasLimit) + _, _ = hasher.Write(buf) + // write NumTransactions + binary.BigEndian.PutUint16(buf[:2], block.NumTransactions) + _, _ = hasher.Write(buf[:2]) + // write NumL1Messages + binary.BigEndian.PutUint16(buf[:2], block.NumL1Messages) + _, _ = hasher.Write(buf[:2]) + } + + // 3. add all tx hashes + for _, txHash := range b.TxHashes { + _, _ = hasher.Write(txHash[:]) + } + + // 4. append empty tx hash up to MaxTxNum + maxTxNum := defaultMaxTxNum + paddingTxHash := common.Hash(defaultPaddingTxHash) + if b.piCfg != nil { + maxTxNum = b.piCfg.MaxTxNum + paddingTxHash = b.piCfg.PaddingTxHash + } + for i := len(b.TxHashes); i < maxTxNum; i++ { + _, _ = hasher.Write(paddingTxHash[:]) + } + + b.hash = new(common.Hash) + _, _ = hasher.Read(b.hash[:]) + + return b.hash +} + +// NewBatchData creates a BatchData given the parent batch information and the traces of the blocks +// included in this batch +func NewBatchData(parentBatch *BatchInfo, blocks []*WrappedBlock, piCfg *PublicInputHashConfig) *BatchData { + batchData := new(BatchData) + batch := &batchData.Batch + + // set BatchIndex, ParentBatchHash + batch.BatchIndex = parentBatch.Index + 1 + batch.ParentBatchHash = common.HexToHash(parentBatch.Hash) + batch.Blocks = make([]abi.IScrollChainBlockContext, len(blocks)) + + var batchTxDataBuf bytes.Buffer + batchTxDataWriter := bufio.NewWriter(&batchTxDataBuf) + + for i, block := range blocks { + batchData.TotalTxNum += uint64(len(block.Transactions)) + batchData.TotalL2Gas += block.Header.GasUsed + + // set baseFee to 0 when it's nil in the block header + baseFee := block.Header.BaseFee + if baseFee == nil { + baseFee = big.NewInt(0) + } + + batch.Blocks[i] = abi.IScrollChainBlockContext{ + BlockHash: block.Header.Hash(), + ParentHash: block.Header.ParentHash, + BlockNumber: block.Header.Number.Uint64(), + Timestamp: block.Header.Time, + BaseFee: baseFee, + GasLimit: block.Header.GasLimit, + NumTransactions: uint16(len(block.Transactions)), + NumL1Messages: 0, // TODO: currently use 0, will re-enable after we use l2geth to include L1 messages + } + + // fill in RLP-encoded transactions + for _, txData := range block.Transactions { + data, _ := hexutil.Decode(txData.Data) + // right now we only support legacy tx + tx := types.NewTx(&types.LegacyTx{ + Nonce: txData.Nonce, + To: txData.To, + Value: txData.Value.ToInt(), + Gas: txData.Gas, + GasPrice: txData.GasPrice.ToInt(), + Data: data, + V: txData.V.ToInt(), + R: txData.R.ToInt(), + S: txData.S.ToInt(), + }) + rlpTxData, _ := tx.MarshalBinary() + var txLen [4]byte + binary.BigEndian.PutUint32(txLen[:], uint32(len(rlpTxData))) + _, _ = batchTxDataWriter.Write(txLen[:]) + _, _ = batchTxDataWriter.Write(rlpTxData) + batchData.TxHashes = append(batchData.TxHashes, tx.Hash()) + } + + if i == 0 { + batch.PrevStateRoot = common.HexToHash(parentBatch.StateRoot) + } + + // set NewStateRoot & WithdrawTrieRoot from the last block + if i == len(blocks)-1 { + batch.NewStateRoot = block.Header.Root + batch.WithdrawTrieRoot = block.WithdrawTrieRoot + } + } + + if err := batchTxDataWriter.Flush(); err != nil { + panic("Buffered I/O flush failed") + } + + batch.L2Transactions = batchTxDataBuf.Bytes() + batchData.piCfg = piCfg + + return batchData +} + +// NewGenesisBatchData generates the batch that contains the genesis block. +func NewGenesisBatchData(genesisBlockTrace *WrappedBlock) *BatchData { + header := genesisBlockTrace.Header + if header.Number.Uint64() != 0 { + panic("invalid genesis block trace: block number is not 0") + } + + batchData := new(BatchData) + batch := &batchData.Batch + + // fill in batch information + batch.BatchIndex = 0 + batch.Blocks = make([]abi.IScrollChainBlockContext, 1) + batch.NewStateRoot = header.Root + // PrevStateRoot, WithdrawTrieRoot, ParentBatchHash should all be 0 + // L2Transactions should be empty + + // fill in block context + batch.Blocks[0] = abi.IScrollChainBlockContext{ + BlockHash: header.Hash(), + ParentHash: header.ParentHash, + BlockNumber: header.Number.Uint64(), + Timestamp: header.Time, + BaseFee: header.BaseFee, + GasLimit: header.GasLimit, + NumTransactions: 0, + NumL1Messages: 0, + } + + return batchData +} + +// newByte32FromBytes converts the bytes in big-endian encoding to 32 bytes in big-endian encoding +func newByte32FromBytes(b []byte) [32]byte { + var byte32 [32]byte + + if len(b) > 32 { + b = b[len(b)-32:] + } + + copy(byte32[32-len(b):], b) + return byte32 +} diff --git a/bridge/internal/types/batch_test.go b/bridge/internal/types/batch_test.go new file mode 100644 index 000000000..e423e5225 --- /dev/null +++ b/bridge/internal/types/batch_test.go @@ -0,0 +1,90 @@ +package types + +import ( + "math/big" + "testing" + + "github.com/scroll-tech/go-ethereum/common" + gethTypes "github.com/scroll-tech/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + + abi "scroll-tech/bridge/abi" +) + +func TestBatchHash(t *testing.T) { + txBytes := common.Hex2Bytes("02f8710582fd14808506e38dccc9825208944d496ccc28058b1d74b7a19541663e21154f9c848801561db11e24a43380c080a0d890606d7a35b2ab0f9b866d62c092d5b163f3e6a55537ae1485aac08c3f8ff7a023997be2d32f53e146b160fff0ba81e81dbb4491c865ab174d15c5b3d28c41ae") + tx := new(gethTypes.Transaction) + if err := tx.UnmarshalBinary(txBytes); err != nil { + t.Fatalf("invalid tx hex string: %s", err) + } + + batchData := new(BatchData) + batchData.TxHashes = append(batchData.TxHashes, tx.Hash()) + batchData.piCfg = &PublicInputHashConfig{ + MaxTxNum: 4, + PaddingTxHash: common.HexToHash("0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6"), + } + + batch := &batchData.Batch + batch.PrevStateRoot = common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000cafe") + + block := abi.IScrollChainBlockContext{ + BlockNumber: 51966, + Timestamp: 123456789, + BaseFee: new(big.Int).SetUint64(0), + GasLimit: 10000000000000000, + NumTransactions: 1, + NumL1Messages: 0, + } + batch.Blocks = append(batch.Blocks, block) + + hash := batchData.Hash() + assert.Equal(t, *hash, common.HexToHash("0xa9f2ca3175794f91226a410ba1e60fff07a405c957562675c4149b77e659d805")) + + // use a different tx hash + txBytes = common.Hex2Bytes("f8628001830f424094000000000000000000000000000000000000bbbb8080820a97a064e07cd8f939e2117724bdcbadc80dda421381cbc2a1f4e0d093d9cc5c5cf68ea03e264227f80852d88743cd9e43998f2746b619180366a87e4531debf9c3fa5dc") + tx = new(gethTypes.Transaction) + if err := tx.UnmarshalBinary(txBytes); err != nil { + t.Fatalf("invalid tx hex string: %s", err) + } + batchData.TxHashes[0] = tx.Hash() + + batchData.hash = nil // clear the cache + assert.Equal(t, *batchData.Hash(), common.HexToHash("0x398cb22bbfa1665c1b342b813267538a4c933d7f92d8bd9184aba0dd1122987b")) +} + +func TestNewGenesisBatch(t *testing.T) { + genesisBlock := &gethTypes.Header{ + UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), + Root: common.HexToHash("0x1b186a7a90ec3b41a2417062fe44dce8ce82ae76bfbb09eae786a4f1be1895f5"), + TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), + ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), + Difficulty: big.NewInt(1), + Number: big.NewInt(0), + GasLimit: 940000000, + GasUsed: 0, + Time: 1639724192, + Extra: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000214f8d488aa9ebf83e30bad45fb8f9c8ee2509f5511caff794753d07e9dfb218cfc233bb62d2c57022783094e1a7edb6f069f8424bb68496a0926b130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + BaseFee: big.NewInt(1000000000), + } + assert.Equal( + t, + genesisBlock.Hash().Hex(), + "0x92826bd3aad2ef70d8061dc4e25150b305d1233d9cd7579433a77d6eb01dae1c", + "wrong genesis block header", + ) + + blockTrace := &WrappedBlock{genesisBlock, nil, common.Hash{}} + batchData := NewGenesisBatchData(blockTrace) + t.Log(batchData.Batch.Blocks[0]) + batchData.piCfg = &PublicInputHashConfig{ + MaxTxNum: 25, + PaddingTxHash: common.HexToHash("0xb5baa665b2664c3bfed7eb46e00ebc110ecf2ebd257854a9bf2b9dbc9b2c08f6"), + } + assert.Equal( + t, + batchData.Hash().Hex(), + "0x65cf210e30f75cf8fd198df124255f73bc08d6324759e828a784fa938e7ac43d", + "wrong genesis batch hash", + ) +} diff --git a/bridge/internal/types/block.go b/bridge/internal/types/block.go new file mode 100644 index 000000000..78d417365 --- /dev/null +++ b/bridge/internal/types/block.go @@ -0,0 +1,21 @@ +package types + +import ( + "github.com/scroll-tech/go-ethereum/common" + "github.com/scroll-tech/go-ethereum/core/types" +) + +// WrappedBlock contains the block's Header, Transactions and WithdrawTrieRoot hash. +type WrappedBlock struct { + Header *types.Header `json:"header"` + // Transactions is only used for recover types.Transactions, the from of types.TransactionData field is missing. + Transactions []*types.TransactionData `json:"transactions"` + WithdrawTrieRoot common.Hash `json:"withdraw_trie_root,omitempty"` +} + +// BatchInfo contains the BlockBatch's main info +type BatchInfo struct { + Index uint64 `json:"index"` + Hash string `json:"hash"` + StateRoot string `json:"state_root"` +} diff --git a/bridge/internal/utils/confirmation.go b/bridge/internal/utils/confirmation.go new file mode 100644 index 000000000..db707d8b9 --- /dev/null +++ b/bridge/internal/utils/confirmation.go @@ -0,0 +1,56 @@ +package utils + +import ( + "context" + "fmt" + "math/big" + + "github.com/scroll-tech/go-ethereum/core/types" + "github.com/scroll-tech/go-ethereum/rpc" +) + +type ethClient interface { + BlockNumber(ctx context.Context) (uint64, error) + HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) +} + +// GetLatestConfirmedBlockNumber get confirmed block number by rpc.BlockNumber type. +func GetLatestConfirmedBlockNumber(ctx context.Context, client ethClient, confirm rpc.BlockNumber) (uint64, error) { + switch true { + case confirm == rpc.SafeBlockNumber || confirm == rpc.FinalizedBlockNumber: + var tag *big.Int + if confirm == rpc.FinalizedBlockNumber { + tag = big.NewInt(int64(rpc.FinalizedBlockNumber)) + } else { + tag = big.NewInt(int64(rpc.SafeBlockNumber)) + } + + header, err := client.HeaderByNumber(ctx, tag) + if err != nil { + return 0, err + } + if !header.Number.IsInt64() { + return 0, fmt.Errorf("received invalid block confirm: %v", header.Number) + } + return header.Number.Uint64(), nil + case confirm == rpc.LatestBlockNumber: + number, err := client.BlockNumber(ctx) + if err != nil { + return 0, err + } + return number, nil + case confirm.Int64() >= 0: // If it's positive integer, consider it as a certain confirm value. + number, err := client.BlockNumber(ctx) + if err != nil { + return 0, err + } + cfmNum := uint64(confirm.Int64()) + + if number >= cfmNum { + return number - cfmNum, nil + } + return 0, nil + default: + return 0, fmt.Errorf("unknown confirmation type: %v", confirm) + } +} diff --git a/bridge/internal/utils/confirmation_test.go b/bridge/internal/utils/confirmation_test.go new file mode 100644 index 000000000..961d0bd5d --- /dev/null +++ b/bridge/internal/utils/confirmation_test.go @@ -0,0 +1,134 @@ +package utils + +import ( + "context" + "encoding/json" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/scroll-tech/go-ethereum/common/math" + "github.com/scroll-tech/go-ethereum/core/types" + "github.com/scroll-tech/go-ethereum/rpc" +) + +var ( + tests = []struct { + input string + mustFail bool + expected rpc.BlockNumber + }{ + {`"0x"`, true, rpc.BlockNumber(0)}, + {`"0x0"`, false, rpc.BlockNumber(0)}, + {`"0X1"`, false, rpc.BlockNumber(1)}, + {`"0x00"`, true, rpc.BlockNumber(0)}, + {`"0x01"`, true, rpc.BlockNumber(0)}, + {`"0x1"`, false, rpc.BlockNumber(1)}, + {`"0x12"`, false, rpc.BlockNumber(18)}, + {`"0x7fffffffffffffff"`, false, rpc.BlockNumber(math.MaxInt64)}, + {`"0x8000000000000000"`, true, rpc.BlockNumber(0)}, + {"0", true, rpc.BlockNumber(0)}, + {`"ff"`, true, rpc.BlockNumber(0)}, + {`"safe"`, false, rpc.SafeBlockNumber}, + {`"finalized"`, false, rpc.FinalizedBlockNumber}, + {`"pending"`, false, rpc.PendingBlockNumber}, + {`"latest"`, false, rpc.LatestBlockNumber}, + {`"earliest"`, false, rpc.EarliestBlockNumber}, + {`someString`, true, rpc.BlockNumber(0)}, + {`""`, true, rpc.BlockNumber(0)}, + {``, true, rpc.BlockNumber(0)}, + } +) + +func TestUnmarshalJSON(t *testing.T) { + for i, test := range tests { + var num rpc.BlockNumber + err := json.Unmarshal([]byte(test.input), &num) + if test.mustFail && err == nil { + t.Errorf("Test %d should fail", i) + continue + } + if !test.mustFail && err != nil { + t.Errorf("Test %d should pass but got err: %v", i, err) + continue + } + if num != test.expected { + t.Errorf("Test %d got unexpected value, want %d, got %d", i, test.expected, num) + } + } +} + +func TestMarshalJSON(t *testing.T) { + for i, test := range tests { + var num rpc.BlockNumber + want, err := json.Marshal(test.expected) + assert.NoError(t, err) + if !test.mustFail { + err = json.Unmarshal([]byte(test.input), &num) + assert.NoError(t, err) + got, err := json.Marshal(&num) + assert.NoError(t, err) + if string(want) != string(got) { + t.Errorf("Test %d got unexpected value, want %d, got %d", i, test.expected, num) + } + } + } +} + +type MockEthClient struct { + val uint64 +} + +func (e MockEthClient) BlockNumber(ctx context.Context) (uint64, error) { + return e.val, nil +} + +func (e MockEthClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + var blockNumber int64 + switch number.Int64() { + case int64(rpc.LatestBlockNumber): + blockNumber = int64(e.val) + case int64(rpc.SafeBlockNumber): + blockNumber = int64(e.val) - 6 + case int64(rpc.FinalizedBlockNumber): + blockNumber = int64(e.val) - 12 + default: + blockNumber = number.Int64() + } + if blockNumber < 0 { + blockNumber = 0 + } + + return &types.Header{Number: new(big.Int).SetInt64(blockNumber)}, nil +} + +func TestGetLatestConfirmedBlockNumber(t *testing.T) { + ctx := context.Background() + client := MockEthClient{} + + testCases := []struct { + blockNumber uint64 + confirmation rpc.BlockNumber + expectedResult uint64 + }{ + {5, 6, 0}, + {7, 6, 1}, + {10, 2, 8}, + {0, 1, 0}, + {3, 0, 3}, + {15, 15, 0}, + {16, rpc.SafeBlockNumber, 10}, + {22, rpc.FinalizedBlockNumber, 10}, + {10, rpc.LatestBlockNumber, 10}, + {5, rpc.SafeBlockNumber, 0}, + {11, rpc.FinalizedBlockNumber, 0}, + } + + for _, testCase := range testCases { + client.val = testCase.blockNumber + confirmed, err := GetLatestConfirmedBlockNumber(ctx, &client, testCase.confirmation) + assert.NoError(t, err) + assert.Equal(t, testCase.expectedResult, confirmed) + } +} diff --git a/bridge/internal/utils/db.go b/bridge/internal/utils/db.go new file mode 100644 index 000000000..91c430906 --- /dev/null +++ b/bridge/internal/utils/db.go @@ -0,0 +1,43 @@ +package utils + +import ( + "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm.io/gorm/logger" + + "scroll-tech/bridge/internal/config" +) + +// InitDB init the db handler +func InitDB(config *config.DBConfig) (*gorm.DB, error) { + db, err := gorm.Open(postgres.Open(config.DSN), &gorm.Config{ + Logger: logger.Default.LogMode(logger.Info), + }) + if err != nil { + return nil, err + } + sqlDB, err := db.DB() + if err != nil { + return nil, err + } + + sqlDB.SetMaxOpenConns(config.MaxOpenNum) + sqlDB.SetMaxIdleConns(config.MaxIdleNum) + + if err = sqlDB.Ping(); err != nil { + return nil, err + } + return db, nil +} + +// CloseDB close the db handler. notice the db handler only can close when then program exit. +func CloseDB(db *gorm.DB) error { + sqlDB, err := db.DB() + if err != nil { + return err + } + if err := sqlDB.Close(); err != nil { + return err + } + return nil +} diff --git a/bridge/internal/utils/utils.go b/bridge/internal/utils/utils.go new file mode 100644 index 000000000..ba1cbd44f --- /dev/null +++ b/bridge/internal/utils/utils.go @@ -0,0 +1,65 @@ +package utils + +import ( + "fmt" + "math/big" + + "github.com/scroll-tech/go-ethereum/accounts/abi" + "github.com/scroll-tech/go-ethereum/common" + "github.com/scroll-tech/go-ethereum/core/types" + "github.com/scroll-tech/go-ethereum/crypto" + + bridgeAbi "scroll-tech/bridge/abi" +) + +// Keccak2 compute the keccack256 of two concatenations of bytes32 +func Keccak2(a common.Hash, b common.Hash) common.Hash { + return common.BytesToHash(crypto.Keccak256(append(a.Bytes()[:], b.Bytes()[:]...))) +} + +// ComputeMessageHash compute the message hash +func ComputeMessageHash( + sender common.Address, + target common.Address, + value *big.Int, + messageNonce *big.Int, + message []byte, +) common.Hash { + data, _ := bridgeAbi.L2ScrollMessengerABI.Pack("relayMessage", sender, target, value, messageNonce, message) + return common.BytesToHash(crypto.Keccak256(data)) +} + +// BufferToUint256Le convert bytes array to uint256 array assuming little-endian +func BufferToUint256Le(buffer []byte) []*big.Int { + buffer256 := make([]*big.Int, len(buffer)/32) + for i := 0; i < len(buffer)/32; i++ { + v := big.NewInt(0) + shft := big.NewInt(1) + for j := 0; j < 32; j++ { + v = new(big.Int).Add(v, new(big.Int).Mul(shft, big.NewInt(int64(buffer[i*32+j])))) + shft = new(big.Int).Mul(shft, big.NewInt(256)) + } + buffer256[i] = v + } + return buffer256 +} + +// UnpackLog unpacks a retrieved log into the provided output structure. +// @todo: add unit test. +func UnpackLog(c *abi.ABI, out interface{}, event string, log types.Log) error { + if log.Topics[0] != c.Events[event].ID { + return fmt.Errorf("event signature mismatch") + } + if len(log.Data) > 0 { + if err := c.UnpackIntoInterface(out, event, log.Data); err != nil { + return err + } + } + var indexed abi.Arguments + for _, arg := range c.Events[event].Inputs { + if arg.Indexed { + indexed = append(indexed, arg) + } + } + return abi.ParseTopics(out, indexed, log.Topics[1:]) +} diff --git a/bridge/internal/utils/utils_test.go b/bridge/internal/utils/utils_test.go new file mode 100644 index 000000000..b24958fac --- /dev/null +++ b/bridge/internal/utils/utils_test.go @@ -0,0 +1,49 @@ +package utils + +import ( + "math/big" + "testing" + + "github.com/scroll-tech/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +func TestKeccak2(t *testing.T) { + hash := Keccak2(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")) + if hash != common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5") { + t.Fatalf("Invalid keccak, want %s, got %s", "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", hash.Hex()) + } + + hash = Keccak2(common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5"), common.HexToHash("0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5")) + if hash != common.HexToHash("0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30") { + t.Fatalf("Invalid keccak, want %s, got %s", "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", hash.Hex()) + } + + hash = Keccak2(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000002")) + if hash != common.HexToHash("0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0") { + t.Fatalf("Invalid keccak, want %s, got %s", "0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0", hash.Hex()) + } +} + +func TestComputeMessageHash(t *testing.T) { + hash := ComputeMessageHash( + common.HexToAddress("0x1C5A77d9FA7eF466951B2F01F724BCa3A5820b63"), + common.HexToAddress("0x4592D8f8D7B001e72Cb26A73e4Fa1806a51aC79d"), + big.NewInt(0), + big.NewInt(1), + []byte("testbridgecontract"), + ) + assert.Equal(t, "0xda253c04595a49017bb54b1b46088c69752b5ad2f0c47971ac76b8b25abec202", hash.String()) +} + +func TestBufferToUint256Le(t *testing.T) { + input := []byte{ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + } + expectedOutput := []*big.Int{big.NewInt(1)} + result := BufferToUint256Le(input) + assert.Equal(t, expectedOutput, result) +} diff --git a/bridge/relayer/params.go b/bridge/relayer/params.go deleted file mode 100644 index 7feed613b..000000000 --- a/bridge/relayer/params.go +++ /dev/null @@ -1,11 +0,0 @@ -package relayer - -const ( - gasPriceDiffPrecision = 1000000 - - defaultGasPriceDiff = 50000 // 5% - - defaultL1MessageRelayMinGasLimit = 130000 // should be enough for both ERC20 and ETH relay - - defaultL2MessageRelayMinGasLimit = 200000 -) diff --git a/bridge/testdata/blockTrace_02.json b/bridge/testdata/blockTrace_02.json new file mode 100644 index 000000000..7e1a207f7 --- /dev/null +++ b/bridge/testdata/blockTrace_02.json @@ -0,0 +1,545 @@ +{ + "withdrawTrieRoot": "0x0000000000000000000000000000000000000000", + "coinbase": { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 2, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + "header": { + "parentHash": "0xe17f08d25ef61a8ee12aa29704b901345a597f5e45a9a0f603ae0f70845b54dc", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x25b792bfd6d6456451f996e9383225e026fff469da205bb916768c0a78fd16af", + "transactionsRoot": "0x3057754c197f33e1fe799e996db6232b5257412feea05b3c1754738f0b33fe32", + "receiptsRoot": "0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x2", + "number": "0x2", + "gasLimit": "0x355418d1e8184", + "gasUsed": "0xa410", + "timestamp": "0x63807b2a", + "extraData": "0xd983010a0d846765746889676f312e31372e3133856c696e75780000000000004b54a94f0df14333e63c8a13dfe6097c1a08b5fd2c225a8dc0f199dae245aead55d6f774a980a0c925be407748d56a14106afda7ddc1dec342e7ee3b0d58a8df01", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x1de9", + "hash": "0xc7b6c7022c8386cdaf6fcd3d4f8d03dce257ae3664a072fdce511ecefce73ad0" + }, + "transactions": [ + { + "type": 0, + "nonce": 0, + "txHash": "0xb2febc1213baec968f6575789108e175273b8da8f412468098893084229f1542", + "gas": 500000, + "gasPrice": "0x3b9aec2e", + "from": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "to": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2", + "chainId": "0xcf55", + "value": "0x152d02c7e14af6000000", + "data": "0x", + "isCreate": false, + "v": "0x19ece", + "r": "0xab07ae99c67aa78e7ba5cf6781e90cc32b219b1de102513d56548a41e86df514", + "s": "0x34cbd19feacd73e8ce64d00c4d1996b9b5243c578fd7f51bfaec288bbaf42a8b" + }, + { + "type": 0, + "nonce": 1, + "txHash": "0xe6ac2ffc543d07f1e280912a2abe3aa659bf83773740681151297ada1bb211dd", + "gas": 500000, + "gasPrice": "0x3b9aec2e", + "from": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "to": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed", + "chainId": "0xcf55", + "value": "0x152d02c7e14af6000000", + "data": "0x", + "isCreate": false, + "v": "0x19ece", + "r": "0xf039985866d8256f10c1be4f7b2cace28d8f20bde27e2604393eb095b7f77316", + "s": "0x5a3e6e81065f2b4604bcec5bd4aba684835996fc3f879380aac1c09c6eed32f1" + } + ], + "storageTrace": { + "rootBefore": "0x2579122e8f9ec1e862e7d415cef2fb495d7698a8e5f0dddc5651ba4236336e7d", + "rootAfter": "0x25b792bfd6d6456451f996e9383225e026fff469da205bb916768c0a78fd16af", + "proofs": { + "0x01bae6BF68E9A03Fb2bc0615b1bf0d69ce9411eD": [ + "0x01204920151d7e3cd9d1b5ba09d3ad6ea157c82d1cc425731f209e71a007165a9c0404000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000000201c5a77d9fa7ef466951b2f01f724bca3a5820b63000000000000000000000000", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ], + "0x1C5A77d9FA7eF466951B2F01F724BCa3A5820b63": [ + "0x01204920151d7e3cd9d1b5ba09d3ad6ea157c82d1cc425731f209e71a007165a9c0404000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000000201c5a77d9fa7ef466951b2f01f724bca3a5820b63000000000000000000000000", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ], + "0xc0c4C8bAEA3f6Acb49b6E1fb9e2ADEcEeaCB0cA2": [ + "0x01204920151d7e3cd9d1b5ba09d3ad6ea157c82d1cc425731f209e71a007165a9c0404000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000000201c5a77d9fa7ef466951b2f01f724bca3a5820b63000000000000000000000000", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ] + } + }, + "executionResults": [ + { + "gas": 21000, + "failed": false, + "returnValue": "", + "from": { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 0, + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + "to": { + "address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2", + "nonce": 0, + "balance": "0x0", + "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "accountAfter": [ + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 1, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffead2fd381eb5006a6eb8", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2", + "nonce": 0, + "balance": "0x152d02c7e14af6000000", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 1, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffead2fd381eb5006a6eb8", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "structLogs": [] + }, + { + "gas": 21000, + "failed": false, + "returnValue": "", + "from": { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 1, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffead2fd381eb5006a6eb8", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + "to": { + "address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed", + "nonce": 0, + "balance": "0x0", + "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "accountAfter": [ + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 2, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed", + "nonce": 0, + "balance": "0x152d02c7e14af6000000", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 2, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "structLogs": [] + } + ], + "mptwitness": [ + { + "address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed", + "accountKey": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0x7d6e333642ba5156dcddf0e5a898765d49fbf2ce15d4e762e8c19e8f2e127925", + "leaf": { + "value": "0xdf92dc6c0dd1c7fde78079ea62863977463f07e542966c6393f4d8cd6cce3117", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0x7d6e333642ba5156dcddf0e5a898765d49fbf2ce15d4e762e8c19e8f2e127925", + "leaf": { + "value": "0xdf92dc6c0dd1c7fde78079ea62863977463f07e542966c6393f4d8cd6cce3117", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + null, + null + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0x7d6e333642ba5156dcddf0e5a898765d49fbf2ce15d4e762e8c19e8f2e127925", + "leaf": { + "value": "0xdf92dc6c0dd1c7fde78079ea62863977463f07e542966c6393f4d8cd6cce3117", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c", + "leaf": { + "value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + { + "nonce": 0, + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "nonce": 2, + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2", + "accountKey": "0x9b38091c0e341793f0e755a1ea7b64bfb06455aced31334598fcfd02d1d94616", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c", + "leaf": { + "value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c", + "leaf": { + "value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + null, + null + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed", + "accountKey": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c", + "leaf": { + "value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c", + "leaf": { + "value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + null, + null + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0xf6b9a9f1e25add11bf5d0705e58f4b7a968b281ec23a8d41e719a0e27d87450c", + "leaf": { + "value": "0x716491d19f5e25dc565d05bbde1f30b343b1489b2d923feb30141d24a87c0a00", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806", + "leaf": { + "value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + { + "nonce": 2, + "balance": "0x200000000000000000000000000000000000000000000000000000000000000", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "nonce": 2, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2", + "accountKey": "0x9b38091c0e341793f0e755a1ea7b64bfb06455aced31334598fcfd02d1d94616", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806", + "leaf": { + "value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806", + "leaf": { + "value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + null, + null + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x01bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed", + "accountKey": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806", + "leaf": { + "value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x1", + "root": "0x06954857b2b6569c7dfe8380f8c7fe72d6b7fefca206b1fe74dc6ffbf97c132e", + "path": [ + { + "value": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b", + "sibling": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806" + } + ], + "leaf": { + "value": "0x45c70c4b7345dd1705ed019271dd1d7fbe2a1054ecefaf3fd2a22388a483072e", + "sibling": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314" + } + } + ], + "accountUpdate": [ + null, + { + "nonce": 0, + "balance": "0x152d02c7e14af6000000", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0x06954857b2b6569c7dfe8380f8c7fe72d6b7fefca206b1fe74dc6ffbf97c132e", + "path": [ + { + "value": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806", + "sibling": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b" + } + ], + "leaf": { + "value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0x06954857b2b6569c7dfe8380f8c7fe72d6b7fefca206b1fe74dc6ffbf97c132e", + "path": [ + { + "value": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806", + "sibling": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b" + } + ], + "leaf": { + "value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + { + "nonce": 2, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "nonce": 2, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0xc0c4c8baea3f6acb49b6e1fb9e2adeceeacb0ca2", + "accountKey": "0x9b38091c0e341793f0e755a1ea7b64bfb06455aced31334598fcfd02d1d94616", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0x06954857b2b6569c7dfe8380f8c7fe72d6b7fefca206b1fe74dc6ffbf97c132e", + "path": [ + { + "value": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b", + "sibling": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806" + } + ], + "leaf": { + "value": "0x45c70c4b7345dd1705ed019271dd1d7fbe2a1054ecefaf3fd2a22388a483072e", + "sibling": "0x7f53dc37d5a264eb72d8ae1a31c82239a385d9f6df23b81c48e97862d6d92314" + } + }, + { + "pathPart": "0x3", + "root": "0xaf16fd780a8c7616b95b20da69f4ff26e0253238e996f9516445d6d6bf92b725", + "path": [ + { + "value": "0x5bbe97e7e66485b203f9dfea64eb7fa7df06959b12cbde2beba14f8f91133a13", + "sibling": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806" + }, + { + "value": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x794953bb5d8aa00f90383ff435ce2ea58e30e1da1061e69455c38496766ec10f", + "sibling": "0x1b9da0b70b242af37d53f5bda27315b2dbd178f6b4b1e026be43cab8d46b850b" + } + ], + "leaf": { + "value": "0x45c70c4b7345dd1705ed019271dd1d7fbe2a1054ecefaf3fd2a22388a483072e", + "sibling": "0x9b38091c0e341793f0e755a1ea7b64bfb06455aced31334598fcfd02d1d94616" + } + } + ], + "accountUpdate": [ + null, + { + "nonce": 0, + "balance": "0x152d02c7e14af6000000", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + } + ] +} diff --git a/bridge/testdata/blockTrace_03.json b/bridge/testdata/blockTrace_03.json new file mode 100644 index 000000000..0939a8167 --- /dev/null +++ b/bridge/testdata/blockTrace_03.json @@ -0,0 +1,12877 @@ +{ + "withdrawTrieRoot": "0x0000000000000000000000000000000000000000", + "coinbase": { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 3, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d683461ce98", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + "header": { + "parentHash": "0xc7b6c7022c8386cdaf6fcd3d4f8d03dce257ae3664a072fdce511ecefce73ad0", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x0000000000000000000000000000000000000000", + "stateRoot": "0x26712be2a2a671df99555f95b601e2e907bd0276db5fb7d3cab35c061b39a91c", + "transactionsRoot": "0x6c4bdf11857e89cf8b34424d31be1db20974460a5b89dcf948adc88e743ebf3e", + "receiptsRoot": "0x3771127daa833dd70db4c01cd854543867176087a16b67154fa8b96a8549e97f", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x2", + "number": "0x3", + "gasLimit": "0x3546c3cbb39e5", + "gasUsed": "0x1197e2", + "timestamp": "0x63807b2d", + "extraData": "0xd983010a0d846765746889676f312e31372e3133856c696e75780000000000000b5467bbc3ca30260309add44eddd3242b6bbac2456e5f65df801113f5d39ad43089a888b7755db442cd6aa2b4a869bc657b219a2daf5927fce87cf47dcad48101", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "baseFeePerGas": "0x1a2c", + "hash": "0x13ddd94de9c585c50c6885d4ef649292c2624ae7c8fc73781ee8785f2564b44c" + }, + "transactions": [ + { + "type": 2, + "nonce": 2, + "txHash": "0xaaaeb971adfac989c7db5426737bc2932756091a5730ea6d5324f93e4cff9713", + "gas": 1152994, + "gasPrice": "0x3b9b0a17", + "from": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "to": null, + "chainId": "0xcf55", + "value": "0x0", + "data": "0x60806040523480156200001157600080fd5b50604051620014b2380380620014b2833981810160405260a08110156200003757600080fd5b815160208301516040808501805191519395929483019291846401000000008211156200006357600080fd5b9083019060208201858111156200007957600080fd5b82516401000000008111828201881017156200009457600080fd5b82525081516020918201929091019080838360005b83811015620000c3578181015183820152602001620000a9565b50505050905090810190601f168015620000f15780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200011557600080fd5b9083019060208201858111156200012b57600080fd5b82516401000000008111828201881017156200014657600080fd5b82525081516020918201929091019080838360005b83811015620001755781810151838201526020016200015b565b50505050905090810190601f168015620001a35780820380516001836020036101000a031916815260200191505b5060405260209081015185519093508592508491620001c8916003918501906200026b565b508051620001de9060049060208401906200026b565b50506005805461ff001960ff1990911660121716905550600680546001600160a01b038088166001600160a01b0319928316179092556007805492871692909116919091179055620002308162000255565b50506005805462010000600160b01b0319163362010000021790555062000307915050565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002ae57805160ff1916838001178555620002de565b82800160010185558215620002de579182015b82811115620002de578251825591602001919060010190620002c1565b50620002ec929150620002f0565b5090565b5b80821115620002ec5760008155600101620002f1565b61119b80620003176000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80635c975abb116100a257806395d89b411161007157806395d89b41146103015780639dc29fac14610309578063a457c2d714610335578063a9059cbb14610361578063dd62ed3e1461038d5761010b565b80635c975abb1461029d57806370a08231146102a55780638456cb59146102cb5780638e50817a146102d35761010b565b8063313ce567116100de578063313ce5671461021d578063395093511461023b5780633f4ba83a1461026757806340c10f19146102715761010b565b806306fdde0314610110578063095ea7b31461018d57806318160ddd146101cd57806323b872dd146101e7575b600080fd5b6101186103bb565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015257818101518382015260200161013a565b50505050905090810190601f16801561017f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101b9600480360360408110156101a357600080fd5b506001600160a01b038135169060200135610451565b604080519115158252519081900360200190f35b6101d561046e565b60408051918252519081900360200190f35b6101b9600480360360608110156101fd57600080fd5b506001600160a01b03813581169160208101359091169060400135610474565b6102256104fb565b6040805160ff9092168252519081900360200190f35b6101b96004803603604081101561025157600080fd5b506001600160a01b038135169060200135610504565b61026f610552565b005b61026f6004803603604081101561028757600080fd5b506001600160a01b0381351690602001356105a9565b6101b9610654565b6101d5600480360360208110156102bb57600080fd5b50356001600160a01b0316610662565b61026f61067d565b61026f600480360360408110156102e957600080fd5b506001600160a01b03813581169160200135166106d2565b610118610757565b61026f6004803603604081101561031f57600080fd5b506001600160a01b0381351690602001356107b8565b6101b96004803603604081101561034b57600080fd5b506001600160a01b03813516906020013561085f565b6101b96004803603604081101561037757600080fd5b506001600160a01b0381351690602001356108c7565b6101d5600480360360408110156103a357600080fd5b506001600160a01b03813581169160200135166108db565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104475780601f1061041c57610100808354040283529160200191610447565b820191906000526020600020905b81548152906001019060200180831161042a57829003601f168201915b5050505050905090565b600061046561045e610906565b848461090a565b50600192915050565b60025490565b60006104818484846109f6565b6104f18461048d610906565b6104ec85604051806060016040528060288152602001611085602891396001600160a01b038a166000908152600160205260408120906104cb610906565b6001600160a01b031681526020810191909152604001600020549190610b51565b61090a565b5060019392505050565b60055460ff1690565b6000610465610511610906565b846104ec8560016000610522610906565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610be8565b6007546001600160a01b0316331461059f576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6105a7610c49565b565b600554610100900460ff16156105f9576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6006546001600160a01b03163314610646576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6106508282610ced565b5050565b600554610100900460ff1690565b6001600160a01b031660009081526020819052604090205490565b6007546001600160a01b031633146106ca576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6105a7610ddd565b6005546201000090046001600160a01b03163314610726576040805162461bcd60e51b815260206004820152600c60248201526b6f6e6c7920466163746f727960a01b604482015290519081900360640190fd5b600780546001600160a01b039283166001600160a01b03199182161790915560068054939092169216919091179055565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104475780601f1061041c57610100808354040283529160200191610447565b600554610100900460ff1615610808576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6006546001600160a01b03163314610855576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6106508282610e65565b600061046561086c610906565b846104ec856040518060600160405280602581526020016111176025913960016000610896610906565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b51565b60006104656108d4610906565b84846109f6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3390565b6001600160a01b03831661094f5760405162461bcd60e51b81526004018080602001828103825260248152602001806110f36024913960400191505060405180910390fd5b6001600160a01b0382166109945760405162461bcd60e51b815260040180806020018281038252602281526020018061103d6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610a3b5760405162461bcd60e51b81526004018080602001828103825260258152602001806110ce6025913960400191505060405180910390fd5b6001600160a01b038216610a805760405162461bcd60e51b8152600401808060200182810382526023815260200180610ff86023913960400191505060405180910390fd5b610a8b838383610f61565b610ac88160405180606001604052806026815260200161105f602691396001600160a01b0386166000908152602081905260409020549190610b51565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610af79082610be8565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610ba5578181015183820152602001610b8d565b50505050905090810190601f168015610bd25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c42576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600554610100900460ff16610c9c576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b6005805461ff00191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610cd0610906565b604080516001600160a01b039092168252519081900360200190a1565b6001600160a01b038216610d48576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610d5460008383610f61565b600254610d619082610be8565b6002556001600160a01b038216600090815260208190526040902054610d879082610be8565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600554610100900460ff1615610e2d576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6005805461ff0019166101001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610cd0610906565b6001600160a01b038216610eaa5760405162461bcd60e51b81526004018080602001828103825260218152602001806110ad6021913960400191505060405180910390fd5b610eb682600083610f61565b610ef38160405180606001604052806022815260200161101b602291396001600160a01b0385166000908152602081905260409020549190610b51565b6001600160a01b038316600090815260208190526040902055600254610f199082610fb5565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b610f6c838383610fb0565b610f74610654565b15610fb05760405162461bcd60e51b815260040180806020018281038252602a81526020018061113c602a913960400191505060405180910390fd5b505050565b6000610c4283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610b5156fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f45524332305061757361626c653a20746f6b656e207472616e73666572207768696c6520706175736564a2646970667358221220e96342bec8f6c2bf72815a39998973b64c3bed57770f402e9a7b7eeda0265d4c64736f6c634300060c00330000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b630000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b6300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000095745544820636f696e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000", + "isCreate": true, + "v": "0x1", + "r": "0x235c1a8d40e8c347890397f1a92e6eadbd6422cf7c210e3e1737f0553c633172", + "s": "0x2f7c0384ddd06970446e74229cd96216da62196dc62395bda52095d44b8a9af7" + } + ], + "storageTrace": { + "rootBefore": "0x25b792bfd6d6456451f996e9383225e026fff469da205bb916768c0a78fd16af", + "rootAfter": "0x26712be2a2a671df99555f95b601e2e907bd0276db5fb7d3cab35c061b39a91c", + "proofs": { + "0x03F8133DD5Ed58838B20AF1296F62F44e69bAa48": [ + "0x0006e87db4b9b3a22a55eaec059b5896ca15c93c227708181cab416887090cf234133a13918f4fa1eb2bdecb129b9506dfa77feb64eadff903b28564e6e797be5b", + "0x00000000000000000000000000000000000000000000000000000000000000000002cf0e006d7e01c8f6a13d46d695bdfd24a7e1a494ad357c11b32ab05713592e", + "0x02", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ], + "0x1C5A77d9FA7eF466951B2F01F724BCa3A5820b63": [ + "0x0006e87db4b9b3a22a55eaec059b5896ca15c93c227708181cab416887090cf234133a13918f4fa1eb2bdecb129b9506dfa77feb64eadff903b28564e6e797be5b", + "0x01204920151d7e3cd9d1b5ba09d3ad6ea157c82d1cc425731f209e71a007165a9c04040000000000000000000000000000000000000000000000000000000000000000000201ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700000000000000000000000000000000000000000000000000000000000000000201c5a77d9fa7ef466951b2f01f724bca3a5820b63000000000000000000000000", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ] + }, + "storageProofs": { + "0x03F8133DD5Ed58838B20AF1296F62F44e69bAa48": { + "0x0000000000000000000000000000000000000000000000000000000000000003": [ + "0x02", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ], + "0x0000000000000000000000000000000000000000000000000000000000000004": [ + "0x02", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ], + "0x0000000000000000000000000000000000000000000000000000000000000005": [ + "0x02", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ], + "0x0000000000000000000000000000000000000000000000000000000000000006": [ + "0x02", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ], + "0x0000000000000000000000000000000000000000000000000000000000000007": [ + "0x02", + "0x5448495320495320534f4d45204d4147494320425954455320464f5220534d54206d3172525867503278704449" + ] + } + } + }, + "executionResults": [ + { + "gas": 1152994, + "failed": false, + "returnValue": "608060405234801561001057600080fd5b506004361061010b5760003560e01c80635c975abb116100a257806395d89b411161007157806395d89b41146103015780639dc29fac14610309578063a457c2d714610335578063a9059cbb14610361578063dd62ed3e1461038d5761010b565b80635c975abb1461029d57806370a08231146102a55780638456cb59146102cb5780638e50817a146102d35761010b565b8063313ce567116100de578063313ce5671461021d578063395093511461023b5780633f4ba83a1461026757806340c10f19146102715761010b565b806306fdde0314610110578063095ea7b31461018d57806318160ddd146101cd57806323b872dd146101e7575b600080fd5b6101186103bb565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015257818101518382015260200161013a565b50505050905090810190601f16801561017f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101b9600480360360408110156101a357600080fd5b506001600160a01b038135169060200135610451565b604080519115158252519081900360200190f35b6101d561046e565b60408051918252519081900360200190f35b6101b9600480360360608110156101fd57600080fd5b506001600160a01b03813581169160208101359091169060400135610474565b6102256104fb565b6040805160ff9092168252519081900360200190f35b6101b96004803603604081101561025157600080fd5b506001600160a01b038135169060200135610504565b61026f610552565b005b61026f6004803603604081101561028757600080fd5b506001600160a01b0381351690602001356105a9565b6101b9610654565b6101d5600480360360208110156102bb57600080fd5b50356001600160a01b0316610662565b61026f61067d565b61026f600480360360408110156102e957600080fd5b506001600160a01b03813581169160200135166106d2565b610118610757565b61026f6004803603604081101561031f57600080fd5b506001600160a01b0381351690602001356107b8565b6101b96004803603604081101561034b57600080fd5b506001600160a01b03813516906020013561085f565b6101b96004803603604081101561037757600080fd5b506001600160a01b0381351690602001356108c7565b6101d5600480360360408110156103a357600080fd5b506001600160a01b03813581169160200135166108db565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104475780601f1061041c57610100808354040283529160200191610447565b820191906000526020600020905b81548152906001019060200180831161042a57829003601f168201915b5050505050905090565b600061046561045e610906565b848461090a565b50600192915050565b60025490565b60006104818484846109f6565b6104f18461048d610906565b6104ec85604051806060016040528060288152602001611085602891396001600160a01b038a166000908152600160205260408120906104cb610906565b6001600160a01b031681526020810191909152604001600020549190610b51565b61090a565b5060019392505050565b60055460ff1690565b6000610465610511610906565b846104ec8560016000610522610906565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610be8565b6007546001600160a01b0316331461059f576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6105a7610c49565b565b600554610100900460ff16156105f9576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6006546001600160a01b03163314610646576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6106508282610ced565b5050565b600554610100900460ff1690565b6001600160a01b031660009081526020819052604090205490565b6007546001600160a01b031633146106ca576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6105a7610ddd565b6005546201000090046001600160a01b03163314610726576040805162461bcd60e51b815260206004820152600c60248201526b6f6e6c7920466163746f727960a01b604482015290519081900360640190fd5b600780546001600160a01b039283166001600160a01b03199182161790915560068054939092169216919091179055565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104475780601f1061041c57610100808354040283529160200191610447565b600554610100900460ff1615610808576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6006546001600160a01b03163314610855576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6106508282610e65565b600061046561086c610906565b846104ec856040518060600160405280602581526020016111176025913960016000610896610906565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b51565b60006104656108d4610906565b84846109f6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3390565b6001600160a01b03831661094f5760405162461bcd60e51b81526004018080602001828103825260248152602001806110f36024913960400191505060405180910390fd5b6001600160a01b0382166109945760405162461bcd60e51b815260040180806020018281038252602281526020018061103d6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610a3b5760405162461bcd60e51b81526004018080602001828103825260258152602001806110ce6025913960400191505060405180910390fd5b6001600160a01b038216610a805760405162461bcd60e51b8152600401808060200182810382526023815260200180610ff86023913960400191505060405180910390fd5b610a8b838383610f61565b610ac88160405180606001604052806026815260200161105f602691396001600160a01b0386166000908152602081905260409020549190610b51565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610af79082610be8565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610ba5578181015183820152602001610b8d565b50505050905090810190601f168015610bd25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c42576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600554610100900460ff16610c9c576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b6005805461ff00191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610cd0610906565b604080516001600160a01b039092168252519081900360200190a1565b6001600160a01b038216610d48576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610d5460008383610f61565b600254610d619082610be8565b6002556001600160a01b038216600090815260208190526040902054610d879082610be8565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600554610100900460ff1615610e2d576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6005805461ff0019166101001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610cd0610906565b6001600160a01b038216610eaa5760405162461bcd60e51b81526004018080602001828103825260218152602001806110ad6021913960400191505060405180910390fd5b610eb682600083610f61565b610ef38160405180606001604052806022815260200161101b602291396001600160a01b0385166000908152602081905260409020549190610b51565b6001600160a01b038316600090815260208190526040902055600254610f199082610fb5565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b610f6c838383610fb0565b610f74610654565b15610fb05760405162461bcd60e51b815260040180806020018281038252602a81526020018061113c602a913960400191505060405180910390fd5b505050565b6000610c4283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610b5156fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f45524332305061757361626c653a20746f6b656e207472616e73666572207768696c6520706175736564a2646970667358221220e96342bec8f6c2bf72815a39998973b64c3bed57770f402e9a7b7eeda0265d4c64736f6c634300060c0033", + "from": { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 2, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + "accountCreated": { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "accountAfter": [ + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 3, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d683461ce98", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "nonce": 3, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d683461ce98", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "byteCode": "0x60806040523480156200001157600080fd5b50604051620014b2380380620014b2833981810160405260a08110156200003757600080fd5b815160208301516040808501805191519395929483019291846401000000008211156200006357600080fd5b9083019060208201858111156200007957600080fd5b82516401000000008111828201881017156200009457600080fd5b82525081516020918201929091019080838360005b83811015620000c3578181015183820152602001620000a9565b50505050905090810190601f168015620000f15780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200011557600080fd5b9083019060208201858111156200012b57600080fd5b82516401000000008111828201881017156200014657600080fd5b82525081516020918201929091019080838360005b83811015620001755781810151838201526020016200015b565b50505050905090810190601f168015620001a35780820380516001836020036101000a031916815260200191505b5060405260209081015185519093508592508491620001c8916003918501906200026b565b508051620001de9060049060208401906200026b565b50506005805461ff001960ff1990911660121716905550600680546001600160a01b038088166001600160a01b0319928316179092556007805492871692909116919091179055620002308162000255565b50506005805462010000600160b01b0319163362010000021790555062000307915050565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002ae57805160ff1916838001178555620002de565b82800160010185558215620002de579182015b82811115620002de578251825591602001919060010190620002c1565b50620002ec929150620002f0565b5090565b5b80821115620002ec5760008155600101620002f1565b61119b80620003176000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80635c975abb116100a257806395d89b411161007157806395d89b41146103015780639dc29fac14610309578063a457c2d714610335578063a9059cbb14610361578063dd62ed3e1461038d5761010b565b80635c975abb1461029d57806370a08231146102a55780638456cb59146102cb5780638e50817a146102d35761010b565b8063313ce567116100de578063313ce5671461021d578063395093511461023b5780633f4ba83a1461026757806340c10f19146102715761010b565b806306fdde0314610110578063095ea7b31461018d57806318160ddd146101cd57806323b872dd146101e7575b600080fd5b6101186103bb565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015257818101518382015260200161013a565b50505050905090810190601f16801561017f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101b9600480360360408110156101a357600080fd5b506001600160a01b038135169060200135610451565b604080519115158252519081900360200190f35b6101d561046e565b60408051918252519081900360200190f35b6101b9600480360360608110156101fd57600080fd5b506001600160a01b03813581169160208101359091169060400135610474565b6102256104fb565b6040805160ff9092168252519081900360200190f35b6101b96004803603604081101561025157600080fd5b506001600160a01b038135169060200135610504565b61026f610552565b005b61026f6004803603604081101561028757600080fd5b506001600160a01b0381351690602001356105a9565b6101b9610654565b6101d5600480360360208110156102bb57600080fd5b50356001600160a01b0316610662565b61026f61067d565b61026f600480360360408110156102e957600080fd5b506001600160a01b03813581169160200135166106d2565b610118610757565b61026f6004803603604081101561031f57600080fd5b506001600160a01b0381351690602001356107b8565b6101b96004803603604081101561034b57600080fd5b506001600160a01b03813516906020013561085f565b6101b96004803603604081101561037757600080fd5b506001600160a01b0381351690602001356108c7565b6101d5600480360360408110156103a357600080fd5b506001600160a01b03813581169160200135166108db565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104475780601f1061041c57610100808354040283529160200191610447565b820191906000526020600020905b81548152906001019060200180831161042a57829003601f168201915b5050505050905090565b600061046561045e610906565b848461090a565b50600192915050565b60025490565b60006104818484846109f6565b6104f18461048d610906565b6104ec85604051806060016040528060288152602001611085602891396001600160a01b038a166000908152600160205260408120906104cb610906565b6001600160a01b031681526020810191909152604001600020549190610b51565b61090a565b5060019392505050565b60055460ff1690565b6000610465610511610906565b846104ec8560016000610522610906565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490610be8565b6007546001600160a01b0316331461059f576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6105a7610c49565b565b600554610100900460ff16156105f9576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6006546001600160a01b03163314610646576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6106508282610ced565b5050565b600554610100900460ff1690565b6001600160a01b031660009081526020819052604090205490565b6007546001600160a01b031633146106ca576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6105a7610ddd565b6005546201000090046001600160a01b03163314610726576040805162461bcd60e51b815260206004820152600c60248201526b6f6e6c7920466163746f727960a01b604482015290519081900360640190fd5b600780546001600160a01b039283166001600160a01b03199182161790915560068054939092169216919091179055565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104475780601f1061041c57610100808354040283529160200191610447565b600554610100900460ff1615610808576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6006546001600160a01b03163314610855576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6106508282610e65565b600061046561086c610906565b846104ec856040518060600160405280602581526020016111176025913960016000610896610906565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190610b51565b60006104656108d4610906565b84846109f6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b3390565b6001600160a01b03831661094f5760405162461bcd60e51b81526004018080602001828103825260248152602001806110f36024913960400191505060405180910390fd5b6001600160a01b0382166109945760405162461bcd60e51b815260040180806020018281038252602281526020018061103d6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316610a3b5760405162461bcd60e51b81526004018080602001828103825260258152602001806110ce6025913960400191505060405180910390fd5b6001600160a01b038216610a805760405162461bcd60e51b8152600401808060200182810382526023815260200180610ff86023913960400191505060405180910390fd5b610a8b838383610f61565b610ac88160405180606001604052806026815260200161105f602691396001600160a01b0386166000908152602081905260409020549190610b51565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610af79082610be8565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115610be05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610ba5578181015183820152602001610b8d565b50505050905090810190601f168015610bd25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610c42576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600554610100900460ff16610c9c576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b6005805461ff00191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610cd0610906565b604080516001600160a01b039092168252519081900360200190a1565b6001600160a01b038216610d48576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b610d5460008383610f61565b600254610d619082610be8565b6002556001600160a01b038216600090815260208190526040902054610d879082610be8565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600554610100900460ff1615610e2d576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6005805461ff0019166101001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610cd0610906565b6001600160a01b038216610eaa5760405162461bcd60e51b81526004018080602001828103825260218152602001806110ad6021913960400191505060405180910390fd5b610eb682600083610f61565b610ef38160405180606001604052806022815260200161101b602291396001600160a01b0385166000908152602081905260409020549190610b51565b6001600160a01b038316600090815260208190526040902055600254610f199082610fb5565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b610f6c838383610fb0565b610f74610654565b15610fb05760405162461bcd60e51b815260040180806020018281038252602a81526020018061113c602a913960400191505060405180910390fd5b505050565b6000610c4283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610b5156fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726f45524332305061757361626c653a20746f6b656e207472616e73666572207768696c6520706175736564a2646970667358221220e96342bec8f6c2bf72815a39998973b64c3bed57770f402e9a7b7eeda0265d4c64736f6c634300060c00330000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b630000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b6300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000095745544820636f696e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000", + "structLogs": [ + { + "pc": 0, + "op": "PUSH1", + "gas": 1015274, + "gasCost": 3, + "depth": 1 + }, + { + "pc": 2, + "op": "PUSH1", + "gas": 1015271, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80" + ] + }, + { + "pc": 4, + "op": "MSTORE", + "gas": 1015268, + "gasCost": 12, + "depth": 1, + "stack": [ + "0x80", + "0x40" + ] + }, + { + "pc": 5, + "op": "CALLVALUE", + "gas": 1015256, + "gasCost": 2, + "depth": 1 + }, + { + "pc": 6, + "op": "DUP1", + "gas": 1015254, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x0" + ] + }, + { + "pc": 7, + "op": "ISZERO", + "gas": 1015251, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x0", + "0x0" + ] + }, + { + "pc": 8, + "op": "PUSH3", + "gas": 1015248, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x0", + "0x1" + ] + }, + { + "pc": 12, + "op": "JUMPI", + "gas": 1015245, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x0", + "0x1", + "0x11" + ] + }, + { + "pc": 17, + "op": "JUMPDEST", + "gas": 1015235, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x0" + ] + }, + { + "pc": 18, + "op": "POP", + "gas": 1015234, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x0" + ] + }, + { + "pc": 19, + "op": "PUSH1", + "gas": 1015232, + "gasCost": 3, + "depth": 1 + }, + { + "pc": 21, + "op": "MLOAD", + "gas": 1015229, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x40" + ] + }, + { + "pc": 22, + "op": "PUSH3", + "gas": 1015226, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80" + ] + }, + { + "pc": 26, + "op": "CODESIZE", + "gas": 1015223, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x80", + "0x14b2" + ], + "extraData": { + "codeList": [ + "0x" + ] + } + }, + { + "pc": 27, + "op": "SUB", + "gas": 1015221, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x14b2", + "0x15d2" + ] + }, + { + "pc": 28, + "op": "DUP1", + "gas": 1015218, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120" + ] + }, + { + "pc": 29, + "op": "PUSH3", + "gas": 1015215, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x120" + ] + }, + { + "pc": 33, + "op": "DUP4", + "gas": 1015212, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x120", + "0x14b2" + ] + }, + { + "pc": 34, + "op": "CODECOPY", + "gas": 1015209, + "gasCost": 60, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x120", + "0x14b2", + "0x80" + ], + "extraData": { + "codeList": [ + "0x" + ] + } + }, + { + "pc": 35, + "op": "DUP2", + "gas": 1015149, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120" + ] + }, + { + "pc": 36, + "op": "DUP2", + "gas": 1015146, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x80" + ] + }, + { + "pc": 37, + "op": "ADD", + "gas": 1015143, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x80", + "0x120" + ] + }, + { + "pc": 38, + "op": "PUSH1", + "gas": 1015140, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1a0" + ] + }, + { + "pc": 40, + "op": "MSTORE", + "gas": 1015137, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1a0", + "0x40" + ] + }, + { + "pc": 41, + "op": "PUSH1", + "gas": 1015134, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120" + ] + }, + { + "pc": 43, + "op": "DUP2", + "gas": 1015131, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0xa0" + ] + }, + { + "pc": 44, + "op": "LT", + "gas": 1015128, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0xa0", + "0x120" + ] + }, + { + "pc": 45, + "op": "ISZERO", + "gas": 1015125, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x0" + ] + }, + { + "pc": 46, + "op": "PUSH3", + "gas": 1015122, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1" + ] + }, + { + "pc": 50, + "op": "JUMPI", + "gas": 1015119, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1", + "0x37" + ] + }, + { + "pc": 55, + "op": "JUMPDEST", + "gas": 1015109, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x80", + "0x120" + ] + }, + { + "pc": 56, + "op": "DUP2", + "gas": 1015108, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120" + ] + }, + { + "pc": 57, + "op": "MLOAD", + "gas": 1015105, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x80" + ] + }, + { + "pc": 58, + "op": "PUSH1", + "gas": 1015102, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 60, + "op": "DUP4", + "gas": 1015099, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x20" + ] + }, + { + "pc": 61, + "op": "ADD", + "gas": 1015096, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x20", + "0x80" + ] + }, + { + "pc": 62, + "op": "MLOAD", + "gas": 1015093, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xa0" + ] + }, + { + "pc": 63, + "op": "PUSH1", + "gas": 1015090, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 65, + "op": "DUP1", + "gas": 1015087, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x40" + ] + }, + { + "pc": 66, + "op": "DUP6", + "gas": 1015084, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x40", + "0x40" + ] + }, + { + "pc": 67, + "op": "ADD", + "gas": 1015081, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x40", + "0x40", + "0x80" + ] + }, + { + "pc": 68, + "op": "DUP1", + "gas": 1015078, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x40", + "0xc0" + ] + }, + { + "pc": 69, + "op": "MLOAD", + "gas": 1015075, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x40", + "0xc0", + "0xc0" + ] + }, + { + "pc": 70, + "op": "SWAP2", + "gas": 1015072, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x40", + "0xc0", + "0xa0" + ] + }, + { + "pc": 71, + "op": "MLOAD", + "gas": 1015069, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xa0", + "0xc0", + "0x40" + ] + }, + { + "pc": 72, + "op": "SWAP4", + "gas": 1015066, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xa0", + "0xc0", + "0x1a0" + ] + }, + { + "pc": 73, + "op": "SWAP6", + "gas": 1015063, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x80", + "0x120", + "0x1a0", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xa0", + "0xc0", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 74, + "op": "SWAP3", + "gas": 1015060, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x120", + "0x1a0", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xa0", + "0xc0", + "0x80" + ] + }, + { + "pc": 75, + "op": "SWAP5", + "gas": 1015057, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x120", + "0x1a0", + "0x80", + "0xa0", + "0xc0", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 76, + "op": "DUP4", + "gas": 1015054, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x80", + "0xa0", + "0xc0", + "0x120" + ] + }, + { + "pc": 77, + "op": "ADD", + "gas": 1015051, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x80", + "0xa0", + "0xc0", + "0x120", + "0x80" + ] + }, + { + "pc": 78, + "op": "SWAP3", + "gas": 1015048, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x80", + "0xa0", + "0xc0", + "0x1a0" + ] + }, + { + "pc": 79, + "op": "SWAP2", + "gas": 1015045, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0xa0", + "0xc0", + "0x80" + ] + }, + { + "pc": 80, + "op": "DUP5", + "gas": 1015042, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0" + ] + }, + { + "pc": 81, + "op": "PUSH5", + "gas": 1015039, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0", + "0x1a0" + ] + }, + { + "pc": 87, + "op": "DUP3", + "gas": 1015036, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0", + "0x1a0", + "0x100000000" + ] + }, + { + "pc": 88, + "op": "GT", + "gas": 1015033, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0", + "0x1a0", + "0x100000000", + "0xa0" + ] + }, + { + "pc": 89, + "op": "ISZERO", + "gas": 1015030, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0", + "0x1a0", + "0x0" + ] + }, + { + "pc": 90, + "op": "PUSH3", + "gas": 1015027, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0", + "0x1a0", + "0x1" + ] + }, + { + "pc": 94, + "op": "JUMPI", + "gas": 1015024, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0", + "0x1a0", + "0x1", + "0x63" + ] + }, + { + "pc": 99, + "op": "JUMPDEST", + "gas": 1015014, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0", + "0x1a0" + ] + }, + { + "pc": 100, + "op": "SWAP1", + "gas": 1015013, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0xa0", + "0x1a0" + ] + }, + { + "pc": 101, + "op": "DUP4", + "gas": 1015010, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1a0", + "0xa0" + ] + }, + { + "pc": 102, + "op": "ADD", + "gas": 1015007, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1a0", + "0xa0", + "0x80" + ] + }, + { + "pc": 103, + "op": "SWAP1", + "gas": 1015004, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1a0", + "0x120" + ] + }, + { + "pc": 104, + "op": "PUSH1", + "gas": 1015001, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0" + ] + }, + { + "pc": 106, + "op": "DUP3", + "gas": 1014998, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x20" + ] + }, + { + "pc": 107, + "op": "ADD", + "gas": 1014995, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x20", + "0x120" + ] + }, + { + "pc": 108, + "op": "DUP6", + "gas": 1014992, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140" + ] + }, + { + "pc": 109, + "op": "DUP2", + "gas": 1014989, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x1a0" + ] + }, + { + "pc": 110, + "op": "GT", + "gas": 1014986, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x1a0", + "0x140" + ] + }, + { + "pc": 111, + "op": "ISZERO", + "gas": 1014983, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x0" + ] + }, + { + "pc": 112, + "op": "PUSH3", + "gas": 1014980, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x1" + ] + }, + { + "pc": 116, + "op": "JUMPI", + "gas": 1014977, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x1", + "0x79" + ] + }, + { + "pc": 121, + "op": "JUMPDEST", + "gas": 1014967, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140" + ] + }, + { + "pc": 122, + "op": "DUP3", + "gas": 1014966, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140" + ] + }, + { + "pc": 123, + "op": "MLOAD", + "gas": 1014963, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x120" + ] + }, + { + "pc": 124, + "op": "PUSH5", + "gas": 1014960, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9" + ] + }, + { + "pc": 130, + "op": "DUP2", + "gas": 1014957, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x100000000" + ] + }, + { + "pc": 131, + "op": "GT", + "gas": 1014954, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x100000000", + "0x9" + ] + }, + { + "pc": 132, + "op": "DUP3", + "gas": 1014951, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x0" + ] + }, + { + "pc": 133, + "op": "DUP3", + "gas": 1014948, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x0", + "0x140" + ] + }, + { + "pc": 134, + "op": "ADD", + "gas": 1014945, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x0", + "0x140", + "0x9" + ] + }, + { + "pc": 135, + "op": "DUP9", + "gas": 1014942, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x0", + "0x149" + ] + }, + { + "pc": 136, + "op": "LT", + "gas": 1014939, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x0", + "0x149", + "0x1a0" + ] + }, + { + "pc": 137, + "op": "OR", + "gas": 1014936, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x0", + "0x0" + ] + }, + { + "pc": 138, + "op": "ISZERO", + "gas": 1014933, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x0" + ] + }, + { + "pc": 139, + "op": "PUSH3", + "gas": 1014930, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x1" + ] + }, + { + "pc": 143, + "op": "JUMPI", + "gas": 1014927, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x1", + "0x94" + ] + }, + { + "pc": 148, + "op": "JUMPDEST", + "gas": 1014917, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9" + ] + }, + { + "pc": 149, + "op": "DUP3", + "gas": 1014916, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9" + ] + }, + { + "pc": 150, + "op": "MSTORE", + "gas": 1014913, + "gasCost": 6, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140", + "0x9", + "0x1a0" + ] + }, + { + "pc": 151, + "op": "POP", + "gas": 1014907, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x140" + ] + }, + { + "pc": 152, + "op": "DUP2", + "gas": 1014905, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0" + ] + }, + { + "pc": 153, + "op": "MLOAD", + "gas": 1014902, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x120" + ] + }, + { + "pc": 154, + "op": "PUSH1", + "gas": 1014899, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x9" + ] + }, + { + "pc": 156, + "op": "SWAP2", + "gas": 1014896, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x1a0", + "0x9", + "0x20" + ] + }, + { + "pc": 157, + "op": "DUP3", + "gas": 1014893, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x20", + "0x9", + "0x1a0" + ] + }, + { + "pc": 158, + "op": "ADD", + "gas": 1014890, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x20", + "0x9", + "0x1a0", + "0x20" + ] + }, + { + "pc": 159, + "op": "SWAP3", + "gas": 1014887, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x120", + "0x20", + "0x9", + "0x1c0" + ] + }, + { + "pc": 160, + "op": "SWAP1", + "gas": 1014884, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x20", + "0x9", + "0x120" + ] + }, + { + "pc": 161, + "op": "SWAP2", + "gas": 1014881, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x20", + "0x120", + "0x9" + ] + }, + { + "pc": 162, + "op": "ADD", + "gas": 1014878, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x9", + "0x120", + "0x20" + ] + }, + { + "pc": 163, + "op": "SWAP1", + "gas": 1014875, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x9", + "0x140" + ] + }, + { + "pc": 164, + "op": "DUP1", + "gas": 1014872, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9" + ] + }, + { + "pc": 165, + "op": "DUP4", + "gas": 1014869, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9" + ] + }, + { + "pc": 166, + "op": "DUP4", + "gas": 1014866, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0" + ] + }, + { + "pc": 167, + "op": "PUSH1", + "gas": 1014863, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140" + ] + }, + { + "pc": 169, + "op": "JUMPDEST", + "gas": 1014860, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0" + ] + }, + { + "pc": 170, + "op": "DUP4", + "gas": 1014859, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0" + ] + }, + { + "pc": 171, + "op": "DUP2", + "gas": 1014856, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x9" + ] + }, + { + "pc": 172, + "op": "LT", + "gas": 1014853, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x9", + "0x0" + ] + }, + { + "pc": 173, + "op": "ISZERO", + "gas": 1014850, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x1" + ] + }, + { + "pc": 174, + "op": "PUSH3", + "gas": 1014847, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x0" + ] + }, + { + "pc": 178, + "op": "JUMPI", + "gas": 1014844, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x0", + "0xc3" + ] + }, + { + "pc": 179, + "op": "DUP2", + "gas": 1014834, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0" + ] + }, + { + "pc": 180, + "op": "DUP2", + "gas": 1014831, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x140" + ] + }, + { + "pc": 181, + "op": "ADD", + "gas": 1014828, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x140", + "0x0" + ] + }, + { + "pc": 182, + "op": "MLOAD", + "gas": 1014825, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x140" + ] + }, + { + "pc": 183, + "op": "DUP4", + "gas": 1014822, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 184, + "op": "DUP3", + "gas": 1014819, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1c0" + ] + }, + { + "pc": 185, + "op": "ADD", + "gas": 1014816, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1c0", + "0x0" + ] + }, + { + "pc": 186, + "op": "MSTORE", + "gas": 1014813, + "gasCost": 6, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1c0" + ] + }, + { + "pc": 187, + "op": "PUSH1", + "gas": 1014807, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0" + ] + }, + { + "pc": 189, + "op": "ADD", + "gas": 1014804, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x0", + "0x20" + ] + }, + { + "pc": 190, + "op": "PUSH3", + "gas": 1014801, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20" + ] + }, + { + "pc": 194, + "op": "JUMP", + "gas": 1014798, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20", + "0xa9" + ] + }, + { + "pc": 169, + "op": "JUMPDEST", + "gas": 1014790, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20" + ] + }, + { + "pc": 170, + "op": "DUP4", + "gas": 1014789, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20" + ] + }, + { + "pc": 171, + "op": "DUP2", + "gas": 1014786, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20", + "0x9" + ] + }, + { + "pc": 172, + "op": "LT", + "gas": 1014783, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20", + "0x9", + "0x20" + ] + }, + { + "pc": 173, + "op": "ISZERO", + "gas": 1014780, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20", + "0x0" + ] + }, + { + "pc": 174, + "op": "PUSH3", + "gas": 1014777, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20", + "0x1" + ] + }, + { + "pc": 178, + "op": "JUMPI", + "gas": 1014774, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20", + "0x1", + "0xc3" + ] + }, + { + "pc": 195, + "op": "JUMPDEST", + "gas": 1014764, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20" + ] + }, + { + "pc": 196, + "op": "POP", + "gas": 1014763, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140", + "0x20" + ] + }, + { + "pc": 197, + "op": "POP", + "gas": 1014761, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0", + "0x140" + ] + }, + { + "pc": 198, + "op": "POP", + "gas": 1014759, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9", + "0x1c0" + ] + }, + { + "pc": 199, + "op": "POP", + "gas": 1014757, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9", + "0x9" + ] + }, + { + "pc": 200, + "op": "SWAP1", + "gas": 1014755, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x140", + "0x9" + ] + }, + { + "pc": 201, + "op": "POP", + "gas": 1014752, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x9", + "0x140" + ] + }, + { + "pc": 202, + "op": "SWAP1", + "gas": 1014750, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c0", + "0x9" + ] + }, + { + "pc": 203, + "op": "DUP2", + "gas": 1014747, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x9", + "0x1c0" + ] + }, + { + "pc": 204, + "op": "ADD", + "gas": 1014744, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x9", + "0x1c0", + "0x9" + ] + }, + { + "pc": 205, + "op": "SWAP1", + "gas": 1014741, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x9", + "0x1c9" + ] + }, + { + "pc": 206, + "op": "PUSH1", + "gas": 1014738, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9" + ] + }, + { + "pc": 208, + "op": "AND", + "gas": 1014735, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1f" + ] + }, + { + "pc": 209, + "op": "DUP1", + "gas": 1014732, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9" + ] + }, + { + "pc": 210, + "op": "ISZERO", + "gas": 1014729, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x9" + ] + }, + { + "pc": 211, + "op": "PUSH3", + "gas": 1014726, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x0" + ] + }, + { + "pc": 215, + "op": "JUMPI", + "gas": 1014723, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x0", + "0xf1" + ] + }, + { + "pc": 216, + "op": "DUP1", + "gas": 1014713, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9" + ] + }, + { + "pc": 217, + "op": "DUP3", + "gas": 1014710, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x9" + ] + }, + { + "pc": 218, + "op": "SUB", + "gas": 1014707, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x9", + "0x1c9" + ] + }, + { + "pc": 219, + "op": "DUP1", + "gas": 1014704, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0" + ] + }, + { + "pc": 220, + "op": "MLOAD", + "gas": 1014701, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x1c0" + ] + }, + { + "pc": 221, + "op": "PUSH1", + "gas": 1014698, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 223, + "op": "DUP4", + "gas": 1014695, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1" + ] + }, + { + "pc": 224, + "op": "PUSH1", + "gas": 1014692, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1", + "0x9" + ] + }, + { + "pc": 226, + "op": "SUB", + "gas": 1014689, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1", + "0x9", + "0x20" + ] + }, + { + "pc": 227, + "op": "PUSH2", + "gas": 1014686, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1", + "0x17" + ] + }, + { + "pc": 230, + "op": "EXP", + "gas": 1014683, + "gasCost": 60, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1", + "0x17", + "0x100" + ] + }, + { + "pc": 231, + "op": "SUB", + "gas": 1014623, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1", + "0x10000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 232, + "op": "NOT", + "gas": 1014620, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffffffffff" + ] + }, + { + "pc": 233, + "op": "AND", + "gas": 1014617, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0xffffffffffffffffff0000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 234, + "op": "DUP2", + "gas": 1014614, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 235, + "op": "MSTORE", + "gas": 1014611, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x1c0" + ] + }, + { + "pc": 236, + "op": "PUSH1", + "gas": 1014608, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0" + ] + }, + { + "pc": 238, + "op": "ADD", + "gas": 1014605, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1c0", + "0x20" + ] + }, + { + "pc": 239, + "op": "SWAP2", + "gas": 1014602, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1c9", + "0x9", + "0x1e0" + ] + }, + { + "pc": 240, + "op": "POP", + "gas": 1014599, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1e0", + "0x9", + "0x1c9" + ] + }, + { + "pc": 241, + "op": "JUMPDEST", + "gas": 1014597, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1e0", + "0x9" + ] + }, + { + "pc": 242, + "op": "POP", + "gas": 1014596, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1e0", + "0x9" + ] + }, + { + "pc": 243, + "op": "PUSH1", + "gas": 1014594, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1e0" + ] + }, + { + "pc": 245, + "op": "MSTORE", + "gas": 1014591, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x1e0", + "0x40" + ] + }, + { + "pc": 246, + "op": "PUSH1", + "gas": 1014588, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0" + ] + }, + { + "pc": 248, + "op": "ADD", + "gas": 1014585, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xc0", + "0x20" + ] + }, + { + "pc": 249, + "op": "DUP1", + "gas": 1014582, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xe0" + ] + }, + { + "pc": 250, + "op": "MLOAD", + "gas": 1014579, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xe0", + "0xe0" + ] + }, + { + "pc": 251, + "op": "PUSH1", + "gas": 1014576, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xe0", + "0xe0" + ] + }, + { + "pc": 253, + "op": "MLOAD", + "gas": 1014573, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x40" + ] + }, + { + "pc": 254, + "op": "SWAP4", + "gas": 1014570, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0" + ] + }, + { + "pc": 255, + "op": "SWAP3", + "gas": 1014567, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x80", + "0xe0", + "0xe0", + "0x1a0" + ] + }, + { + "pc": 256, + "op": "SWAP2", + "gas": 1014564, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0xe0", + "0xe0", + "0x80" + ] + }, + { + "pc": 257, + "op": "SWAP1", + "gas": 1014561, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0" + ] + }, + { + "pc": 258, + "op": "DUP5", + "gas": 1014558, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0" + ] + }, + { + "pc": 259, + "op": "PUSH5", + "gas": 1014555, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0" + ] + }, + { + "pc": 265, + "op": "DUP3", + "gas": 1014552, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0", + "0x100000000" + ] + }, + { + "pc": 266, + "op": "GT", + "gas": 1014549, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0", + "0x100000000", + "0xe0" + ] + }, + { + "pc": 267, + "op": "ISZERO", + "gas": 1014546, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0", + "0x0" + ] + }, + { + "pc": 268, + "op": "PUSH3", + "gas": 1014543, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0", + "0x1" + ] + }, + { + "pc": 272, + "op": "JUMPI", + "gas": 1014540, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0", + "0x1", + "0x115" + ] + }, + { + "pc": 277, + "op": "JUMPDEST", + "gas": 1014530, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0" + ] + }, + { + "pc": 278, + "op": "SWAP1", + "gas": 1014529, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0xe0", + "0x1e0" + ] + }, + { + "pc": 279, + "op": "DUP4", + "gas": 1014526, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x1e0", + "0xe0" + ] + }, + { + "pc": 280, + "op": "ADD", + "gas": 1014523, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x1e0", + "0xe0", + "0x80" + ] + }, + { + "pc": 281, + "op": "SWAP1", + "gas": 1014520, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x1e0", + "0x160" + ] + }, + { + "pc": 282, + "op": "PUSH1", + "gas": 1014517, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0" + ] + }, + { + "pc": 284, + "op": "DUP3", + "gas": 1014514, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x20" + ] + }, + { + "pc": 285, + "op": "ADD", + "gas": 1014511, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x20", + "0x160" + ] + }, + { + "pc": 286, + "op": "DUP6", + "gas": 1014508, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180" + ] + }, + { + "pc": 287, + "op": "DUP2", + "gas": 1014505, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x1a0" + ] + }, + { + "pc": 288, + "op": "GT", + "gas": 1014502, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x1a0", + "0x180" + ] + }, + { + "pc": 289, + "op": "ISZERO", + "gas": 1014499, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x0" + ] + }, + { + "pc": 290, + "op": "PUSH3", + "gas": 1014496, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x1" + ] + }, + { + "pc": 294, + "op": "JUMPI", + "gas": 1014493, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x1", + "0x12b" + ] + }, + { + "pc": 299, + "op": "JUMPDEST", + "gas": 1014483, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180" + ] + }, + { + "pc": 300, + "op": "DUP3", + "gas": 1014482, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180" + ] + }, + { + "pc": 301, + "op": "MLOAD", + "gas": 1014479, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x160" + ] + }, + { + "pc": 302, + "op": "PUSH5", + "gas": 1014476, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4" + ] + }, + { + "pc": 308, + "op": "DUP2", + "gas": 1014473, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x100000000" + ] + }, + { + "pc": 309, + "op": "GT", + "gas": 1014470, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x100000000", + "0x4" + ] + }, + { + "pc": 310, + "op": "DUP3", + "gas": 1014467, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x0" + ] + }, + { + "pc": 311, + "op": "DUP3", + "gas": 1014464, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x0", + "0x180" + ] + }, + { + "pc": 312, + "op": "ADD", + "gas": 1014461, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x0", + "0x180", + "0x4" + ] + }, + { + "pc": 313, + "op": "DUP9", + "gas": 1014458, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x0", + "0x184" + ] + }, + { + "pc": 314, + "op": "LT", + "gas": 1014455, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x0", + "0x184", + "0x1a0" + ] + }, + { + "pc": 315, + "op": "OR", + "gas": 1014452, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x0", + "0x0" + ] + }, + { + "pc": 316, + "op": "ISZERO", + "gas": 1014449, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x0" + ] + }, + { + "pc": 317, + "op": "PUSH3", + "gas": 1014446, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x1" + ] + }, + { + "pc": 321, + "op": "JUMPI", + "gas": 1014443, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x1", + "0x146" + ] + }, + { + "pc": 326, + "op": "JUMPDEST", + "gas": 1014433, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4" + ] + }, + { + "pc": 327, + "op": "DUP3", + "gas": 1014432, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4" + ] + }, + { + "pc": 328, + "op": "MSTORE", + "gas": 1014429, + "gasCost": 6, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180", + "0x4", + "0x1e0" + ] + }, + { + "pc": 329, + "op": "POP", + "gas": 1014423, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x180" + ] + }, + { + "pc": 330, + "op": "DUP2", + "gas": 1014421, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0" + ] + }, + { + "pc": 331, + "op": "MLOAD", + "gas": 1014418, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x160" + ] + }, + { + "pc": 332, + "op": "PUSH1", + "gas": 1014415, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x4" + ] + }, + { + "pc": 334, + "op": "SWAP2", + "gas": 1014412, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x1e0", + "0x4", + "0x20" + ] + }, + { + "pc": 335, + "op": "DUP3", + "gas": 1014409, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x20", + "0x4", + "0x1e0" + ] + }, + { + "pc": 336, + "op": "ADD", + "gas": 1014406, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x20", + "0x4", + "0x1e0", + "0x20" + ] + }, + { + "pc": 337, + "op": "SWAP3", + "gas": 1014403, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x160", + "0x20", + "0x4", + "0x200" + ] + }, + { + "pc": 338, + "op": "SWAP1", + "gas": 1014400, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x20", + "0x4", + "0x160" + ] + }, + { + "pc": 339, + "op": "SWAP2", + "gas": 1014397, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x20", + "0x160", + "0x4" + ] + }, + { + "pc": 340, + "op": "ADD", + "gas": 1014394, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x4", + "0x160", + "0x20" + ] + }, + { + "pc": 341, + "op": "SWAP1", + "gas": 1014391, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x4", + "0x180" + ] + }, + { + "pc": 342, + "op": "DUP1", + "gas": 1014388, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4" + ] + }, + { + "pc": 343, + "op": "DUP4", + "gas": 1014385, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4" + ] + }, + { + "pc": 344, + "op": "DUP4", + "gas": 1014382, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200" + ] + }, + { + "pc": 345, + "op": "PUSH1", + "gas": 1014379, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180" + ] + }, + { + "pc": 347, + "op": "JUMPDEST", + "gas": 1014376, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0" + ] + }, + { + "pc": 348, + "op": "DUP4", + "gas": 1014375, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0" + ] + }, + { + "pc": 349, + "op": "DUP2", + "gas": 1014372, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x4" + ] + }, + { + "pc": 350, + "op": "LT", + "gas": 1014369, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x4", + "0x0" + ] + }, + { + "pc": 351, + "op": "ISZERO", + "gas": 1014366, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x1" + ] + }, + { + "pc": 352, + "op": "PUSH3", + "gas": 1014363, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x0" + ] + }, + { + "pc": 356, + "op": "JUMPI", + "gas": 1014360, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x0", + "0x175" + ] + }, + { + "pc": 357, + "op": "DUP2", + "gas": 1014350, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0" + ] + }, + { + "pc": 358, + "op": "DUP2", + "gas": 1014347, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x180" + ] + }, + { + "pc": 359, + "op": "ADD", + "gas": 1014344, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x180", + "0x0" + ] + }, + { + "pc": 360, + "op": "MLOAD", + "gas": 1014341, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x180" + ] + }, + { + "pc": 361, + "op": "DUP4", + "gas": 1014338, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x5745544800000000000000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 362, + "op": "DUP3", + "gas": 1014335, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x200" + ] + }, + { + "pc": 363, + "op": "ADD", + "gas": 1014332, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x200", + "0x0" + ] + }, + { + "pc": 364, + "op": "MSTORE", + "gas": 1014329, + "gasCost": 6, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x200" + ] + }, + { + "pc": 365, + "op": "PUSH1", + "gas": 1014323, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0" + ] + }, + { + "pc": 367, + "op": "ADD", + "gas": 1014320, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x0", + "0x20" + ] + }, + { + "pc": 368, + "op": "PUSH3", + "gas": 1014317, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20" + ] + }, + { + "pc": 372, + "op": "JUMP", + "gas": 1014314, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20", + "0x15b" + ] + }, + { + "pc": 347, + "op": "JUMPDEST", + "gas": 1014306, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20" + ] + }, + { + "pc": 348, + "op": "DUP4", + "gas": 1014305, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20" + ] + }, + { + "pc": 349, + "op": "DUP2", + "gas": 1014302, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20", + "0x4" + ] + }, + { + "pc": 350, + "op": "LT", + "gas": 1014299, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20", + "0x4", + "0x20" + ] + }, + { + "pc": 351, + "op": "ISZERO", + "gas": 1014296, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20", + "0x0" + ] + }, + { + "pc": 352, + "op": "PUSH3", + "gas": 1014293, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20", + "0x1" + ] + }, + { + "pc": 356, + "op": "JUMPI", + "gas": 1014290, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20", + "0x1", + "0x175" + ] + }, + { + "pc": 373, + "op": "JUMPDEST", + "gas": 1014280, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20" + ] + }, + { + "pc": 374, + "op": "POP", + "gas": 1014279, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180", + "0x20" + ] + }, + { + "pc": 375, + "op": "POP", + "gas": 1014277, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200", + "0x180" + ] + }, + { + "pc": 376, + "op": "POP", + "gas": 1014275, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4", + "0x200" + ] + }, + { + "pc": 377, + "op": "POP", + "gas": 1014273, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4", + "0x4" + ] + }, + { + "pc": 378, + "op": "SWAP1", + "gas": 1014271, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x180", + "0x4" + ] + }, + { + "pc": 379, + "op": "POP", + "gas": 1014268, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x4", + "0x180" + ] + }, + { + "pc": 380, + "op": "SWAP1", + "gas": 1014266, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x200", + "0x4" + ] + }, + { + "pc": 381, + "op": "DUP2", + "gas": 1014263, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x4", + "0x200" + ] + }, + { + "pc": 382, + "op": "ADD", + "gas": 1014260, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x4", + "0x200", + "0x4" + ] + }, + { + "pc": 383, + "op": "SWAP1", + "gas": 1014257, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x4", + "0x204" + ] + }, + { + "pc": 384, + "op": "PUSH1", + "gas": 1014254, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4" + ] + }, + { + "pc": 386, + "op": "AND", + "gas": 1014251, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x1f" + ] + }, + { + "pc": 387, + "op": "DUP1", + "gas": 1014248, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4" + ] + }, + { + "pc": 388, + "op": "ISZERO", + "gas": 1014245, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x4" + ] + }, + { + "pc": 389, + "op": "PUSH3", + "gas": 1014242, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x0" + ] + }, + { + "pc": 393, + "op": "JUMPI", + "gas": 1014239, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x0", + "0x1a3" + ] + }, + { + "pc": 394, + "op": "DUP1", + "gas": 1014229, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4" + ] + }, + { + "pc": 395, + "op": "DUP3", + "gas": 1014226, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x4" + ] + }, + { + "pc": 396, + "op": "SUB", + "gas": 1014223, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x4", + "0x204" + ] + }, + { + "pc": 397, + "op": "DUP1", + "gas": 1014220, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200" + ] + }, + { + "pc": 398, + "op": "MLOAD", + "gas": 1014217, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x200" + ] + }, + { + "pc": 399, + "op": "PUSH1", + "gas": 1014214, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 401, + "op": "DUP4", + "gas": 1014211, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x1" + ] + }, + { + "pc": 402, + "op": "PUSH1", + "gas": 1014208, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x1", + "0x4" + ] + }, + { + "pc": 404, + "op": "SUB", + "gas": 1014205, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x1", + "0x4", + "0x20" + ] + }, + { + "pc": 405, + "op": "PUSH2", + "gas": 1014202, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x1", + "0x1c" + ] + }, + { + "pc": 408, + "op": "EXP", + "gas": 1014199, + "gasCost": 60, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x1", + "0x1c", + "0x100" + ] + }, + { + "pc": 409, + "op": "SUB", + "gas": 1014139, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x1", + "0x100000000000000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 410, + "op": "NOT", + "gas": 1014136, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ] + }, + { + "pc": 411, + "op": "AND", + "gas": 1014133, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0xffffffff00000000000000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 412, + "op": "DUP2", + "gas": 1014130, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 413, + "op": "MSTORE", + "gas": 1014127, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x200" + ] + }, + { + "pc": 414, + "op": "PUSH1", + "gas": 1014124, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200" + ] + }, + { + "pc": 416, + "op": "ADD", + "gas": 1014121, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x200", + "0x20" + ] + }, + { + "pc": 417, + "op": "SWAP2", + "gas": 1014118, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x204", + "0x4", + "0x220" + ] + }, + { + "pc": 418, + "op": "POP", + "gas": 1014115, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x220", + "0x4", + "0x204" + ] + }, + { + "pc": 419, + "op": "JUMPDEST", + "gas": 1014113, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x220", + "0x4" + ] + }, + { + "pc": 420, + "op": "POP", + "gas": 1014112, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x220", + "0x4" + ] + }, + { + "pc": 421, + "op": "PUSH1", + "gas": 1014110, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x220" + ] + }, + { + "pc": 423, + "op": "MSTORE", + "gas": 1014107, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x220", + "0x40" + ] + }, + { + "pc": 424, + "op": "PUSH1", + "gas": 1014104, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0" + ] + }, + { + "pc": 426, + "op": "SWAP1", + "gas": 1014101, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0xe0", + "0x20" + ] + }, + { + "pc": 427, + "op": "DUP2", + "gas": 1014098, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0x20", + "0xe0" + ] + }, + { + "pc": 428, + "op": "ADD", + "gas": 1014095, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0x20", + "0xe0", + "0x20" + ] + }, + { + "pc": 429, + "op": "MLOAD", + "gas": 1014092, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0x20", + "0x100" + ] + }, + { + "pc": 430, + "op": "DUP6", + "gas": 1014089, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0x20", + "0x12" + ] + }, + { + "pc": 431, + "op": "MLOAD", + "gas": 1014086, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0x20", + "0x12", + "0x1a0" + ] + }, + { + "pc": 432, + "op": "SWAP1", + "gas": 1014083, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0x20", + "0x12", + "0x9" + ] + }, + { + "pc": 433, + "op": "SWAP4", + "gas": 1014080, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x1a0", + "0x80", + "0x20", + "0x9", + "0x12" + ] + }, + { + "pc": 434, + "op": "POP", + "gas": 1014077, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x80", + "0x20", + "0x9", + "0x1a0" + ] + }, + { + "pc": 435, + "op": "DUP6", + "gas": 1014075, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x80", + "0x20", + "0x9" + ] + }, + { + "pc": 436, + "op": "SWAP3", + "gas": 1014072, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x80", + "0x20", + "0x9", + "0x1a0" + ] + }, + { + "pc": 437, + "op": "POP", + "gas": 1014069, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x20", + "0x9", + "0x80" + ] + }, + { + "pc": 438, + "op": "DUP5", + "gas": 1014067, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x20", + "0x9" + ] + }, + { + "pc": 439, + "op": "SWAP2", + "gas": 1014064, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x20", + "0x9", + "0x1e0" + ] + }, + { + "pc": 440, + "op": "PUSH3", + "gas": 1014061, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x9", + "0x20" + ] + }, + { + "pc": 444, + "op": "SWAP2", + "gas": 1014058, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x9", + "0x20", + "0x1c8" + ] + }, + { + "pc": 445, + "op": "PUSH1", + "gas": 1014055, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x20", + "0x9" + ] + }, + { + "pc": 447, + "op": "SWAP2", + "gas": 1014052, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x20", + "0x9", + "0x3" + ] + }, + { + "pc": 448, + "op": "DUP6", + "gas": 1014049, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x9", + "0x20" + ] + }, + { + "pc": 449, + "op": "ADD", + "gas": 1014046, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x9", + "0x20", + "0x1a0" + ] + }, + { + "pc": 450, + "op": "SWAP1", + "gas": 1014043, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x9", + "0x1c0" + ] + }, + { + "pc": 451, + "op": "PUSH3", + "gas": 1014040, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9" + ] + }, + { + "pc": 455, + "op": "JUMP", + "gas": 1014037, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x26b" + ] + }, + { + "pc": 619, + "op": "JUMPDEST", + "gas": 1014029, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9" + ] + }, + { + "pc": 620, + "op": "DUP3", + "gas": 1014028, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9" + ] + }, + { + "pc": 621, + "op": "DUP1", + "gas": 1014025, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3" + ] + }, + { + "pc": 622, + "op": "SLOAD", + "gas": 1014022, + "gasCost": 2100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x3" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000003", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 623, + "op": "PUSH1", + "gas": 1011922, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0" + ] + }, + { + "pc": 625, + "op": "DUP2", + "gas": 1011919, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0x1" + ] + }, + { + "pc": 626, + "op": "PUSH1", + "gas": 1011916, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0x1", + "0x0" + ] + }, + { + "pc": 628, + "op": "AND", + "gas": 1011913, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0x1", + "0x0", + "0x1" + ] + }, + { + "pc": 629, + "op": "ISZERO", + "gas": 1011910, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0x1", + "0x0" + ] + }, + { + "pc": 630, + "op": "PUSH2", + "gas": 1011907, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0x1", + "0x1" + ] + }, + { + "pc": 633, + "op": "MUL", + "gas": 1011904, + "gasCost": 5, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0x1", + "0x1", + "0x100" + ] + }, + { + "pc": 634, + "op": "SUB", + "gas": 1011899, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0x1", + "0x100" + ] + }, + { + "pc": 635, + "op": "AND", + "gas": 1011896, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0xff" + ] + }, + { + "pc": 636, + "op": "PUSH1", + "gas": 1011893, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0" + ] + }, + { + "pc": 638, + "op": "SWAP1", + "gas": 1011890, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0", + "0x2" + ] + }, + { + "pc": 639, + "op": "DIV", + "gas": 1011887, + "gasCost": 5, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x2", + "0x0" + ] + }, + { + "pc": 640, + "op": "SWAP1", + "gas": 1011882, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x3", + "0x0" + ] + }, + { + "pc": 641, + "op": "PUSH1", + "gas": 1011879, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x0", + "0x3" + ] + }, + { + "pc": 643, + "op": "MSTORE", + "gas": 1011876, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x0", + "0x3", + "0x0" + ] + }, + { + "pc": 644, + "op": "PUSH1", + "gas": 1011873, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x0" + ] + }, + { + "pc": 646, + "op": "PUSH1", + "gas": 1011870, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x0", + "0x20" + ] + }, + { + "pc": 648, + "op": "SHA3", + "gas": 1011867, + "gasCost": 36, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x0", + "0x20", + "0x0" + ] + }, + { + "pc": 649, + "op": "SWAP1", + "gas": 1011831, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0x0", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 650, + "op": "PUSH1", + "gas": 1011828, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x0" + ] + }, + { + "pc": 652, + "op": "ADD", + "gas": 1011825, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x0", + "0x1f" + ] + }, + { + "pc": 653, + "op": "PUSH1", + "gas": 1011822, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1f" + ] + }, + { + "pc": 655, + "op": "SWAP1", + "gas": 1011819, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1f", + "0x20" + ] + }, + { + "pc": 656, + "op": "DIV", + "gas": 1011816, + "gasCost": 5, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x20", + "0x1f" + ] + }, + { + "pc": 657, + "op": "DUP2", + "gas": 1011811, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x0" + ] + }, + { + "pc": 658, + "op": "ADD", + "gas": 1011808, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x0", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 659, + "op": "SWAP3", + "gas": 1011805, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x1c0", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 660, + "op": "DUP3", + "gas": 1011802, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0" + ] + }, + { + "pc": 661, + "op": "PUSH1", + "gas": 1011799, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x9" + ] + }, + { + "pc": 663, + "op": "LT", + "gas": 1011796, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x9", + "0x1f" + ] + }, + { + "pc": 664, + "op": "PUSH3", + "gas": 1011793, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x0" + ] + }, + { + "pc": 668, + "op": "JUMPI", + "gas": 1011790, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x0", + "0x2ae" + ] + }, + { + "pc": 669, + "op": "DUP1", + "gas": 1011780, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0" + ] + }, + { + "pc": 670, + "op": "MLOAD", + "gas": 1011777, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x1c0" + ] + }, + { + "pc": 671, + "op": "PUSH1", + "gas": 1011774, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 673, + "op": "NOT", + "gas": 1011771, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0xff" + ] + }, + { + "pc": 674, + "op": "AND", + "gas": 1011768, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" + ] + }, + { + "pc": 675, + "op": "DUP4", + "gas": 1011765, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 676, + "op": "DUP1", + "gas": 1011762, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x9" + ] + }, + { + "pc": 677, + "op": "ADD", + "gas": 1011759, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x9", + "0x9" + ] + }, + { + "pc": 678, + "op": "OR", + "gas": 1011756, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000000", + "0x12" + ] + }, + { + "pc": 679, + "op": "DUP6", + "gas": 1011753, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000012" + ] + }, + { + "pc": 680, + "op": "SSTORE", + "gas": 1011750, + "gasCost": 20000, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x3" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000003", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 681, + "op": "PUSH3", + "gas": 991750, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0" + ] + }, + { + "pc": 685, + "op": "JUMP", + "gas": 991747, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0", + "0x2de" + ] + }, + { + "pc": 734, + "op": "JUMPDEST", + "gas": 991739, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0" + ] + }, + { + "pc": 735, + "op": "POP", + "gas": 991738, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1c0" + ] + }, + { + "pc": 736, + "op": "PUSH3", + "gas": 991736, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 740, + "op": "SWAP3", + "gas": 991733, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x2ec" + ] + }, + { + "pc": 741, + "op": "SWAP2", + "gas": 991730, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0x9", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 742, + "op": "POP", + "gas": 991727, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x9" + ] + }, + { + "pc": 743, + "op": "PUSH3", + "gas": 991725, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 747, + "op": "JUMP", + "gas": 991722, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x2f0" + ] + }, + { + "pc": 752, + "op": "JUMPDEST", + "gas": 991714, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 753, + "op": "JUMPDEST", + "gas": 991713, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 754, + "op": "DUP1", + "gas": 991712, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 755, + "op": "DUP3", + "gas": 991709, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 756, + "op": "GT", + "gas": 991706, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 757, + "op": "ISZERO", + "gas": 991703, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x0" + ] + }, + { + "pc": 758, + "op": "PUSH3", + "gas": 991700, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1" + ] + }, + { + "pc": 762, + "op": "JUMPI", + "gas": 991697, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x1", + "0x2ec" + ] + }, + { + "pc": 748, + "op": "JUMPDEST", + "gas": 991687, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 749, + "op": "POP", + "gas": 991686, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 750, + "op": "SWAP1", + "gas": 991684, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0x2ec", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 751, + "op": "JUMP", + "gas": 991681, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", + "0x2ec" + ] + }, + { + "pc": 748, + "op": "JUMPDEST", + "gas": 991673, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 749, + "op": "POP", + "gas": 991672, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b" + ] + }, + { + "pc": 750, + "op": "SWAP1", + "gas": 991670, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1c8", + "0x3" + ] + }, + { + "pc": 751, + "op": "JUMP", + "gas": 991667, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x3", + "0x1c8" + ] + }, + { + "pc": 456, + "op": "JUMPDEST", + "gas": 991659, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x3" + ] + }, + { + "pc": 457, + "op": "POP", + "gas": 991658, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x3" + ] + }, + { + "pc": 458, + "op": "DUP1", + "gas": 991656, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0" + ] + }, + { + "pc": 459, + "op": "MLOAD", + "gas": 991653, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1e0" + ] + }, + { + "pc": 460, + "op": "PUSH3", + "gas": 991650, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x4" + ] + }, + { + "pc": 464, + "op": "SWAP1", + "gas": 991647, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x4", + "0x1de" + ] + }, + { + "pc": 465, + "op": "PUSH1", + "gas": 991644, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4" + ] + }, + { + "pc": 467, + "op": "SWAP1", + "gas": 991641, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x4" + ] + }, + { + "pc": 468, + "op": "PUSH1", + "gas": 991638, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x4" + ] + }, + { + "pc": 470, + "op": "DUP5", + "gas": 991635, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x4", + "0x20" + ] + }, + { + "pc": 471, + "op": "ADD", + "gas": 991632, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x4", + "0x20", + "0x1e0" + ] + }, + { + "pc": 472, + "op": "SWAP1", + "gas": 991629, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x4", + "0x200" + ] + }, + { + "pc": 473, + "op": "PUSH3", + "gas": 991626, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4" + ] + }, + { + "pc": 477, + "op": "JUMP", + "gas": 991623, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x26b" + ] + }, + { + "pc": 619, + "op": "JUMPDEST", + "gas": 991615, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4" + ] + }, + { + "pc": 620, + "op": "DUP3", + "gas": 991614, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4" + ] + }, + { + "pc": 621, + "op": "DUP1", + "gas": 991611, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4" + ] + }, + { + "pc": 622, + "op": "SLOAD", + "gas": 991608, + "gasCost": 2100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x4" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000004", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 623, + "op": "PUSH1", + "gas": 989508, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0" + ] + }, + { + "pc": 625, + "op": "DUP2", + "gas": 989505, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0x1" + ] + }, + { + "pc": 626, + "op": "PUSH1", + "gas": 989502, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0x1", + "0x0" + ] + }, + { + "pc": 628, + "op": "AND", + "gas": 989499, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0x1", + "0x0", + "0x1" + ] + }, + { + "pc": 629, + "op": "ISZERO", + "gas": 989496, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0x1", + "0x0" + ] + }, + { + "pc": 630, + "op": "PUSH2", + "gas": 989493, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0x1", + "0x1" + ] + }, + { + "pc": 633, + "op": "MUL", + "gas": 989490, + "gasCost": 5, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0x1", + "0x1", + "0x100" + ] + }, + { + "pc": 634, + "op": "SUB", + "gas": 989485, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0x1", + "0x100" + ] + }, + { + "pc": 635, + "op": "AND", + "gas": 989482, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0xff" + ] + }, + { + "pc": 636, + "op": "PUSH1", + "gas": 989479, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0" + ] + }, + { + "pc": 638, + "op": "SWAP1", + "gas": 989476, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0", + "0x2" + ] + }, + { + "pc": 639, + "op": "DIV", + "gas": 989473, + "gasCost": 5, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x2", + "0x0" + ] + }, + { + "pc": 640, + "op": "SWAP1", + "gas": 989468, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x4", + "0x0" + ] + }, + { + "pc": 641, + "op": "PUSH1", + "gas": 989465, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x0", + "0x4" + ] + }, + { + "pc": 643, + "op": "MSTORE", + "gas": 989462, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x0", + "0x4", + "0x0" + ] + }, + { + "pc": 644, + "op": "PUSH1", + "gas": 989459, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x0" + ] + }, + { + "pc": 646, + "op": "PUSH1", + "gas": 989456, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x0", + "0x20" + ] + }, + { + "pc": 648, + "op": "SHA3", + "gas": 989453, + "gasCost": 36, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x0", + "0x20", + "0x0" + ] + }, + { + "pc": 649, + "op": "SWAP1", + "gas": 989417, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x0", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 650, + "op": "PUSH1", + "gas": 989414, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x0" + ] + }, + { + "pc": 652, + "op": "ADD", + "gas": 989411, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x0", + "0x1f" + ] + }, + { + "pc": 653, + "op": "PUSH1", + "gas": 989408, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x1f" + ] + }, + { + "pc": 655, + "op": "SWAP1", + "gas": 989405, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x1f", + "0x20" + ] + }, + { + "pc": 656, + "op": "DIV", + "gas": 989402, + "gasCost": 5, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x20", + "0x1f" + ] + }, + { + "pc": 657, + "op": "DUP2", + "gas": 989397, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x0" + ] + }, + { + "pc": 658, + "op": "ADD", + "gas": 989394, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x0", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 659, + "op": "SWAP3", + "gas": 989391, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x200", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 660, + "op": "DUP3", + "gas": 989388, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200" + ] + }, + { + "pc": 661, + "op": "PUSH1", + "gas": 989385, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x4" + ] + }, + { + "pc": 663, + "op": "LT", + "gas": 989382, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x4", + "0x1f" + ] + }, + { + "pc": 664, + "op": "PUSH3", + "gas": 989379, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x0" + ] + }, + { + "pc": 668, + "op": "JUMPI", + "gas": 989376, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x0", + "0x2ae" + ] + }, + { + "pc": 669, + "op": "DUP1", + "gas": 989366, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200" + ] + }, + { + "pc": 670, + "op": "MLOAD", + "gas": 989363, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x200" + ] + }, + { + "pc": 671, + "op": "PUSH1", + "gas": 989360, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 673, + "op": "NOT", + "gas": 989357, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0xff" + ] + }, + { + "pc": 674, + "op": "AND", + "gas": 989354, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" + ] + }, + { + "pc": 675, + "op": "DUP4", + "gas": 989351, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000" + ] + }, + { + "pc": 676, + "op": "DUP1", + "gas": 989348, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x4" + ] + }, + { + "pc": 677, + "op": "ADD", + "gas": 989345, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x4", + "0x4" + ] + }, + { + "pc": 678, + "op": "OR", + "gas": 989342, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000000", + "0x8" + ] + }, + { + "pc": 679, + "op": "DUP6", + "gas": 989339, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000008" + ] + }, + { + "pc": 680, + "op": "SSTORE", + "gas": 989336, + "gasCost": 20000, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x4" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000004", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 681, + "op": "PUSH3", + "gas": 969336, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200" + ] + }, + { + "pc": 685, + "op": "JUMP", + "gas": 969333, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200", + "0x2de" + ] + }, + { + "pc": 734, + "op": "JUMPDEST", + "gas": 969325, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200" + ] + }, + { + "pc": 735, + "op": "POP", + "gas": 969324, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x200" + ] + }, + { + "pc": 736, + "op": "PUSH3", + "gas": 969322, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 740, + "op": "SWAP3", + "gas": 969319, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x2ec" + ] + }, + { + "pc": 741, + "op": "SWAP2", + "gas": 969316, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 742, + "op": "POP", + "gas": 969313, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x4" + ] + }, + { + "pc": 743, + "op": "PUSH3", + "gas": 969311, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 747, + "op": "JUMP", + "gas": 969308, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x2f0" + ] + }, + { + "pc": 752, + "op": "JUMPDEST", + "gas": 969300, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 753, + "op": "JUMPDEST", + "gas": 969299, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 754, + "op": "DUP1", + "gas": 969298, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 755, + "op": "DUP3", + "gas": 969295, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 756, + "op": "GT", + "gas": 969292, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 757, + "op": "ISZERO", + "gas": 969289, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x0" + ] + }, + { + "pc": 758, + "op": "PUSH3", + "gas": 969286, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x1" + ] + }, + { + "pc": 762, + "op": "JUMPI", + "gas": 969283, + "gasCost": 10, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x1", + "0x2ec" + ] + }, + { + "pc": 748, + "op": "JUMPDEST", + "gas": 969273, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 749, + "op": "POP", + "gas": 969272, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 750, + "op": "SWAP1", + "gas": 969270, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x2ec", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 751, + "op": "JUMP", + "gas": 969267, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b", + "0x2ec" + ] + }, + { + "pc": 748, + "op": "JUMPDEST", + "gas": 969259, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 749, + "op": "POP", + "gas": 969258, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4", + "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b" + ] + }, + { + "pc": 750, + "op": "SWAP1", + "gas": 969256, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x1de", + "0x4" + ] + }, + { + "pc": 751, + "op": "JUMP", + "gas": 969253, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x4", + "0x1de" + ] + }, + { + "pc": 478, + "op": "JUMPDEST", + "gas": 969245, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x4" + ] + }, + { + "pc": 479, + "op": "POP", + "gas": 969244, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0", + "0x4" + ] + }, + { + "pc": 480, + "op": "POP", + "gas": 969242, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x1e0" + ] + }, + { + "pc": 481, + "op": "PUSH1", + "gas": 969240, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0" + ] + }, + { + "pc": 483, + "op": "DUP1", + "gas": 969237, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5" + ] + }, + { + "pc": 484, + "op": "SLOAD", + "gas": 969234, + "gasCost": 2100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0x5" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000005", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 485, + "op": "PUSH2", + "gas": 967134, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0x0" + ] + }, + { + "pc": 488, + "op": "NOT", + "gas": 967131, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0x0", + "0xff00" + ] + }, + { + "pc": 489, + "op": "PUSH1", + "gas": 967128, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff" + ] + }, + { + "pc": 491, + "op": "NOT", + "gas": 967125, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff", + "0xff" + ] + }, + { + "pc": 492, + "op": "SWAP1", + "gas": 967122, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" + ] + }, + { + "pc": 493, + "op": "SWAP2", + "gas": 967119, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff" + ] + }, + { + "pc": 494, + "op": "AND", + "gas": 967116, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", + "0x0" + ] + }, + { + "pc": 495, + "op": "PUSH1", + "gas": 967113, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff", + "0x0" + ] + }, + { + "pc": 497, + "op": "OR", + "gas": 967110, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff", + "0x0", + "0x12" + ] + }, + { + "pc": 498, + "op": "AND", + "gas": 967107, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff", + "0x12" + ] + }, + { + "pc": 499, + "op": "SWAP1", + "gas": 967104, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x5", + "0x12" + ] + }, + { + "pc": 500, + "op": "SSTORE", + "gas": 967101, + "gasCost": 20000, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0", + "0x12", + "0x5" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000005", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 501, + "op": "POP", + "gas": 947101, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1a0" + ] + }, + { + "pc": 502, + "op": "PUSH1", + "gas": 947099, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12" + ] + }, + { + "pc": 504, + "op": "DUP1", + "gas": 947096, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6" + ] + }, + { + "pc": 505, + "op": "SLOAD", + "gas": 947093, + "gasCost": 2100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x6" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000006", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 506, + "op": "PUSH1", + "gas": 944993, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0" + ] + }, + { + "pc": 508, + "op": "PUSH1", + "gas": 944990, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0x1" + ] + }, + { + "pc": 510, + "op": "PUSH1", + "gas": 944987, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0x1", + "0x1" + ] + }, + { + "pc": 512, + "op": "SHL", + "gas": 944984, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0x1", + "0x1", + "0xa0" + ] + }, + { + "pc": 513, + "op": "SUB", + "gas": 944981, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0x1", + "0x10000000000000000000000000000000000000000" + ] + }, + { + "pc": 514, + "op": "DUP1", + "gas": 944978, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff" + ] + }, + { + "pc": 515, + "op": "DUP9", + "gas": 944975, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffff" + ] + }, + { + "pc": 516, + "op": "AND", + "gas": 944972, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 517, + "op": "PUSH1", + "gas": 944969, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 519, + "op": "PUSH1", + "gas": 944966, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1" + ] + }, + { + "pc": 521, + "op": "PUSH1", + "gas": 944963, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1", + "0x1" + ] + }, + { + "pc": 523, + "op": "SHL", + "gas": 944960, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1", + "0x1", + "0xa0" + ] + }, + { + "pc": 524, + "op": "SUB", + "gas": 944957, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1", + "0x10000000000000000000000000000000000000000" + ] + }, + { + "pc": 525, + "op": "NOT", + "gas": 944954, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xffffffffffffffffffffffffffffffffffffffff" + ] + }, + { + "pc": 526, + "op": "SWAP3", + "gas": 944951, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0x0", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000" + ] + }, + { + "pc": 527, + "op": "DUP4", + "gas": 944948, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0" + ] + }, + { + "pc": 528, + "op": "AND", + "gas": 944945, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000" + ] + }, + { + "pc": 529, + "op": "OR", + "gas": 944942, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0" + ] + }, + { + "pc": 530, + "op": "SWAP1", + "gas": 944939, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 531, + "op": "SWAP3", + "gas": 944936, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x6", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xffffffffffffffffffffffffffffffffffffffff" + ] + }, + { + "pc": 532, + "op": "SSTORE", + "gas": 944933, + "gasCost": 20000, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0xffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x6" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000006", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 533, + "op": "PUSH1", + "gas": 924933, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0xffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000" + ] + }, + { + "pc": 535, + "op": "DUP1", + "gas": 924930, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0xffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x7" + ] + }, + { + "pc": 536, + "op": "SLOAD", + "gas": 924927, + "gasCost": 2100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0xffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x7", + "0x7" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000007", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 537, + "op": "SWAP3", + "gas": 922827, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0xffffffffffffffffffffffffffffffffffffffff", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x7", + "0x0" + ] + }, + { + "pc": 538, + "op": "DUP8", + "gas": 922824, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x0", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x7", + "0xffffffffffffffffffffffffffffffffffffffff" + ] + }, + { + "pc": 539, + "op": "AND", + "gas": 922821, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x0", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x7", + "0xffffffffffffffffffffffffffffffffffffffff", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 540, + "op": "SWAP3", + "gas": 922818, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x0", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x7", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 541, + "op": "SWAP1", + "gas": 922815, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x7", + "0x0" + ] + }, + { + "pc": 542, + "op": "SWAP2", + "gas": 922812, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000", + "0x0", + "0x7" + ] + }, + { + "pc": 543, + "op": "AND", + "gas": 922809, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x7", + "0x0", + "0xffffffffffffffffffffffff0000000000000000000000000000000000000000" + ] + }, + { + "pc": 544, + "op": "SWAP2", + "gas": 922806, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x7", + "0x0" + ] + }, + { + "pc": 545, + "op": "SWAP1", + "gas": 922803, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x0", + "0x7", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 546, + "op": "SWAP2", + "gas": 922800, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x0", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x7" + ] + }, + { + "pc": 547, + "op": "OR", + "gas": 922797, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x7", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0" + ] + }, + { + "pc": 548, + "op": "SWAP1", + "gas": 922794, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x7", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 549, + "op": "SSTORE", + "gas": 922791, + "gasCost": 20000, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x7" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000007", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }, + { + "pc": 550, + "op": "PUSH3", + "gas": 902791, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12" + ] + }, + { + "pc": 554, + "op": "DUP2", + "gas": 902788, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230" + ] + }, + { + "pc": 555, + "op": "PUSH3", + "gas": 902785, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12" + ] + }, + { + "pc": 559, + "op": "JUMP", + "gas": 902782, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x255" + ] + }, + { + "pc": 597, + "op": "JUMPDEST", + "gas": 902774, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12" + ] + }, + { + "pc": 598, + "op": "PUSH1", + "gas": 902773, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12" + ] + }, + { + "pc": 600, + "op": "DUP1", + "gas": 902770, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5" + ] + }, + { + "pc": 601, + "op": "SLOAD", + "gas": 902767, + "gasCost": 100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5", + "0x5" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000005", + "value": "0x0000000000000000000000000000000000000000000000000000000000000012" + } + } + ] + } + }, + { + "pc": 602, + "op": "PUSH1", + "gas": 902667, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5", + "0x12" + ] + }, + { + "pc": 604, + "op": "NOT", + "gas": 902664, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5", + "0x12", + "0xff" + ] + }, + { + "pc": 605, + "op": "AND", + "gas": 902661, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5", + "0x12", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" + ] + }, + { + "pc": 606, + "op": "PUSH1", + "gas": 902658, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5", + "0x0" + ] + }, + { + "pc": 608, + "op": "SWAP3", + "gas": 902655, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5", + "0x0", + "0xff" + ] + }, + { + "pc": 609, + "op": "SWAP1", + "gas": 902652, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0xff", + "0x5", + "0x0", + "0x12" + ] + }, + { + "pc": 610, + "op": "SWAP3", + "gas": 902649, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0xff", + "0x5", + "0x12", + "0x0" + ] + }, + { + "pc": 611, + "op": "AND", + "gas": 902646, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x0", + "0x5", + "0x12", + "0xff" + ] + }, + { + "pc": 612, + "op": "SWAP2", + "gas": 902643, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x0", + "0x5", + "0x12" + ] + }, + { + "pc": 613, + "op": "SWAP1", + "gas": 902640, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5", + "0x0" + ] + }, + { + "pc": 614, + "op": "SWAP2", + "gas": 902637, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x0", + "0x5" + ] + }, + { + "pc": 615, + "op": "OR", + "gas": 902634, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x5", + "0x0", + "0x12" + ] + }, + { + "pc": 616, + "op": "SWAP1", + "gas": 902631, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x5", + "0x12" + ] + }, + { + "pc": 617, + "op": "SSTORE", + "gas": 902628, + "gasCost": 100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230", + "0x12", + "0x5" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000005", + "value": "0x0000000000000000000000000000000000000000000000000000000000000012" + } + } + ] + } + }, + { + "pc": 618, + "op": "JUMP", + "gas": 902528, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12", + "0x230" + ] + }, + { + "pc": 560, + "op": "JUMPDEST", + "gas": 902520, + "gasCost": 1, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12" + ] + }, + { + "pc": 561, + "op": "POP", + "gas": 902519, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0", + "0x12" + ] + }, + { + "pc": 562, + "op": "POP", + "gas": 902517, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1e0" + ] + }, + { + "pc": 563, + "op": "PUSH1", + "gas": 902515, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0" + ] + }, + { + "pc": 565, + "op": "DUP1", + "gas": 902512, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5" + ] + }, + { + "pc": 566, + "op": "SLOAD", + "gas": 902509, + "gasCost": 100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x5" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000005", + "value": "0x0000000000000000000000000000000000000000000000000000000000000012" + } + } + ] + } + }, + { + "pc": 567, + "op": "PUSH3", + "gas": 902409, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12" + ] + }, + { + "pc": 571, + "op": "PUSH1", + "gas": 902406, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0x10000" + ] + }, + { + "pc": 573, + "op": "PUSH1", + "gas": 902403, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0x10000", + "0x1" + ] + }, + { + "pc": 575, + "op": "SHL", + "gas": 902400, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0x10000", + "0x1", + "0xb0" + ] + }, + { + "pc": 576, + "op": "SUB", + "gas": 902397, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0x10000", + "0x100000000000000000000000000000000000000000000" + ] + }, + { + "pc": 577, + "op": "NOT", + "gas": 902394, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0xffffffffffffffffffffffffffffffffffffffff0000" + ] + }, + { + "pc": 578, + "op": "AND", + "gas": 902391, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0xffffffffffffffffffff0000000000000000000000000000000000000000ffff" + ] + }, + { + "pc": 579, + "op": "CALLER", + "gas": 902388, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12" + ] + }, + { + "pc": 580, + "op": "PUSH3", + "gas": 902386, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 584, + "op": "MUL", + "gas": 902383, + "gasCost": 5, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x10000" + ] + }, + { + "pc": 585, + "op": "OR", + "gas": 902378, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x12", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b630000" + ] + }, + { + "pc": 586, + "op": "SWAP1", + "gas": 902375, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x5", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b630012" + ] + }, + { + "pc": 587, + "op": "SSTORE", + "gas": 902372, + "gasCost": 100, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b630012", + "0x5" + ], + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5745544820636f696e0000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b630012", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63" + }, + "extraData": { + "proofList": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "nonce": 1, + "balance": "0x0", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000005", + "value": "0x0000000000000000000000000000000000000000000000000000000000000012" + } + } + ] + } + }, + { + "pc": 588, + "op": "POP", + "gas": 902272, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1a0" + ] + }, + { + "pc": 589, + "op": "PUSH3", + "gas": 902270, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 593, + "op": "SWAP2", + "gas": 902267, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x307" + ] + }, + { + "pc": 594, + "op": "POP", + "gas": 902264, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x307", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 595, + "op": "POP", + "gas": 902262, + "gasCost": 2, + "depth": 1, + "stack": [ + "0x307", + "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63" + ] + }, + { + "pc": 596, + "op": "JUMP", + "gas": 902260, + "gasCost": 8, + "depth": 1, + "stack": [ + "0x307" + ] + }, + { + "pc": 775, + "op": "JUMPDEST", + "gas": 902252, + "gasCost": 1, + "depth": 1 + }, + { + "pc": 776, + "op": "PUSH2", + "gas": 902251, + "gasCost": 3, + "depth": 1 + }, + { + "pc": 779, + "op": "DUP1", + "gas": 902248, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x119b" + ] + }, + { + "pc": 780, + "op": "PUSH3", + "gas": 902245, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x119b", + "0x119b" + ] + }, + { + "pc": 784, + "op": "PUSH1", + "gas": 902242, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x119b", + "0x119b", + "0x317" + ] + }, + { + "pc": 786, + "op": "CODECOPY", + "gas": 902239, + "gasCost": 836, + "depth": 1, + "stack": [ + "0x119b", + "0x119b", + "0x317", + "0x0" + ], + "extraData": { + "codeList": [ + "0x" + ] + } + }, + { + "pc": 787, + "op": "PUSH1", + "gas": 901403, + "gasCost": 3, + "depth": 1, + "stack": [ + "0x119b" + ] + }, + { + "pc": 789, + "op": "RETURN", + "gas": 901400, + "gasCost": 0, + "depth": 1, + "stack": [ + "0x119b", + "0x0" + ] + } + ] + } + ], + "mptwitness": [ + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "accountKey": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0xaf16fd780a8c7616b95b20da69f4ff26e0253238e996f9516445d6d6bf92b725", + "path": [ + { + "value": "0x5bbe97e7e66485b203f9dfea64eb7fa7df06959b12cbde2beba14f8f91133a13", + "sibling": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806" + }, + { + "value": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ] + }, + { + "pathPart": "0x1", + "root": "0x08ebb525664ab0c02c49587ec298d42388319f0c57a3018a7984f77a69b06a20", + "path": [ + { + "value": "0xf0a9432907471588a0e83aa9201193de159efe3b31e9112d6981c2be8ce45104", + "sibling": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806" + }, + { + "value": "0x5c70b599f4da7e6c8271703a7677e703fa0cab9088232a1c0ee99aa3112fd51e", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x33c5435c783d711eca3cb21179f8afaf6dd0be8ca0f066d0daace28b17fc281d", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + } + ], + "accountUpdate": [ + null, + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0x08ebb525664ab0c02c49587ec298d42388319f0c57a3018a7984f77a69b06a20", + "path": [ + { + "value": "0x34f20c09876841ab1c180877223cc915ca96589b05ecea552aa2b3b9b47de806", + "sibling": "0xf0a9432907471588a0e83aa9201193de159efe3b31e9112d6981c2be8ce45104" + } + ], + "leaf": { + "value": "0xf199fe1a085b5bb134e90d0bfdaf70579fa703ab3db986a6730b44cfd5207b15", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0x5ccb01b192af8237bf448abf2c7fb6531ce162936172524eac258b40f32f0812", + "path": [ + { + "value": "0xdae1cffcb0f5fe3e341a9a514f9c06a6feaac97547b8ee2db69b239b880b9e19", + "sibling": "0xf0a9432907471588a0e83aa9201193de159efe3b31e9112d6981c2be8ce45104" + } + ], + "leaf": { + "value": "0xaa040d2c798b9c0db0484dcb8461200c9a92fa6a76c1bb58ec582d2c2d2edd22", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + { + "nonce": 2, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "nonce": 3, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "accountKey": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0x5ccb01b192af8237bf448abf2c7fb6531ce162936172524eac258b40f32f0812", + "path": [ + { + "value": "0xf0a9432907471588a0e83aa9201193de159efe3b31e9112d6981c2be8ce45104", + "sibling": "0xdae1cffcb0f5fe3e341a9a514f9c06a6feaac97547b8ee2db69b239b880b9e19" + }, + { + "value": "0x5c70b599f4da7e6c8271703a7677e703fa0cab9088232a1c0ee99aa3112fd51e", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x33c5435c783d711eca3cb21179f8afaf6dd0be8ca0f066d0daace28b17fc281d", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + }, + { + "pathPart": "0x1", + "root": "0x5ccb01b192af8237bf448abf2c7fb6531ce162936172524eac258b40f32f0812", + "path": [ + { + "value": "0xf0a9432907471588a0e83aa9201193de159efe3b31e9112d6981c2be8ce45104", + "sibling": "0xdae1cffcb0f5fe3e341a9a514f9c06a6feaac97547b8ee2db69b239b880b9e19" + }, + { + "value": "0x5c70b599f4da7e6c8271703a7677e703fa0cab9088232a1c0ee99aa3112fd51e", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x33c5435c783d711eca3cb21179f8afaf6dd0be8ca0f066d0daace28b17fc281d", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + } + ], + "accountUpdate": [ + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0x5ccb01b192af8237bf448abf2c7fb6531ce162936172524eac258b40f32f0812", + "path": [ + { + "value": "0xdae1cffcb0f5fe3e341a9a514f9c06a6feaac97547b8ee2db69b239b880b9e19", + "sibling": "0xf0a9432907471588a0e83aa9201193de159efe3b31e9112d6981c2be8ce45104" + } + ], + "leaf": { + "value": "0xaa040d2c798b9c0db0484dcb8461200c9a92fa6a76c1bb58ec582d2c2d2edd22", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0xe1aa47a8831f65f972375542bbb23710ec9c671be8e9eafe81d1bb7136aab928", + "path": [ + { + "value": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24", + "sibling": "0xf0a9432907471588a0e83aa9201193de159efe3b31e9112d6981c2be8ce45104" + } + ], + "leaf": { + "value": "0x882042a20c02edac064ed39dbcf5350bd3399c7747a7703d7960686e3101dd02", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + { + "nonce": 3, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d6a00d4dd70", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "nonce": 3, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d683461ce98", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "accountKey": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0xe1aa47a8831f65f972375542bbb23710ec9c671be8e9eafe81d1bb7136aab928", + "path": [ + { + "value": "0xf0a9432907471588a0e83aa9201193de159efe3b31e9112d6981c2be8ce45104", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x5c70b599f4da7e6c8271703a7677e703fa0cab9088232a1c0ee99aa3112fd51e", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x33c5435c783d711eca3cb21179f8afaf6dd0be8ca0f066d0daace28b17fc281d", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + }, + { + "pathPart": "0x1", + "root": "0xf09f669e4c99f58724043334be91d4474f70f1b893d7fd38764cec3917e65527", + "path": [ + { + "value": "0xe29200112e851398dda8f8932f2d348b9a1a13a247d81c6ad74a9102c220e62a", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x2ecc09123c5664b42e67e469c75a3692135a4d24b077a20c162fadf5ffde0f0c", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x4e7dad23bae2633b0173032b06fa8576108b3e9c12070849666bd3e38439a10a", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + } + ], + "accountUpdate": [ + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x1c5a77d9fa7ef466951b2f01f724bca3a5820b63", + "accountKey": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920", + "accountPath": [ + { + "pathPart": "0x0", + "root": "0xf09f669e4c99f58724043334be91d4474f70f1b893d7fd38764cec3917e65527", + "path": [ + { + "value": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24", + "sibling": "0xe29200112e851398dda8f8932f2d348b9a1a13a247d81c6ad74a9102c220e62a" + } + ], + "leaf": { + "value": "0x882042a20c02edac064ed39dbcf5350bd3399c7747a7703d7960686e3101dd02", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + }, + { + "pathPart": "0x0", + "root": "0xf09f669e4c99f58724043334be91d4474f70f1b893d7fd38764cec3917e65527", + "path": [ + { + "value": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24", + "sibling": "0xe29200112e851398dda8f8932f2d348b9a1a13a247d81c6ad74a9102c220e62a" + } + ], + "leaf": { + "value": "0x882042a20c02edac064ed39dbcf5350bd3399c7747a7703d7960686e3101dd02", + "sibling": "0x9c5a1607a0719e201f7325c41c2dc857a16eadd309bab5d1d93c7e1d15204920" + } + } + ], + "accountUpdate": [ + { + "nonce": 3, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d683461ce98", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "nonce": 3, + "balance": "0x1ffffffffffffffffffffffffffffffffffffffffffd5a5fa703d683461ce98", + "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + } + ], + "commonStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "statePath": [ + null, + null + ], + "stateUpdate": [ + null, + null + ] + }, + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "accountKey": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0xf09f669e4c99f58724043334be91d4474f70f1b893d7fd38764cec3917e65527", + "path": [ + { + "value": "0xe29200112e851398dda8f8932f2d348b9a1a13a247d81c6ad74a9102c220e62a", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x2ecc09123c5664b42e67e469c75a3692135a4d24b077a20c162fadf5ffde0f0c", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x4e7dad23bae2633b0173032b06fa8576108b3e9c12070849666bd3e38439a10a", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + }, + { + "pathPart": "0x1", + "root": "0x3ff0a2bcb6d82f6c65b9743f2167554a38c00f716d30bf176550e9bbf211de02", + "path": [ + { + "value": "0x1bfd41162e3f41ae3e58194190067b7106d4de0c16b555f8a3d962b7e75a9127", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0xb7a86f10915a67ec505541bdc1fe3e00ae12ff4f817c2a8ef8d8f72861531f1a", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x5ae28e9db9a7b45743017db7696411292e9af5adb0ff11737a8936b69ef28403", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + } + ], + "accountUpdate": [ + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + }, + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + } + ], + "stateKey": "0x84d07ce01938a8e3278d5a7b52cf4b853666886e48d30f623413b0a36e2b8e17", + "statePath": [ + { + "pathPart": "0x0", + "root": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "pathPart": "0x0", + "root": "0x9ed40c6ac1bdb532038ee26104d46ebe84b2184716fc96410c5228e05c901017", + "leaf": { + "value": "0x5cdff6c2c2ed92a182c2eeed8a689f39d0af361f9f15ceb8ffc2309f3a746920", + "sibling": "0x84d07ce01938a8e3278d5a7b52cf4b853666886e48d30f623413b0a36e2b8e17" + } + } + ], + "stateUpdate": [ + null, + { + "key": "0x0000000000000000000000000000000000000000000000000000000000000003", + "value": "0x5745544820636f696e0000000000000000000000000000000000000000000012" + } + ] + }, + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "accountKey": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0x3ff0a2bcb6d82f6c65b9743f2167554a38c00f716d30bf176550e9bbf211de02", + "path": [ + { + "value": "0x1bfd41162e3f41ae3e58194190067b7106d4de0c16b555f8a3d962b7e75a9127", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0xb7a86f10915a67ec505541bdc1fe3e00ae12ff4f817c2a8ef8d8f72861531f1a", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x5ae28e9db9a7b45743017db7696411292e9af5adb0ff11737a8936b69ef28403", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + }, + { + "pathPart": "0x1", + "root": "0x2e941dbce9c9463767e526ff1dc64448b54c4f38206985b291d08ff65f572c2b", + "path": [ + { + "value": "0x1f197a0287d09d7e4900d018a82a827087484a0df5333b12691a3cd4370ba911", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x9d5e14515e7dfae33e52c8267bc216c26e0a14e70235f5e562419a156a43a305", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x428cf4a59656f7c6327c6e90e01288157ce4d9e8de13c4868bbccd18d1fc112c", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + } + ], + "accountUpdate": [ + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + }, + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + } + ], + "stateKey": "0x8e1ee9fe8054b1fa6d3989af4e3ca88a801f67f4a497c85ca0fe469d89272923", + "statePath": [ + { + "pathPart": "0x0", + "root": "0x9ed40c6ac1bdb532038ee26104d46ebe84b2184716fc96410c5228e05c901017", + "leaf": { + "value": "0x5cdff6c2c2ed92a182c2eeed8a689f39d0af361f9f15ceb8ffc2309f3a746920", + "sibling": "0x84d07ce01938a8e3278d5a7b52cf4b853666886e48d30f623413b0a36e2b8e17" + } + }, + { + "pathPart": "0x2", + "root": "0x89e588c8124ca0250a33c78c46584d603e4c12cea897c47dfc6cefa83402c41e", + "path": [ + { + "value": "0x73719ac007efd4480d52c2f7803dd61d2647851dd99df6a81303d484b617e213", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x37dbfd51b8cacf779ca71e9cfc9d13acc3db6cb917642dd18ca03b10bd9a2f18", + "sibling": "0x9ed40c6ac1bdb532038ee26104d46ebe84b2184716fc96410c5228e05c901017" + } + ], + "leaf": { + "value": "0xf03a062f7dac12aa4a8e1ecf3706890ce02e02be5e95d00650d1c43b6f5d0026", + "sibling": "0x8e1ee9fe8054b1fa6d3989af4e3ca88a801f67f4a497c85ca0fe469d89272923" + } + } + ], + "stateUpdate": [ + null, + { + "key": "0x0000000000000000000000000000000000000000000000000000000000000004", + "value": "0x5745544800000000000000000000000000000000000000000000000000000008" + } + ] + }, + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "accountKey": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0x2e941dbce9c9463767e526ff1dc64448b54c4f38206985b291d08ff65f572c2b", + "path": [ + { + "value": "0x1f197a0287d09d7e4900d018a82a827087484a0df5333b12691a3cd4370ba911", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x9d5e14515e7dfae33e52c8267bc216c26e0a14e70235f5e562419a156a43a305", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x428cf4a59656f7c6327c6e90e01288157ce4d9e8de13c4868bbccd18d1fc112c", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + }, + { + "pathPart": "0x1", + "root": "0xf5ebd4c93bb15cd7e6be4adc0406d735327d712d6d0e5b6dd587739baca12907", + "path": [ + { + "value": "0xcd4f19c0ea5a8b7177bcdd705074451332d09ee076b071d08ac5bceb44566d19", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x088f92b5290bf701751c5bf33463ba87323c4546c0c059ce061c33fc759a9424", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x120a27869531ba07c327622f2e437105062409003b859a79bdd8673c7f989b29", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + } + ], + "accountUpdate": [ + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + }, + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + } + ], + "stateKey": "0x68af6119e1c208c6d4e4a54e37e40c0ae109e97895d0970707e4b8face49940e", + "statePath": [ + { + "pathPart": "0x0", + "root": "0x89e588c8124ca0250a33c78c46584d603e4c12cea897c47dfc6cefa83402c41e", + "path": [ + { + "value": "0x73719ac007efd4480d52c2f7803dd61d2647851dd99df6a81303d484b617e213", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x9ed40c6ac1bdb532038ee26104d46ebe84b2184716fc96410c5228e05c901017", + "sibling": "0x37dbfd51b8cacf779ca71e9cfc9d13acc3db6cb917642dd18ca03b10bd9a2f18" + } + ], + "leaf": { + "value": "0x5cdff6c2c2ed92a182c2eeed8a689f39d0af361f9f15ceb8ffc2309f3a746920", + "sibling": "0x84d07ce01938a8e3278d5a7b52cf4b853666886e48d30f623413b0a36e2b8e17" + } + }, + { + "pathPart": "0x0", + "root": "0xa2ca8943f203126deccf79c17dc15904e4f5c15961f7bf869cef74053802ea28", + "path": [ + { + "value": "0x6c1ec8ffe1a58a389a0e3b733d1213b88983aacab48d06d8d923fe3fc9d0422e", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0xfc8dcec425a54dcee11a565b2448cd4422d93b16e60ff73c484c2ce8e138b52b", + "sibling": "0x37dbfd51b8cacf779ca71e9cfc9d13acc3db6cb917642dd18ca03b10bd9a2f18" + }, + { + "value": "0x65a94cbfc1b45c9e0abd5e951a14145d5c8d10628e023b788358e5550d4a7824", + "sibling": "0x9ed40c6ac1bdb532038ee26104d46ebe84b2184716fc96410c5228e05c901017" + } + ], + "leaf": { + "value": "0xacce20d02c097a1d31fba5c0b1df801db982fc92bb9414a8587b800f52b6f61c", + "sibling": "0x68af6119e1c208c6d4e4a54e37e40c0ae109e97895d0970707e4b8face49940e" + } + } + ], + "stateUpdate": [ + null, + { + "key": "0x0000000000000000000000000000000000000000000000000000000000000005", + "value": "0x000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b630012" + } + ] + }, + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "accountKey": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0xf5ebd4c93bb15cd7e6be4adc0406d735327d712d6d0e5b6dd587739baca12907", + "path": [ + { + "value": "0xcd4f19c0ea5a8b7177bcdd705074451332d09ee076b071d08ac5bceb44566d19", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x088f92b5290bf701751c5bf33463ba87323c4546c0c059ce061c33fc759a9424", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x120a27869531ba07c327622f2e437105062409003b859a79bdd8673c7f989b29", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + }, + { + "pathPart": "0x1", + "root": "0xfea77ab872522019f637cb99a0a35fab9fd7584f55b818622f5d04c496d8d912", + "path": [ + { + "value": "0x8bc098f2af6fc222476a060d160298ae3f123e2ac7c601869229f369b225f40f", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x7c15f1737fc59c2a1afebe163ee856733a4a6b82de66d50843ab7b46a97a9909", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x000f9969c209a3805df18d1e43e7a40409553d4ff3753e4d0571a6e944b1c517", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + } + ], + "accountUpdate": [ + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + }, + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + } + ], + "stateKey": "0x046b3f7277dd2bb9226a061aa719407156457c66b932f8c7241f7b754470dc20", + "statePath": [ + { + "pathPart": "0x4", + "root": "0xa2ca8943f203126deccf79c17dc15904e4f5c15961f7bf869cef74053802ea28", + "path": [ + { + "value": "0x6c1ec8ffe1a58a389a0e3b733d1213b88983aacab48d06d8d923fe3fc9d0422e", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0xfc8dcec425a54dcee11a565b2448cd4422d93b16e60ff73c484c2ce8e138b52b", + "sibling": "0x37dbfd51b8cacf779ca71e9cfc9d13acc3db6cb917642dd18ca03b10bd9a2f18" + }, + { + "value": "0x9ed40c6ac1bdb532038ee26104d46ebe84b2184716fc96410c5228e05c901017", + "sibling": "0x65a94cbfc1b45c9e0abd5e951a14145d5c8d10628e023b788358e5550d4a7824" + } + ], + "leaf": { + "value": "0x5cdff6c2c2ed92a182c2eeed8a689f39d0af361f9f15ceb8ffc2309f3a746920", + "sibling": "0x84d07ce01938a8e3278d5a7b52cf4b853666886e48d30f623413b0a36e2b8e17" + } + }, + { + "pathPart": "0x4", + "root": "0x1f176cbfa5e0254f11c0146aa502cd1c84aac713c124c677b1bfafabf15f892b", + "path": [ + { + "value": "0x31a041ed93b6641f89e8295967d7cd4801aa8ca73e1f81e439122f36f3b7f710", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0xe5f76af6ebb792a20b480a6994b5c2264054d10c610fb8fbb75f2ab5ae9fcb01", + "sibling": "0x37dbfd51b8cacf779ca71e9cfc9d13acc3db6cb917642dd18ca03b10bd9a2f18" + }, + { + "value": "0x7d1b789f4a5411516280fd3b0104a3b5fdc5bbd6df8ea767168c373f15d8ff2d", + "sibling": "0x65a94cbfc1b45c9e0abd5e951a14145d5c8d10628e023b788358e5550d4a7824" + }, + { + "value": "0x3bdbeda9aef8d46ff022e68dff577618fe293b56e576f511353dc0345b89222d", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x0b20aef3078beadd95e24db8e1c2d204637fa6ad65a7177fb374818f7c953d1f", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x128c276138eb3d65b85b8c4444a6ce99c7c8f1bbf5346702ab7970a7afdc2123", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x1c3730c4f23bd1e76d6c9f8a2ae1374ef08b8d19c36afef8ffed8969fcfd9529", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x0658a357d896574c898607cb184a4c7f17e85191f40d1e7a0bfce95b8803f713", + "sibling": "0x9ed40c6ac1bdb532038ee26104d46ebe84b2184716fc96410c5228e05c901017" + } + ], + "leaf": { + "value": "0xa2c927e0a1f39fba117081072216e7c98a8ba79511734bb5e2ef40b12dcc2c12", + "sibling": "0x046b3f7277dd2bb9226a061aa719407156457c66b932f8c7241f7b754470dc20" + } + } + ], + "stateUpdate": [ + null, + { + "key": "0x0000000000000000000000000000000000000000000000000000000000000006", + "value": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63" + } + ] + }, + { + "address": "0x03f8133dd5ed58838b20af1296f62f44e69baa48", + "accountKey": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c", + "accountPath": [ + { + "pathPart": "0x1", + "root": "0xfea77ab872522019f637cb99a0a35fab9fd7584f55b818622f5d04c496d8d912", + "path": [ + { + "value": "0x8bc098f2af6fc222476a060d160298ae3f123e2ac7c601869229f369b225f40f", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0x7c15f1737fc59c2a1afebe163ee856733a4a6b82de66d50843ab7b46a97a9909", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0x000f9969c209a3805df18d1e43e7a40409553d4ff3753e4d0571a6e944b1c517", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + }, + { + "pathPart": "0x1", + "root": "0x1ca9391b065cb3cad3b75fdb7602bd07e9e201b6955f5599df71a6a2e22b7126", + "path": [ + { + "value": "0x6c8ac076e40ea7a2bacfa1f2eb4d16228358901eaeb2ff23de2617c2d69d761a", + "sibling": "0x549430921a06705ecd4ebf9a8635f5c735807a4d1aebcdaf6010c8241c8a7e24" + }, + { + "value": "0xc57a28be62e1405f969d7c595ca68ee57ff8c1ea8c1152110958fe5c04993b02", + "sibling": "0x2e591357b02ab3117c35ad94a4e1a724fdbd95d6463da1f6c8017e6d000ecf02" + } + ], + "leaf": { + "value": "0xa4d874cdd5069fb3049ab6fa98e8a38c4147b3aee9ee81c51898a1d95fd9d805", + "sibling": "0x357d8fb5134f3dc48eb1118c6a16ba14eee5d49fe9adaebd5879932694bf320c" + } + } + ], + "accountUpdate": [ + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + }, + { + "nonce": 1, + "balance": "0x0", + "codeHash": "0x07c28a1f146e6cc6b10bf3e1b0072b4e11300b7fe80d4543dc3bc8bef3e95843" + } + ], + "stateKey": "0x9e288b3b74343a5f7113836c1764ad0b125ea3cccfa1164bb0bf061d8f409e00", + "statePath": [ + { + "pathPart": "0x2", + "root": "0x1f176cbfa5e0254f11c0146aa502cd1c84aac713c124c677b1bfafabf15f892b", + "path": [ + { + "value": "0x31a041ed93b6641f89e8295967d7cd4801aa8ca73e1f81e439122f36f3b7f710", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x37dbfd51b8cacf779ca71e9cfc9d13acc3db6cb917642dd18ca03b10bd9a2f18", + "sibling": "0xe5f76af6ebb792a20b480a6994b5c2264054d10c610fb8fbb75f2ab5ae9fcb01" + } + ], + "leaf": { + "value": "0xf03a062f7dac12aa4a8e1ecf3706890ce02e02be5e95d00650d1c43b6f5d0026", + "sibling": "0x8e1ee9fe8054b1fa6d3989af4e3ca88a801f67f4a497c85ca0fe469d89272923" + } + }, + { + "pathPart": "0x1e", + "root": "0x6415bf82698d10370b73f5729ca9744ad2c933d642c1d59db83708e2eddfab25", + "path": [ + { + "value": "0x05d10e87783ea65c9d90f440ceb8c2f147012020a7dbd6f9fd95de35720dd616", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x8047642edb3ed776a59784d319750041a9721b507b98941a8c3d723039a52c1a", + "sibling": "0xe5f76af6ebb792a20b480a6994b5c2264054d10c610fb8fbb75f2ab5ae9fcb01" + }, + { + "value": "0x20b3db0acca1e9b17bb14d3990d75f2a112e1658c75a151bceb5976912a8072b", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0xd71ff7f2d6d380b7b5d964421c3306112edea7598b290d7c383873354ae0d31a", + "sibling": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "value": "0x82b38622562739a63a73c983080da4bf23621a5b834eed4bc96f8b60cabe7a29", + "sibling": "0x37dbfd51b8cacf779ca71e9cfc9d13acc3db6cb917642dd18ca03b10bd9a2f18" + } + ], + "leaf": { + "value": "0xa2c927e0a1f39fba117081072216e7c98a8ba79511734bb5e2ef40b12dcc2c12", + "sibling": "0x9e288b3b74343a5f7113836c1764ad0b125ea3cccfa1164bb0bf061d8f409e00" + } + } + ], + "stateUpdate": [ + null, + { + "key": "0x0000000000000000000000000000000000000000000000000000000000000007", + "value": "0x0000000000000000000000001c5a77d9fa7ef466951b2f01f724bca3a5820b63" + } + ] + } + ] +} diff --git a/bridge/tests/bridge_test.go b/bridge/tests/bridge_test.go index 9fca99efc..7f6665bdd 100644 --- a/bridge/tests/bridge_test.go +++ b/bridge/tests/bridge_test.go @@ -9,11 +9,15 @@ import ( "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/stretchr/testify/assert" - - bcmd "scroll-tech/bridge/cmd" - "scroll-tech/bridge/mock_bridge" + "gorm.io/gorm" "scroll-tech/common/docker" + + bcmd "scroll-tech/bridge/cmd" + "scroll-tech/bridge/internal/config" + "scroll-tech/bridge/internal/orm/migrate" + "scroll-tech/bridge/internal/utils" + "scroll-tech/bridge/mock_bridge" ) var ( @@ -41,9 +45,24 @@ var ( l2MessengerAddress common.Address ) +func setupDB(t *testing.T) *gorm.DB { + cfg := &config.DBConfig{ + DSN: base.DBConfig.DSN, + DriverName: base.DBConfig.DriverName, + MaxOpenNum: base.DBConfig.MaxOpenNum, + MaxIdleNum: base.DBConfig.MaxIdleNum, + } + db, err := utils.InitDB(cfg) + assert.NoError(t, err) + sqlDB, err := db.DB() + assert.NoError(t, err) + assert.NoError(t, migrate.ResetDB(sqlDB)) + return db +} + func TestMain(m *testing.M) { base = docker.NewDockerApp() - bridgeApp = bcmd.NewBridgeApp(base, "../config.json") + bridgeApp = bcmd.NewBridgeApp(base, "../conf/config.json") m.Run() bridgeApp.Free() base.Free() diff --git a/bridge/tests/gas_oracle_test.go b/bridge/tests/gas_oracle_test.go index eb5a07c8a..643881576 100644 --- a/bridge/tests/gas_oracle_test.go +++ b/bridge/tests/gas_oracle_test.go @@ -6,24 +6,22 @@ import ( "testing" "github.com/scroll-tech/go-ethereum/common" - geth_types "github.com/scroll-tech/go-ethereum/core/types" + gethTypes "github.com/scroll-tech/go-ethereum/core/types" "github.com/stretchr/testify/assert" + "gorm.io/gorm" "scroll-tech/common/types" - "scroll-tech/bridge/relayer" - "scroll-tech/bridge/watcher" - - "scroll-tech/database" - "scroll-tech/database/migrate" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/controller/watcher" + "scroll-tech/bridge/internal/orm" + bridgeTypes "scroll-tech/bridge/internal/types" + "scroll-tech/bridge/internal/utils" ) func testImportL1GasPrice(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(base.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupDB(t) + defer utils.CloseDB(db) prepareContracts(t) @@ -45,48 +43,39 @@ func testImportL1GasPrice(t *testing.T) { err = l1Watcher.FetchBlockHeader(number) assert.NoError(t, err) + l1BlockOrm := orm.NewL1Block(db) // check db status - latestBlockHeight, err := db.GetLatestL1BlockHeight() + latestBlockHeight, err := l1BlockOrm.GetLatestL1BlockHeight() assert.NoError(t, err) assert.Equal(t, number, latestBlockHeight) - blocks, err := db.GetL1BlockInfos(map[string]interface{}{ - "number": latestBlockHeight, - }) + blocks, err := l1BlockOrm.GetL1Blocks(map[string]interface{}{"number": latestBlockHeight}) assert.NoError(t, err) assert.Equal(t, len(blocks), 1) - assert.Equal(t, blocks[0].GasOracleStatus, types.GasOraclePending) - assert.Equal(t, blocks[0].OracleTxHash.Valid, false) + assert.Empty(t, blocks[0].OracleTxHash) + assert.Equal(t, types.GasOracleStatus(blocks[0].GasOracleStatus), types.GasOraclePending) // relay gas price l1Relayer.ProcessGasPriceOracle() - blocks, err = db.GetL1BlockInfos(map[string]interface{}{ - "number": latestBlockHeight, - }) + blocks, err = l1BlockOrm.GetL1Blocks(map[string]interface{}{"number": latestBlockHeight}) assert.NoError(t, err) assert.Equal(t, len(blocks), 1) - assert.Equal(t, blocks[0].GasOracleStatus, types.GasOracleImporting) - assert.Equal(t, blocks[0].OracleTxHash.Valid, true) + assert.NotEmpty(t, blocks[0].OracleTxHash) + assert.Equal(t, types.GasOracleStatus(blocks[0].GasOracleStatus), types.GasOracleImporting) } func testImportL2GasPrice(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(base.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() - + db := setupDB(t) + defer utils.CloseDB(db) prepareContracts(t) l2Cfg := bridgeApp.Config.L2Config - - // Create L2Relayer l2Relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Client, db, l2Cfg.RelayerConfig) assert.NoError(t, err) // add fake blocks - traces := []*types.WrappedBlock{ + traces := []*bridgeTypes.WrappedBlock{ { - Header: &geth_types.Header{ + Header: &gethTypes.Header{ Number: big.NewInt(1), ParentHash: common.Hash{}, Difficulty: big.NewInt(0), @@ -96,32 +85,35 @@ func testImportL2GasPrice(t *testing.T) { WithdrawTrieRoot: common.Hash{}, }, } - assert.NoError(t, db.InsertWrappedBlocks(traces)) - parentBatch := &types.BlockBatch{ + blockTraceOrm := orm.NewBlockTrace(db) + assert.NoError(t, blockTraceOrm.InsertWrappedBlocks(traces)) + + parentBatch := &bridgeTypes.BatchInfo{ Index: 0, Hash: "0x0000000000000000000000000000000000000000", } - batchData := types.NewBatchData(parentBatch, []*types.WrappedBlock{ - traces[0], - }, l2Cfg.BatchProposerConfig.PublicInputConfig) - - // add fake batch - dbTx, err := db.Beginx() + batchData := bridgeTypes.NewBatchData(parentBatch, []*bridgeTypes.WrappedBlock{traces[0]}, l2Cfg.BatchProposerConfig.PublicInputConfig) + blockBatchOrm := orm.NewBlockBatch(db) + err = db.Transaction(func(tx *gorm.DB) error { + _, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batchData) + if dbTxErr != nil { + return dbTxErr + } + return nil + }) assert.NoError(t, err) - assert.NoError(t, db.NewBatchInDBTx(dbTx, batchData)) - assert.NoError(t, dbTx.Commit()) // check db status - batch, err := db.GetLatestBatch() + batch, err := blockBatchOrm.GetLatestBatch() assert.NoError(t, err) - assert.Equal(t, batch.OracleStatus, types.GasOraclePending) - assert.Equal(t, batch.OracleTxHash.Valid, false) + assert.Empty(t, batch.OracleTxHash) + assert.Equal(t, types.GasOracleStatus(batch.OracleStatus), types.GasOraclePending) // relay gas price l2Relayer.ProcessGasPriceOracle() - batch, err = db.GetLatestBatch() + batch, err = blockBatchOrm.GetLatestBatch() assert.NoError(t, err) - assert.Equal(t, batch.OracleStatus, types.GasOracleImporting) - assert.Equal(t, batch.OracleTxHash.Valid, true) + assert.NotEmpty(t, batch.OracleTxHash) + assert.Equal(t, types.GasOracleStatus(batch.OracleStatus), types.GasOracleImporting) } diff --git a/bridge/tests/l1_message_relay_test.go b/bridge/tests/l1_message_relay_test.go index b6048f46d..30de008c4 100644 --- a/bridge/tests/l1_message_relay_test.go +++ b/bridge/tests/l1_message_relay_test.go @@ -13,19 +13,15 @@ import ( "scroll-tech/common/types" - "scroll-tech/bridge/relayer" - "scroll-tech/bridge/watcher" - - "scroll-tech/database" - "scroll-tech/database/migrate" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/controller/watcher" + "scroll-tech/bridge/internal/orm" + "scroll-tech/bridge/internal/utils" ) func testRelayL1MessageSucceed(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(base.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupDB(t) + defer utils.CloseDB(db) prepareContracts(t) @@ -56,21 +52,22 @@ func testRelayL1MessageSucceed(t *testing.T) { // l1 watch process events l1Watcher.FetchContractEvent() + l1MessageOrm := orm.NewL1Message(db) // check db status - msg, err := db.GetL1MessageByQueueIndex(nonce.Uint64()) + msg, err := l1MessageOrm.GetL1MessageByQueueIndex(nonce.Uint64()) assert.NoError(t, err) - assert.Equal(t, msg.Status, types.MsgPending) + assert.Equal(t, types.MsgStatus(msg.Status), types.MsgPending) assert.Equal(t, msg.Target, l2Auth.From.String()) // process l1 messages l1Relayer.ProcessSavedEvents() - msg, err = db.GetL1MessageByQueueIndex(nonce.Uint64()) + + l1Message, err := l1MessageOrm.GetL1MessageByQueueIndex(nonce.Uint64()) assert.NoError(t, err) - assert.Equal(t, msg.Status, types.MsgSubmitted) - relayTxHash, err := db.GetRelayL1MessageTxHash(nonce.Uint64()) - assert.NoError(t, err) - assert.Equal(t, true, relayTxHash.Valid) - relayTx, _, err := l2Client.TransactionByHash(context.Background(), common.HexToHash(relayTxHash.String)) + assert.NotEmpty(t, l1Message.Layer2Hash) + assert.Equal(t, types.MsgStatus(l1Message.Status), types.MsgSubmitted) + + relayTx, _, err := l2Client.TransactionByHash(context.Background(), common.HexToHash(l1Message.Layer2Hash)) assert.NoError(t, err) relayTxReceipt, err := bind.WaitMined(context.Background(), l2Client, relayTx) assert.NoError(t, err) @@ -78,7 +75,7 @@ func testRelayL1MessageSucceed(t *testing.T) { // fetch message relayed events l2Watcher.FetchContractEvent() - msg, err = db.GetL1MessageByQueueIndex(nonce.Uint64()) + msg, err = l1MessageOrm.GetL1MessageByQueueIndex(nonce.Uint64()) assert.NoError(t, err) - assert.Equal(t, msg.Status, types.MsgConfirmed) + assert.Equal(t, types.MsgStatus(msg.Status), types.MsgConfirmed) } diff --git a/bridge/tests/l2_message_relay_test.go b/bridge/tests/l2_message_relay_test.go index e4da97905..348a1edf2 100644 --- a/bridge/tests/l2_message_relay_test.go +++ b/bridge/tests/l2_message_relay_test.go @@ -2,30 +2,29 @@ package tests import ( "context" + "errors" "math/big" "testing" "github.com/scroll-tech/go-ethereum/accounts/abi/bind" "github.com/scroll-tech/go-ethereum/common" - geth_types "github.com/scroll-tech/go-ethereum/core/types" + gethTypes "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/rpc" "github.com/stretchr/testify/assert" + "gorm.io/gorm" "scroll-tech/common/types" - "scroll-tech/bridge/relayer" - "scroll-tech/bridge/watcher" - - "scroll-tech/database" - "scroll-tech/database/migrate" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/controller/watcher" + "scroll-tech/bridge/internal/orm" + bridgeTypes "scroll-tech/bridge/internal/types" + "scroll-tech/bridge/internal/utils" ) func testRelayL2MessageSucceed(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(base.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupDB(t) + defer utils.CloseDB(db) prepareContracts(t) @@ -50,24 +49,27 @@ func testRelayL2MessageSucceed(t *testing.T) { assert.NoError(t, err) sendReceipt, err := bind.WaitMined(context.Background(), l2Client, sendTx) assert.NoError(t, err) - if sendReceipt.Status != geth_types.ReceiptStatusSuccessful || err != nil { + if sendReceipt.Status != gethTypes.ReceiptStatusSuccessful || err != nil { t.Fatalf("Call failed") } // l2 watch process events l2Watcher.FetchContractEvent() + l2MessageOrm := orm.NewL2Message(db) + blockTraceOrm := orm.NewBlockTrace(db) + blockBatchOrm := orm.NewBlockBatch(db) // check db status - msg, err := db.GetL2MessageByNonce(nonce.Uint64()) + msg, err := l2MessageOrm.GetL2MessageByNonce(nonce.Uint64()) assert.NoError(t, err) - assert.Equal(t, msg.Status, types.MsgPending) + assert.Equal(t, types.MsgStatus(msg.Status), types.MsgPending) assert.Equal(t, msg.Sender, l2Auth.From.String()) assert.Equal(t, msg.Target, l1Auth.From.String()) // add fake blocks - traces := []*types.WrappedBlock{ + traces := []*bridgeTypes.WrappedBlock{ { - Header: &geth_types.Header{ + Header: &gethTypes.Header{ Number: sendReceipt.BlockNumber, ParentHash: common.Hash{}, Difficulty: big.NewInt(0), @@ -77,46 +79,54 @@ func testRelayL2MessageSucceed(t *testing.T) { WithdrawTrieRoot: common.Hash{}, }, } - assert.NoError(t, db.InsertWrappedBlocks(traces)) + assert.NoError(t, blockTraceOrm.InsertWrappedBlocks(traces)) - parentBatch := &types.BlockBatch{ + parentBatch := &bridgeTypes.BatchInfo{ Index: 0, Hash: "0x0000000000000000000000000000000000000000", } - batchData := types.NewBatchData(parentBatch, []*types.WrappedBlock{ - traces[0], - }, l2Cfg.BatchProposerConfig.PublicInputConfig) + batchData := bridgeTypes.NewBatchData(parentBatch, []*bridgeTypes.WrappedBlock{traces[0]}, l2Cfg.BatchProposerConfig.PublicInputConfig) batchHash := batchData.Hash().String() - // add fake batch - dbTx, err := db.Beginx() + err = db.Transaction(func(tx *gorm.DB) error { + rowsAffected, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batchData) + if dbTxErr != nil { + return dbTxErr + } + if rowsAffected != 1 { + dbTxErr = errors.New("the InsertBlockBatchByBatchData affected row is not 1") + return dbTxErr + } + var blockIDs = make([]uint64, len(batchData.Batch.Blocks)) + for i, block := range batchData.Batch.Blocks { + blockIDs[i] = block.BlockNumber + } + dbTxErr = blockTraceOrm.UpdateBatchHashForL2Blocks(tx, blockIDs, batchHash) + if dbTxErr != nil { + return dbTxErr + } + return nil + }) assert.NoError(t, err) - assert.NoError(t, db.NewBatchInDBTx(dbTx, batchData)) - var blockIDs = make([]uint64, len(batchData.Batch.Blocks)) - for i, block := range batchData.Batch.Blocks { - blockIDs[i] = block.BlockNumber - } - err = db.SetBatchHashForL2BlocksInDBTx(dbTx, blockIDs, batchHash) - assert.NoError(t, err) - assert.NoError(t, dbTx.Commit()) // add dummy proof tProof := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} tInstanceCommitments := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} - err = db.UpdateProofByHash(context.Background(), batchHash, tProof, tInstanceCommitments, 100) + err = blockBatchOrm.UpdateProofByHash(context.Background(), batchHash, tProof, tInstanceCommitments, 100) assert.NoError(t, err) - err = db.UpdateProvingStatus(batchHash, types.ProvingTaskVerified) + err = blockBatchOrm.UpdateProvingStatus(batchHash, types.ProvingTaskVerified) assert.NoError(t, err) // process pending batch and check status - l2Relayer.SendCommitTx([]*types.BatchData{batchData}) - status, err := db.GetRollupStatus(batchHash) + assert.NoError(t, l2Relayer.SendCommitTx([]*bridgeTypes.BatchData{batchData})) + + blockBatches, err := blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batchHash}, nil, 1) assert.NoError(t, err) - assert.Equal(t, types.RollupCommitting, status) - commitTxHash, err := db.GetCommitTxHash(batchHash) - assert.NoError(t, err) - assert.Equal(t, true, commitTxHash.Valid) - commitTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(commitTxHash.String)) + assert.Equal(t, 1, len(blockBatches)) + assert.NotEmpty(t, blockBatches[0].CommitTxHash) + assert.Equal(t, types.RollupCommitting, types.RollupStatus(blockBatches[0].RollupStatus)) + + commitTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(blockBatches[0].CommitTxHash)) assert.NoError(t, err) commitTxReceipt, err := bind.WaitMined(context.Background(), l1Client, commitTx) assert.NoError(t, err) @@ -125,19 +135,21 @@ func testRelayL2MessageSucceed(t *testing.T) { // fetch CommitBatch rollup events err = l1Watcher.FetchContractEvent() assert.NoError(t, err) - status, err = db.GetRollupStatus(batchHash) + statuses, err := blockBatchOrm.GetRollupStatusByHashList([]string{batchHash}) assert.NoError(t, err) - assert.Equal(t, types.RollupCommitted, status) + assert.Equal(t, 1, len(statuses)) + assert.Equal(t, types.RollupCommitted, statuses[0]) // process committed batch and check status l2Relayer.ProcessCommittedBatches() - status, err = db.GetRollupStatus(batchHash) + + blockBatchWithFinalizeTxHash, err := blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batchHash}, nil, 1) assert.NoError(t, err) - assert.Equal(t, types.RollupFinalizing, status) - finalizeTxHash, err := db.GetFinalizeTxHash(batchHash) - assert.NoError(t, err) - assert.Equal(t, true, finalizeTxHash.Valid) - finalizeTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(finalizeTxHash.String)) + assert.Equal(t, 1, len(blockBatchWithFinalizeTxHash)) + assert.NotEmpty(t, blockBatchWithFinalizeTxHash[0].FinalizeTxHash) + assert.Equal(t, types.RollupFinalizing, types.RollupStatus(blockBatchWithFinalizeTxHash[0].RollupStatus)) + + finalizeTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(blockBatchWithFinalizeTxHash[0].FinalizeTxHash)) assert.NoError(t, err) finalizeTxReceipt, err := bind.WaitMined(context.Background(), l1Client, finalizeTx) assert.NoError(t, err) @@ -146,19 +158,21 @@ func testRelayL2MessageSucceed(t *testing.T) { // fetch FinalizeBatch events err = l1Watcher.FetchContractEvent() assert.NoError(t, err) - status, err = db.GetRollupStatus(batchHash) + statuses, err = blockBatchOrm.GetRollupStatusByHashList([]string{batchHash}) assert.NoError(t, err) - assert.Equal(t, types.RollupFinalized, status) + assert.Equal(t, 1, len(statuses)) + assert.Equal(t, types.RollupFinalized, statuses[0]) // process l2 messages l2Relayer.ProcessSavedEvents() - msg, err = db.GetL2MessageByNonce(nonce.Uint64()) + + l2Messages, err := l2MessageOrm.GetL2Messages(map[string]interface{}{"nonce": nonce.Uint64()}, nil, 1) assert.NoError(t, err) - assert.Equal(t, msg.Status, types.MsgSubmitted) - relayTxHash, err := db.GetRelayL2MessageTxHash(nonce.Uint64()) - assert.NoError(t, err) - assert.Equal(t, true, relayTxHash.Valid) - relayTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(relayTxHash.String)) + assert.Equal(t, 1, len(l2Messages)) + assert.NotEmpty(t, l2Messages[0].Layer1Hash) + assert.Equal(t, types.MsgStatus(l2Messages[0].Status), types.MsgSubmitted) + + relayTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(l2Messages[0].Layer1Hash)) assert.NoError(t, err) relayTxReceipt, err := bind.WaitMined(context.Background(), l1Client, relayTx) assert.NoError(t, err) @@ -167,7 +181,7 @@ func testRelayL2MessageSucceed(t *testing.T) { // fetch message relayed events err = l1Watcher.FetchContractEvent() assert.NoError(t, err) - msg, err = db.GetL2MessageByNonce(nonce.Uint64()) + msg, err = l2MessageOrm.GetL2MessageByNonce(nonce.Uint64()) assert.NoError(t, err) - assert.Equal(t, msg.Status, types.MsgConfirmed) + assert.Equal(t, types.MsgStatus(msg.Status), types.MsgConfirmed) } diff --git a/bridge/tests/rollup_test.go b/bridge/tests/rollup_test.go index bf6688bf0..7fb7ca29a 100644 --- a/bridge/tests/rollup_test.go +++ b/bridge/tests/rollup_test.go @@ -2,30 +2,28 @@ package tests import ( "context" + "errors" "math/big" "testing" "github.com/scroll-tech/go-ethereum/accounts/abi/bind" "github.com/scroll-tech/go-ethereum/common" - geth_types "github.com/scroll-tech/go-ethereum/core/types" + gethTypes "github.com/scroll-tech/go-ethereum/core/types" "github.com/stretchr/testify/assert" + "gorm.io/gorm" "scroll-tech/common/types" - "scroll-tech/common/utils" - "scroll-tech/bridge/relayer" - "scroll-tech/bridge/watcher" - - "scroll-tech/database" - "scroll-tech/database/migrate" + "scroll-tech/bridge/internal/controller/relayer" + "scroll-tech/bridge/internal/controller/watcher" + "scroll-tech/bridge/internal/orm" + bridgeTypes "scroll-tech/bridge/internal/types" + "scroll-tech/bridge/internal/utils" ) func testCommitBatchAndFinalizeBatch(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(base.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() + db := setupDB(t) + defer utils.CloseDB(db) prepareContracts(t) @@ -38,58 +36,73 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) { l1Cfg := bridgeApp.Config.L1Config l1Watcher := watcher.NewL1WatcherClient(context.Background(), l1Client, 0, l1Cfg.Confirmations, l1Cfg.L1MessengerAddress, l1Cfg.L1MessageQueueAddress, l1Cfg.ScrollChainContractAddress, db) + blockTraceOrm := orm.NewBlockTrace(db) + // add some blocks to db - var wrappedBlocks []*types.WrappedBlock + var wrappedBlocks []*bridgeTypes.WrappedBlock var parentHash common.Hash for i := 1; i <= 10; i++ { - header := geth_types.Header{ + header := gethTypes.Header{ Number: big.NewInt(int64(i)), ParentHash: parentHash, Difficulty: big.NewInt(0), BaseFee: big.NewInt(0), } - wrappedBlocks = append(wrappedBlocks, &types.WrappedBlock{ + wrappedBlocks = append(wrappedBlocks, &bridgeTypes.WrappedBlock{ Header: &header, Transactions: nil, WithdrawTrieRoot: common.Hash{}, }) parentHash = header.Hash() } - assert.NoError(t, db.InsertWrappedBlocks(wrappedBlocks)) + assert.NoError(t, blockTraceOrm.InsertWrappedBlocks(wrappedBlocks)) - parentBatch := &types.BlockBatch{ + parentBatch := &bridgeTypes.BatchInfo{ Index: 0, Hash: "0x0000000000000000000000000000000000000000", } - batchData := types.NewBatchData(parentBatch, []*types.WrappedBlock{ + + tmpWrapBlocks := []*bridgeTypes.WrappedBlock{ wrappedBlocks[0], wrappedBlocks[1], - }, l2Cfg.BatchProposerConfig.PublicInputConfig) + } + batchData := bridgeTypes.NewBatchData(parentBatch, tmpWrapBlocks, l2Cfg.BatchProposerConfig.PublicInputConfig) batchHash := batchData.Hash().String() - // add one batch to db - dbTx, err := db.Beginx() + blockBatchOrm := orm.NewBlockBatch(db) + err = db.Transaction(func(tx *gorm.DB) error { + rowsAffected, dbTxErr := blockBatchOrm.InsertBlockBatchByBatchData(tx, batchData) + if dbTxErr != nil { + return dbTxErr + } + if rowsAffected != 1 { + dbTxErr = errors.New("the InsertBlockBatchByBatchData affected row is not 1") + return dbTxErr + } + var blockIDs = make([]uint64, len(batchData.Batch.Blocks)) + for i, block := range batchData.Batch.Blocks { + blockIDs[i] = block.BlockNumber + } + dbTxErr = blockTraceOrm.UpdateBatchHashForL2Blocks(tx, blockIDs, batchHash) + if dbTxErr != nil { + return dbTxErr + } + return nil + }) assert.NoError(t, err) - assert.NoError(t, db.NewBatchInDBTx(dbTx, batchData)) - var blockIDs = make([]uint64, len(batchData.Batch.Blocks)) - for i, block := range batchData.Batch.Blocks { - blockIDs[i] = block.BlockNumber - } - err = db.SetBatchHashForL2BlocksInDBTx(dbTx, blockIDs, batchHash) - assert.NoError(t, err) - assert.NoError(t, dbTx.Commit()) // process pending batch and check status - assert.NoError(t, l2Relayer.SendCommitTx([]*types.BatchData{batchData})) + assert.NoError(t, l2Relayer.SendCommitTx([]*bridgeTypes.BatchData{batchData})) - status, err := db.GetRollupStatus(batchHash) + blockBatches, err := blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batchHash}, nil, 1) assert.NoError(t, err) - assert.Equal(t, types.RollupCommitting, status) - commitTxHash, err := db.GetCommitTxHash(batchHash) - assert.NoError(t, err) - assert.Equal(t, true, commitTxHash.Valid) - commitTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(commitTxHash.String)) + assert.Equal(t, 1, len(blockBatches)) + assert.NotEmpty(t, true, blockBatches[0].CommitTxHash) + assert.NotEmpty(t, true, blockBatches[0].RollupStatus) + assert.Equal(t, types.RollupStatus(blockBatches[0].RollupStatus), types.RollupCommitting) + + commitTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(blockBatches[0].CommitTxHash)) assert.NoError(t, err) commitTxReceipt, err := bind.WaitMined(context.Background(), l1Client, commitTx) assert.NoError(t, err) @@ -98,33 +111,33 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) { // fetch rollup events err = l1Watcher.FetchContractEvent() assert.NoError(t, err) - ok := utils.TryTimes(20, func() bool { - status, err = db.GetRollupStatus(batchHash) - return err == nil && status == types.RollupCommitted - }) - assert.True(t, ok) + statuses, err := blockBatchOrm.GetRollupStatusByHashList([]string{batchHash}) + assert.NoError(t, err) + assert.Equal(t, 1, len(statuses)) + assert.Equal(t, types.RollupCommitted, statuses[0]) // add dummy proof tProof := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} tInstanceCommitments := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} - err = db.UpdateProofByHash(context.Background(), batchHash, tProof, tInstanceCommitments, 100) + err = blockBatchOrm.UpdateProofByHash(context.Background(), batchHash, tProof, tInstanceCommitments, 100) assert.NoError(t, err) - err = db.UpdateProvingStatus(batchHash, types.ProvingTaskVerified) + err = blockBatchOrm.UpdateProvingStatus(batchHash, types.ProvingTaskVerified) assert.NoError(t, err) // process committed batch and check status l2Relayer.ProcessCommittedBatches() - ok = utils.TryTimes(20, func() bool { - status, err = db.GetRollupStatus(batchHash) - return err == nil && status == types.RollupFinalizing - }) - assert.True(t, ok) - - finalizeTxHash, err := db.GetFinalizeTxHash(batchHash) + statuses, err = blockBatchOrm.GetRollupStatusByHashList([]string{batchHash}) assert.NoError(t, err) - assert.Equal(t, true, finalizeTxHash.Valid) - finalizeTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(finalizeTxHash.String)) + assert.Equal(t, 1, len(statuses)) + assert.Equal(t, types.RollupFinalizing, statuses[0]) + + blockBatches, err = blockBatchOrm.GetBlockBatches(map[string]interface{}{"hash": batchHash}, nil, 1) + assert.NoError(t, err) + assert.Equal(t, 1, len(blockBatches)) + assert.NotEmpty(t, blockBatches[0].FinalizeTxHash) + + finalizeTx, _, err := l1Client.TransactionByHash(context.Background(), common.HexToHash(blockBatches[0].FinalizeTxHash)) assert.NoError(t, err) finalizeTxReceipt, err := bind.WaitMined(context.Background(), l1Client, finalizeTx) assert.NoError(t, err) @@ -133,7 +146,8 @@ func testCommitBatchAndFinalizeBatch(t *testing.T) { // fetch rollup events err = l1Watcher.FetchContractEvent() assert.NoError(t, err) - status, err = db.GetRollupStatus(batchHash) + statuses, err = blockBatchOrm.GetRollupStatusByHashList([]string{batchHash}) assert.NoError(t, err) - assert.Equal(t, types.RollupFinalized, status) + assert.Equal(t, 1, len(statuses)) + assert.Equal(t, types.RollupFinalized, statuses[0]) } diff --git a/bridge/watcher/batch_proposer_test.go b/bridge/watcher/batch_proposer_test.go deleted file mode 100644 index 1401c6c6e..000000000 --- a/bridge/watcher/batch_proposer_test.go +++ /dev/null @@ -1,199 +0,0 @@ -package watcher - -import ( - "context" - "fmt" - "math" - "strings" - "testing" - "time" - - "github.com/agiledragon/gomonkey/v2" - "github.com/scroll-tech/go-ethereum/common" - geth_types "github.com/scroll-tech/go-ethereum/core/types" - "github.com/stretchr/testify/assert" - - "scroll-tech/database" - "scroll-tech/database/migrate" - - "scroll-tech/bridge/config" - "scroll-tech/bridge/relayer" - - "scroll-tech/common/types" -) - -func testBatchProposerProposeBatch(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() - - p := &BatchProposer{ - batchGasThreshold: 1000, - batchTxNumThreshold: 10, - batchTimeSec: 300, - commitCalldataSizeLimit: 500, - orm: db, - } - patchGuard := gomonkey.ApplyMethodFunc(p.orm, "GetL2WrappedBlocks", func(fields map[string]interface{}, args ...string) ([]*types.WrappedBlock, error) { - hash, _ := fields["hash"].(string) - if hash == "blockWithLongData" { - longData := strings.Repeat("0", 1000) - return []*types.WrappedBlock{{ - Transactions: []*geth_types.TransactionData{{ - Data: longData, - }}, - }}, nil - } - return []*types.WrappedBlock{{ - Transactions: []*geth_types.TransactionData{{ - Data: "short", - }}, - }}, nil - }) - defer patchGuard.Reset() - patchGuard.ApplyPrivateMethod(p, "createBatchForBlocks", func(*BatchProposer, []*types.BlockInfo) error { - return nil - }) - - block1 := &types.BlockInfo{Number: 1, GasUsed: 100, TxNum: 1, BlockTimestamp: uint64(time.Now().Unix()) - 200} - block2 := &types.BlockInfo{Number: 2, GasUsed: 200, TxNum: 2, BlockTimestamp: uint64(time.Now().Unix())} - block3 := &types.BlockInfo{Number: 3, GasUsed: 300, TxNum: 11, BlockTimestamp: uint64(time.Now().Unix())} - block4 := &types.BlockInfo{Number: 4, GasUsed: 1001, TxNum: 3, BlockTimestamp: uint64(time.Now().Unix())} - blockOutdated := &types.BlockInfo{Number: 1, GasUsed: 100, TxNum: 1, BlockTimestamp: uint64(time.Now().Add(-400 * time.Second).Unix())} - blockWithLongData := &types.BlockInfo{Hash: "blockWithLongData", Number: 5, GasUsed: 500, TxNum: 1, BlockTimestamp: uint64(time.Now().Unix())} - - testCases := []struct { - description string - blocks []*types.BlockInfo - expectedRes bool - }{ - {"Empty block list", []*types.BlockInfo{}, false}, - {"Single block exceeding gas threshold", []*types.BlockInfo{block4}, true}, - {"Single block exceeding transaction number threshold", []*types.BlockInfo{block3}, true}, - {"Multiple blocks meeting thresholds", []*types.BlockInfo{block1, block2, block3}, true}, - {"Multiple blocks not meeting thresholds", []*types.BlockInfo{block1, block2}, false}, - {"Outdated and valid block", []*types.BlockInfo{blockOutdated, block2}, true}, - {"Single block with long data", []*types.BlockInfo{blockWithLongData}, true}, - } - - for _, tc := range testCases { - t.Run(tc.description, func(t *testing.T) { - assert.Equal(t, tc.expectedRes, p.proposeBatch(tc.blocks), "Failed on: %s", tc.description) - }) - } -} - -func testBatchProposerBatchGeneration(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - ctx := context.Background() - subCtx, cancel := context.WithCancel(ctx) - - defer func() { - cancel() - db.Close() - }() - - // Insert traces into db. - assert.NoError(t, db.InsertWrappedBlocks([]*types.WrappedBlock{wrappedBlock1})) - - l2cfg := cfg.L2Config - wc := NewL2WatcherClient(context.Background(), l2Cli, l2cfg.Confirmations, l2cfg.L2MessengerAddress, l2cfg.L2MessageQueueAddress, l2cfg.WithdrawTrieRootSlot, db) - loopToFetchEvent(subCtx, wc) - - batch, err := db.GetLatestBatch() - assert.NoError(t, err) - - // Create a new batch. - batchData := types.NewBatchData(&types.BlockBatch{ - Index: 0, - Hash: batch.Hash, - StateRoot: batch.StateRoot, - }, []*types.WrappedBlock{wrappedBlock1}, nil) - - relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Cli, db, cfg.L2Config.RelayerConfig) - assert.NoError(t, err) - - proposer := NewBatchProposer(context.Background(), &config.BatchProposerConfig{ - ProofGenerationFreq: 1, - BatchGasThreshold: 3000000, - BatchTxNumThreshold: 135, - BatchTimeSec: 1, - BatchBlocksLimit: 100, - }, relayer, db) - proposer.TryProposeBatch() - - infos, err := db.GetUnbatchedL2Blocks(map[string]interface{}{}, - fmt.Sprintf("order by number ASC LIMIT %d", 100)) - assert.NoError(t, err) - assert.Equal(t, 0, len(infos)) - - exist, err := db.BatchRecordExist(batchData.Hash().Hex()) - assert.NoError(t, err) - assert.Equal(t, true, exist) -} - -func testBatchProposerGracefulRestart(t *testing.T) { - // Create db handler and reset db. - db, err := database.NewOrmFactory(cfg.DBConfig) - assert.NoError(t, err) - assert.NoError(t, migrate.ResetDB(db.GetDB().DB)) - defer db.Close() - - relayer, err := relayer.NewLayer2Relayer(context.Background(), l2Cli, db, cfg.L2Config.RelayerConfig) - assert.NoError(t, err) - - // Insert traces into db. - assert.NoError(t, db.InsertWrappedBlocks([]*types.WrappedBlock{wrappedBlock2})) - - // Insert block batch into db. - batchData1 := types.NewBatchData(&types.BlockBatch{ - Index: 0, - Hash: common.Hash{}.String(), - StateRoot: common.Hash{}.String(), - }, []*types.WrappedBlock{wrappedBlock1}, nil) - - parentBatch2 := &types.BlockBatch{ - Index: batchData1.Batch.BatchIndex, - Hash: batchData1.Hash().Hex(), - StateRoot: batchData1.Batch.NewStateRoot.String(), - } - batchData2 := types.NewBatchData(parentBatch2, []*types.WrappedBlock{wrappedBlock2}, nil) - - dbTx, err := db.Beginx() - assert.NoError(t, err) - assert.NoError(t, db.NewBatchInDBTx(dbTx, batchData1)) - assert.NoError(t, db.NewBatchInDBTx(dbTx, batchData2)) - assert.NoError(t, db.SetBatchHashForL2BlocksInDBTx(dbTx, []uint64{ - batchData1.Batch.Blocks[0].BlockNumber}, batchData1.Hash().Hex())) - assert.NoError(t, db.SetBatchHashForL2BlocksInDBTx(dbTx, []uint64{ - batchData2.Batch.Blocks[0].BlockNumber}, batchData2.Hash().Hex())) - assert.NoError(t, dbTx.Commit()) - - assert.NoError(t, db.UpdateRollupStatus(context.Background(), batchData1.Hash().Hex(), types.RollupFinalized)) - - batchHashes, err := db.GetPendingBatches(math.MaxInt32) - assert.NoError(t, err) - assert.Equal(t, 1, len(batchHashes)) - assert.Equal(t, batchData2.Hash().Hex(), batchHashes[0]) - // test p.recoverBatchDataBuffer(). - _ = NewBatchProposer(context.Background(), &config.BatchProposerConfig{ - ProofGenerationFreq: 1, - BatchGasThreshold: 3000000, - BatchTxNumThreshold: 135, - BatchTimeSec: 1, - BatchBlocksLimit: 100, - }, relayer, db) - - batchHashes, err = db.GetPendingBatches(math.MaxInt32) - assert.NoError(t, err) - assert.Equal(t, 0, len(batchHashes)) - - exist, err := db.BatchRecordExist(batchData2.Hash().Hex()) - assert.NoError(t, err) - assert.Equal(t, true, exist) -} diff --git a/common/go.mod b/common/go.mod index ca1427bee..4f8b1ccc5 100644 --- a/common/go.mod +++ b/common/go.mod @@ -37,7 +37,7 @@ require ( github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/snappy v0.0.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -45,7 +45,7 @@ require ( github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/uint256 v1.2.0 // indirect + github.com/holiman/uint256 v1.2.2 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/iden3/go-iden3-crypto v0.0.15 // indirect github.com/influxdata/influxdb v1.8.3 // indirect diff --git a/common/go.sum b/common/go.sum index 59bf2e91b..460db69da 100644 --- a/common/go.sum +++ b/common/go.sum @@ -151,8 +151,9 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -187,8 +188,8 @@ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuW github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= +github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= diff --git a/common/version/version.go b/common/version/version.go index 1b51c90b3..57cb3e25e 100644 --- a/common/version/version.go +++ b/common/version/version.go @@ -5,7 +5,7 @@ import ( "runtime/debug" ) -var tag = "v3.1.1" +var tag = "v3.1.2" var commit = func() string { if info, ok := debug.ReadBuildInfo(); ok { diff --git a/coordinator/go.mod b/coordinator/go.mod index 63371022f..47d8aae30 100644 --- a/coordinator/go.mod +++ b/coordinator/go.mod @@ -14,7 +14,9 @@ require ( require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/uuid v1.3.0 // indirect + github.com/holiman/uint256 v1.2.2 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/kr/pretty v0.3.1 // indirect diff --git a/coordinator/go.sum b/coordinator/go.sum index 9c037f084..242d1ed61 100644 --- a/coordinator/go.sum +++ b/coordinator/go.sum @@ -31,7 +31,8 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -42,7 +43,8 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= +github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= diff --git a/go.work.sum b/go.work.sum index 6f33ade4c..aec57857f 100644 --- a/go.work.sum +++ b/go.work.sum @@ -250,6 +250,7 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGa github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gotestyourself/gotestyourself v1.4.0 h1:CDSlSIuRL/Fsc72Ln5lMybtrCvSRDddsHsDRG/nP7Rg= github.com/gotestyourself/gotestyourself v1.4.0/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= @@ -278,7 +279,6 @@ github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yi github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= @@ -411,7 +411,6 @@ github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZL github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344 h1:m+8fKfQwCAy1QjzINvKe/pYtLjo2dl59x2w9YSEJxuY= github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/tinylib/msgp v1.0.2 h1:DfdQrzQa7Yh2es9SuLkixqxuXS2SxsdYn0KbdrOGWD8= @@ -432,7 +431,6 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6 h1:YdYsPAZ2pC6Tow/n github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg= @@ -448,7 +446,6 @@ golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20191227195350-da58074b4299 h1:zQpM52jfKHG6II1ISZY1ZcpygvuSFZpLwfluuF89XOg= golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 h1:rxKZ2gOnYxjfmakvUUqh9Gyb6KXfrj7JWTxORTYqb0E= golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= @@ -456,7 +453,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNT golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -466,16 +462,13 @@ golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -488,7 +481,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= @@ -499,7 +491,6 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= @@ -527,6 +518,7 @@ gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 h1:a6cXbcDDUk gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v1.4.0 h1:BjtEgfuw8Qyd+jPvQz8CfoxiO/UjFEidWinwEXZiWv0= gotest.tools v1.4.0/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o= diff --git a/roller/go.mod b/roller/go.mod index d10de54d0..6288bdae5 100644 --- a/roller/go.mod +++ b/roller/go.mod @@ -15,18 +15,21 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea // indirect + github.com/deckarep/golang-set v1.8.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/uuid v1.3.0 // indirect - github.com/gorilla/websocket v1.4.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/holiman/uint256 v1.2.2 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/iden3/go-iden3-crypto v0.0.15 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect @@ -41,7 +44,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.2 // indirect golang.org/x/crypto v0.9.0 // indirect golang.org/x/sys v0.8.0 // indirect - golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect + golang.org/x/time v0.3.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/roller/go.sum b/roller/go.sum index 99e3a1856..b36abf886 100644 --- a/roller/go.sum +++ b/roller/go.sum @@ -18,8 +18,8 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0= -github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -29,15 +29,17 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= +github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= @@ -59,11 +61,13 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -131,12 +135,13 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/tests/integration-test/go.mod b/tests/integration-test/go.mod index c68379ef5..80dc5e38f 100644 --- a/tests/integration-test/go.mod +++ b/tests/integration-test/go.mod @@ -14,8 +14,10 @@ require ( github.com/deckarep/golang-set v1.8.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.1 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/holiman/uint256 v1.2.2 // indirect github.com/iden3/go-iden3-crypto v0.0.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect diff --git a/tests/integration-test/go.sum b/tests/integration-test/go.sum index fe7e7eece..802a92d2e 100644 --- a/tests/integration-test/go.sum +++ b/tests/integration-test/go.sum @@ -9,12 +9,12 @@ github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsP github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= diff --git a/tests/integration-test/integration_test.go b/tests/integration-test/integration_test.go index e97b4d691..1782f984e 100644 --- a/tests/integration-test/integration_test.go +++ b/tests/integration-test/integration_test.go @@ -36,7 +36,7 @@ var ( func TestMain(m *testing.M) { base = docker.NewDockerApp() - bridgeApp = bcmd.NewBridgeApp(base, "../../bridge/config.json") + bridgeApp = bcmd.NewBridgeApp(base, "../../bridge/conf/config.json") coordinatorApp = capp.NewCoordinatorApp(base, "../../coordinator/config.json") rollerApp = rapp.NewRollerApp(base, "../../roller/config.json", coordinatorApp.WSEndpoint()) m.Run()