diff --git a/cmd/main.go b/cmd/main.go index 2bd5e59..1a01dce 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -106,7 +106,7 @@ func start(cliCtx *cli.Context) error { log.Fatal("error getting chain ID from l1 with address: %+v", err) } - ethMan, err := etherman.New(ethClient, *auth) + ethMan, err := etherman.New(ethClient, *auth, c) if err != nil { log.Fatal(err) } diff --git a/config/config.go b/config/config.go index 57c1123..4868baf 100644 --- a/config/config.go +++ b/config/config.go @@ -23,7 +23,7 @@ const ( FlagCfg = "cfg" ) -type FullNodeRPCs map[common.Address]string +type FullNodeRPCs map[uint32]string // Config represents the full configuration of the data node type Config struct { @@ -37,8 +37,9 @@ type Config struct { } type L1Config struct { - ChainID int64 - NodeURL string + ChainID int64 + NodeURL string + RollupManagerContract common.Address } type Telemetry struct { diff --git a/etherman/etherman.go b/etherman/etherman.go index 70049a2..83039ca 100644 --- a/etherman/etherman.go +++ b/etherman/etherman.go @@ -3,9 +3,11 @@ package etherman import ( "context" "errors" + "github.com/0xPolygon/beethoven/config" "math/big" "time" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonrollupmanager" "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/state" @@ -27,25 +29,33 @@ const ( type Etherman struct { ethClient EthereumClient auth bind.TransactOpts + config *config.Config } -func New(ethClient EthereumClient, auth bind.TransactOpts) (Etherman, error) { +func New(ethClient EthereumClient, auth bind.TransactOpts, cfg *config.Config) (Etherman, error) { return Etherman{ ethClient: ethClient, auth: auth, + config: cfg, }, nil } -func (e *Etherman) GetSequencerAddr(l1Contract common.Address) (common.Address, error) { - _, contract, err := e.contractCaller(common.Address{}, l1Contract) +func (e *Etherman) GetSequencerAddr(rollupId uint32) (common.Address, error) { + address, err := e.getTrustedSequencerAddress(rollupId) if err != nil { + log.Errorf("error requesting the 'TrustedSequencer' address: %s", err) return common.Address{}, err } - return contract.TrustedSequencer(&bind.CallOpts{Pending: false}) + return address, nil } -func (e *Etherman) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, proof tx.ZKP) (data []byte, err error) { +func (e *Etherman) BuildTrustedVerifyBatchesTxData( + lastVerifiedBatch, + newVerifiedBatch uint64, + proof tx.ZKP, + rollupId uint32, +) (data []byte, err error) { var newLocalExitRoot [HashLength]byte copy(newLocalExitRoot[:], proof.NewLocalExitRoot.Bytes()) var newStateRoot [HashLength]byte @@ -65,6 +75,7 @@ func (e *Etherman) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifie return abi.Pack( "verifyBatchesTrustedAggregator", + rollupId, pendStateNum, lastVerifiedBatch, newVerifiedBatch, @@ -78,20 +89,32 @@ func (e *Etherman) CallContract(ctx context.Context, call ethereum.CallMsg, bloc return e.ethClient.CallContract(ctx, call, blockNumber) } -func (e *Etherman) contractCaller(from, to common.Address) (*bind.TransactOpts, *polygonzkevm.Polygonzkevm, error) { - opts := bind.TransactOpts{} - opts.From = from - opts.NoSend = true - // force nonce, gas limit and gas price to avoid querying it from the chain - opts.Nonce = big.NewInt(1) - opts.GasLimit = uint64(1) - opts.GasPrice = big.NewInt(1) - contract, err := polygonzkevm.NewPolygonzkevm(to, e.ethClient) +func (e *Etherman) getRollupContractAddress(rollupId uint32) (common.Address, error) { + contract, err := polygonrollupmanager.NewPolygonrollupmanager(e.config.L1.RollupManagerContract, e.ethClient) + if err != nil { + return common.Address{}, err + } + + rollupData, err := contract.RollupIDToRollupData(&bind.CallOpts{Pending: false}, rollupId) + if err != nil { + return common.Address{}, err + } + + return rollupData.RollupContract, nil +} + +func (e *Etherman) getTrustedSequencerAddress(rollupId uint32) (common.Address, error) { + rollupContractAddress, err := e.getRollupContractAddress(rollupId) if err != nil { - log.Errorf("error instantiating contract: %s", err) - return nil, nil, err + return common.Address{}, err } - return &opts, contract, nil + + contract, err := polygonzkevm.NewPolygonzkevm(rollupContractAddress, e.ethClient) + if err != nil { + return common.Address{}, err + } + + return contract.TrustedSequencer(&bind.CallOpts{Pending: false}) } // CheckTxWasMined check if a tx was already mined diff --git a/etherman/etherman_test.go b/etherman/etherman_test.go index 3d79705..6944c81 100644 --- a/etherman/etherman_test.go +++ b/etherman/etherman_test.go @@ -3,17 +3,18 @@ package etherman import ( "context" "errors" + "github.com/0xPolygon/beethoven/config" + cdkTypes "github.com/0xPolygon/beethoven/rpc/types" + "github.com/0xPolygon/beethoven/tx" + "github.com/ethereum/go-ethereum/crypto" "math/big" "testing" "github.com/0xPolygon/beethoven/mocks" - cdkTypes "github.com/0xPolygon/beethoven/rpc/types" - "github.com/0xPolygon/beethoven/tx" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -36,6 +37,7 @@ func getEtherman(ethClientMock EthereumClient) Etherman { Context: context.TODO(), NoSend: false, }, + &config.Config{}, ) return ethman @@ -45,12 +47,31 @@ func TestGetSequencerAddr(t *testing.T) { t.Parallel() assert := assert.New(t) - t.Run("Returns expected error (improperly formatted output)", func(t *testing.T) { + t.Run("Returns expected error on 'TrustedSequencer' call (improperly formatted output)", func(t *testing.T) { t.Parallel() ethClient := new(mocks.EthereumClientMock) ethman := getEtherman(ethClient) + ethClient.On( + "CallContract", + mock.Anything, + ethereum.CallMsg{ + From: common.HexToAddress("0x0000000000000000000000000000000000000000"), + To: &common.Address{}, + Gas: 0, + GasPrice: nil, + GasFeeCap: nil, + GasTipCap: nil, + Value: nil, + Data: common.Hex2Bytes("f9c4c2ae0000000000000000000000000000000000000000000000000000000000000001"), + }, + (*big.Int)(nil), + ).Return( // Invalid return value below to provocate error + common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"), + nil, + ).Once() + ethClient.On( "CallContract", mock.Anything, @@ -70,7 +91,38 @@ func TestGetSequencerAddr(t *testing.T) { nil, ).Once() - _, err := ethman.GetSequencerAddr(common.HexToAddress("0x0000000000000000000000000000000000000000")) + _, err := ethman.GetSequencerAddr(1) + + assert.ErrorContains(err, "abi: improperly formatted output:") + ethClient.AssertExpectations(t) + }) + + t.Run("Returns expected error on 'RollupIDToRollupData' call (improperly formatted output)", func(t *testing.T) { + t.Parallel() + + ethClient := new(mocks.EthereumClientMock) + ethman := getEtherman(ethClient) + + ethClient.On( + "CallContract", + mock.Anything, + ethereum.CallMsg{ + From: common.HexToAddress("0x0000000000000000000000000000000000000000"), + To: &common.Address{}, + Gas: 0, + GasPrice: nil, + GasFeeCap: nil, + GasTipCap: nil, + Value: nil, + Data: common.Hex2Bytes("f9c4c2ae0000000000000000000000000000000000000000000000000000000000000001"), + }, + (*big.Int)(nil), + ).Return( // Invalid return value below to provocate error + common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"), + nil, + ).Once() + + _, err := ethman.GetSequencerAddr(1) assert.ErrorContains(err, "abi: improperly formatted output:") ethClient.AssertExpectations(t) @@ -83,6 +135,25 @@ func TestGetSequencerAddr(t *testing.T) { ethman := getEtherman(ethClient) ethClient.On( + "CallContract", + mock.Anything, + ethereum.CallMsg{ + From: common.HexToAddress("0x0000000000000000000000000000000000000000"), + To: &common.Address{}, + Gas: 0, + GasPrice: nil, + GasFeeCap: nil, + GasTipCap: nil, + Value: nil, + Data: common.Hex2Bytes("f9c4c2ae0000000000000000000000000000000000000000000000000000000000000001"), + }, + (*big.Int)(nil), + ).Return( // Invalid return value below to provocate error + common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001"), + nil, + ).Once() + + ethClient.On( // Call "TrustedSequencer" property on rollup contract "CallContract", mock.Anything, ethereum.CallMsg{ @@ -96,7 +167,7 @@ func TestGetSequencerAddr(t *testing.T) { nil, ).Once() - returnValue, err := ethman.GetSequencerAddr(common.HexToAddress("0x0000000000000000000000000000000000000000")) + returnValue, err := ethman.GetSequencerAddr(1) assert.Equal(common.Address{}, returnValue) assert.NoError(err) @@ -120,6 +191,7 @@ func TestBuildTrustedVerifyBatches(t *testing.T) { NewLocalExitRoot: common.HexToHash("0x002"), Proof: cdkTypes.ArgBytes("0x30030030030003003300300030033003000300330030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030003003003000300300300030030030"), }, + 1, ) assert.ErrorContains(err, "invalid proof length. Expected length: 1538, Actual length 1534") diff --git a/go.mod b/go.mod index 4ed32cb..4ff15a4 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/0xPolygon/cdk-data-availability v0.0.3 - github.com/0xPolygonHermez/zkevm-node v0.4.5 + github.com/0xPolygonHermez/zkevm-node v0.5.0-RC4 github.com/ethereum/go-ethereum v1.13.8 github.com/gobuffalo/packr/v2 v2.8.3 github.com/jackc/pgconn v1.14.1 @@ -14,13 +14,13 @@ require ( github.com/rubenv/sql-migrate v1.6.0 github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.8.4 - github.com/urfave/cli/v2 v2.25.7 + github.com/urfave/cli/v2 v2.26.0 go.opentelemetry.io/otel/exporters/prometheus v0.44.0 go.opentelemetry.io/otel/sdk/metric v1.21.0 ) require ( - github.com/0xPolygonHermez/zkevm-data-streamer v0.1.15 // indirect + github.com/0xPolygonHermez/zkevm-data-streamer v0.1.17 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/StackExchange/wmi v1.2.1 // indirect @@ -66,7 +66,7 @@ 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.4.0 // indirect + github.com/google/uuid v1.5.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 @@ -144,7 +144,7 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.15.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/grpc v1.59.0 // indirect + google.golang.org/grpc v1.60.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index f189228..cdead9e 100644 --- a/go.sum +++ b/go.sum @@ -39,10 +39,10 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/0xPolygon/cdk-data-availability v0.0.3 h1:ft0j1H7Q8hYT0AcapM9DmZS9FkAC1JGD+7QrOBhWRWA= github.com/0xPolygon/cdk-data-availability v0.0.3/go.mod h1:nA2O2ZzuvrR1pJLAmzTjuhUBSlCT0Noz2WI6HZfhvsg= -github.com/0xPolygonHermez/zkevm-data-streamer v0.1.15 h1:WmSnrlSHzlpkD33mRoUVlxScR6f+xig9pMKqYM8n+hQ= -github.com/0xPolygonHermez/zkevm-data-streamer v0.1.15/go.mod h1:VrOfhxA3y9XVpZh2jpBqwv7eGBKwxgKJ7jVTzFr6vYI= -github.com/0xPolygonHermez/zkevm-node v0.4.5 h1:spFfHtQ5b0NB32FcFj0ELYGRxhaWgsE67bMxQTr81+o= -github.com/0xPolygonHermez/zkevm-node v0.4.5/go.mod h1:53xLWQDtrRygFT0mzTVqhH6J5Vrbg1Th866npGW9NME= +github.com/0xPolygonHermez/zkevm-data-streamer v0.1.17 h1:pCA2k5ke1otBTNAyE8yiSlkDwpZxvJQH55Nf0GXWvfk= +github.com/0xPolygonHermez/zkevm-data-streamer v0.1.17/go.mod h1:0QkAXcFa92mFJrCbN3UPUJGJYes851yEgYHLONnaosE= +github.com/0xPolygonHermez/zkevm-node v0.5.0-RC4 h1:xQYFDA4+JQ/5PO28n+AC+yz+/Ase2mGPRYbc52i6m/w= +github.com/0xPolygonHermez/zkevm-node v0.5.0-RC4/go.mod h1:/+coO2Mg0Zj2NR9XHTB2FVPYT7V7YGx+wXeAidhuFBs= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -337,8 +337,8 @@ github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8q github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -525,8 +525,8 @@ 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.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -722,8 +722,8 @@ github.com/umbracle/ethgo v0.1.4-0.20230712173909-df37dddf16f0 h1:wE2g4ydxJk8kdR github.com/umbracle/ethgo v0.1.4-0.20230712173909-df37dddf16f0/go.mod h1:J+OZNfRCtbaYW3AEc0m47GhwAzlNJjcr9vO86nzOr6E= github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 h1:10Nbw6cACsnQm7r34zlpJky+IzxVLRk6MKTS2d3Vp0E= github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI= +github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -1197,8 +1197,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/interop/executor.go b/interop/executor.go index 425c56c..9c9d16c 100644 --- a/interop/executor.go +++ b/interop/executor.go @@ -56,8 +56,8 @@ 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 - if _, ok := e.config.FullNodeRPCs[tx.Tx.L1Contract]; !ok { - return fmt.Errorf("there is no RPC registered for %s", tx.Tx.L1Contract) + if _, ok := e.config.FullNodeRPCs[tx.Tx.RollupID]; !ok { + return fmt.Errorf("there is no RPC registered for %v", tx.Tx.RollupID) } return nil @@ -78,13 +78,14 @@ func (e *Executor) verifyZKP(ctx context.Context, stx tx.SignedTx) error { uint64(stx.Tx.LastVerifiedBatch), uint64(stx.Tx.NewVerifiedBatch), stx.Tx.ZKP, + stx.Tx.RollupID, ) if err != nil { return fmt.Errorf("failed to build verify ZKP tx: %s", err) } msg := ethereum.CallMsg{ From: e.interopAdminAddr, - To: &stx.Tx.L1Contract, + To: &e.config.L1.RollupManagerContract, Data: l1TxData, } res, err := e.etherman.CallContract(ctx, msg, nil) @@ -102,7 +103,7 @@ func (e *Executor) verifySignature(stx tx.SignedTx) error { return errors.New("failed to get signer") } - sequencer, err := e.etherman.GetSequencerAddr(stx.Tx.L1Contract) + sequencer, err := e.etherman.GetSequencerAddr(stx.Tx.RollupID) if err != nil { return errors.New("failed to get admin from L1") } @@ -117,7 +118,7 @@ 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 - zkEVMClient := e.ZkEVMClientCreator.NewClient(e.config.FullNodeRPCs[signedTx.Tx.L1Contract]) + zkEVMClient := e.ZkEVMClientCreator.NewClient(e.config.FullNodeRPCs[signedTx.Tx.RollupID]) batch, err := zkEVMClient.BatchByNumber( ctx, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), @@ -144,6 +145,7 @@ func (e *Executor) Settle(ctx context.Context, signedTx tx.SignedTx, dbTx pgx.Tx uint64(signedTx.Tx.LastVerifiedBatch), uint64(signedTx.Tx.NewVerifiedBatch), signedTx.Tx.ZKP, + signedTx.Tx.RollupID, ) if err != nil { return common.Hash{}, fmt.Errorf("failed to build verify ZKP tx: %s", err) @@ -154,7 +156,7 @@ func (e *Executor) Settle(ctx context.Context, signedTx tx.SignedTx, dbTx pgx.Tx ethTxManOwner, signedTx.Tx.Hash().Hex(), e.interopAdminAddr, - &signedTx.Tx.L1Contract, + &e.config.L1.RollupManagerContract, big.NewInt(0), l1TxData, 0, diff --git a/interop/executor_test.go b/interop/executor_test.go index bc005fa..63bbdb1 100644 --- a/interop/executor_test.go +++ b/interop/executor_test.go @@ -38,8 +38,8 @@ func TestNewExecutor(t *testing.T) { func TestExecutor_CheckTx(t *testing.T) { cfg := &config.Config{ - FullNodeRPCs: map[common.Address]string{ - common.HexToAddress("0x1234567890abcdef"): "http://localhost:8545", + FullNodeRPCs: map[uint32]string{ + 1: "http://localhost:8545", }, } interopAdminAddr := common.HexToAddress("0x1234567890abcdef") @@ -56,7 +56,7 @@ func TestExecutor_CheckTx(t *testing.T) { ZKP: tx.ZKP{ Proof: []byte("sampleProof"), }, - L1Contract: common.HexToAddress("0x1234567890abcdef"), + RollupID: 1, }, } @@ -70,7 +70,7 @@ func TestExecutor_CheckTx(t *testing.T) { ZKP: tx.ZKP{ Proof: []byte("sampleProof"), }, - L1Contract: common.HexToAddress("0xdeadbeef"), + RollupID: 0, }, } @@ -89,15 +89,29 @@ func TestExecutor_VerifyZKP(t *testing.T) { ZKP: tx.ZKP{ Proof: []byte("sampleProof"), }, - L1Contract: common.HexToAddress("0x1234567890abcdef"), + RollupID: 1, } - 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() + etherman.On( + "BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), + uint64(tnx.NewVerifiedBatch), + mock.Anything, + uint32(1), + ).Return( + []byte{}, + nil, + ).Once() + + etherman.On( + "CallContract", + mock.Anything, + mock.Anything, + mock.Anything, + ).Return( + []byte{}, + nil, + ).Once() executor := New(nil, cfg, interopAdminAddr, etherman, ethTxManager) @@ -125,7 +139,7 @@ func TestExecutor_VerifySignature(t *testing.T) { ZKP: tx.ZKP{ Proof: []byte("sampleProof"), }, - L1Contract: common.HexToAddress("0x1234567890abcdef"), + RollupID: 1, } pk, err := crypto.GenerateKey() @@ -134,8 +148,13 @@ func TestExecutor_VerifySignature(t *testing.T) { signedTx, err := txn.Sign(pk) require.NoError(t, err) - etherman.On("GetSequencerAddr", mock.Anything). - Return(crypto.PubkeyToAddress(pk.PublicKey), nil).Once() + etherman.On( + "GetSequencerAddr", + uint32(1), + ).Return( + crypto.PubkeyToAddress(pk.PublicKey), + nil, + ).Once() err = executor.verifySignature(*signedTx) require.NoError(t, err) @@ -159,7 +178,6 @@ func TestExecutor_Execute(t *testing.T) { NewStateRoot: common.BytesToHash([]byte("sampleNewStateRoot")), Proof: []byte("sampleProof"), }, - L1Contract: common.HexToAddress("0x1234567890abcdef"), }, } @@ -200,20 +218,37 @@ func TestExecutor_Settle(t *testing.T) { ZKP: tx.ZKP{ Proof: []byte("sampleProof"), }, - L1Contract: common.HexToAddress("0x1234567890abcdef"), + RollupID: 1, }, } l1TxData := []byte("sampleL1TxData") - etherman.On("BuildTrustedVerifyBatchesTxData", - uint64(signedTx.Tx.LastVerifiedBatch), uint64(signedTx.Tx.NewVerifiedBatch), signedTx.Tx.ZKP). - Return(l1TxData, nil).Once() + etherman.On( + "BuildTrustedVerifyBatchesTxData", + uint64(signedTx.Tx.LastVerifiedBatch), + uint64(signedTx.Tx.NewVerifiedBatch), + signedTx.Tx.ZKP, + uint32(1), + ).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() + ethTxManager.On( + "Add", + ctx, ethTxManOwner, + txHash, + interopAdminAddr, + &cfg.L1.RollupManagerContract, + big.NewInt(0), + l1TxData, + uint64(0), + dbTx, + ).Return( + nil, + ).Once() hash, err := executor.Settle(ctx, signedTx, dbTx) require.NoError(t, err) diff --git a/mocks/mocks.go b/mocks/mocks.go index 95a68bc..dae56d9 100644 --- a/mocks/mocks.go +++ b/mocks/mocks.go @@ -21,15 +21,19 @@ type EthermanMock struct { mock.Mock } -func (e *EthermanMock) GetSequencerAddr(l1Contract common.Address) (common.Address, error) { - args := e.Called(l1Contract) +func (e *EthermanMock) GetSequencerAddr(rollupId uint32) (common.Address, error) { + args := e.Called(rollupId) 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) +func (e *EthermanMock) BuildTrustedVerifyBatchesTxData( + lastVerifiedBatch, + newVerifiedBatch uint64, + proof tx.ZKP, + rollupId uint32, +) (data []byte, err error) { + args := e.Called(lastVerifiedBatch, newVerifiedBatch, proof, rollupId) return args.Get(0).([]byte), args.Error(1) //nolint:forcetypeassert } diff --git a/rpc/rpc.go b/rpc/rpc.go index dc502a4..b2bfe4e 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -43,7 +43,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(signedTx); err != nil { - return "0x0", rpctypes.NewRPCError(rpctypes.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 %d", signedTx.Tx.RollupID)) } // Verify ZKP using eth_call diff --git a/rpc/rpc_test.go b/rpc/rpc_test.go index 1840e48..0b6fbb2 100644 --- a/rpc/rpc_test.go +++ b/rpc/rpc_test.go @@ -149,16 +149,16 @@ func TestInteropEndpointsSendTx(t *testing.T) { testFn := func(cfg testConfig) { fullNodeRPCs := config.FullNodeRPCs{ - common.BytesToAddress([]byte{1, 2, 3, 4}): "someRPC", + 1: "someRPC", } tnx := tx.Tx{ - L1Contract: common.BytesToAddress([]byte{1, 2, 3, 4}), LastVerifiedBatch: beethovenTypes.ArgUint64(1), NewVerifiedBatch: *beethovenTypes.ArgUint64Ptr(2), ZKP: tx.ZKP{ NewStateRoot: common.BigToHash(big.NewInt(11)), NewLocalExitRoot: common.BigToHash(big.NewInt(11)), }, + RollupID: 1, } signedTx := &tx.SignedTx{Tx: tnx} ethermanMock := new(mocks.EthermanMock) @@ -173,6 +173,7 @@ func TestInteropEndpointsSendTx(t *testing.T) { log.WithFields("module", "test"), &config.Config{ FullNodeRPCs: fullNodeRPCs, + L1: config.L1Config{RollupManagerContract: common.HexToAddress("0xdeadbeef")}, }, common.HexToAddress("0xadmin"), ethermanMock, @@ -207,28 +208,58 @@ func TestInteropEndpointsSendTx(t *testing.T) { } if !cfg.canBuildZKProof { - ethermanMock.On("BuildTrustedVerifyBatchesTxData", - uint64(tnx.LastVerifiedBatch), uint64(tnx.NewVerifiedBatch), mock.Anything). - Return([]byte{}, errors.New("error")).Once() + ethermanMock.On( + "BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), + uint64(tnx.NewVerifiedBatch), + mock.Anything, + uint32(1), + ).Return( + []byte{}, + errors.New("error"), + ).Once() + executeTestFn() return } - ethermanMock.On("BuildTrustedVerifyBatchesTxData", - uint64(tnx.LastVerifiedBatch), uint64(tnx.NewVerifiedBatch), mock.Anything). - Return([]byte{1, 2}, nil).Once() + ethermanMock.On( + "BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), + uint64(tnx.NewVerifiedBatch), + mock.Anything, + uint32(1), + ).Return( + []byte{1, 2}, + nil, + ).Once() if !cfg.isZKProofValid { - ethermanMock.On("CallContract", mock.Anything, mock.Anything, mock.Anything). - Return([]byte{}, errors.New("error")).Once() + ethermanMock.On( + "CallContract", + mock.Anything, + mock.Anything, + mock.Anything, + ).Return( + []byte{}, + errors.New("error"), + ).Once() + executeTestFn() return } - ethermanMock.On("CallContract", mock.Anything, mock.Anything, mock.Anything). - Return([]byte{1, 2}, nil).Once() + ethermanMock.On( + "CallContract", + mock.Anything, + mock.Anything, + mock.Anything, + ).Return( + []byte{1, 2}, + nil, + ).Once() if !cfg.isTxSigned { executeTestFn() @@ -245,92 +276,210 @@ func TestInteropEndpointsSendTx(t *testing.T) { signedTx = stx if !cfg.isAdminRetrieved { - ethermanMock.On("GetSequencerAddr", tnx.L1Contract).Return(common.Address{}, errors.New("error")).Once() + ethermanMock.On( + "GetSequencerAddr", + uint32(1), + ).Return( + common.Address{}, + errors.New("error"), + ).Once() + executeTestFn() return } if !cfg.isSignerValid { - ethermanMock.On("GetSequencerAddr", tnx.L1Contract).Return(common.BytesToAddress([]byte{1, 2, 3, 4}), nil).Once() + ethermanMock.On( + "GetSequencerAddr", + uint32(1), + ).Return( + common.BytesToAddress([]byte{1, 2, 3, 4}), + nil, + ).Once() + executeTestFn() return } - ethermanMock.On("GetSequencerAddr", tnx.L1Contract).Return(crypto.PubkeyToAddress(privateKey.PublicKey), nil).Once() - zkEVMClientCreatorMock.On("NewClient", mock.Anything).Return(zkEVMClientMock) + ethermanMock.On( + "GetSequencerAddr", + uint32(1), + ).Return( + crypto.PubkeyToAddress(privateKey.PublicKey), + nil, + ).Once() + + zkEVMClientCreatorMock.On( + "NewClient", + mock.Anything, + ).Return( + zkEVMClientMock, + ) if !cfg.canGetBatch { - zkEVMClientMock.On("BatchByNumber", mock.Anything, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch))).Return( - nil, errors.New("error"), + zkEVMClientMock.On( + "BatchByNumber", + mock.Anything, + big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), + ).Return( + nil, + errors.New("error"), ).Once() + executeTestFn() return } if !cfg.isBatchValid { - zkEVMClientMock.On("BatchByNumber", mock.Anything, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch))).Return( + zkEVMClientMock.On( + "BatchByNumber", + mock.Anything, + big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), + ).Return( &validiumTypes.Batch{ StateRoot: common.BigToHash(big.NewInt(12)), - }, nil, + }, + nil, ).Once() + executeTestFn() return } - zkEVMClientMock.On("BatchByNumber", mock.Anything, big.NewInt(int64(signedTx.Tx.NewVerifiedBatch))).Return( + zkEVMClientMock.On( + "BatchByNumber", + mock.Anything, + big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)), + ).Return( &validiumTypes.Batch{ StateRoot: common.BigToHash(big.NewInt(11)), LocalExitRoot: common.BigToHash(big.NewInt(11)), - }, nil, + }, + nil, ).Once() if !cfg.isDbTxOpen { - dbMock.On("BeginStateTransaction", mock.Anything).Return(nil, errors.New("error")).Once() + dbMock.On( + "BeginStateTransaction", + mock.Anything, + ).Return( + nil, + errors.New("error"), + ).Once() + executeTestFn() return } - dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil).Once() + dbMock.On( + "BeginStateTransaction", + mock.Anything, + ).Return( + txMock, + nil, + ).Once() if !cfg.isTxAddedToEthTxMan { - ethTxManagerMock.On("Add", mock.Anything, ethTxManOwner, signedTx.Tx.Hash().Hex(), mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything, txMock).Return(errors.New("error")).Once() - txMock.On("Rollback", mock.Anything).Return(nil).Once() + ethTxManagerMock.On( + "Add", + mock.Anything, + ethTxManOwner, + signedTx.Tx.Hash().Hex(), + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + txMock, + ).Return( + errors.New("error"), + ).Once() - ethermanMock.On("BuildTrustedVerifyBatchesTxData", - uint64(tnx.LastVerifiedBatch), uint64(tnx.NewVerifiedBatch), mock.Anything). - Return([]byte{1, 2}, nil).Once() + txMock.On( + "Rollback", + mock.Anything, + ).Return( + nil, + ).Once() + + ethermanMock.On( + "BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), + uint64(tnx.NewVerifiedBatch), + mock.Anything, + uint32(1), + ).Return( + []byte{1, 2}, + nil, + ).Once() executeTestFn() return } - ethTxManagerMock.On("Add", mock.Anything, ethTxManOwner, signedTx.Tx.Hash().Hex(), mock.Anything, - mock.Anything, mock.Anything, mock.Anything, mock.Anything, txMock).Return(nil).Once() + ethTxManagerMock.On( + "Add", + mock.Anything, + ethTxManOwner, + signedTx.Tx.Hash().Hex(), + mock.Anything, + 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() + 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() + ethermanMock.On( + "BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), + uint64(tnx.NewVerifiedBatch), + mock.Anything, + uint32(1), + ).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() + ethermanMock.On( + "BuildTrustedVerifyBatchesTxData", + uint64(tnx.LastVerifiedBatch), + uint64(tnx.NewVerifiedBatch), + mock.Anything, + uint32(1), + ).Return( + []byte{1, 2}, + nil, + ).Once() + + txMock.On( + "Commit", + mock.Anything, + ).Return( + nil, + ).Once() - txMock.On("Commit", mock.Anything).Return(nil).Once() executeTestFn() } diff --git a/tx/tx.go b/tx/tx.go index 790f2a5..eba003b 100644 --- a/tx/tx.go +++ b/tx/tx.go @@ -2,17 +2,16 @@ package tx import ( "crypto/ecdsa" - "github.com/0xPolygon/beethoven/rpc/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) -// type L1Concensus string +// type L1Consensus string // const ( -// Rollup L1Concensus = "rollup" -// Validium L1Concensus = "validium" +// Rollup L1Consensus = "rollup" +// Validium L1Consensus = "validium" // ) type ZKP struct { @@ -22,9 +21,9 @@ type ZKP struct { } type Tx struct { - L1Contract common.Address `json:"l1Contract"` - // L1Concensus L1Con census + // L1Consensus L1Consensus // Batches []types.Batch + RollupID uint32 LastVerifiedBatch types.ArgUint64 `json:"lastVerifiedBatch"` NewVerifiedBatch types.ArgUint64 `json:"newVerifiedBatch"` ZKP ZKP `json:"ZKP"` diff --git a/types/interfaces.go b/types/interfaces.go index b61de5d..2a198a6 100644 --- a/types/interfaces.go +++ b/types/interfaces.go @@ -17,8 +17,8 @@ type DBInterface interface { } type EthermanInterface interface { - GetSequencerAddr(l1Contract common.Address) (common.Address, error) - BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, proof tx.ZKP) (data []byte, err error) + GetSequencerAddr(rollupId uint32) (common.Address, error) + BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, proof tx.ZKP, rollupId uint32) (data []byte, err error) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) }