From 4ea8b19f81b4b42cf6da0a6fac02090839d8e731 Mon Sep 17 00:00:00 2001 From: tclemos Date: Thu, 4 Apr 2024 17:29:53 -0300 Subject: [PATCH] fix deltaTimeStamp and TimestampLimit for eth_call --- state/transaction.go | 12 +- test/contracts/auto/CounterAndBlock.sol | 15 + .../bin/CounterAndBlock/CounterAndBlock.go | 287 ++++++++++++++++++ test/e2e/sc_test.go | 104 +++++++ 4 files changed, 412 insertions(+), 6 deletions(-) create mode 100644 test/contracts/auto/CounterAndBlock.sol create mode 100644 test/contracts/bin/CounterAndBlock/CounterAndBlock.go diff --git a/state/transaction.go b/state/transaction.go index 6b7907b8b5..355fdad9ad 100644 --- a/state/transaction.go +++ b/state/transaction.go @@ -509,8 +509,7 @@ func (s *State) internalProcessUnsignedTransactionV2(ctx context.Context, tx *ty } nonce := loadedNonce.Uint64() - deltaTimestamp := uint32(uint64(time.Now().Unix()) - l2Block.Time()) - transactions := s.BuildChangeL2Block(deltaTimestamp, uint32(0)) + transactions := s.BuildChangeL2Block(uint32(0), uint32(0)) batchL2Data, err := EncodeUnsignedTransaction(*tx, s.cfg.ChainID, &nonce, forkID) if err != nil { @@ -535,7 +534,7 @@ func (s *State) internalProcessUnsignedTransactionV2(ctx context.Context, tx *ty // v2 fields L1InfoRoot: l2Block.BlockInfoRoot().Bytes(), - TimestampLimit: uint64(time.Now().Unix()), + TimestampLimit: l2Block.Time(), SkipFirstChangeL2Block: cFalse, SkipWriteBlockInfoRoot: cTrue, } @@ -543,14 +542,15 @@ func (s *State) internalProcessUnsignedTransactionV2(ctx context.Context, tx *ty processBatchRequestV2.NoCounters = cTrue } - log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.From]: %v", processBatchRequestV2.From) log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.OldBatchNum]: %v", processBatchRequestV2.OldBatchNum) log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.OldStateRoot]: %v", hex.EncodeToHex(processBatchRequestV2.OldStateRoot)) log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.OldAccInputHash]: %v", hex.EncodeToHex(processBatchRequestV2.OldAccInputHash)) + log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.Coinbase]: %v", processBatchRequestV2.Coinbase) - log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.ForkId]: %v", processBatchRequestV2.ForkId) - log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.ChainId]: %v", processBatchRequestV2.ChainId) log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.UpdateMerkleTree]: %v", processBatchRequestV2.UpdateMerkleTree) + log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.ChainId]: %v", processBatchRequestV2.ChainId) + log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.ForkId]: %v", processBatchRequestV2.ForkId) + log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.From]: %v", processBatchRequestV2.From) log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.ContextId]: %v", processBatchRequestV2.ContextId) log.Debugf("internalProcessUnsignedTransactionV2[processBatchRequestV2.L1InfoRoot]: %v", hex.EncodeToHex(processBatchRequestV2.L1InfoRoot)) diff --git a/test/contracts/auto/CounterAndBlock.sol b/test/contracts/auto/CounterAndBlock.sol new file mode 100644 index 0000000000..53035f0634 --- /dev/null +++ b/test/contracts/auto/CounterAndBlock.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; + +contract CounterAndBlock { + uint public count; + + function increment() external { + count += 1; + } + + function getCount() public view returns (uint, uint) { + return (count, block.timestamp); + } +} diff --git a/test/contracts/bin/CounterAndBlock/CounterAndBlock.go b/test/contracts/bin/CounterAndBlock/CounterAndBlock.go new file mode 100644 index 0000000000..c066117f4d --- /dev/null +++ b/test/contracts/bin/CounterAndBlock/CounterAndBlock.go @@ -0,0 +1,287 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package CounterAndBlock + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// CounterAndBlockMetaData contains all meta data concerning the CounterAndBlock contract. +var CounterAndBlockMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"increment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5060eb8061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c806306661abd146041578063a87d942c14605c578063d09de08a146071575b600080fd5b604960005481565b6040519081526020015b60405180910390f35b60005460408051918252426020830152016053565b60776079565b005b6001600080828254608991906090565b9091555050565b6000821982111560b057634e487b7160e01b600052601160045260246000fd5b50019056fea26469706673582212205aa9aebefdfb857d27d7bdc8475c08138617cc37e78c2e6bd98acb9a1484994964736f6c634300080c0033", +} + +// CounterAndBlockABI is the input ABI used to generate the binding from. +// Deprecated: Use CounterAndBlockMetaData.ABI instead. +var CounterAndBlockABI = CounterAndBlockMetaData.ABI + +// CounterAndBlockBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use CounterAndBlockMetaData.Bin instead. +var CounterAndBlockBin = CounterAndBlockMetaData.Bin + +// DeployCounterAndBlock deploys a new Ethereum contract, binding an instance of CounterAndBlock to it. +func DeployCounterAndBlock(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *CounterAndBlock, error) { + parsed, err := CounterAndBlockMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(CounterAndBlockBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CounterAndBlock{CounterAndBlockCaller: CounterAndBlockCaller{contract: contract}, CounterAndBlockTransactor: CounterAndBlockTransactor{contract: contract}, CounterAndBlockFilterer: CounterAndBlockFilterer{contract: contract}}, nil +} + +// CounterAndBlock is an auto generated Go binding around an Ethereum contract. +type CounterAndBlock struct { + CounterAndBlockCaller // Read-only binding to the contract + CounterAndBlockTransactor // Write-only binding to the contract + CounterAndBlockFilterer // Log filterer for contract events +} + +// CounterAndBlockCaller is an auto generated read-only Go binding around an Ethereum contract. +type CounterAndBlockCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CounterAndBlockTransactor is an auto generated write-only Go binding around an Ethereum contract. +type CounterAndBlockTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CounterAndBlockFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type CounterAndBlockFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CounterAndBlockSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type CounterAndBlockSession struct { + Contract *CounterAndBlock // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CounterAndBlockCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type CounterAndBlockCallerSession struct { + Contract *CounterAndBlockCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// CounterAndBlockTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type CounterAndBlockTransactorSession struct { + Contract *CounterAndBlockTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CounterAndBlockRaw is an auto generated low-level Go binding around an Ethereum contract. +type CounterAndBlockRaw struct { + Contract *CounterAndBlock // Generic contract binding to access the raw methods on +} + +// CounterAndBlockCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type CounterAndBlockCallerRaw struct { + Contract *CounterAndBlockCaller // Generic read-only contract binding to access the raw methods on +} + +// CounterAndBlockTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type CounterAndBlockTransactorRaw struct { + Contract *CounterAndBlockTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewCounterAndBlock creates a new instance of CounterAndBlock, bound to a specific deployed contract. +func NewCounterAndBlock(address common.Address, backend bind.ContractBackend) (*CounterAndBlock, error) { + contract, err := bindCounterAndBlock(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CounterAndBlock{CounterAndBlockCaller: CounterAndBlockCaller{contract: contract}, CounterAndBlockTransactor: CounterAndBlockTransactor{contract: contract}, CounterAndBlockFilterer: CounterAndBlockFilterer{contract: contract}}, nil +} + +// NewCounterAndBlockCaller creates a new read-only instance of CounterAndBlock, bound to a specific deployed contract. +func NewCounterAndBlockCaller(address common.Address, caller bind.ContractCaller) (*CounterAndBlockCaller, error) { + contract, err := bindCounterAndBlock(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CounterAndBlockCaller{contract: contract}, nil +} + +// NewCounterAndBlockTransactor creates a new write-only instance of CounterAndBlock, bound to a specific deployed contract. +func NewCounterAndBlockTransactor(address common.Address, transactor bind.ContractTransactor) (*CounterAndBlockTransactor, error) { + contract, err := bindCounterAndBlock(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CounterAndBlockTransactor{contract: contract}, nil +} + +// NewCounterAndBlockFilterer creates a new log filterer instance of CounterAndBlock, bound to a specific deployed contract. +func NewCounterAndBlockFilterer(address common.Address, filterer bind.ContractFilterer) (*CounterAndBlockFilterer, error) { + contract, err := bindCounterAndBlock(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CounterAndBlockFilterer{contract: contract}, nil +} + +// bindCounterAndBlock binds a generic wrapper to an already deployed contract. +func bindCounterAndBlock(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CounterAndBlockMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_CounterAndBlock *CounterAndBlockRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CounterAndBlock.Contract.CounterAndBlockCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_CounterAndBlock *CounterAndBlockRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CounterAndBlock.Contract.CounterAndBlockTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_CounterAndBlock *CounterAndBlockRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CounterAndBlock.Contract.CounterAndBlockTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_CounterAndBlock *CounterAndBlockCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CounterAndBlock.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_CounterAndBlock *CounterAndBlockTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CounterAndBlock.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_CounterAndBlock *CounterAndBlockTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CounterAndBlock.Contract.contract.Transact(opts, method, params...) +} + +// Count is a free data retrieval call binding the contract method 0x06661abd. +// +// Solidity: function count() view returns(uint256) +func (_CounterAndBlock *CounterAndBlockCaller) Count(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _CounterAndBlock.contract.Call(opts, &out, "count") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Count is a free data retrieval call binding the contract method 0x06661abd. +// +// Solidity: function count() view returns(uint256) +func (_CounterAndBlock *CounterAndBlockSession) Count() (*big.Int, error) { + return _CounterAndBlock.Contract.Count(&_CounterAndBlock.CallOpts) +} + +// Count is a free data retrieval call binding the contract method 0x06661abd. +// +// Solidity: function count() view returns(uint256) +func (_CounterAndBlock *CounterAndBlockCallerSession) Count() (*big.Int, error) { + return _CounterAndBlock.Contract.Count(&_CounterAndBlock.CallOpts) +} + +// GetCount is a free data retrieval call binding the contract method 0xa87d942c. +// +// Solidity: function getCount() view returns(uint256, uint256) +func (_CounterAndBlock *CounterAndBlockCaller) GetCount(opts *bind.CallOpts) (*big.Int, *big.Int, error) { + var out []interface{} + err := _CounterAndBlock.contract.Call(opts, &out, "getCount") + + if err != nil { + return *new(*big.Int), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return out0, out1, err + +} + +// GetCount is a free data retrieval call binding the contract method 0xa87d942c. +// +// Solidity: function getCount() view returns(uint256, uint256) +func (_CounterAndBlock *CounterAndBlockSession) GetCount() (*big.Int, *big.Int, error) { + return _CounterAndBlock.Contract.GetCount(&_CounterAndBlock.CallOpts) +} + +// GetCount is a free data retrieval call binding the contract method 0xa87d942c. +// +// Solidity: function getCount() view returns(uint256, uint256) +func (_CounterAndBlock *CounterAndBlockCallerSession) GetCount() (*big.Int, *big.Int, error) { + return _CounterAndBlock.Contract.GetCount(&_CounterAndBlock.CallOpts) +} + +// Increment is a paid mutator transaction binding the contract method 0xd09de08a. +// +// Solidity: function increment() returns() +func (_CounterAndBlock *CounterAndBlockTransactor) Increment(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CounterAndBlock.contract.Transact(opts, "increment") +} + +// Increment is a paid mutator transaction binding the contract method 0xd09de08a. +// +// Solidity: function increment() returns() +func (_CounterAndBlock *CounterAndBlockSession) Increment() (*types.Transaction, error) { + return _CounterAndBlock.Contract.Increment(&_CounterAndBlock.TransactOpts) +} + +// Increment is a paid mutator transaction binding the contract method 0xd09de08a. +// +// Solidity: function increment() returns() +func (_CounterAndBlock *CounterAndBlockTransactorSession) Increment() (*types.Transaction, error) { + return _CounterAndBlock.Contract.Increment(&_CounterAndBlock.TransactOpts) +} diff --git a/test/e2e/sc_test.go b/test/e2e/sc_test.go index 736e47ded4..46311b4eb9 100644 --- a/test/e2e/sc_test.go +++ b/test/e2e/sc_test.go @@ -9,6 +9,7 @@ import ( "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Counter" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/CounterAndBlock" "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/EmitLog2" "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/FailureTest" "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Read" @@ -646,3 +647,106 @@ func TestRead(t *testing.T) { require.Equal(t, 0, big.NewInt(2).Cmp(value)) } } + +func TestCounterAndBlock(t *testing.T) { + if testing.Short() { + t.Skip() + } + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { require.NoError(t, operations.Teardown()) }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + for _, network := range networks { + log.Debugf(network.Name) + client := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + _, scTx, sc, err := CounterAndBlock.DeployCounterAndBlock(auth, client) + require.NoError(t, err) + + logTx(scTx) + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + scReceipt, err := client.TransactionReceipt(ctx, scTx.Hash()) + require.NoError(t, err) + + scBlock, err := client.BlockByNumber(ctx, scReceipt.BlockNumber) + require.NoError(t, err) + + count, ts, err := sc.GetCount(&bind.CallOpts{Pending: false, BlockNumber: scBlock.Number()}) + require.NoError(t, err) + + assert.Equal(t, 0, count.Cmp(big.NewInt(0))) + assert.Equal(t, ts.Uint64(), scBlock.Time()) + + const numberOfIncrements = 5 + type result struct { + tx *types.Transaction + receipt *types.Receipt + block *types.Block + expectedCount *big.Int + } + + results := make([]result, 0, numberOfIncrements) + for i := 0; i < numberOfIncrements; i++ { + tx, err := sc.Increment(auth) + require.NoError(t, err) + + logTx(tx) + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + receipt, err := client.TransactionReceipt(ctx, tx.Hash()) + require.NoError(t, err) + + block, err := client.BlockByNumber(ctx, receipt.BlockNumber) + require.NoError(t, err) + + results = append(results, result{ + tx: tx, + expectedCount: big.NewInt(int64(i) + 1), + receipt: receipt, + block: block, + }) + } + + const numberOfChecks = 2 + + // checks against first increment + for _, r := range results { + for i := 0; i < numberOfChecks; i++ { + count, ts, err = sc.GetCount(&bind.CallOpts{Pending: false, BlockNumber: r.block.Number()}) + require.NoError(t, err) + assert.Equal(t, r.expectedCount.Uint64(), count.Uint64()) + assert.Equal(t, r.block.Time(), ts.Uint64()) + + time.Sleep(time.Second) + } + } + + latestIncrement := results[len(results)-1] + // checks against second increment with latest block + for i := 0; i < numberOfChecks; i++ { + latestBlock, err := client.BlockByNumber(ctx, nil) + require.NoError(t, err) + + count, ts, err = sc.GetCount(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + assert.Equal(t, latestIncrement.expectedCount.Uint64(), count.Uint64()) + assert.Equal(t, latestBlock.Time(), ts.Uint64()) + + time.Sleep(time.Second) + } + } +}