From 78c803d0df4054f202b7a90b03ffcef0e54dcbb7 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Fri, 15 Dec 2023 15:58:25 +0100 Subject: [PATCH 01/28] Refactor code a bit --- go.mod | 6 ++- go.sum | 10 +++++ interop/execute.go | 68 ++++++++++++++++++++++++++++++++++ {rpc => interop}/interfaces.go | 2 +- interop/interop.go | 63 +++++++++++++++++++++++++++++++ interop/verify.go | 61 ++++++++++++++++++++++++++++++ 6 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 interop/execute.go rename {rpc => interop}/interfaces.go (98%) create mode 100644 interop/interop.go create mode 100644 interop/verify.go diff --git a/go.mod b/go.mod index 1fa86a9..f8f5da2 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/0xPolygon/cdk-validium-node v0.0.2-0.20230922123231-07ce723e6268 github.com/ethereum/go-ethereum v1.13.5 github.com/gobuffalo/packr/v2 v2.8.3 - github.com/jackc/pgx/v4 v4.18.1 github.com/jackc/pgconn v1.14.1 + github.com/jackc/pgx/v4 v4.18.1 github.com/mitchellh/mapstructure v1.5.0 github.com/prometheus/client_golang v1.17.0 github.com/rubenv/sql-migrate v1.5.2 @@ -44,6 +44,7 @@ require ( github.com/dlclark/regexp2 v1.7.0 // indirect github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/fatih/color v1.14.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/getsentry/sentry-go v0.18.0 // indirect @@ -64,6 +65,7 @@ require ( github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hermeznetwork/tracerr v0.3.2 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect @@ -89,6 +91,8 @@ require ( github.com/markbates/errx v1.1.0 // indirect github.com/markbates/oncer v1.0.0 // indirect github.com/markbates/safe v1.0.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect diff --git a/go.sum b/go.sum index 2659396..ee722e7 100644 --- a/go.sum +++ b/go.sum @@ -185,6 +185,9 @@ github.com/ethereum/go-ethereum v1.13.5 h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= @@ -351,6 +354,8 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I= +github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= @@ -513,7 +518,9 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 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.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -523,6 +530,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1002,9 +1010,11 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220715151400-c0bba94af5f8/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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/interop/execute.go b/interop/execute.go new file mode 100644 index 0000000..d356ed1 --- /dev/null +++ b/interop/execute.go @@ -0,0 +1,68 @@ +package interop + +import ( + "context" + "fmt" + "math/big" + "silencer/tx" + + "github.com/0xPolygon/cdk-validium-node/jsonrpc/client" + "github.com/0xPolygon/cdk-validium-node/log" + "github.com/ethereum/go-ethereum/common" +) + +const ethTxManOwner = "interop" + +func (app *Interop) Execute(signedTx tx.SignedTx) error { + ctx := context.TODO() + + // Check expected root vs root from the managed full node + // TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581 + // when this happens we should go async from here, since processing all the batches could take a lot of time + zkEVMClient := client.NewClient(app.config.FullNodeRPCs[signedTx.Tx.L1Contract.String()]) + batch, err := zkEVMClient.BatchByNumber( + ctx, + big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), + ) + if err != nil { + return fmt.Errorf("failed to get batch from our node, error: %s", err) + } + if batch.StateRoot != signedTx.Tx.ZKP.NewStateRoot || batch.LocalExitRoot != signedTx.Tx.ZKP.NewLocalExitRoot { + return fmt.Errorf( + "Missmatch detected, expected local exit root: %s actual: %s. expected state root: %s actual: %s", + signedTx.Tx.ZKP.NewLocalExitRoot.Hex(), + batch.LocalExitRoot.Hex(), + signedTx.Tx.ZKP.NewStateRoot.Hex(), + batch.StateRoot.Hex(), + ) + } + + return nil +} + +func (app *Interop) Settle(signedTx tx.SignedTx) (common.Hash, error) { + // // Send L1 tx + // Verify ZKP using eth_call + l1TxData, err := app.etherman.BuildTrustedVerifyBatchesTxData( + uint64(signedTx.Tx.LastVerifiedBatch), + uint64(signedTx.Tx.NewVerifiedBatch), + signedTx.Tx.ZKP, + ) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to build verify ZKP tx: %s", err) + } + + if err := app.ethTxMan.Add( + context.Background(), + ethTxManOwner, + signedTx.Tx.Hash().Hex(), + app.interopAdminAddr, + &signedTx.Tx.L1Contract, + nil, + l1TxData, + ); err != nil { + return common.Hash{}, fmt.Errorf("failed to add tx to ethTxMan, error: %s", err) + } + log.Debugf("successfuly added tx %s to ethTxMan", signedTx.Tx.Hash().Hex()) + return signedTx.Tx.Hash(), nil +} diff --git a/rpc/interfaces.go b/interop/interfaces.go similarity index 98% rename from rpc/interfaces.go rename to interop/interfaces.go index 112bf16..7e8200b 100644 --- a/rpc/interfaces.go +++ b/interop/interfaces.go @@ -1,4 +1,4 @@ -package rpc +package interop import ( "context" diff --git a/interop/interop.go b/interop/interop.go new file mode 100644 index 0000000..0e8c65b --- /dev/null +++ b/interop/interop.go @@ -0,0 +1,63 @@ +package interop + +import ( + "crypto/ecdsa" + "log" + "math/big" + + "github.com/0xPolygon/beethoven/config" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/hashicorp/go-hclog" +) + +const ( + AppVersion uint64 = 1 +) + +type Interop struct { + logger hclog.Logger + addr common.Address + config *config.Config + ethTxMan *ethtxmanager.Client + etherman etherman.EthermanInterface + interopAdminAddr common.Address +} + +func NewSilencer(logger hclog.Logger, cfg *config.Config, privateKey *ecdsa.PrivateKey, state *State) *Interop { + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + // Prepare Etherman + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(cfg.L1.ChainID)) + if err != nil { + log.Fatal(err) + } + ethMan, err := etherman.New(cfg.L1.NodeURL, *auth) + if err != nil { + log.Fatal(err) + } + + // Prepare EthTxMan client + ethTxManagerStorage, err := ethtxmanager.NewBoltDBStorage(cfg.BaseConfig.RootDir + "/ethtxmanager.db") + if err != nil { + log.Fatal(err) + } + etm := ethtxmanager.New(cfg.EthTxManager, ðMan, ethTxManagerStorage, ðMan) + + e, err := etherman.New(cfg.L1.NodeURL, bind.TransactOpts{}) + if err != nil { + log.Fatal(err) + } + + return &Interop{ + ID: cfg.Moniker, + logger: logger, + addr: addr, + state: state, + config: cfg, + ethTxMan: etm, + etherman: &e, + } +} diff --git a/interop/verify.go b/interop/verify.go new file mode 100644 index 0000000..97cadcf --- /dev/null +++ b/interop/verify.go @@ -0,0 +1,61 @@ +package interop + +import ( + "context" + "errors" + "fmt" + + "github.com/0xPolygon/beethoven/tx" + + "github.com/ethereum/go-ethereum" +) + +func (i *Interop) Verify(tx tx.SignedTx) error { + err := i.VerifyZKP(tx) + if err != nil { + return fmt.Errorf("failed to verify ZKP: %s", err) + } + + return i.VerifySignature(tx) +} + +func (i *Interop) VerifyZKP(stx tx.SignedTx) error { + // Verify ZKP using eth_call + l1TxData, err := i.etherman.BuildTrustedVerifyBatchesTxData( + uint64(stx.Tx.LastVerifiedBatch), + uint64(stx.Tx.NewVerifiedBatch), + stx.Tx.ZKP, + ) + if err != nil { + return fmt.Errorf("failed to build verify ZKP tx: %s", err) + } + msg := ethereum.CallMsg{ + From: i.interopAdminAddr, + To: &stx.Tx.L1Contract, + Data: l1TxData, + } + res, err := i.etherman.CallContract(context.Background(), msg, nil) + if err != nil { + return fmt.Errorf("failed to call verify ZKP response: %s, error: %s", res, err) + } + + return nil +} + +func (i *Interop) VerifySignature(stx tx.SignedTx) error { + // Auth: check signature vs admin + signer, err := stx.Signer() + if err != nil { + return errors.New("failed to get signer") + } + + sequencer, err := i.etherman.GetSequencerAddr(stx.Tx.L1Contract) + if err != nil { + return errors.New("failed to get admin from L1") + } + if sequencer != signer { + return errors.New("unexpected signer") + } + + return nil +} From d6f42d86fc94bdda2d889ae81e4f1c7218493203 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Fri, 15 Dec 2023 17:24:46 +0100 Subject: [PATCH 02/28] Fixing some errors --- config/config.go | 6 +++-- interop/check.go | 20 +++++++++++++++++ interop/execute.go | 9 +++++--- interop/interop.go | 56 ++++++++++++---------------------------------- rpc/rpc.go | 36 +++++++++++++++-------------- 5 files changed, 63 insertions(+), 64 deletions(-) create mode 100644 interop/check.go diff --git a/config/config.go b/config/config.go index 42ad7f3..ce55f8b 100644 --- a/config/config.go +++ b/config/config.go @@ -6,13 +6,13 @@ import ( "path/filepath" "strings" - "github.com/0xPolygon/beethoven/rpc" "github.com/0xPolygon/cdk-validium-node/config/types" "github.com/0xPolygon/cdk-validium-node/db" "github.com/0xPolygon/cdk-validium-node/ethtxmanager" "github.com/0xPolygon/cdk-validium-node/jsonrpc" "github.com/0xPolygon/cdk-validium-node/log" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" "github.com/mitchellh/mapstructure" "github.com/spf13/viper" "github.com/urfave/cli/v2" @@ -23,9 +23,11 @@ const ( FlagCfg = "cfg" ) +type FullNodeRPCs map[common.Address]string + // Config represents the full configuration of the data node type Config struct { - FullNodeRPCs rpc.FullNodeRPCs `mapstructure:"FullNodeRPCs"` + FullNodeRPCs FullNodeRPCs `mapstructure:"FullNodeRPCs"` RPC jsonrpc.Config `mapstructure:"RPC"` Log log.Config `mapstructure:"Log"` DB db.Config `mapstructure:"DB"` diff --git a/interop/check.go b/interop/check.go new file mode 100644 index 0000000..9bd19d7 --- /dev/null +++ b/interop/check.go @@ -0,0 +1,20 @@ +package interop + +import ( + "context" + "fmt" + + "github.com/0xPolygon/beethoven/tx" +) + +func (i *Interop) CheckTx(ctx context.Context, tx tx.SignedTx) error { + i.logger.Debug("check tx") + + // Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed) + // TODO: The JSON parsing of the contract is incorrect + if _, ok := i.config.FullNodeRPCs[tx.Tx.L1Contract]; !ok { + return fmt.Errorf("there is no RPC registered for %s", tx.Tx.L1Contract) + } + + return nil +} diff --git a/interop/execute.go b/interop/execute.go index d356ed1..d5c15f7 100644 --- a/interop/execute.go +++ b/interop/execute.go @@ -4,7 +4,9 @@ import ( "context" "fmt" "math/big" - "silencer/tx" + + "github.com/0xPolygon/beethoven/tx" + "github.com/jackc/pgx/v4" "github.com/0xPolygon/cdk-validium-node/jsonrpc/client" "github.com/0xPolygon/cdk-validium-node/log" @@ -19,7 +21,7 @@ func (app *Interop) Execute(signedTx tx.SignedTx) error { // Check expected root vs root from the managed full node // TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581 // when this happens we should go async from here, since processing all the batches could take a lot of time - zkEVMClient := client.NewClient(app.config.FullNodeRPCs[signedTx.Tx.L1Contract.String()]) + zkEVMClient := client.NewClient(app.config.FullNodeRPCs[signedTx.Tx.L1Contract]) batch, err := zkEVMClient.BatchByNumber( ctx, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), @@ -40,7 +42,7 @@ func (app *Interop) Execute(signedTx tx.SignedTx) error { return nil } -func (app *Interop) Settle(signedTx tx.SignedTx) (common.Hash, error) { +func (app *Interop) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) { // // Send L1 tx // Verify ZKP using eth_call l1TxData, err := app.etherman.BuildTrustedVerifyBatchesTxData( @@ -60,6 +62,7 @@ func (app *Interop) Settle(signedTx tx.SignedTx) (common.Hash, error) { &signedTx.Tx.L1Contract, nil, l1TxData, + dbTx, ); err != nil { return common.Hash{}, fmt.Errorf("failed to add tx to ethTxMan, error: %s", err) } diff --git a/interop/interop.go b/interop/interop.go index 0e8c65b..b9f456c 100644 --- a/interop/interop.go +++ b/interop/interop.go @@ -1,15 +1,9 @@ package interop import ( - "crypto/ecdsa" - "log" - "math/big" - "github.com/0xPolygon/beethoven/config" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/hashicorp/go-hclog" ) @@ -19,45 +13,23 @@ const ( type Interop struct { logger hclog.Logger - addr common.Address - config *config.Config - ethTxMan *ethtxmanager.Client - etherman etherman.EthermanInterface interopAdminAddr common.Address + config *config.Config + ethTxMan EthTxManager + etherman EthermanInterface } -func NewSilencer(logger hclog.Logger, cfg *config.Config, privateKey *ecdsa.PrivateKey, state *State) *Interop { - addr := crypto.PubkeyToAddress(privateKey.PublicKey) - - // Prepare Etherman - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(cfg.L1.ChainID)) - if err != nil { - log.Fatal(err) - } - ethMan, err := etherman.New(cfg.L1.NodeURL, *auth) - if err != nil { - log.Fatal(err) - } - - // Prepare EthTxMan client - ethTxManagerStorage, err := ethtxmanager.NewBoltDBStorage(cfg.BaseConfig.RootDir + "/ethtxmanager.db") - if err != nil { - log.Fatal(err) - } - etm := ethtxmanager.New(cfg.EthTxManager, ðMan, ethTxManagerStorage, ðMan) - - e, err := etherman.New(cfg.L1.NodeURL, bind.TransactOpts{}) - if err != nil { - log.Fatal(err) - } - +func New(logger hclog.Logger, cfg *config.Config, + interopAdminAddr common.Address, + db DBInterface, + etherman EthermanInterface, + ethTxManager EthTxManager, +) *Interop { return &Interop{ - ID: cfg.Moniker, - logger: logger, - addr: addr, - state: state, - config: cfg, - ethTxMan: etm, - etherman: &e, + logger: logger, + interopAdminAddr: interopAdminAddr, + config: cfg, + ethTxMan: ethTxManager, + etherman: etherman, } } diff --git a/rpc/rpc.go b/rpc/rpc.go index b317f7e..f327a1b 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -5,6 +5,8 @@ import ( "fmt" "math/big" + "github.com/0xPolygon/beethoven/config" + "github.com/0xPolygon/beethoven/interop" "github.com/0xPolygon/beethoven/tx" "github.com/0xPolygon/cdk-validium-node/jsonrpc/client" "github.com/0xPolygon/cdk-validium-node/jsonrpc/types" @@ -19,37 +21,37 @@ const ( ethTxManOwner = "interop" ) -type FullNodeRPCs map[common.Address]string - -var _ ZkEVMClientClientCreator = (*zkEVMClientCreator)(nil) +var _ interop.ZkEVMClientClientCreator = (*zkEVMClientCreator)(nil) type zkEVMClientCreator struct{} -func (zc *zkEVMClientCreator) NewClient(rpc string) ZkEVMClientInterface { +func (zc *zkEVMClientCreator) NewClient(rpc string) interop.ZkEVMClientInterface { return client.NewClient(rpc) } // InteropEndpoints contains implementations for the "interop" RPC endpoints type InteropEndpoints struct { - db DBInterface - etherman EthermanInterface - interopAdminAddr common.Address - fullNodeRPCs FullNodeRPCs - ethTxManager EthTxManager - zkEVMClientCreator ZkEVMClientClientCreator + interop *interop.Interop + db interop.DBInterface + etherman interop.EthermanInterface + // interopAdminAddr common.Address + fullNodeRPCs config.FullNodeRPCs + ethTxManager interop.EthTxManager + zkEVMClientCreator interop.ZkEVMClientClientCreator } // NewInteropEndpoints returns InteropEndpoints func NewInteropEndpoints( - interopAdminAddr common.Address, - db DBInterface, - etherman EthermanInterface, - fullNodeRPCs FullNodeRPCs, - ethTxManager EthTxManager, + interop *interop.Interop, + // interopAdminAddr common.Address, + db interop.DBInterface, + etherman interop.EthermanInterface, + fullNodeRPCs config.FullNodeRPCs, + ethTxManager interop.EthTxManager, ) *InteropEndpoints { return &InteropEndpoints{ - db: db, - interopAdminAddr: interopAdminAddr, + db: db, + // interopAdminAddr: interopAdminAddr, etherman: etherman, fullNodeRPCs: fullNodeRPCs, ethTxManager: ethTxManager, From a5dbbcae5c0e742c04055b23841e4ae665e73dae Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Sat, 16 Dec 2023 10:35:32 +0100 Subject: [PATCH 03/28] Better naming --- interop/check.go | 6 +++--- interop/execute.go | 12 ++++++------ interop/{interop.go => executor.go} | 10 +++------- interop/verify.go | 16 ++++++++-------- rpc/rpc.go | 4 ++-- 5 files changed, 22 insertions(+), 26 deletions(-) rename interop/{interop.go => executor.go} (87%) diff --git a/interop/check.go b/interop/check.go index 9bd19d7..a89df5a 100644 --- a/interop/check.go +++ b/interop/check.go @@ -7,12 +7,12 @@ import ( "github.com/0xPolygon/beethoven/tx" ) -func (i *Interop) CheckTx(ctx context.Context, tx tx.SignedTx) error { - i.logger.Debug("check tx") +func (e *Executor) CheckTx(ctx context.Context, tx tx.SignedTx) error { + e.logger.Debug("check tx") // Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed) // TODO: The JSON parsing of the contract is incorrect - if _, ok := i.config.FullNodeRPCs[tx.Tx.L1Contract]; !ok { + if _, ok := e.config.FullNodeRPCs[tx.Tx.L1Contract]; !ok { return fmt.Errorf("there is no RPC registered for %s", tx.Tx.L1Contract) } diff --git a/interop/execute.go b/interop/execute.go index d5c15f7..a379b17 100644 --- a/interop/execute.go +++ b/interop/execute.go @@ -15,13 +15,13 @@ import ( const ethTxManOwner = "interop" -func (app *Interop) Execute(signedTx tx.SignedTx) error { +func (e *Executor) Execute(signedTx tx.SignedTx) error { ctx := context.TODO() // Check expected root vs root from the managed full node // TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581 // when this happens we should go async from here, since processing all the batches could take a lot of time - zkEVMClient := client.NewClient(app.config.FullNodeRPCs[signedTx.Tx.L1Contract]) + zkEVMClient := client.NewClient(e.config.FullNodeRPCs[signedTx.Tx.L1Contract]) batch, err := zkEVMClient.BatchByNumber( ctx, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), @@ -42,10 +42,10 @@ func (app *Interop) Execute(signedTx tx.SignedTx) error { return nil } -func (app *Interop) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) { +func (e *Executor) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) { // // Send L1 tx // Verify ZKP using eth_call - l1TxData, err := app.etherman.BuildTrustedVerifyBatchesTxData( + l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( uint64(signedTx.Tx.LastVerifiedBatch), uint64(signedTx.Tx.NewVerifiedBatch), signedTx.Tx.ZKP, @@ -54,11 +54,11 @@ func (app *Interop) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, erro return common.Hash{}, fmt.Errorf("failed to build verify ZKP tx: %s", err) } - if err := app.ethTxMan.Add( + if err := e.ethTxMan.Add( context.Background(), ethTxManOwner, signedTx.Tx.Hash().Hex(), - app.interopAdminAddr, + e.interopAdminAddr, &signedTx.Tx.L1Contract, nil, l1TxData, diff --git a/interop/interop.go b/interop/executor.go similarity index 87% rename from interop/interop.go rename to interop/executor.go index b9f456c..703db9c 100644 --- a/interop/interop.go +++ b/interop/executor.go @@ -7,11 +7,7 @@ import ( "github.com/hashicorp/go-hclog" ) -const ( - AppVersion uint64 = 1 -) - -type Interop struct { +type Executor struct { logger hclog.Logger interopAdminAddr common.Address config *config.Config @@ -24,8 +20,8 @@ func New(logger hclog.Logger, cfg *config.Config, db DBInterface, etherman EthermanInterface, ethTxManager EthTxManager, -) *Interop { - return &Interop{ +) *Executor { + return &Executor{ logger: logger, interopAdminAddr: interopAdminAddr, config: cfg, diff --git a/interop/verify.go b/interop/verify.go index 97cadcf..a529dd7 100644 --- a/interop/verify.go +++ b/interop/verify.go @@ -10,18 +10,18 @@ import ( "github.com/ethereum/go-ethereum" ) -func (i *Interop) Verify(tx tx.SignedTx) error { - err := i.VerifyZKP(tx) +func (e *Executor) Verify(tx tx.SignedTx) error { + err := e.VerifyZKP(tx) if err != nil { return fmt.Errorf("failed to verify ZKP: %s", err) } - return i.VerifySignature(tx) + return e.VerifySignature(tx) } -func (i *Interop) VerifyZKP(stx tx.SignedTx) error { +func (e *Executor) VerifyZKP(stx tx.SignedTx) error { // Verify ZKP using eth_call - l1TxData, err := i.etherman.BuildTrustedVerifyBatchesTxData( + l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( uint64(stx.Tx.LastVerifiedBatch), uint64(stx.Tx.NewVerifiedBatch), stx.Tx.ZKP, @@ -30,11 +30,11 @@ func (i *Interop) VerifyZKP(stx tx.SignedTx) error { return fmt.Errorf("failed to build verify ZKP tx: %s", err) } msg := ethereum.CallMsg{ - From: i.interopAdminAddr, + From: e.interopAdminAddr, To: &stx.Tx.L1Contract, Data: l1TxData, } - res, err := i.etherman.CallContract(context.Background(), msg, nil) + res, err := e.etherman.CallContract(context.Background(), msg, nil) if err != nil { return fmt.Errorf("failed to call verify ZKP response: %s, error: %s", res, err) } @@ -42,7 +42,7 @@ func (i *Interop) VerifyZKP(stx tx.SignedTx) error { return nil } -func (i *Interop) VerifySignature(stx tx.SignedTx) error { +func (i *Executor) VerifySignature(stx tx.SignedTx) error { // Auth: check signature vs admin signer, err := stx.Signer() if err != nil { diff --git a/rpc/rpc.go b/rpc/rpc.go index f327a1b..8527686 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -31,7 +31,7 @@ func (zc *zkEVMClientCreator) NewClient(rpc string) interop.ZkEVMClientInterface // InteropEndpoints contains implementations for the "interop" RPC endpoints type InteropEndpoints struct { - interop *interop.Interop + interop *interop.Executor db interop.DBInterface etherman interop.EthermanInterface // interopAdminAddr common.Address @@ -42,7 +42,7 @@ type InteropEndpoints struct { // NewInteropEndpoints returns InteropEndpoints func NewInteropEndpoints( - interop *interop.Interop, + interop *interop.Executor, // interopAdminAddr common.Address, db interop.DBInterface, etherman interop.EthermanInterface, From 0c436fc7532c21bde3eda05a241b6c7ed7a4dad3 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Mon, 18 Dec 2023 11:30:22 +0100 Subject: [PATCH 04/28] Continue refactor --- cmd/main.go | 18 ++++++-- config/config.go | 2 - interop/query.go | 24 +++++++++++ rpc/rpc.go | 110 +++++++++-------------------------------------- 4 files changed, 60 insertions(+), 94 deletions(-) create mode 100644 interop/query.go diff --git a/cmd/main.go b/cmd/main.go index 58df2fa..814f051 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -27,6 +27,7 @@ import ( "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/db" "github.com/0xPolygon/beethoven/etherman" + "github.com/0xPolygon/beethoven/interop" "github.com/0xPolygon/beethoven/network" "github.com/0xPolygon/beethoven/rpc" ) @@ -124,6 +125,18 @@ func start(cliCtx *cli.Context) error { log.Fatal(err) } + ctx, cancel := context.WithTimeout(context.Background(), i.rpcTimeout) + defer cancel() + + executor := interop.New( + log, + c, + addr, + storage, + ethMan, + etm, + ) + // Register services server := jsonrpc.NewServer( c.RPC, @@ -133,9 +146,8 @@ func start(cliCtx *cli.Context) error { &dummyinterfaces.DummyStorage{}, []jsonrpc.Service{ { - Name: rpc.INTEROP, - Service: rpc.NewInteropEndpoints(addr, storage, ðMan, - c.FullNodeRPCs, c.RPC.ReadTimeout.Duration, etm), + Name: rpc.INTEROP, + Service: rpc.NewInteropEndpoints(ctx, executor, storage), }, }, ) diff --git a/config/config.go b/config/config.go index daf68a8..ce55f8b 100644 --- a/config/config.go +++ b/config/config.go @@ -16,8 +16,6 @@ import ( "github.com/mitchellh/mapstructure" "github.com/spf13/viper" "github.com/urfave/cli/v2" - - "github.com/0xPolygon/beethoven/rpc" ) const ( diff --git a/interop/query.go b/interop/query.go new file mode 100644 index 0000000..9f230cc --- /dev/null +++ b/interop/query.go @@ -0,0 +1,24 @@ +package interop + +import ( + "context" + "fmt" + + "github.com/0xPolygon/cdk-validium-node/jsonrpc/types" + "github.com/ethereum/go-ethereum/common" + "github.com/jackc/pgx/v4" +) + +func (e *Executor) GetTxStatus(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (result interface{}, err types.Error) { + res, innerErr := e.ethTxMan.Result(ctx, ethTxManOwner, hash.Hex(), dbTx) + if innerErr != nil { + result = "0x0" + err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) + + return + } + + result = res.Status.String() + + return +} diff --git a/rpc/rpc.go b/rpc/rpc.go index 3590f98..2f23e86 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -3,15 +3,11 @@ package rpc import ( "context" "fmt" - "math/big" - "time" - "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/interop" "github.com/0xPolygon/cdk-validium-node/jsonrpc/client" "github.com/0xPolygon/cdk-validium-node/jsonrpc/types" "github.com/0xPolygon/cdk-validium-node/log" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/0xPolygon/beethoven/tx" @@ -33,126 +29,62 @@ func (zc *zkEVMClientCreator) NewClient(rpc string) interop.ZkEVMClientInterface // InteropEndpoints contains implementations for the "interop" RPC endpoints type InteropEndpoints struct { - interop *interop.Executor + ctx context.Context + executor *interop.Executor db interop.DBInterface - etherman interop.EthermanInterface - // interopAdminAddr common.Address - fullNodeRPCs config.FullNodeRPCs - rpcTimeout time.Duration - ethTxManager interop.EthTxManager - zkEVMClientCreator interop.ZkEVMClientClientCreator } // NewInteropEndpoints returns InteropEndpoints func NewInteropEndpoints( - interop *interop.Executor, - // interopAdminAddr common.Address, + ctx context.Context, + executor *interop.Executor, db interop.DBInterface, - etherman interop.EthermanInterface, - fullNodeRPCs config.FullNodeRPCs, - rpcTimeout time.Duration, - ethTxManager interop.EthTxManager, ) *InteropEndpoints { return &InteropEndpoints{ - db: db, - // interopAdminAddr: interopAdminAddr, - etherman: etherman, - fullNodeRPCs: fullNodeRPCs, - rpcTimeout: rpcTimeout, - ethTxManager: ethTxManager, - zkEVMClientCreator: &zkEVMClientCreator{}, + ctx: ctx, + executor: executor, + db: db, } } func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, types.Error) { - ctx, cancel := context.WithTimeout(context.Background(), i.rpcTimeout) - defer cancel() - // Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed) - if _, ok := i.fullNodeRPCs[signedTx.Tx.L1Contract]; !ok { + if err := i.executor.CheckTx(i.ctx, signedTx); err != nil { return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("there is no RPC registered for %s", signedTx.Tx.L1Contract)) } // Verify ZKP using eth_call - l1TxData, err := i.etherman.BuildTrustedVerifyBatchesTxData( - uint64(signedTx.Tx.LastVerifiedBatch), - uint64(signedTx.Tx.NewVerifiedBatch), - signedTx.Tx.ZKP, - ) - if err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to build verify ZKP tx: %s", err)) - } - msg := ethereum.CallMsg{ - From: i.interopAdminAddr, - To: &signedTx.Tx.L1Contract, - Data: l1TxData, - } - res, err := i.etherman.CallContract(ctx, msg, nil) - if err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to call verify ZKP response: %s, error: %s", res, err)) + if err := i.executor.Verify(signedTx); err != nil { + return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to verify tx: %s", err)) } - // Auth: check signature vs admin - signer, err := signedTx.Signer() - if err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, "failed to get signer") - } - - sequencer, err := i.etherman.GetSequencerAddr(signedTx.Tx.L1Contract) - if err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, "failed to get admin from L1") - } - - if sequencer != signer { - return "0x0", types.NewRPCError(types.DefaultErrorCode, "unexpected signer") - } - - // Check expected root vs root from the managed full node - // TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581 - // when this happens we should go async from here, since processing all the batches could take a lot of time - zkEVMClient := i.zkEVMClientCreator.NewClient(i.fullNodeRPCs[signedTx.Tx.L1Contract]) - batch, err := zkEVMClient.BatchByNumber( - ctx, - big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), - ) - if err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get batch from our node, error: %s", err)) - } - - if batch.StateRoot != signedTx.Tx.ZKP.NewStateRoot || batch.LocalExitRoot != signedTx.Tx.ZKP.NewLocalExitRoot { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf( - "Mismatch detected, expected local exit root: %s actual: %s. expected state root: %s actual: %s", - signedTx.Tx.ZKP.NewLocalExitRoot.Hex(), - batch.LocalExitRoot.Hex(), - signedTx.Tx.ZKP.NewStateRoot.Hex(), - batch.StateRoot.Hex(), - )) + if err := i.executor.Execute(signedTx); err != nil { + return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to execute tx: %s", err)) } // Send L1 tx - dbTx, err := i.db.BeginStateTransaction(ctx) + dbTx, err := i.db.BeginStateTransaction(i.ctx) if err != nil { return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to begin dbTx, error: %s", err)) } - err = i.ethTxManager.Add(ctx, ethTxManOwner, signedTx.Tx.Hash().Hex(), i.interopAdminAddr, &signedTx.Tx.L1Contract, nil, l1TxData, dbTx) + + _, err = i.executor.Settle(signedTx, dbTx) if err != nil { - if errRollback := dbTx.Rollback(ctx); errRollback != nil { + if errRollback := dbTx.Rollback(i.ctx); errRollback != nil { log.Error("rollback err: ", errRollback) } return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to add tx to ethTxMan, error: %s", err)) } - if err := dbTx.Commit(ctx); err != nil { + if err := dbTx.Commit(i.ctx); err != nil { return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to commit dbTx, error: %s", err)) } log.Debugf("successfuly added tx %s to ethTxMan", signedTx.Tx.Hash().Hex()) + return signedTx.Tx.Hash(), nil } func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, err types.Error) { - ctx, cancel := context.WithTimeout(context.Background(), i.rpcTimeout) - defer cancel() - - dbTx, innerErr := i.db.BeginStateTransaction(ctx) + dbTx, innerErr := i.db.BeginStateTransaction(i.ctx) if innerErr != nil { result = "0x0" err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to begin dbTx, error: %s", innerErr)) @@ -161,13 +93,13 @@ func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, er } defer func() { - if innerErr := dbTx.Rollback(ctx); innerErr != nil { + if innerErr := dbTx.Rollback(i.ctx); innerErr != nil { result = "0x0" err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to rollback dbTx, error: %s", innerErr)) } }() - res, innerErr := i.ethTxManager.Result(ctx, ethTxManOwner, hash.Hex(), dbTx) + res, innerErr := i.executor.GetTxStatus(i.ctx, hash, dbTx) if innerErr != nil { result = "0x0" err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) From a5ce8a0832f7ef7b0e944e0c9beeb971b4ca1087 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Mon, 18 Dec 2023 11:39:48 +0100 Subject: [PATCH 05/28] Almost working --- cmd/main.go | 4 ++-- interop/executor.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 814f051..c2415c2 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -125,11 +125,11 @@ func start(cliCtx *cli.Context) error { log.Fatal(err) } - ctx, cancel := context.WithTimeout(context.Background(), i.rpcTimeout) + ctx, cancel := context.WithTimeout(context.Background(), c.RPC.ReadTimeout.Duration) defer cancel() executor := interop.New( - log, + log.WithFields("module", "executor"), c, addr, storage, diff --git a/interop/executor.go b/interop/executor.go index 703db9c..77c4306 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -3,19 +3,19 @@ package interop import ( "github.com/0xPolygon/beethoven/config" + "github.com/0xPolygon/cdk-validium-node/log" "github.com/ethereum/go-ethereum/common" - "github.com/hashicorp/go-hclog" ) type Executor struct { - logger hclog.Logger + logger *log.Logger interopAdminAddr common.Address config *config.Config ethTxMan EthTxManager etherman EthermanInterface } -func New(logger hclog.Logger, cfg *config.Config, +func New(logger *log.Logger, cfg *config.Config, interopAdminAddr common.Address, db DBInterface, etherman EthermanInterface, From 41328d168f8eb40acf2e581649a2047fe1b8ab1c Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Mon, 18 Dec 2023 11:58:46 +0100 Subject: [PATCH 06/28] Fixes --- cmd/main.go | 2 +- interop/query.go | 2 +- rpc/rpc.go | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index c2415c2..303ef33 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -133,7 +133,7 @@ func start(cliCtx *cli.Context) error { c, addr, storage, - ethMan, + ðMan, etm, ) diff --git a/interop/query.go b/interop/query.go index 9f230cc..9fd4eb4 100644 --- a/interop/query.go +++ b/interop/query.go @@ -9,7 +9,7 @@ import ( "github.com/jackc/pgx/v4" ) -func (e *Executor) GetTxStatus(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (result interface{}, err types.Error) { +func (e *Executor) GetTxStatus(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (result string, err types.Error) { res, innerErr := e.ethTxMan.Result(ctx, ethTxManOwner, hash.Hex(), dbTx) if innerErr != nil { result = "0x0" diff --git a/rpc/rpc.go b/rpc/rpc.go index 2f23e86..cf1a6cd 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -99,7 +99,7 @@ func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, er } }() - res, innerErr := i.executor.GetTxStatus(i.ctx, hash, dbTx) + result, innerErr = i.executor.GetTxStatus(i.ctx, hash, dbTx) if innerErr != nil { result = "0x0" err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) @@ -107,7 +107,5 @@ func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, er return } - result = res.Status.String() - return } From dd3e2c2c442e07ff3c1dc19a52c1a542a24b66a8 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Mon, 18 Dec 2023 17:54:20 +0100 Subject: [PATCH 07/28] Update interop/verify.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> --- interop/verify.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interop/verify.go b/interop/verify.go index a529dd7..16d4d72 100644 --- a/interop/verify.go +++ b/interop/verify.go @@ -42,14 +42,14 @@ func (e *Executor) VerifyZKP(stx tx.SignedTx) error { return nil } -func (i *Executor) VerifySignature(stx tx.SignedTx) error { +func (e *Executor) VerifySignature(stx tx.SignedTx) error { // Auth: check signature vs admin signer, err := stx.Signer() if err != nil { return errors.New("failed to get signer") } - sequencer, err := i.etherman.GetSequencerAddr(stx.Tx.L1Contract) + sequencer, err := e.etherman.GetSequencerAddr(stx.Tx.L1Contract) if err != nil { return errors.New("failed to get admin from L1") } From aad375adb9884f24d810837f1840b2700b9f4da6 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Mon, 18 Dec 2023 18:24:28 +0100 Subject: [PATCH 08/28] Move code around --- cmd/main.go | 1 - interop/check.go | 20 ------ interop/execute.go | 71 ---------------------- interop/executor.go | 144 +++++++++++++++++++++++++++++++++++++++++++- interop/query.go | 24 -------- interop/verify.go | 61 ------------------- 6 files changed, 143 insertions(+), 178 deletions(-) delete mode 100644 interop/check.go delete mode 100644 interop/execute.go delete mode 100644 interop/query.go delete mode 100644 interop/verify.go diff --git a/cmd/main.go b/cmd/main.go index 303ef33..8e55fdb 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -132,7 +132,6 @@ func start(cliCtx *cli.Context) error { log.WithFields("module", "executor"), c, addr, - storage, ðMan, etm, ) diff --git a/interop/check.go b/interop/check.go deleted file mode 100644 index a89df5a..0000000 --- a/interop/check.go +++ /dev/null @@ -1,20 +0,0 @@ -package interop - -import ( - "context" - "fmt" - - "github.com/0xPolygon/beethoven/tx" -) - -func (e *Executor) CheckTx(ctx context.Context, tx tx.SignedTx) error { - e.logger.Debug("check tx") - - // Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed) - // TODO: The JSON parsing of the contract is incorrect - if _, ok := e.config.FullNodeRPCs[tx.Tx.L1Contract]; !ok { - return fmt.Errorf("there is no RPC registered for %s", tx.Tx.L1Contract) - } - - return nil -} diff --git a/interop/execute.go b/interop/execute.go deleted file mode 100644 index a379b17..0000000 --- a/interop/execute.go +++ /dev/null @@ -1,71 +0,0 @@ -package interop - -import ( - "context" - "fmt" - "math/big" - - "github.com/0xPolygon/beethoven/tx" - "github.com/jackc/pgx/v4" - - "github.com/0xPolygon/cdk-validium-node/jsonrpc/client" - "github.com/0xPolygon/cdk-validium-node/log" - "github.com/ethereum/go-ethereum/common" -) - -const ethTxManOwner = "interop" - -func (e *Executor) Execute(signedTx tx.SignedTx) error { - ctx := context.TODO() - - // Check expected root vs root from the managed full node - // TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581 - // when this happens we should go async from here, since processing all the batches could take a lot of time - zkEVMClient := client.NewClient(e.config.FullNodeRPCs[signedTx.Tx.L1Contract]) - batch, err := zkEVMClient.BatchByNumber( - ctx, - big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), - ) - if err != nil { - return fmt.Errorf("failed to get batch from our node, error: %s", err) - } - if batch.StateRoot != signedTx.Tx.ZKP.NewStateRoot || batch.LocalExitRoot != signedTx.Tx.ZKP.NewLocalExitRoot { - return fmt.Errorf( - "Missmatch detected, expected local exit root: %s actual: %s. expected state root: %s actual: %s", - signedTx.Tx.ZKP.NewLocalExitRoot.Hex(), - batch.LocalExitRoot.Hex(), - signedTx.Tx.ZKP.NewStateRoot.Hex(), - batch.StateRoot.Hex(), - ) - } - - return nil -} - -func (e *Executor) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) { - // // Send L1 tx - // Verify ZKP using eth_call - l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( - uint64(signedTx.Tx.LastVerifiedBatch), - uint64(signedTx.Tx.NewVerifiedBatch), - signedTx.Tx.ZKP, - ) - if err != nil { - return common.Hash{}, fmt.Errorf("failed to build verify ZKP tx: %s", err) - } - - if err := e.ethTxMan.Add( - context.Background(), - ethTxManOwner, - signedTx.Tx.Hash().Hex(), - e.interopAdminAddr, - &signedTx.Tx.L1Contract, - nil, - l1TxData, - dbTx, - ); err != nil { - return common.Hash{}, fmt.Errorf("failed to add tx to ethTxMan, error: %s", err) - } - log.Debugf("successfuly added tx %s to ethTxMan", signedTx.Tx.Hash().Hex()) - return signedTx.Tx.Hash(), nil -} diff --git a/interop/executor.go b/interop/executor.go index 77c4306..ccdda46 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -1,10 +1,20 @@ package interop import ( + "context" + "errors" + "fmt" + "math/big" + "github.com/0xPolygon/beethoven/config" + "github.com/0xPolygon/beethoven/tx" + "github.com/0xPolygon/cdk-validium-node/jsonrpc/client" + "github.com/0xPolygon/cdk-validium-node/jsonrpc/types" "github.com/0xPolygon/cdk-validium-node/log" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" + "github.com/jackc/pgx/v4" ) type Executor struct { @@ -17,7 +27,6 @@ type Executor struct { func New(logger *log.Logger, cfg *config.Config, interopAdminAddr common.Address, - db DBInterface, etherman EthermanInterface, ethTxManager EthTxManager, ) *Executor { @@ -29,3 +38,136 @@ func New(logger *log.Logger, cfg *config.Config, etherman: etherman, } } + +const ethTxManOwner = "interop" + +func (e *Executor) CheckTx(ctx context.Context, tx tx.SignedTx) error { + e.logger.Debug("check tx") + + // Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed) + // TODO: The JSON parsing of the contract is incorrect + if _, ok := e.config.FullNodeRPCs[tx.Tx.L1Contract]; !ok { + return fmt.Errorf("there is no RPC registered for %s", tx.Tx.L1Contract) + } + + return nil +} + +func (e *Executor) Verify(tx tx.SignedTx) error { + err := e.VerifyZKP(tx) + if err != nil { + return fmt.Errorf("failed to verify ZKP: %s", err) + } + + return e.VerifySignature(tx) +} + +func (e *Executor) VerifyZKP(stx tx.SignedTx) error { + // Verify ZKP using eth_call + l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( + uint64(stx.Tx.LastVerifiedBatch), + uint64(stx.Tx.NewVerifiedBatch), + stx.Tx.ZKP, + ) + if err != nil { + return fmt.Errorf("failed to build verify ZKP tx: %s", err) + } + msg := ethereum.CallMsg{ + From: e.interopAdminAddr, + To: &stx.Tx.L1Contract, + Data: l1TxData, + } + res, err := e.etherman.CallContract(context.Background(), msg, nil) + if err != nil { + return fmt.Errorf("failed to call verify ZKP response: %s, error: %s", res, err) + } + + return nil +} + +func (e *Executor) VerifySignature(stx tx.SignedTx) error { + // Auth: check signature vs admin + signer, err := stx.Signer() + if err != nil { + return errors.New("failed to get signer") + } + + sequencer, err := e.etherman.GetSequencerAddr(stx.Tx.L1Contract) + if err != nil { + return errors.New("failed to get admin from L1") + } + if sequencer != signer { + return errors.New("unexpected signer") + } + + return nil +} + +func (e *Executor) Execute(signedTx tx.SignedTx) error { + ctx := context.TODO() + + // Check expected root vs root from the managed full node + // TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581 + // when this happens we should go async from here, since processing all the batches could take a lot of time + zkEVMClient := client.NewClient(e.config.FullNodeRPCs[signedTx.Tx.L1Contract]) + batch, err := zkEVMClient.BatchByNumber( + ctx, + big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), + ) + if err != nil { + return fmt.Errorf("failed to get batch from our node, error: %s", err) + } + if batch.StateRoot != signedTx.Tx.ZKP.NewStateRoot || batch.LocalExitRoot != signedTx.Tx.ZKP.NewLocalExitRoot { + return fmt.Errorf( + "Missmatch detected, expected local exit root: %s actual: %s. expected state root: %s actual: %s", + signedTx.Tx.ZKP.NewLocalExitRoot.Hex(), + batch.LocalExitRoot.Hex(), + signedTx.Tx.ZKP.NewStateRoot.Hex(), + batch.StateRoot.Hex(), + ) + } + + return nil +} + +func (e *Executor) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) { + // // Send L1 tx + // Verify ZKP using eth_call + l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( + uint64(signedTx.Tx.LastVerifiedBatch), + uint64(signedTx.Tx.NewVerifiedBatch), + signedTx.Tx.ZKP, + ) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to build verify ZKP tx: %s", err) + } + + if err := e.ethTxMan.Add( + context.Background(), + ethTxManOwner, + signedTx.Tx.Hash().Hex(), + e.interopAdminAddr, + &signedTx.Tx.L1Contract, + nil, + l1TxData, + dbTx, + ); err != nil { + return common.Hash{}, fmt.Errorf("failed to add tx to ethTxMan, error: %s", err) + } + log.Debugf("successfuly added tx %s to ethTxMan", signedTx.Tx.Hash().Hex()) + return signedTx.Tx.Hash(), nil +} + +func (e *Executor) GetTxStatus(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (result string, err types.Error) { + res, innerErr := e.ethTxMan.Result(ctx, ethTxManOwner, hash.Hex(), dbTx) + if innerErr != nil { + result = "0x0" + err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) + + return + } + + result = res.Status.String() + + return +} diff --git a/interop/query.go b/interop/query.go deleted file mode 100644 index 9fd4eb4..0000000 --- a/interop/query.go +++ /dev/null @@ -1,24 +0,0 @@ -package interop - -import ( - "context" - "fmt" - - "github.com/0xPolygon/cdk-validium-node/jsonrpc/types" - "github.com/ethereum/go-ethereum/common" - "github.com/jackc/pgx/v4" -) - -func (e *Executor) GetTxStatus(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (result string, err types.Error) { - res, innerErr := e.ethTxMan.Result(ctx, ethTxManOwner, hash.Hex(), dbTx) - if innerErr != nil { - result = "0x0" - err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) - - return - } - - result = res.Status.String() - - return -} diff --git a/interop/verify.go b/interop/verify.go deleted file mode 100644 index 16d4d72..0000000 --- a/interop/verify.go +++ /dev/null @@ -1,61 +0,0 @@ -package interop - -import ( - "context" - "errors" - "fmt" - - "github.com/0xPolygon/beethoven/tx" - - "github.com/ethereum/go-ethereum" -) - -func (e *Executor) Verify(tx tx.SignedTx) error { - err := e.VerifyZKP(tx) - if err != nil { - return fmt.Errorf("failed to verify ZKP: %s", err) - } - - return e.VerifySignature(tx) -} - -func (e *Executor) VerifyZKP(stx tx.SignedTx) error { - // Verify ZKP using eth_call - l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( - uint64(stx.Tx.LastVerifiedBatch), - uint64(stx.Tx.NewVerifiedBatch), - stx.Tx.ZKP, - ) - if err != nil { - return fmt.Errorf("failed to build verify ZKP tx: %s", err) - } - msg := ethereum.CallMsg{ - From: e.interopAdminAddr, - To: &stx.Tx.L1Contract, - Data: l1TxData, - } - res, err := e.etherman.CallContract(context.Background(), msg, nil) - if err != nil { - return fmt.Errorf("failed to call verify ZKP response: %s, error: %s", res, err) - } - - return nil -} - -func (e *Executor) VerifySignature(stx tx.SignedTx) error { - // Auth: check signature vs admin - signer, err := stx.Signer() - if err != nil { - return errors.New("failed to get signer") - } - - sequencer, err := e.etherman.GetSequencerAddr(stx.Tx.L1Contract) - if err != nil { - return errors.New("failed to get admin from L1") - } - if sequencer != signer { - return errors.New("unexpected signer") - } - - return nil -} From f31a42692c9e0f8ec43637e0ce21721005ed3033 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Tue, 19 Dec 2023 12:53:00 +0100 Subject: [PATCH 09/28] Fix tests --- rpc/rpc_test.go | 63 +++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index 6a24cc8..d9bda0f 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -3,13 +3,17 @@ package rpc import ( "context" "errors" - "github.com/0xPolygon/beethoven/mocks" "math/big" "testing" "time" + "github.com/0xPolygon/beethoven/config" + "github.com/0xPolygon/beethoven/interop" + "github.com/0xPolygon/beethoven/mocks" + "github.com/0xPolygon/cdk-validium-node/ethtxmanager" validiumTypes "github.com/0xPolygon/cdk-validium-node/jsonrpc/types" + "github.com/0xPolygon/cdk-validium-node/log" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -23,7 +27,7 @@ import ( const rpcRequestTimeout = 10 * time.Second -var _ EthermanInterface = (*ethermanMock)(nil) +var _ interop.EthermanInterface = (*ethermanMock)(nil) type ethermanMock struct { mock.Mock @@ -49,7 +53,7 @@ func (e *ethermanMock) CallContract(ctx context.Context, call ethereum.CallMsg, return args.Get(0).([]byte), args.Error(1) //nolint:forcetypeassert } -var _ DBInterface = (*dbMock)(nil) +var _ interop.DBInterface = (*dbMock)(nil) type dbMock struct { mock.Mock @@ -66,7 +70,7 @@ func (db *dbMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { return tx, args.Error(1) } -var _ EthTxManager = (*ethTxManagerMock)(nil) +var _ interop.EthTxManager = (*ethTxManagerMock)(nil) type ethTxManagerMock struct { mock.Mock @@ -98,7 +102,7 @@ func (e *ethTxManagerMock) ProcessPendingMonitoredTxs(ctx context.Context, owner e.Called(ctx, owner, failedResultHandler, dbTx) } -var _ ZkEVMClientInterface = (*zkEVMClientMock)(nil) +var _ interop.ZkEVMClientInterface = (*zkEVMClientMock)(nil) type zkEVMClientMock struct { mock.Mock @@ -115,16 +119,16 @@ func (zkc *zkEVMClientMock) BatchByNumber(ctx context.Context, number *big.Int) return batch, args.Error(1) } -var _ ZkEVMClientClientCreator = (*zkEVMClientCreatorMock)(nil) +var _ interop.ZkEVMClientClientCreator = (*zkEVMClientCreatorMock)(nil) type zkEVMClientCreatorMock struct { mock.Mock } -func (zc *zkEVMClientCreatorMock) NewClient(rpc string) ZkEVMClientInterface { +func (zc *zkEVMClientCreatorMock) NewClient(rpc string) interop.ZkEVMClientInterface { args := zc.Called(rpc) - return args.Get(0).(ZkEVMClientInterface) //nolint:forcetypeassert + return args.Get(0).(interop.ZkEVMClientInterface) //nolint:forcetypeassert } func TestInteropEndpointsGetTxStatus(t *testing.T) { @@ -136,14 +140,14 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { dbMock := new(dbMock) dbMock.On("BeginStateTransaction", mock.Anything).Return(nil, errors.New("error")).Once() - i := NewInteropEndpoints( + e := interop.New( + log.WithFields("module", "test"), + &config.Config{}, common.HexToAddress("0xadmin"), - dbMock, new(ethermanMock), - nil, - rpcRequestTimeout, new(ethTxManagerMock), ) + i := NewInteropEndpoints(context.Background(), e, dbMock) result, err := i.GetTxStatus(common.HexToHash("0xsomeTxHash")) @@ -168,14 +172,14 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { txManagerMock.On("Result", mock.Anything, ethTxManOwner, txHash.Hex(), txMock). Return(ethtxmanager.MonitoredTxResult{}, errors.New("error")).Once() - i := NewInteropEndpoints( + e := interop.New( + log.WithFields("module", "test"), + &config.Config{}, common.HexToAddress("0xadmin"), - dbMock, new(ethermanMock), - nil, - rpcRequestTimeout, - txManagerMock, + new(ethTxManagerMock), ) + i := NewInteropEndpoints(context.Background(), e, dbMock) result, err := i.GetTxStatus(txHash) @@ -212,14 +216,14 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { txManagerMock.On("Result", mock.Anything, ethTxManOwner, txHash.Hex(), txMock). Return(result, nil).Once() - i := NewInteropEndpoints( + e := interop.New( + log.WithFields("module", "test"), + &config.Config{}, common.HexToAddress("0xadmin"), - dbMock, new(ethermanMock), - nil, - rpcRequestTimeout, - txManagerMock, + new(ethTxManagerMock), ) + i := NewInteropEndpoints(context.Background(), e, dbMock) status, err := i.GetTxStatus(txHash) @@ -252,7 +256,7 @@ func TestInteropEndpointsSendTx(t *testing.T) { } testFn := func(cfg testConfig) { - fullNodeRPCs := FullNodeRPCs{ + fullNodeRPCs := config.FullNodeRPCs{ common.BytesToAddress([]byte{1, 2, 3, 4}): "someRPC", } tnx := tx.Tx{ @@ -273,7 +277,16 @@ func TestInteropEndpointsSendTx(t *testing.T) { ethTxManagerMock := new(ethTxManagerMock) executeTestFn := func() { - i := NewInteropEndpoints(common.HexToAddress("0xadmin"), dbMock, ethermanMock, fullNodeRPCs, rpcRequestTimeout, ethTxManagerMock) + e := interop.New( + log.WithFields("module", "test"), + &config.Config{ + FullNodeRPCs: fullNodeRPCs, + }, + common.HexToAddress("0xadmin"), + ethermanMock, + ethTxManagerMock, + ) + i := NewInteropEndpoints(context.Background(), e, dbMock) i.zkEVMClientCreator = zkEVMClientCreatorMock result, err := i.SendTx(*signedTx) @@ -295,7 +308,7 @@ func TestInteropEndpointsSendTx(t *testing.T) { } if !cfg.isL1ContractInMap { - fullNodeRPCs = FullNodeRPCs{} + fullNodeRPCs = config.FullNodeRPCs{} executeTestFn() return From 071769201be4712c76183bb18a6985c16d38d1dd Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Wed, 20 Dec 2023 15:57:25 +0100 Subject: [PATCH 10/28] fix test --- rpc/rpc_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index d9bda0f..e50d7a4 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -287,7 +287,7 @@ func TestInteropEndpointsSendTx(t *testing.T) { ethTxManagerMock, ) i := NewInteropEndpoints(context.Background(), e, dbMock) - i.zkEVMClientCreator = zkEVMClientCreatorMock + // i.zkEVMClientCreator = zkEVMClientCreatorMock result, err := i.SendTx(*signedTx) From bd8c414ee5c58885a176df2bfbf613dce036b836 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Tue, 2 Jan 2024 17:14:57 +0100 Subject: [PATCH 11/28] Fix merge issues --- config/config.go | 2 +- go.mod | 12 ++++-------- go.sum | 11 ----------- interop/executor.go | 7 ++++--- rpc/rpc_test.go | 2 +- 5 files changed, 10 insertions(+), 24 deletions(-) diff --git a/config/config.go b/config/config.go index 3298d1e..57c1123 100644 --- a/config/config.go +++ b/config/config.go @@ -27,7 +27,7 @@ type FullNodeRPCs map[common.Address]string // Config represents the full configuration of the data node type Config struct { - FullNodeRPCs rpc.FullNodeRPCs `mapstructure:"FullNodeRPCs"` + FullNodeRPCs FullNodeRPCs `mapstructure:"FullNodeRPCs"` RPC jRPC.Config `mapstructure:"RPC"` Log log.Config `mapstructure:"Log"` DB db.Config `mapstructure:"DB"` diff --git a/go.mod b/go.mod index 126dab9..4ed32cb 100644 --- a/go.mod +++ b/go.mod @@ -48,8 +48,7 @@ require ( github.com/dlclark/regexp2 v1.7.0 // indirect github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/fatih/color v1.14.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect @@ -67,9 +66,8 @@ require ( github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/hashicorp/go-hclog v1.6.2 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hermeznetwork/tracerr v0.3.2 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect @@ -95,10 +93,8 @@ require ( github.com/markbates/errx v1.1.0 // indirect github.com/markbates/oncer v1.0.0 // indirect github.com/markbates/safe v1.0.1 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 06d2935..f189228 100644 --- a/go.sum +++ b/go.sum @@ -188,9 +188,6 @@ github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fh github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= @@ -355,8 +352,6 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I= -github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= @@ -520,9 +515,7 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 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.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -532,7 +525,6 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1004,12 +996,9 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220715151400-c0bba94af5f8/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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/interop/executor.go b/interop/executor.go index ccdda46..b686cc5 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -9,9 +9,9 @@ import ( "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/tx" - "github.com/0xPolygon/cdk-validium-node/jsonrpc/client" - "github.com/0xPolygon/cdk-validium-node/jsonrpc/types" - "github.com/0xPolygon/cdk-validium-node/log" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/jackc/pgx/v4" @@ -150,6 +150,7 @@ func (e *Executor) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error &signedTx.Tx.L1Contract, nil, l1TxData, + 0, dbTx, ); err != nil { return common.Hash{}, fmt.Errorf("failed to add tx to ethTxMan, error: %s", err) diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index a9ab5c9..373a139 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -14,6 +14,7 @@ import ( beethovenTypes "github.com/0xPolygon/beethoven/rpc/types" "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" validiumTypes "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -22,7 +23,6 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/0xPolygon/beethoven/mocks" "github.com/0xPolygon/beethoven/tx" ) From 543599da95470a3ff4f2ea4ef5ad4a841bbe64ac Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Tue, 2 Jan 2024 17:24:42 +0100 Subject: [PATCH 12/28] Fix lint --- rpc/rpc_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index 373a139..fd321a6 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -5,7 +5,6 @@ import ( "errors" "math/big" "testing" - "time" "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/interop" @@ -26,8 +25,6 @@ import ( "github.com/0xPolygon/beethoven/tx" ) -const rpcRequestTimeout = 10 * time.Second - var _ interop.EthermanInterface = (*ethermanMock)(nil) type ethermanMock struct { From 813fac18ae647fc3a2d06783759e7f77abaa2786 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Wed, 3 Jan 2024 17:10:25 +0100 Subject: [PATCH 13/28] Fix tests --- interop/executor.go | 34 ++++++++++++++++++++++------------ rpc/rpc.go | 9 --------- rpc/rpc_test.go | 6 +++--- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/interop/executor.go b/interop/executor.go index b686cc5..64580e6 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -8,8 +8,8 @@ import ( "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/tx" - "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum" @@ -17,12 +17,21 @@ import ( "github.com/jackc/pgx/v4" ) +var _ ZkEVMClientClientCreator = (*zkEVMClientCreator)(nil) + +type zkEVMClientCreator struct{} + +func (zc *zkEVMClientCreator) NewClient(rpc string) ZkEVMClientInterface { + return client.NewClient(rpc) +} + type Executor struct { - logger *log.Logger - interopAdminAddr common.Address - config *config.Config - ethTxMan EthTxManager - etherman EthermanInterface + logger *log.Logger + interopAdminAddr common.Address + config *config.Config + ethTxMan EthTxManager + etherman EthermanInterface + ZkEVMClientCreator ZkEVMClientClientCreator } func New(logger *log.Logger, cfg *config.Config, @@ -31,11 +40,12 @@ func New(logger *log.Logger, cfg *config.Config, ethTxManager EthTxManager, ) *Executor { return &Executor{ - logger: logger, - interopAdminAddr: interopAdminAddr, - config: cfg, - ethTxMan: ethTxManager, - etherman: etherman, + logger: logger, + interopAdminAddr: interopAdminAddr, + config: cfg, + ethTxMan: ethTxManager, + etherman: etherman, + ZkEVMClientCreator: &zkEVMClientCreator{}, } } @@ -109,7 +119,7 @@ func (e *Executor) Execute(signedTx tx.SignedTx) error { // Check expected root vs root from the managed full node // TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581 // when this happens we should go async from here, since processing all the batches could take a lot of time - zkEVMClient := client.NewClient(e.config.FullNodeRPCs[signedTx.Tx.L1Contract]) + zkEVMClient := e.ZkEVMClientCreator.NewClient(e.config.FullNodeRPCs[signedTx.Tx.L1Contract]) batch, err := zkEVMClient.BatchByNumber( ctx, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), diff --git a/rpc/rpc.go b/rpc/rpc.go index c3bb90a..108b42f 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/0xPolygon/beethoven/interop" - "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum/common" @@ -19,14 +18,6 @@ const ( ethTxManOwner = "interop" ) -var _ interop.ZkEVMClientClientCreator = (*zkEVMClientCreator)(nil) - -type zkEVMClientCreator struct{} - -func (zc *zkEVMClientCreator) NewClient(rpc string) interop.ZkEVMClientInterface { - return client.NewClient(rpc) -} - // InteropEndpoints contains implementations for the "interop" RPC endpoints type InteropEndpoints struct { ctx context.Context diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index fd321a6..591d1c7 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -175,7 +175,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { &config.Config{}, common.HexToAddress("0xadmin"), new(ethermanMock), - new(ethTxManagerMock), + txManagerMock, ) i := NewInteropEndpoints(context.Background(), e, dbMock) @@ -219,7 +219,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { &config.Config{}, common.HexToAddress("0xadmin"), new(ethermanMock), - new(ethTxManagerMock), + txManagerMock, ) i := NewInteropEndpoints(context.Background(), e, dbMock) @@ -285,7 +285,7 @@ func TestInteropEndpointsSendTx(t *testing.T) { ethTxManagerMock, ) i := NewInteropEndpoints(context.Background(), e, dbMock) - // i.zkEVMClientCreator = zkEVMClientCreatorMock + i.executor.ZkEVMClientCreator = zkEVMClientCreatorMock result, err := i.SendTx(*signedTx) From f9ba0721a32e22a312cc4cf6c2dfef4c2eb5f1ab Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Wed, 3 Jan 2024 20:12:05 +0100 Subject: [PATCH 14/28] Fix typo --- interop/executor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interop/executor.go b/interop/executor.go index 64580e6..2b34a2b 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -129,7 +129,7 @@ func (e *Executor) Execute(signedTx tx.SignedTx) error { } if batch.StateRoot != signedTx.Tx.ZKP.NewStateRoot || batch.LocalExitRoot != signedTx.Tx.ZKP.NewLocalExitRoot { return fmt.Errorf( - "Missmatch detected, expected local exit root: %s actual: %s. expected state root: %s actual: %s", + "Mismatch detected, expected local exit root: %s actual: %s. expected state root: %s actual: %s", signedTx.Tx.ZKP.NewLocalExitRoot.Hex(), batch.LocalExitRoot.Hex(), signedTx.Tx.ZKP.NewStateRoot.Hex(), From 574e01811e5b51d5fa04f95bab5e760fc6957125 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Wed, 3 Jan 2024 20:20:36 +0100 Subject: [PATCH 15/28] Fix tests --- rpc/rpc_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index 591d1c7..ceac090 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -407,6 +407,11 @@ func TestInteropEndpointsSendTx(t *testing.T) { ethTxManagerMock.On("Add", mock.Anything, ethTxManOwner, signedTx.Tx.Hash().Hex(), mock.Anything, mock.Anything, mock.Anything, mock.Anything, txMock).Return(errors.New("error")).Once() txMock.On("Rollback", mock.Anything).Return(nil).Once() + + ethermanMock.On("BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), uint64(tnx.NewVerifiedBatch), mock.Anything). + Return([]byte{1, 2}, nil).Once() + executeTestFn() return @@ -417,11 +422,20 @@ func TestInteropEndpointsSendTx(t *testing.T) { if !cfg.isTxCommitted { txMock.On("Commit", mock.Anything).Return(errors.New("error")).Once() + + ethermanMock.On("BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), uint64(tnx.NewVerifiedBatch), mock.Anything). + Return([]byte{1, 2}, nil).Once() + executeTestFn() return } + ethermanMock.On("BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), uint64(tnx.NewVerifiedBatch), mock.Anything). + Return([]byte{1, 2}, nil).Once() + txMock.On("Commit", mock.Anything).Return(nil).Once() executeTestFn() } From 72afdc44ab0de98b70f60ce1dbcf0b0553ed2653 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 13:50:59 +0100 Subject: [PATCH 16/28] Refactor and tests --- interop/executor.go | 23 +++--- interop/executor_test.go | 58 +++++++++++++ rpc/rpc.go | 30 +++---- rpc/rpc_test.go | 135 ++++--------------------------- test/mocks.go | 120 +++++++++++++++++++++++++++ {interop => types}/interfaces.go | 2 +- 6 files changed, 222 insertions(+), 146 deletions(-) create mode 100644 interop/executor_test.go create mode 100644 test/mocks.go rename {interop => types}/interfaces.go (98%) diff --git a/interop/executor.go b/interop/executor.go index 2b34a2b..bc223d8 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -8,20 +8,21 @@ import ( "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/tx" - "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygon/beethoven/types" - "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + rpctypes "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/jackc/pgx/v4" ) -var _ ZkEVMClientClientCreator = (*zkEVMClientCreator)(nil) +var _ types.ZkEVMClientClientCreator = (*zkEVMClientCreator)(nil) type zkEVMClientCreator struct{} -func (zc *zkEVMClientCreator) NewClient(rpc string) ZkEVMClientInterface { +func (zc *zkEVMClientCreator) NewClient(rpc string) types.ZkEVMClientInterface { return client.NewClient(rpc) } @@ -29,15 +30,15 @@ type Executor struct { logger *log.Logger interopAdminAddr common.Address config *config.Config - ethTxMan EthTxManager - etherman EthermanInterface - ZkEVMClientCreator ZkEVMClientClientCreator + ethTxMan types.EthTxManager + etherman types.EthermanInterface + ZkEVMClientCreator types.ZkEVMClientClientCreator } func New(logger *log.Logger, cfg *config.Config, interopAdminAddr common.Address, - etherman EthermanInterface, - ethTxManager EthTxManager, + etherman types.EthermanInterface, + ethTxManager types.EthTxManager, ) *Executor { return &Executor{ logger: logger, @@ -169,11 +170,11 @@ func (e *Executor) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error return signedTx.Tx.Hash(), nil } -func (e *Executor) GetTxStatus(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (result string, err types.Error) { +func (e *Executor) GetTxStatus(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (result string, err rpctypes.Error) { res, innerErr := e.ethTxMan.Result(ctx, ethTxManOwner, hash.Hex(), dbTx) if innerErr != nil { result = "0x0" - err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) + err = rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) return } diff --git a/interop/executor_test.go b/interop/executor_test.go new file mode 100644 index 0000000..8ee89f0 --- /dev/null +++ b/interop/executor_test.go @@ -0,0 +1,58 @@ +package interop + +import ( + "context" + "testing" + + "github.com/0xPolygon/beethoven/config" + "github.com/0xPolygon/beethoven/test" + "github.com/0xPolygon/beethoven/tx" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +func TestNewExecutor(t *testing.T) { + cfg := &config.Config{ + // Set your desired config values here + } + interopAdminAddr := common.HexToAddress("0x1234567890abcdef") + etherman := &test.EthermanMock{} + ethTxManager := &test.EthTxManagerMock{} + + executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) + + assert.NotNil(t, executor) + assert.Equal(t, interopAdminAddr, executor.interopAdminAddr) + assert.Equal(t, cfg, executor.config) + assert.Equal(t, ethTxManager, executor.ethTxMan) + assert.Equal(t, etherman, executor.etherman) + assert.NotNil(t, executor.ZkEVMClientCreator) +} + +func TestExecutor_CheckTx(t *testing.T) { + cfg := &config.Config{ + // Set your desired config values here + } + interopAdminAddr := common.HexToAddress("0x1234567890abcdef") + etherman := &test.EthermanMock{} + ethTxManager := &test.EthTxManagerMock{} + + executor := New(log.WithFields("test", "test"), cfg, interopAdminAddr, etherman, ethTxManager) + + // Create a sample signed transaction for testing + signedTx := tx.SignedTx{ + Tx: tx.Tx{ + LastVerifiedBatch: 0, + NewVerifiedBatch: 1, + ZKP: tx.ZKP{ + Proof: []byte("sampleProof"), + }, + L1Contract: common.HexToAddress("0x1234567890abcdef"), + }, + } + + err := executor.CheckTx(context.Background(), signedTx) + assert.NoError(t, err) +} diff --git a/rpc/rpc.go b/rpc/rpc.go index 108b42f..d24e5e0 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -5,7 +5,9 @@ import ( "fmt" "github.com/0xPolygon/beethoven/interop" - "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygon/beethoven/types" + + rpctypes "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum/common" @@ -22,14 +24,14 @@ const ( type InteropEndpoints struct { ctx context.Context executor *interop.Executor - db interop.DBInterface + db types.DBInterface } // NewInteropEndpoints returns InteropEndpoints func NewInteropEndpoints( ctx context.Context, executor *interop.Executor, - db interop.DBInterface, + db types.DBInterface, ) *InteropEndpoints { return &InteropEndpoints{ ctx: ctx, @@ -38,25 +40,25 @@ func NewInteropEndpoints( } } -func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, types.Error) { +func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, rpctypes.Error) { // Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed) if err := i.executor.CheckTx(i.ctx, signedTx); err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("there is no RPC registered for %s", signedTx.Tx.L1Contract)) + return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("there is no RPC registered for %s", signedTx.Tx.L1Contract)) } // Verify ZKP using eth_call if err := i.executor.Verify(signedTx); err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to verify tx: %s", err)) + return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to verify tx: %s", err)) } if err := i.executor.Execute(signedTx); err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to execute tx: %s", err)) + return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to execute tx: %s", err)) } // Send L1 tx dbTx, err := i.db.BeginStateTransaction(i.ctx) if err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to begin dbTx, error: %s", err)) + return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to begin dbTx, error: %s", err)) } _, err = i.executor.Settle(signedTx, dbTx) @@ -64,21 +66,21 @@ func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, types.Erro if errRollback := dbTx.Rollback(i.ctx); errRollback != nil { log.Error("rollback err: ", errRollback) } - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to add tx to ethTxMan, error: %s", err)) + return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to add tx to ethTxMan, error: %s", err)) } if err := dbTx.Commit(i.ctx); err != nil { - return "0x0", types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to commit dbTx, error: %s", err)) + return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to commit dbTx, error: %s", err)) } log.Debugf("successfuly added tx %s to ethTxMan", signedTx.Tx.Hash().Hex()) return signedTx.Tx.Hash(), nil } -func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, err types.Error) { +func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, err rpctypes.Error) { dbTx, innerErr := i.db.BeginStateTransaction(i.ctx) if innerErr != nil { result = "0x0" - err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to begin dbTx, error: %s", innerErr)) + err = rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to begin dbTx, error: %s", innerErr)) return } @@ -86,14 +88,14 @@ func (i *InteropEndpoints) GetTxStatus(hash common.Hash) (result interface{}, er defer func() { if innerErr := dbTx.Rollback(i.ctx); innerErr != nil { result = "0x0" - err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to rollback dbTx, error: %s", innerErr)) + err = rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to rollback dbTx, error: %s", innerErr)) } }() result, innerErr = i.executor.GetTxStatus(i.ctx, hash, dbTx) if innerErr != nil { result = "0x0" - err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) + err = rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr)) return } diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index ceac090..036eef7 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -9,141 +9,36 @@ import ( "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/interop" "github.com/0xPolygon/beethoven/mocks" + "github.com/0xPolygon/beethoven/test" beethovenTypes "github.com/0xPolygon/beethoven/rpc/types" "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" validiumTypes "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/jackc/pgx/v4" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/0xPolygon/beethoven/tx" ) -var _ interop.EthermanInterface = (*ethermanMock)(nil) - -type ethermanMock struct { - mock.Mock -} - -func (e *ethermanMock) GetSequencerAddr(l1Contract common.Address) (common.Address, error) { - args := e.Called(l1Contract) - - return args.Get(0).(common.Address), args.Error(1) //nolint:forcetypeassert -} - -func (e *ethermanMock) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, - newVerifiedBatch uint64, proof tx.ZKP) (data []byte, err error) { - args := e.Called(lastVerifiedBatch, newVerifiedBatch, proof) - - return args.Get(0).([]byte), args.Error(1) //nolint:forcetypeassert -} - -func (e *ethermanMock) CallContract(ctx context.Context, call ethereum.CallMsg, - blockNumber *big.Int) ([]byte, error) { - args := e.Called(ctx, call, blockNumber) - - return args.Get(0).([]byte), args.Error(1) //nolint:forcetypeassert -} - -var _ interop.DBInterface = (*dbMock)(nil) - -type dbMock struct { - mock.Mock -} - -func (db *dbMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { - args := db.Called(ctx) - - tx, ok := args.Get(0).(pgx.Tx) - if !ok { - return nil, args.Error(1) - } - - return tx, args.Error(1) -} - -var _ interop.EthTxManager = (*ethTxManagerMock)(nil) - -type ethTxManagerMock struct { - mock.Mock -} - -func (e *ethTxManagerMock) Add(ctx context.Context, owner, id string, - from common.Address, to *common.Address, value *big.Int, data []byte, gasOffset uint64, dbTx pgx.Tx) error { - args := e.Called(ctx, owner, id, from, to, value, data, dbTx) - - return args.Error(0) -} - -func (e *ethTxManagerMock) Result(ctx context.Context, owner, - id string, dbTx pgx.Tx) (ethtxmanager.MonitoredTxResult, error) { - args := e.Called(ctx, owner, id, dbTx) - - return args.Get(0).(ethtxmanager.MonitoredTxResult), args.Error(1) //nolint:forcetypeassert -} - -func (e *ethTxManagerMock) ResultsByStatus(ctx context.Context, owner string, - statuses []ethtxmanager.MonitoredTxStatus, dbTx pgx.Tx) ([]ethtxmanager.MonitoredTxResult, error) { - e.Called(ctx, owner, statuses, dbTx) - - return nil, nil -} - -func (e *ethTxManagerMock) ProcessPendingMonitoredTxs(ctx context.Context, owner string, - failedResultHandler ethtxmanager.ResultHandler, dbTx pgx.Tx) { - e.Called(ctx, owner, failedResultHandler, dbTx) -} - -var _ interop.ZkEVMClientInterface = (*zkEVMClientMock)(nil) - -type zkEVMClientMock struct { - mock.Mock -} - -func (zkc *zkEVMClientMock) BatchByNumber(ctx context.Context, number *big.Int) (*validiumTypes.Batch, error) { - args := zkc.Called(ctx, number) - - batch, ok := args.Get(0).(*validiumTypes.Batch) - if !ok { - return nil, args.Error(1) - } - - return batch, args.Error(1) -} - -var _ interop.ZkEVMClientClientCreator = (*zkEVMClientCreatorMock)(nil) - -type zkEVMClientCreatorMock struct { - mock.Mock -} - -func (zc *zkEVMClientCreatorMock) NewClient(rpc string) interop.ZkEVMClientInterface { - args := zc.Called(rpc) - - return args.Get(0).(interop.ZkEVMClientInterface) //nolint:forcetypeassert -} - func TestInteropEndpointsGetTxStatus(t *testing.T) { t.Parallel() t.Run("BeginStateTransaction returns an error", func(t *testing.T) { t.Parallel() - dbMock := new(dbMock) + dbMock := new(test.DbMock) dbMock.On("BeginStateTransaction", mock.Anything).Return(nil, errors.New("error")).Once() e := interop.New( log.WithFields("module", "test"), &config.Config{}, common.HexToAddress("0xadmin"), - new(ethermanMock), - new(ethTxManagerMock), + new(test.EthermanMock), + new(test.EthTxManagerMock), ) i := NewInteropEndpoints(context.Background(), e, dbMock) @@ -163,10 +58,10 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { txMock := new(mocks.TxMock) txMock.On("Rollback", mock.Anything).Return(nil).Once() - dbMock := new(dbMock) + dbMock := new(test.DbMock) dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil).Once() - txManagerMock := new(ethTxManagerMock) + txManagerMock := new(test.EthTxManagerMock) txManagerMock.On("Result", mock.Anything, ethTxManOwner, txHash.Hex(), txMock). Return(ethtxmanager.MonitoredTxResult{}, errors.New("error")).Once() @@ -174,7 +69,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { log.WithFields("module", "test"), &config.Config{}, common.HexToAddress("0xadmin"), - new(ethermanMock), + new(test.EthermanMock), txManagerMock, ) i := NewInteropEndpoints(context.Background(), e, dbMock) @@ -207,10 +102,10 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { txMock := new(mocks.TxMock) txMock.On("Rollback", mock.Anything).Return(nil).Once() - dbMock := new(dbMock) + dbMock := new(test.DbMock) dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil).Once() - txManagerMock := new(ethTxManagerMock) + txManagerMock := new(test.EthTxManagerMock) txManagerMock.On("Result", mock.Anything, ethTxManOwner, txHash.Hex(), txMock). Return(result, nil).Once() @@ -218,7 +113,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { log.WithFields("module", "test"), &config.Config{}, common.HexToAddress("0xadmin"), - new(ethermanMock), + new(test.EthermanMock), txManagerMock, ) i := NewInteropEndpoints(context.Background(), e, dbMock) @@ -267,12 +162,12 @@ func TestInteropEndpointsSendTx(t *testing.T) { }, } signedTx := &tx.SignedTx{Tx: tnx} - ethermanMock := new(ethermanMock) - zkEVMClientCreatorMock := new(zkEVMClientCreatorMock) - zkEVMClientMock := new(zkEVMClientMock) - dbMock := new(dbMock) + ethermanMock := new(test.EthermanMock) + zkEVMClientCreatorMock := new(test.ZkEVMClientCreatorMock) + zkEVMClientMock := new(test.ZkEVMClientMock) + dbMock := new(test.DbMock) txMock := new(mocks.TxMock) - ethTxManagerMock := new(ethTxManagerMock) + ethTxManagerMock := new(test.EthTxManagerMock) executeTestFn := func() { e := interop.New( diff --git a/test/mocks.go b/test/mocks.go new file mode 100644 index 0000000..9221dac --- /dev/null +++ b/test/mocks.go @@ -0,0 +1,120 @@ +package test + +import ( + "context" + "math/big" + + "github.com/0xPolygon/beethoven/tx" + "github.com/0xPolygon/beethoven/types" + + "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" + validiumTypes "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/jackc/pgx/v4" + "github.com/stretchr/testify/mock" +) + +var _ types.EthermanInterface = (*EthermanMock)(nil) + +type EthermanMock struct { + mock.Mock +} + +func (e *EthermanMock) GetSequencerAddr(l1Contract common.Address) (common.Address, error) { + args := e.Called(l1Contract) + + return args.Get(0).(common.Address), args.Error(1) //nolint:forcetypeassert +} + +func (e *EthermanMock) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, + newVerifiedBatch uint64, proof tx.ZKP) (data []byte, err error) { + args := e.Called(lastVerifiedBatch, newVerifiedBatch, proof) + + return args.Get(0).([]byte), args.Error(1) //nolint:forcetypeassert +} + +func (e *EthermanMock) CallContract(ctx context.Context, call ethereum.CallMsg, + blockNumber *big.Int) ([]byte, error) { + args := e.Called(ctx, call, blockNumber) + + return args.Get(0).([]byte), args.Error(1) //nolint:forcetypeassert +} + +var _ types.DBInterface = (*DbMock)(nil) + +type DbMock struct { + mock.Mock +} + +func (db *DbMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { + args := db.Called(ctx) + + tx, ok := args.Get(0).(pgx.Tx) + if !ok { + return nil, args.Error(1) + } + + return tx, args.Error(1) +} + +var _ types.EthTxManager = (*EthTxManagerMock)(nil) + +type EthTxManagerMock struct { + mock.Mock +} + +func (e *EthTxManagerMock) Add(ctx context.Context, owner, id string, + from common.Address, to *common.Address, value *big.Int, data []byte, gasOffset uint64, dbTx pgx.Tx) error { + args := e.Called(ctx, owner, id, from, to, value, data, dbTx) + + return args.Error(0) +} + +func (e *EthTxManagerMock) Result(ctx context.Context, owner, + id string, dbTx pgx.Tx) (ethtxmanager.MonitoredTxResult, error) { + args := e.Called(ctx, owner, id, dbTx) + + return args.Get(0).(ethtxmanager.MonitoredTxResult), args.Error(1) //nolint:forcetypeassert +} + +func (e *EthTxManagerMock) ResultsByStatus(ctx context.Context, owner string, + statuses []ethtxmanager.MonitoredTxStatus, dbTx pgx.Tx) ([]ethtxmanager.MonitoredTxResult, error) { + e.Called(ctx, owner, statuses, dbTx) + + return nil, nil +} + +func (e *EthTxManagerMock) ProcessPendingMonitoredTxs(ctx context.Context, owner string, + failedResultHandler ethtxmanager.ResultHandler, dbTx pgx.Tx) { + e.Called(ctx, owner, failedResultHandler, dbTx) +} + +var _ types.ZkEVMClientInterface = (*ZkEVMClientMock)(nil) + +type ZkEVMClientMock struct { + mock.Mock +} + +func (zkc *ZkEVMClientMock) BatchByNumber(ctx context.Context, number *big.Int) (*validiumTypes.Batch, error) { + args := zkc.Called(ctx, number) + + batch, ok := args.Get(0).(*validiumTypes.Batch) + if !ok { + return nil, args.Error(1) + } + + return batch, args.Error(1) +} + +var _ types.ZkEVMClientClientCreator = (*ZkEVMClientCreatorMock)(nil) + +type ZkEVMClientCreatorMock struct { + mock.Mock +} + +func (zc *ZkEVMClientCreatorMock) NewClient(rpc string) types.ZkEVMClientInterface { + args := zc.Called(rpc) + + return args.Get(0).(types.ZkEVMClientInterface) //nolint:forcetypeassert +} diff --git a/interop/interfaces.go b/types/interfaces.go similarity index 98% rename from interop/interfaces.go rename to types/interfaces.go index 8b58b29..b61de5d 100644 --- a/interop/interfaces.go +++ b/types/interfaces.go @@ -1,4 +1,4 @@ -package interop +package types import ( "context" From 245704ed836ac6325469af4579897684d9cc09ed Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 15:12:32 +0100 Subject: [PATCH 17/28] Add more tests --- interop/executor_test.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/interop/executor_test.go b/interop/executor_test.go index 8ee89f0..3f9c497 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -33,7 +33,9 @@ func TestNewExecutor(t *testing.T) { func TestExecutor_CheckTx(t *testing.T) { cfg := &config.Config{ - // Set your desired config values here + FullNodeRPCs: map[common.Address]string{ + common.HexToAddress("0x1234567890abcdef"): "http://localhost:8545", + }, } interopAdminAddr := common.HexToAddress("0x1234567890abcdef") etherman := &test.EthermanMock{} @@ -55,4 +57,18 @@ func TestExecutor_CheckTx(t *testing.T) { err := executor.CheckTx(context.Background(), signedTx) assert.NoError(t, err) + + signedTx = tx.SignedTx{ + Tx: tx.Tx{ + LastVerifiedBatch: 0, + NewVerifiedBatch: 1, + ZKP: tx.ZKP{ + Proof: []byte("sampleProof"), + }, + L1Contract: common.HexToAddress("0xdeadbeef"), + }, + } + + err = executor.CheckTx(context.Background(), signedTx) + assert.Error(t, err) } From ba5b6ea5efedb4c8d7cbf1e508c2c58ad7bb1906 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 16:51:29 +0100 Subject: [PATCH 18/28] More coverage --- interop/executor_test.go | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/interop/executor_test.go b/interop/executor_test.go index 3f9c497..a621d02 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -11,6 +11,7 @@ import ( "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" ) func TestNewExecutor(t *testing.T) { @@ -72,3 +73,66 @@ func TestExecutor_CheckTx(t *testing.T) { err = executor.CheckTx(context.Background(), signedTx) assert.Error(t, err) } + +func TestExecutor_VerifyZKP(t *testing.T) { + cfg := &config.Config{ + // Set your desired config values here + } + interopAdminAddr := common.HexToAddress("0x1234567890abcdef") + etherman := &test.EthermanMock{} + ethTxManager := &test.EthTxManagerMock{} + tnx := tx.Tx{ + LastVerifiedBatch: 0, + NewVerifiedBatch: 1, + ZKP: tx.ZKP{ + Proof: []byte("sampleProof"), + }, + L1Contract: common.HexToAddress("0x1234567890abcdef"), + } + + etherman.On("BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), uint64(tnx.NewVerifiedBatch), mock.Anything). + Return([]byte{}, nil).Once() + + etherman.On("CallContract", mock.Anything, mock.Anything, mock.Anything). + Return([]byte{}, nil).Once() + + executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) + + // Create a sample signed transaction for testing + signedTx := tx.SignedTx{ + Tx: tnx, + } + + err := executor.VerifyZKP(signedTx) + assert.NoError(t, err) + etherman.AssertExpectations(t) +} +func TestExecutor_VerifySignature(t *testing.T) { + cfg := &config.Config{ + // Set your desired config values here + } + interopAdminAddr := common.HexToAddress("0x1234567890abcdef") + etherman := &test.EthermanMock{} + ethTxManager := &test.EthTxManagerMock{} + + executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) + + // Create a sample signed transaction for testing + signedTx := tx.SignedTx{ + Tx: tx.Tx{ + LastVerifiedBatch: 0, + NewVerifiedBatch: 1, + ZKP: tx.ZKP{ + Proof: []byte("sampleProof"), + }, + L1Contract: common.HexToAddress("0x1234567890abcdef"), + }, + } + + etherman.On("GetSequencerAddr", mock.Anything). + Return([]byte{}, nil).Once() + + err := executor.VerifySignature(signedTx) + assert.NoError(t, err) +} From a966245c8ca2204f2bf30e57f99f0502e79fba92 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 17:31:07 +0100 Subject: [PATCH 19/28] Add test --- interop/executor_test.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/interop/executor_test.go b/interop/executor_test.go index a621d02..82440cb 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -10,8 +10,10 @@ import ( "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) func TestNewExecutor(t *testing.T) { @@ -108,6 +110,7 @@ func TestExecutor_VerifyZKP(t *testing.T) { assert.NoError(t, err) etherman.AssertExpectations(t) } + func TestExecutor_VerifySignature(t *testing.T) { cfg := &config.Config{ // Set your desired config values here @@ -118,21 +121,25 @@ func TestExecutor_VerifySignature(t *testing.T) { executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) - // Create a sample signed transaction for testing - signedTx := tx.SignedTx{ - Tx: tx.Tx{ - LastVerifiedBatch: 0, - NewVerifiedBatch: 1, - ZKP: tx.ZKP{ - Proof: []byte("sampleProof"), - }, - L1Contract: common.HexToAddress("0x1234567890abcdef"), + txn := tx.Tx{ + LastVerifiedBatch: 0, + NewVerifiedBatch: 1, + ZKP: tx.ZKP{ + Proof: []byte("sampleProof"), }, + L1Contract: common.HexToAddress("0x1234567890abcdef"), } + pk, err := crypto.GenerateKey() + require.NoError(t, err) + + signedTx, err := txn.Sign(pk) + require.NoError(t, err) + etherman.On("GetSequencerAddr", mock.Anything). - Return([]byte{}, nil).Once() + Return(crypto.PubkeyToAddress(pk.PublicKey), nil).Once() - err := executor.VerifySignature(signedTx) - assert.NoError(t, err) + err = executor.VerifySignature(*signedTx) + require.NoError(t, err) + etherman.AssertExpectations(t) } From 795d5ee2fe6fd70ecf01f5c7aad83b34b4bb7cef Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 17:41:48 +0100 Subject: [PATCH 20/28] More tests --- interop/executor_test.go | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/interop/executor_test.go b/interop/executor_test.go index 82440cb..e5a8c28 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -2,12 +2,14 @@ package interop import ( "context" + "math/big" "testing" "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/test" "github.com/0xPolygon/beethoven/tx" + rpctypes "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -143,3 +145,45 @@ func TestExecutor_VerifySignature(t *testing.T) { require.NoError(t, err) etherman.AssertExpectations(t) } + +func TestExecutor_Execute(t *testing.T) { + cfg := &config.Config{} + interopAdminAddr := common.HexToAddress("0x1234567890abcdef") + etherman := &test.EthermanMock{} + ethTxManager := &test.EthTxManagerMock{} + + executor := New(log.WithFields("test", "test"), cfg, interopAdminAddr, etherman, ethTxManager) + + // Create a sample signed transaction for testing + signedTx := tx.SignedTx{ + Tx: tx.Tx{ + LastVerifiedBatch: 0, + NewVerifiedBatch: 1, + ZKP: tx.ZKP{ + NewStateRoot: common.BytesToHash([]byte("sampleNewStateRoot")), + Proof: []byte("sampleProof"), + }, + L1Contract: common.HexToAddress("0x1234567890abcdef"), + }, + } + + // Mock the ZkEVMClientCreator.NewClient method + mockZkEVMClientCreator := &test.ZkEVMClientCreatorMock{} + mockZkEVMClient := &test.ZkEVMClientMock{} + + mockZkEVMClientCreator.On("NewClient", mock.Anything).Return(mockZkEVMClient).Once() + mockZkEVMClient.On("BatchByNumber", mock.Anything, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch))). + Return(&rpctypes.Batch{ + StateRoot: signedTx.Tx.ZKP.NewStateRoot, + LocalExitRoot: signedTx.Tx.ZKP.NewLocalExitRoot, + // Add other necessary fields here + }, nil).Once() + + // Set the ZkEVMClientCreator to return the mock ZkEVMClient + executor.ZkEVMClientCreator = mockZkEVMClientCreator + + err := executor.Execute(signedTx) + require.NoError(t, err) + mockZkEVMClientCreator.AssertExpectations(t) + mockZkEVMClient.AssertExpectations(t) +} From 73d9a755e51f9fcbd77fcbadeea66e49b63b4c4d Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 17:49:54 +0100 Subject: [PATCH 21/28] Move mocks to correct place --- interop/executor_test.go | 26 +++++++++++++------------- {test => mocks}/mocks.go | 2 +- rpc/rpc_test.go | 29 ++++++++++++++--------------- 3 files changed, 28 insertions(+), 29 deletions(-) rename {test => mocks}/mocks.go (99%) diff --git a/interop/executor_test.go b/interop/executor_test.go index e5a8c28..e8ac158 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/0xPolygon/beethoven/config" - "github.com/0xPolygon/beethoven/test" + "github.com/0xPolygon/beethoven/mocks" "github.com/0xPolygon/beethoven/tx" rpctypes "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" @@ -23,8 +23,8 @@ func TestNewExecutor(t *testing.T) { // Set your desired config values here } interopAdminAddr := common.HexToAddress("0x1234567890abcdef") - etherman := &test.EthermanMock{} - ethTxManager := &test.EthTxManagerMock{} + etherman := &mocks.EthermanMock{} + ethTxManager := &mocks.EthTxManagerMock{} executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) @@ -43,8 +43,8 @@ func TestExecutor_CheckTx(t *testing.T) { }, } interopAdminAddr := common.HexToAddress("0x1234567890abcdef") - etherman := &test.EthermanMock{} - ethTxManager := &test.EthTxManagerMock{} + etherman := &mocks.EthermanMock{} + ethTxManager := &mocks.EthTxManagerMock{} executor := New(log.WithFields("test", "test"), cfg, interopAdminAddr, etherman, ethTxManager) @@ -83,8 +83,8 @@ func TestExecutor_VerifyZKP(t *testing.T) { // Set your desired config values here } interopAdminAddr := common.HexToAddress("0x1234567890abcdef") - etherman := &test.EthermanMock{} - ethTxManager := &test.EthTxManagerMock{} + etherman := &mocks.EthermanMock{} + ethTxManager := &mocks.EthTxManagerMock{} tnx := tx.Tx{ LastVerifiedBatch: 0, NewVerifiedBatch: 1, @@ -118,8 +118,8 @@ func TestExecutor_VerifySignature(t *testing.T) { // Set your desired config values here } interopAdminAddr := common.HexToAddress("0x1234567890abcdef") - etherman := &test.EthermanMock{} - ethTxManager := &test.EthTxManagerMock{} + etherman := &mocks.EthermanMock{} + ethTxManager := &mocks.EthTxManagerMock{} executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) @@ -149,8 +149,8 @@ func TestExecutor_VerifySignature(t *testing.T) { func TestExecutor_Execute(t *testing.T) { cfg := &config.Config{} interopAdminAddr := common.HexToAddress("0x1234567890abcdef") - etherman := &test.EthermanMock{} - ethTxManager := &test.EthTxManagerMock{} + etherman := &mocks.EthermanMock{} + ethTxManager := &mocks.EthTxManagerMock{} executor := New(log.WithFields("test", "test"), cfg, interopAdminAddr, etherman, ethTxManager) @@ -168,8 +168,8 @@ func TestExecutor_Execute(t *testing.T) { } // Mock the ZkEVMClientCreator.NewClient method - mockZkEVMClientCreator := &test.ZkEVMClientCreatorMock{} - mockZkEVMClient := &test.ZkEVMClientMock{} + mockZkEVMClientCreator := &mocks.ZkEVMClientCreatorMock{} + mockZkEVMClient := &mocks.ZkEVMClientMock{} mockZkEVMClientCreator.On("NewClient", mock.Anything).Return(mockZkEVMClient).Once() mockZkEVMClient.On("BatchByNumber", mock.Anything, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch))). diff --git a/test/mocks.go b/mocks/mocks.go similarity index 99% rename from test/mocks.go rename to mocks/mocks.go index 9221dac..26acadc 100644 --- a/test/mocks.go +++ b/mocks/mocks.go @@ -1,4 +1,4 @@ -package test +package mocks import ( "context" diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index 036eef7..e972db6 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -9,7 +9,6 @@ import ( "github.com/0xPolygon/beethoven/config" "github.com/0xPolygon/beethoven/interop" "github.com/0xPolygon/beethoven/mocks" - "github.com/0xPolygon/beethoven/test" beethovenTypes "github.com/0xPolygon/beethoven/rpc/types" "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" @@ -30,15 +29,15 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { t.Run("BeginStateTransaction returns an error", func(t *testing.T) { t.Parallel() - dbMock := new(test.DbMock) + dbMock := new(mocks.DbMock) dbMock.On("BeginStateTransaction", mock.Anything).Return(nil, errors.New("error")).Once() e := interop.New( log.WithFields("module", "test"), &config.Config{}, common.HexToAddress("0xadmin"), - new(test.EthermanMock), - new(test.EthTxManagerMock), + new(mocks.EthermanMock), + new(mocks.EthTxManagerMock), ) i := NewInteropEndpoints(context.Background(), e, dbMock) @@ -58,10 +57,10 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { txMock := new(mocks.TxMock) txMock.On("Rollback", mock.Anything).Return(nil).Once() - dbMock := new(test.DbMock) + dbMock := new(mocks.DbMock) dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil).Once() - txManagerMock := new(test.EthTxManagerMock) + txManagerMock := new(mocks.EthTxManagerMock) txManagerMock.On("Result", mock.Anything, ethTxManOwner, txHash.Hex(), txMock). Return(ethtxmanager.MonitoredTxResult{}, errors.New("error")).Once() @@ -69,7 +68,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { log.WithFields("module", "test"), &config.Config{}, common.HexToAddress("0xadmin"), - new(test.EthermanMock), + new(mocks.EthermanMock), txManagerMock, ) i := NewInteropEndpoints(context.Background(), e, dbMock) @@ -102,10 +101,10 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { txMock := new(mocks.TxMock) txMock.On("Rollback", mock.Anything).Return(nil).Once() - dbMock := new(test.DbMock) + dbMock := new(mocks.DbMock) dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil).Once() - txManagerMock := new(test.EthTxManagerMock) + txManagerMock := new(mocks.EthTxManagerMock) txManagerMock.On("Result", mock.Anything, ethTxManOwner, txHash.Hex(), txMock). Return(result, nil).Once() @@ -113,7 +112,7 @@ func TestInteropEndpointsGetTxStatus(t *testing.T) { log.WithFields("module", "test"), &config.Config{}, common.HexToAddress("0xadmin"), - new(test.EthermanMock), + new(mocks.EthermanMock), txManagerMock, ) i := NewInteropEndpoints(context.Background(), e, dbMock) @@ -162,12 +161,12 @@ func TestInteropEndpointsSendTx(t *testing.T) { }, } signedTx := &tx.SignedTx{Tx: tnx} - ethermanMock := new(test.EthermanMock) - zkEVMClientCreatorMock := new(test.ZkEVMClientCreatorMock) - zkEVMClientMock := new(test.ZkEVMClientMock) - dbMock := new(test.DbMock) + ethermanMock := new(mocks.EthermanMock) + zkEVMClientCreatorMock := new(mocks.ZkEVMClientCreatorMock) + zkEVMClientMock := new(mocks.ZkEVMClientMock) + dbMock := new(mocks.DbMock) txMock := new(mocks.TxMock) - ethTxManagerMock := new(test.EthTxManagerMock) + ethTxManagerMock := new(mocks.EthTxManagerMock) executeTestFn := func() { e := interop.New( From 472b3f367701c258ab584e531cf578801a435a1f Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 18:29:20 +0100 Subject: [PATCH 22/28] Tests --- interop/executor.go | 6 +++--- interop/executor_test.go | 41 ++++++++++++++++++++++++++++++++++++++++ mocks/mocks.go | 2 +- rpc/rpc.go | 2 +- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/interop/executor.go b/interop/executor.go index bc223d8..7f7ac0a 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -141,7 +141,7 @@ func (e *Executor) Execute(signedTx tx.SignedTx) error { return nil } -func (e *Executor) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) { +func (e *Executor) Settle(ctx context.Context, signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) { // // Send L1 tx // Verify ZKP using eth_call l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( @@ -154,12 +154,12 @@ func (e *Executor) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error } if err := e.ethTxMan.Add( - context.Background(), + ctx, ethTxManOwner, signedTx.Tx.Hash().Hex(), e.interopAdminAddr, &signedTx.Tx.L1Contract, - nil, + big.NewInt(0), l1TxData, 0, dbTx, diff --git a/interop/executor_test.go b/interop/executor_test.go index e8ac158..31c3f3d 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -187,3 +187,44 @@ func TestExecutor_Execute(t *testing.T) { mockZkEVMClientCreator.AssertExpectations(t) mockZkEVMClient.AssertExpectations(t) } + +func TestExecutor_Settle(t *testing.T) { + cfg := &config.Config{ + // Set your desired config values here + } + interopAdminAddr := common.HexToAddress("0x1234567890abcdef") + etherman := &mocks.EthermanMock{} + ethTxManager := &mocks.EthTxManagerMock{} + dbTx := &mocks.TxMock{} + + executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) + + signedTx := tx.SignedTx{ + Tx: tx.Tx{ + LastVerifiedBatch: 0, + NewVerifiedBatch: 1, + ZKP: tx.ZKP{ + Proof: []byte("sampleProof"), + }, + L1Contract: common.HexToAddress("0x1234567890abcdef"), + }, + } + + l1TxData := []byte("sampleL1TxData") + etherman.On("BuildTrustedVerifyBatchesTxData", + uint64(signedTx.Tx.LastVerifiedBatch), uint64(signedTx.Tx.NewVerifiedBatch), signedTx.Tx.ZKP). + Return(l1TxData, nil).Once() + + ctx := context.Background() + txHash := signedTx.Tx.Hash().Hex() + ethTxManager.On("Add", + ctx, ethTxManOwner, txHash, interopAdminAddr, &signedTx.Tx.L1Contract, big.NewInt(0), l1TxData, uint64(0), dbTx). + Return(nil).Once() + + hash, err := executor.Settle(ctx, signedTx, dbTx) + require.NoError(t, err) + assert.Equal(t, signedTx.Tx.Hash(), hash) + + etherman.AssertExpectations(t) + ethTxManager.AssertExpectations(t) +} diff --git a/mocks/mocks.go b/mocks/mocks.go index 26acadc..95a68bc 100644 --- a/mocks/mocks.go +++ b/mocks/mocks.go @@ -66,7 +66,7 @@ type EthTxManagerMock struct { func (e *EthTxManagerMock) Add(ctx context.Context, owner, id string, from common.Address, to *common.Address, value *big.Int, data []byte, gasOffset uint64, dbTx pgx.Tx) error { - args := e.Called(ctx, owner, id, from, to, value, data, dbTx) + args := e.Called(ctx, owner, id, from, to, value, data, gasOffset, dbTx) return args.Error(0) } diff --git a/rpc/rpc.go b/rpc/rpc.go index d24e5e0..52139ae 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -61,7 +61,7 @@ func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, rpctypes.E return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to begin dbTx, error: %s", err)) } - _, err = i.executor.Settle(signedTx, dbTx) + _, err = i.executor.Settle(i.ctx, signedTx, dbTx) if err != nil { if errRollback := dbTx.Rollback(i.ctx); errRollback != nil { log.Error("rollback err: ", errRollback) From 9aea6f1f91cb77ba6adfbb1cec119c5be3c43c32 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 18:49:49 +0100 Subject: [PATCH 23/28] Fix test --- rpc/rpc_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index e972db6..1840e48 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -299,7 +299,7 @@ func TestInteropEndpointsSendTx(t *testing.T) { if !cfg.isTxAddedToEthTxMan { ethTxManagerMock.On("Add", mock.Anything, ethTxManOwner, signedTx.Tx.Hash().Hex(), mock.Anything, - mock.Anything, mock.Anything, mock.Anything, txMock).Return(errors.New("error")).Once() + mock.Anything, mock.Anything, mock.Anything, mock.Anything, txMock).Return(errors.New("error")).Once() txMock.On("Rollback", mock.Anything).Return(nil).Once() ethermanMock.On("BuildTrustedVerifyBatchesTxData", @@ -312,7 +312,7 @@ func TestInteropEndpointsSendTx(t *testing.T) { } ethTxManagerMock.On("Add", mock.Anything, ethTxManOwner, signedTx.Tx.Hash().Hex(), mock.Anything, - mock.Anything, mock.Anything, mock.Anything, txMock).Return(nil).Once() + mock.Anything, mock.Anything, mock.Anything, mock.Anything, txMock).Return(nil).Once() if !cfg.isTxCommitted { txMock.On("Commit", mock.Anything).Return(errors.New("error")).Once() From 0a011738ea153ee4ad5a68718d463090784a55c9 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Thu, 4 Jan 2024 19:11:29 +0100 Subject: [PATCH 24/28] Cover more --- interop/executor_test.go | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/interop/executor_test.go b/interop/executor_test.go index 31c3f3d..e7ead13 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -2,6 +2,7 @@ package interop import ( "context" + "errors" "math/big" "testing" @@ -9,6 +10,7 @@ import ( "github.com/0xPolygon/beethoven/mocks" "github.com/0xPolygon/beethoven/tx" + "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" rpctypes "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum/common" @@ -228,3 +230,44 @@ func TestExecutor_Settle(t *testing.T) { etherman.AssertExpectations(t) ethTxManager.AssertExpectations(t) } + +func TestExecutor_GetTxStatus(t *testing.T) { + cfg := &config.Config{ + // Set your desired config values here + } + interopAdminAddr := common.HexToAddress("0x1234567890abcdef") + etherman := &mocks.EthermanMock{} + ethTxManager := &mocks.EthTxManagerMock{} + dbTx := &mocks.TxMock{} + + executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) + + hash := common.HexToHash("0x1234567890abcdef") + expectedResult := "0x1" + expectedError := rpctypes.NewRPCError(rpctypes.DefaultErrorCode, "failed to get tx, error: sampleError") + + ethTxManager.On("Result", mock.Anything, ethTxManOwner, hash.Hex(), dbTx). + Return(ethtxmanager.MonitoredTxResult{ + ID: "0x1", + Status: ethtxmanager.MonitoredTxStatus("0x1"), + }, nil).Once() + + result, err := executor.GetTxStatus(context.Background(), hash, dbTx) + + assert.Equal(t, expectedResult, result) + assert.NoError(t, err) + + ethTxManager.On("Result", mock.Anything, ethTxManOwner, hash.Hex(), dbTx). + Return(ethtxmanager.MonitoredTxResult{ + ID: "0x0", + Status: ethtxmanager.MonitoredTxStatus("0x1"), + }, errors.New("sampleError")).Once() + + result, err = executor.GetTxStatus(context.Background(), hash, dbTx) + + assert.Equal(t, "0x0", result) + assert.Equal(t, expectedError, err) + + etherman.AssertExpectations(t) + ethTxManager.AssertExpectations(t) +} From 58a5d6a73234a81f1c842560440d4b78de6f33a3 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Mon, 8 Jan 2024 12:04:29 +0100 Subject: [PATCH 25/28] Apply context in several places --- interop/executor.go | 12 +++++------- interop/executor_test.go | 4 ++-- rpc/rpc.go | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/interop/executor.go b/interop/executor.go index 7f7ac0a..63c6d32 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -64,8 +64,8 @@ func (e *Executor) CheckTx(ctx context.Context, tx tx.SignedTx) error { return nil } -func (e *Executor) Verify(tx tx.SignedTx) error { - err := e.VerifyZKP(tx) +func (e *Executor) Verify(ctx context.Context, tx tx.SignedTx) error { + err := e.VerifyZKP(ctx, tx) if err != nil { return fmt.Errorf("failed to verify ZKP: %s", err) } @@ -73,7 +73,7 @@ func (e *Executor) Verify(tx tx.SignedTx) error { return e.VerifySignature(tx) } -func (e *Executor) VerifyZKP(stx tx.SignedTx) error { +func (e *Executor) VerifyZKP(ctx context.Context, stx tx.SignedTx) error { // Verify ZKP using eth_call l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( uint64(stx.Tx.LastVerifiedBatch), @@ -88,7 +88,7 @@ func (e *Executor) VerifyZKP(stx tx.SignedTx) error { To: &stx.Tx.L1Contract, Data: l1TxData, } - res, err := e.etherman.CallContract(context.Background(), msg, nil) + res, err := e.etherman.CallContract(ctx, msg, nil) if err != nil { return fmt.Errorf("failed to call verify ZKP response: %s, error: %s", res, err) } @@ -114,9 +114,7 @@ func (e *Executor) VerifySignature(stx tx.SignedTx) error { return nil } -func (e *Executor) Execute(signedTx tx.SignedTx) error { - ctx := context.TODO() - +func (e *Executor) Execute(ctx context.Context, signedTx tx.SignedTx) error { // Check expected root vs root from the managed full node // TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581 // when this happens we should go async from here, since processing all the batches could take a lot of time diff --git a/interop/executor_test.go b/interop/executor_test.go index e7ead13..5a39b65 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -110,7 +110,7 @@ func TestExecutor_VerifyZKP(t *testing.T) { Tx: tnx, } - err := executor.VerifyZKP(signedTx) + err := executor.VerifyZKP(context.Background(), signedTx) assert.NoError(t, err) etherman.AssertExpectations(t) } @@ -184,7 +184,7 @@ func TestExecutor_Execute(t *testing.T) { // Set the ZkEVMClientCreator to return the mock ZkEVMClient executor.ZkEVMClientCreator = mockZkEVMClientCreator - err := executor.Execute(signedTx) + err := executor.Execute(context.Background(), signedTx) require.NoError(t, err) mockZkEVMClientCreator.AssertExpectations(t) mockZkEVMClient.AssertExpectations(t) diff --git a/rpc/rpc.go b/rpc/rpc.go index 52139ae..77375e9 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -47,11 +47,11 @@ func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, rpctypes.E } // Verify ZKP using eth_call - if err := i.executor.Verify(signedTx); err != nil { + if err := i.executor.Verify(i.ctx, signedTx); err != nil { return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to verify tx: %s", err)) } - if err := i.executor.Execute(signedTx); err != nil { + if err := i.executor.Execute(i.ctx, signedTx); err != nil { return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("failed to execute tx: %s", err)) } From c1d05f4011e1c8843ea1992294ae912abea812fe Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Tue, 9 Jan 2024 11:35:31 +0100 Subject: [PATCH 26/28] Fix comment --- interop/executor.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interop/executor.go b/interop/executor.go index 63c6d32..d0c7a32 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -140,8 +140,7 @@ func (e *Executor) Execute(ctx context.Context, signedTx tx.SignedTx) error { } func (e *Executor) Settle(ctx context.Context, signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) { - // // Send L1 tx - // Verify ZKP using eth_call + // Send L1 tx l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( uint64(signedTx.Tx.LastVerifiedBatch), uint64(signedTx.Tx.NewVerifiedBatch), From b3c19d74c4680fc86354ead47b4f8d516db3c5e3 Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Tue, 9 Jan 2024 18:02:05 +0100 Subject: [PATCH 27/28] Apply feedback --- interop/executor.go | 11 +++++------ interop/executor_test.go | 28 +++++++++------------------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/interop/executor.go b/interop/executor.go index d0c7a32..425c56c 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -52,8 +52,7 @@ func New(logger *log.Logger, cfg *config.Config, const ethTxManOwner = "interop" -func (e *Executor) CheckTx(ctx context.Context, tx tx.SignedTx) error { - e.logger.Debug("check tx") +func (e *Executor) CheckTx(tx tx.SignedTx) error { // Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed) // TODO: The JSON parsing of the contract is incorrect @@ -65,15 +64,15 @@ func (e *Executor) CheckTx(ctx context.Context, tx tx.SignedTx) error { } func (e *Executor) Verify(ctx context.Context, tx tx.SignedTx) error { - err := e.VerifyZKP(ctx, tx) + err := e.verifyZKP(ctx, tx) if err != nil { return fmt.Errorf("failed to verify ZKP: %s", err) } - return e.VerifySignature(tx) + return e.verifySignature(tx) } -func (e *Executor) VerifyZKP(ctx context.Context, stx tx.SignedTx) error { +func (e *Executor) verifyZKP(ctx context.Context, stx tx.SignedTx) error { // Verify ZKP using eth_call l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData( uint64(stx.Tx.LastVerifiedBatch), @@ -96,7 +95,7 @@ func (e *Executor) VerifyZKP(ctx context.Context, stx tx.SignedTx) error { return nil } -func (e *Executor) VerifySignature(stx tx.SignedTx) error { +func (e *Executor) verifySignature(stx tx.SignedTx) error { // Auth: check signature vs admin signer, err := stx.Signer() if err != nil { diff --git a/interop/executor_test.go b/interop/executor_test.go index 5a39b65..bc005fa 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -21,9 +21,7 @@ import ( ) func TestNewExecutor(t *testing.T) { - cfg := &config.Config{ - // Set your desired config values here - } + cfg := &config.Config{} interopAdminAddr := common.HexToAddress("0x1234567890abcdef") etherman := &mocks.EthermanMock{} ethTxManager := &mocks.EthTxManagerMock{} @@ -62,7 +60,7 @@ func TestExecutor_CheckTx(t *testing.T) { }, } - err := executor.CheckTx(context.Background(), signedTx) + err := executor.CheckTx(signedTx) assert.NoError(t, err) signedTx = tx.SignedTx{ @@ -76,14 +74,12 @@ func TestExecutor_CheckTx(t *testing.T) { }, } - err = executor.CheckTx(context.Background(), signedTx) + err = executor.CheckTx(signedTx) assert.Error(t, err) } func TestExecutor_VerifyZKP(t *testing.T) { - cfg := &config.Config{ - // Set your desired config values here - } + cfg := &config.Config{} interopAdminAddr := common.HexToAddress("0x1234567890abcdef") etherman := &mocks.EthermanMock{} ethTxManager := &mocks.EthTxManagerMock{} @@ -110,15 +106,13 @@ func TestExecutor_VerifyZKP(t *testing.T) { Tx: tnx, } - err := executor.VerifyZKP(context.Background(), signedTx) + err := executor.verifyZKP(context.Background(), signedTx) assert.NoError(t, err) etherman.AssertExpectations(t) } func TestExecutor_VerifySignature(t *testing.T) { - cfg := &config.Config{ - // Set your desired config values here - } + cfg := &config.Config{} interopAdminAddr := common.HexToAddress("0x1234567890abcdef") etherman := &mocks.EthermanMock{} ethTxManager := &mocks.EthTxManagerMock{} @@ -143,7 +137,7 @@ func TestExecutor_VerifySignature(t *testing.T) { etherman.On("GetSequencerAddr", mock.Anything). Return(crypto.PubkeyToAddress(pk.PublicKey), nil).Once() - err = executor.VerifySignature(*signedTx) + err = executor.verifySignature(*signedTx) require.NoError(t, err) etherman.AssertExpectations(t) } @@ -191,9 +185,7 @@ func TestExecutor_Execute(t *testing.T) { } func TestExecutor_Settle(t *testing.T) { - cfg := &config.Config{ - // Set your desired config values here - } + cfg := &config.Config{} interopAdminAddr := common.HexToAddress("0x1234567890abcdef") etherman := &mocks.EthermanMock{} ethTxManager := &mocks.EthTxManagerMock{} @@ -232,9 +224,7 @@ func TestExecutor_Settle(t *testing.T) { } func TestExecutor_GetTxStatus(t *testing.T) { - cfg := &config.Config{ - // Set your desired config values here - } + cfg := &config.Config{} interopAdminAddr := common.HexToAddress("0x1234567890abcdef") etherman := &mocks.EthermanMock{} ethTxManager := &mocks.EthTxManagerMock{} From 39dc9bf7993998f78cb739ebe5480586578806bc Mon Sep 17 00:00:00 2001 From: Victor Castell <0x@vcastellm.xyz> Date: Tue, 9 Jan 2024 18:04:12 +0100 Subject: [PATCH 28/28] Fix signature --- rpc/rpc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/rpc.go b/rpc/rpc.go index 77375e9..dc502a4 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -42,7 +42,7 @@ func NewInteropEndpoints( func (i *InteropEndpoints) SendTx(signedTx tx.SignedTx) (interface{}, rpctypes.Error) { // Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed) - if err := i.executor.CheckTx(i.ctx, signedTx); err != nil { + if err := i.executor.CheckTx(signedTx); err != nil { return "0x0", rpctypes.NewRPCError(rpctypes.DefaultErrorCode, fmt.Sprintf("there is no RPC registered for %s", signedTx.Tx.L1Contract)) }