diff --git a/.gitignore b/.gitignore index df1935cf4a..61d31262fe 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,4 @@ target/ yarn-error.log das/dasrpc/wireFormat.pb.go das/dasrpc/wireFormat_grpc.pb.go - +local/ diff --git a/arbnode/api.go b/arbnode/api.go index c261352771..866dd3669a 100644 --- a/arbnode/api.go +++ b/arbnode/api.go @@ -29,3 +29,13 @@ func (a *BlockValidatorAPI) RevalidateBlock(ctx context.Context, blockNum rpc.Bl } return a.val.ValidateBlock(ctx, header, moduleRoot) } + +func (a *BlockValidatorAPI) LatestValidatedBlock(ctx context.Context) (uint64, error) { + block := a.val.LastBlockValidated() + return block, nil +} + +func (a *BlockValidatorAPI) LatestValidatedBlockHash(ctx context.Context) (common.Hash, error) { + _, hash := a.val.LastBlockValidatedAndHash() + return hash, nil +} diff --git a/arbnode/arb_interface.go b/arbnode/arb_interface.go index a2e626c1a5..8dbc6a78e9 100644 --- a/arbnode/arb_interface.go +++ b/arbnode/arb_interface.go @@ -20,6 +20,7 @@ type TransactionPublisher interface { type ArbInterface struct { txStreamer *TransactionStreamer txPublisher TransactionPublisher + arbNode *Node } func NewArbInterface(txStreamer *TransactionStreamer, txPublisher TransactionPublisher) (*ArbInterface, error) { @@ -29,6 +30,10 @@ func NewArbInterface(txStreamer *TransactionStreamer, txPublisher TransactionPub }, nil } +func (a *ArbInterface) Initialize(n *Node) { + a.arbNode = n +} + func (a *ArbInterface) PublishTransaction(ctx context.Context, tx *types.Transaction) error { return a.txPublisher.PublishTransaction(ctx, tx) } @@ -40,3 +45,7 @@ func (a *ArbInterface) TransactionStreamer() *TransactionStreamer { func (a *ArbInterface) BlockChain() *core.BlockChain { return a.txStreamer.bc } + +func (a *ArbInterface) ArbNode() interface{} { + return a.arbNode +} diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 4a2a844e36..041f5e3f09 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -196,9 +196,9 @@ func TestTransactionStreamer(t *testing.T) { } } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbnode/node-interface.go b/arbnode/node-interface.go index dc9f0d1418..9dfc506f1e 100644 --- a/arbnode/node-interface.go +++ b/arbnode/node-interface.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -23,10 +24,12 @@ import ( "github.com/offchainlabs/nitro/arbos/arbosState" "github.com/offchainlabs/nitro/arbos/retryables" "github.com/offchainlabs/nitro/arbos/util" + "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/solgen/go/node_interfacegen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/merkletree" + "github.com/offchainlabs/nitro/validator" ) type Message = types.Message @@ -48,6 +51,7 @@ func ApplyNodeInterface( estimateMethod := nodeInterface.Methods["estimateRetryableTicket"] outboxMethod := nodeInterface.Methods["constructOutboxProof"] + findBatchMethod := nodeInterface.Methods["findBatchContainingBlock"] calldata := msg.Data() if len(calldata) < 4 { @@ -95,9 +99,7 @@ func ApplyNodeInterface( // ArbitrumSubmitRetryableTx is unsigned so the following won't panic msg, err := types.NewTx(submitTx).AsMessage(types.NewArbitrumSigner(nil), nil) return msg, nil, err - } - - if bytes.Equal(outboxMethod.ID, calldata[:4]) { + } else if bytes.Equal(outboxMethod.ID, calldata[:4]) { inputs, err := outboxMethod.Inputs.Unpack(calldata[4:]) if err != nil { return msg, nil, err @@ -109,10 +111,31 @@ func ApplyNodeInterface( return msg, nil, fmt.Errorf("leaf %v is newer than root of size %v", leaf, size) } - method := nodeInterface.Methods["constructOutboxProof"] - res, err := nodeInterfaceConstructOutboxProof(msg, ctx, size, leaf, backend, method) + res, err := nodeInterfaceConstructOutboxProof(msg, ctx, size, leaf, backend, outboxMethod) return msg, res, err + } else if bytes.Equal(findBatchMethod.ID, calldata[:4]) { + inputs, err := findBatchMethod.Inputs.Unpack(calldata[4:]) + if err != nil { + return msg, nil, err + } + block, _ := inputs[0].(uint64) + batch, err := nodeInterfaceFindBatchContainingBlock(ctx, backend, block) + if err != nil { + return msg, nil, err + } + returnData, err := findBatchMethod.Outputs.Pack(batch) + if err != nil { + return msg, nil, fmt.Errorf("internal error: failed to encode outputs: %w", err) + } + + res := &ExecutionResult{ + UsedGas: 0, + Err: nil, + ReturnData: returnData, + ScheduledTxes: nil, + } + return msg, res, err } return msg, nil, errors.New("method does not exist in NodeInterface.sol") @@ -393,6 +416,40 @@ func nodeInterfaceConstructOutboxProof( return result, nil } +func nodeInterfaceFindBatchContainingBlock(ctx context.Context, backend core.NodeInterfaceBackendAPI, block uint64) (uint64, error) { + apiBackend, ok := backend.(*arbitrum.APIBackend) + if !ok { + return 0, errors.New("API backend isn't Arbitrum") + } + arbNode, ok := apiBackend.GetArbitrumNode().(*Node) + if !ok { + return 0, errors.New("failed to get Arbitrum Node from backend") + } + genesis, err := arbNode.TxStreamer.GetGenesisBlockNumber() + if err != nil { + return 0, err + } + if block <= genesis { + return 0, fmt.Errorf("block %v is part of genesis", block) + } + pos := arbutil.BlockNumberToMessageCount(block, genesis) - 1 + high, err := arbNode.InboxTracker.GetBatchCount() + if err != nil { + return 0, err + } + high-- + latestCount, err := arbNode.InboxTracker.GetBatchMessageCount(high) + if err != nil { + return 0, err + } + latestBlock := arbutil.MessageCountToBlockNumber(latestCount, genesis) + if int64(block) > latestBlock { + return 0, fmt.Errorf("requested block %v is after latest on-chain block %v published in batch %v", block, latestBlock, high) + } + + return validator.FindBatchContainingMessageIndex(arbNode.InboxTracker, pos, high) +} + func init() { nodeInterface, err := abi.JSON(strings.NewReader(node_interfacegen.NodeInterfaceABI)) if err != nil { diff --git a/arbnode/node.go b/arbnode/node.go index 39a09a6143..631f9c0a52 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -674,7 +674,12 @@ func CreateNode(stack *node.Node, chainDb ethdb.Database, config *Config, l2Bloc } func (n *Node) Start(ctx context.Context) error { - err := n.TxPublisher.Initialize(ctx) + n.ArbInterface.Initialize(n) + err := n.Backend.Start() + if err != nil { + return err + } + err = n.TxPublisher.Initialize(ctx) if err != nil { return err } @@ -766,6 +771,9 @@ func (n *Node) StopAndWait() { } n.TxStreamer.StopAndWait() n.ArbInterface.BlockChain().Stop() + if err := n.Backend.Stop(); err != nil { + log.Error("backend stop", "err", err) + } } func CreateDefaultStack() (*node.Node, error) { diff --git a/arbos/addressSet/addressSet_test.go b/arbos/addressSet/addressSet_test.go index 769a0e6cd3..7a70184a27 100644 --- a/arbos/addressSet/addressSet_test.go +++ b/arbos/addressSet/addressSet_test.go @@ -137,9 +137,9 @@ func size(t *testing.T, aset *AddressSet) uint64 { return size } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbos/addressTable/addressTable_test.go b/arbos/addressTable/addressTable_test.go index b76ba81742..6b06ed3406 100644 --- a/arbos/addressTable/addressTable_test.go +++ b/arbos/addressTable/addressTable_test.go @@ -140,9 +140,9 @@ func size(t *testing.T, atab *AddressTable) uint64 { return size } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbos/arbosState/common_test.go b/arbos/arbosState/common_test.go index 0370cf9f8c..c4bf070415 100644 --- a/arbos/arbosState/common_test.go +++ b/arbos/arbosState/common_test.go @@ -9,9 +9,9 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbos/blockhash/blockhash_test.go b/arbos/blockhash/blockhash_test.go index 9bd9322b99..0179113500 100644 --- a/arbos/blockhash/blockhash_test.go +++ b/arbos/blockhash/blockhash_test.go @@ -75,9 +75,9 @@ func TestBlockhash(t *testing.T) { } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbos/blsTable/bls_test.go b/arbos/blsTable/bls_test.go index 215ebf86bc..3784a63c9f 100644 --- a/arbos/blsTable/bls_test.go +++ b/arbos/blsTable/bls_test.go @@ -45,9 +45,9 @@ func TestLegacyBLS(t *testing.T) { } } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbos/common_test.go b/arbos/common_test.go index d137d71bd5..c3fb070171 100644 --- a/arbos/common_test.go +++ b/arbos/common_test.go @@ -9,9 +9,9 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbos/internal_tx.go b/arbos/internal_tx.go index 60a35f1da5..aec8792ec5 100644 --- a/arbos/internal_tx.go +++ b/arbos/internal_tx.go @@ -40,7 +40,7 @@ func InternalTxStartBlock( } return &types.ArbitrumInternalTx{ ChainId: chainId, - Type: arbInternalTxStartBlock, + SubType: arbInternalTxStartBlock, Data: data, L2BlockNumber: l2BlockNum, } diff --git a/arbos/l1pricing/common_test.go b/arbos/l1pricing/common_test.go index 26ae2659ed..077790c114 100644 --- a/arbos/l1pricing/common_test.go +++ b/arbos/l1pricing/common_test.go @@ -9,9 +9,9 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbos/l2pricing/l2pricing_test.go b/arbos/l2pricing/l2pricing_test.go index 3974beea4c..90fe1575d9 100644 --- a/arbos/l2pricing/l2pricing_test.go +++ b/arbos/l2pricing/l2pricing_test.go @@ -155,9 +155,9 @@ func rateEstimate(t *testing.T, pricing *L2PricingState) uint64 { return value } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/arbstate/geth_test.go b/arbstate/geth_test.go index 693c1e72e7..33b11d5235 100644 --- a/arbstate/geth_test.go +++ b/arbstate/geth_test.go @@ -137,9 +137,9 @@ func RunMessagesThroughAPI(t *testing.T, msgs [][]byte, statedb *state.StateDB) } } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/blockscout b/blockscout index cf1b8b1f3f..0048176413 160000 --- a/blockscout +++ b/blockscout @@ -1 +1 @@ -Subproject commit cf1b8b1f3f20b46f234dd597db4823a7c57bed51 +Subproject commit 00481764130bad02625aa17dbec8830fa0f59428 diff --git a/blsSignatures/blsSignatures_test.go b/blsSignatures/blsSignatures_test.go index a1e55ab7a6..34ef17ad9d 100644 --- a/blsSignatures/blsSignatures_test.go +++ b/blsSignatures/blsSignatures_test.go @@ -4,8 +4,9 @@ package blsSignatures import ( - "github.com/offchainlabs/nitro/util/testhelpers" "testing" + + "github.com/offchainlabs/nitro/util/testhelpers" ) func TestValidSignature(t *testing.T) { @@ -106,9 +107,9 @@ func TestSignatureAggregationDifferentMessages(t *testing.T) { } } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/broadcaster/broadcaster_test.go b/broadcaster/broadcaster_test.go index e3589d95b5..a25deb9320 100644 --- a/broadcaster/broadcaster_test.go +++ b/broadcaster/broadcaster_test.go @@ -127,9 +127,9 @@ func TestBroadcasterMessagesRemovedOnConfirmation(t *testing.T) { } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/contracts/src/mocks/Simple.sol b/contracts/src/mocks/Simple.sol index 98286a7762..28c2905906 100644 --- a/contracts/src/mocks/Simple.sol +++ b/contracts/src/mocks/Simple.sol @@ -7,10 +7,22 @@ pragma solidity ^0.8.0; contract Simple { uint64 public counter; + event CounterEvent(uint64 count); + event NullEvent(); + function increment() external { counter++; } + function incrementEmit() external { + counter++; + emit CounterEvent(counter); + } + + function emitNullEvent() external { + emit NullEvent(); + } + function checkBlockHashes() external view returns (uint256) { require(blockhash(block.number - 1) != blockhash(block.number - 2), "SAME_BLOCK_HASH"); return block.number; diff --git a/contracts/src/node-interface/NodeInterface.sol b/contracts/src/node-interface/NodeInterface.sol index ee656325a0..c5b5f53b06 100644 --- a/contracts/src/node-interface/NodeInterface.sol +++ b/contracts/src/node-interface/NodeInterface.sol @@ -47,4 +47,11 @@ interface NodeInterface { bytes32 root, bytes32[] memory proof ); + + /** + * @notice Finds the L1 batch containing a requested L2 block, reverting if none does + * @param block The L2 block being queried + * @return batch The L1 block containing the requested L2 block + */ + function findBatchContainingBlock(uint64 block) external view returns (uint64 batch); } diff --git a/das/das_test.go b/das/das_test.go index 1726287ad3..2bb64ac537 100644 --- a/das/das_test.go +++ b/das/das_test.go @@ -71,9 +71,9 @@ func TestDASMissingMessage(t *testing.T) { } } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/go-ethereum b/go-ethereum index 950a481438..d159bdf607 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 950a481438c773cc9b73a25418f1a8ac433f7388 +Subproject commit d159bdf607ee328b3a5c6e5a054a0b7e2d7f17a2 diff --git a/precompiles/ArbAddressTable_test.go b/precompiles/ArbAddressTable_test.go index 24ccdbcfbc..d55cb26759 100644 --- a/precompiles/ArbAddressTable_test.go +++ b/precompiles/ArbAddressTable_test.go @@ -162,9 +162,9 @@ func newMockEVMForTesting() *vm.EVM { return evm } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/system_tests/block_hash_test.go b/system_tests/block_hash_test.go index 0f7aa41508..eb96d5e380 100644 --- a/system_tests/block_hash_test.go +++ b/system_tests/block_hash_test.go @@ -19,7 +19,7 @@ func TestBlockHash(t *testing.T) { l2info, _, l2client, _, _, _, stack := CreateTestNodeOnL1(t, ctx, true) defer stack.Close() - auth := l2info.GetDefaultTransactOpts("Faucet") + auth := l2info.GetDefaultTransactOpts("Faucet", ctx) _, _, simple, err := mocksgen.DeploySimple(&auth, l2client) Require(t, err) diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go new file mode 100644 index 0000000000..ad6520c715 --- /dev/null +++ b/system_tests/bloom_test.go @@ -0,0 +1,121 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package arbtest + +import ( + "context" + "math/big" + "math/rand" + "testing" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/solgen/go/mocksgen" +) + +func TestBloom(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + nodeconfig := arbnode.ConfigDefaultL2Test() + nodeconfig.RPC.BloomBitsBlocks = 256 + nodeconfig.RPC.BloomConfirms = 1 + l2info, node, client := CreateTestL2WithConfig(t, ctx, nil, nodeconfig, false) + defer node.StopAndWait() + + l2info.GenerateAccount("User2") + + ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + ownerTxOpts.Context = ctx + _, tx, simple, err := mocksgen.DeploySimple(&ownerTxOpts, client) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + simpleABI, err := mocksgen.SimpleMetaData.GetAbi() + Require(t, err) + + countsNum := 800 + eventsNum := 20 + nullEventsNum := 50 + + eventCounts := make(map[uint64]struct{}) + nullEventCounts := make(map[uint64]struct{}) + + for i := 0; i < eventsNum; i++ { + count := uint64(rand.Int() % countsNum) + eventCounts[count] = struct{}{} + } + + for i := 0; i < nullEventsNum; i++ { + count := uint64(rand.Int() % countsNum) + nullEventCounts[count] = struct{}{} + } + + for i := 0; i <= countsNum; i++ { + var tx *types.Transaction + var err error + _, sendNullEvent := nullEventCounts[uint64(i)] + if sendNullEvent { + tx, err = simple.EmitNullEvent(&ownerTxOpts) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + } + + _, sendEvent := eventCounts[uint64(i)] + if sendEvent { + tx, err = simple.IncrementEmit(&ownerTxOpts) + } else { + tx, err = simple.Increment(&ownerTxOpts) + } + Require(t, err) + _, err = EnsureTxSucceeded(ctx, client, tx) + Require(t, err) + if i%100 == 0 { + t.Log("counts: ", i, "/", countsNum) + } + } + + for { + sectionSize, sectionNum := node.Backend.APIBackend().BloomStatus() + if sectionSize != 256 { + Fail(t, "unexpected section size: ", sectionSize) + } + t.Log("sections: ", sectionNum, "/", uint64(countsNum)/sectionSize) + if sectionSize*(sectionNum+1) > uint64(countsNum) && sectionNum > 1 { + break + } + <-time.After(time.Second) + } + lastHeader, err := client.HeaderByNumber(ctx, nil) + Require(t, err) + nullEventQuery := ethereum.FilterQuery{ + FromBlock: big.NewInt(0), + ToBlock: lastHeader.Number, + Topics: [][]common.Hash{{simpleABI.Events["NullEvent"].ID}}, + } + logs, err := client.FilterLogs(ctx, nullEventQuery) + Require(t, err) + if len(logs) != len(nullEventCounts) { + Fail(t, "expected ", len(nullEventCounts), " logs, got ", len(logs)) + } + incrementEventQuery := ethereum.FilterQuery{ + Topics: [][]common.Hash{{simpleABI.Events["CounterEvent"].ID}}, + } + logs, err = client.FilterLogs(ctx, incrementEventQuery) + Require(t, err) + if len(logs) != len(eventCounts) { + Fail(t, "expected ", len(eventCounts), " logs, got ", len(logs)) + } + for _, log := range logs { + parsedLog, err := simple.ParseCounterEvent(log) + Require(t, err) + _, expected := eventCounts[parsedLog.Count-1] + if !expected { + Fail(t, "unxpected count in logs: ", parsedLog.Count) + } + } +} diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 68cce6f6df..0ee85e758d 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -60,7 +60,7 @@ func TransferBalance(t *testing.T, from, to string, amount *big.Int, l2info info func SendSignedTxViaL1(t *testing.T, ctx context.Context, l1info *BlockchainTestInfo, l1client arbutil.L1Interface, l2client arbutil.L1Interface, delayedTx *types.Transaction) *types.Receipt { delayedInboxContract, err := bridgegen.NewInbox(l1info.GetAddress("Inbox"), l1client) Require(t, err) - usertxopts := l1info.GetDefaultTransactOpts("User") + usertxopts := l1info.GetDefaultTransactOpts("User", ctx) txbytes, err := delayedTx.MarshalBinary() Require(t, err) @@ -149,7 +149,7 @@ func DeployOnTestL1(t *testing.T, ctx context.Context, l1info info, l1client cli l1info.PrepareTx("Faucet", "Sequencer", 30000, big.NewInt(9223372036854775807), nil), l1info.PrepareTx("Faucet", "User", 30000, big.NewInt(9223372036854775807), nil)}) - l1TransactionOpts := l1info.GetDefaultTransactOpts("RollupOwner") + l1TransactionOpts := l1info.GetDefaultTransactOpts("RollupOwner", ctx) wasmModuleRoot, err := validator.DefaultNitroMachineConfig.ReadLatestWasmModuleRoot() Require(t, err) addresses, err := arbnode.DeployOnL1(ctx, l1client, &l1TransactionOpts, l1info.GetAddress("Sequencer"), 0, wasmModuleRoot, chainId, arbnode.TestL1ReaderConfig) @@ -198,7 +198,7 @@ func CreateTestNodeOnL1WithConfig(t *testing.T, ctx context.Context, isSequencer addresses := DeployOnTestL1(t, ctx, l1info, l1client, chainConfig.ChainID) var sequencerTxOptsPtr *bind.TransactOpts if isSequencer { - sequencerTxOpts := l1info.GetDefaultTransactOpts("Sequencer") + sequencerTxOpts := l1info.GetDefaultTransactOpts("Sequencer", ctx) sequencerTxOptsPtr = &sequencerTxOpts } @@ -233,7 +233,7 @@ func CreateTestL2WithConfig(t *testing.T, ctx context.Context, l2Info *Blockchai client := ClientForArbBackend(t, node.Backend) if takeOwnership { - debugAuth := l2info.GetDefaultTransactOpts("Owner") + debugAuth := l2info.GetDefaultTransactOpts("Owner", ctx) // make auth a chain owner arbdebug, err := precompilesgen.NewArbDebug(common.HexToAddress("0xff"), client) @@ -249,7 +249,7 @@ func CreateTestL2WithConfig(t *testing.T, ctx context.Context, l2Info *Blockchai return l2info, node, client } -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, text ...interface{}) { t.Helper() testhelpers.RequireImpl(t, err, text...) } diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index ae46a427e1..b47a84f224 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -20,7 +20,7 @@ func TestDeploy(t *testing.T) { defer cancel() l2info, _, client := CreateTestL2(t, ctx) - auth := l2info.GetDefaultTransactOpts("Owner") + auth := l2info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient _, tx, simple, err := mocksgen.DeploySimple(&auth, client) @@ -46,7 +46,7 @@ func TestEstimate(t *testing.T) { defer cancel() l2info, _, client := CreateTestL2(t, ctx) - auth := l2info.GetDefaultTransactOpts("Owner") + auth := l2info.GetDefaultTransactOpts("Owner", ctx) auth.GasMargin = 0 // don't adjust, we want to see if the estimate alone is sufficient gasPrice := big.NewInt(2 * params.GWei) diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 799398015d..e292ecf989 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -26,8 +26,8 @@ func TestTips(t *testing.T) { l2info, _, l2client, l1info, _, l1client, stack := CreateTestNodeOnL1(t, ctx, true) defer stack.Close() - auth := l2info.GetDefaultTransactOpts("Owner") - callOpts := l2info.GetDefaultCallOpts("Owner") + auth := l2info.GetDefaultTransactOpts("Owner", ctx) + callOpts := l2info.GetDefaultCallOpts("Owner", ctx) aggregator := testhelpers.RandomAddress() // get the network fee account @@ -86,7 +86,7 @@ func TestSequencerWontPostWhenNotPreferred(t *testing.T) { defer cancel() l2info, _, client := CreateTestL2(t, ctx) - auth := l2info.GetDefaultTransactOpts("Owner") + auth := l2info.GetDefaultTransactOpts("Owner", ctx) // prefer a 3rd party aggregator arbAggregator, err := precompilesgen.NewArbAggregator(common.HexToAddress("0x6d"), client) @@ -110,7 +110,7 @@ func TestSequencerFeePaid(t *testing.T) { l2info, _, l2client, _, _, _, stack := CreateTestNodeOnL1(t, ctx, true) defer stack.Close() - callOpts := l2info.GetDefaultCallOpts("Owner") + callOpts := l2info.GetDefaultCallOpts("Owner", ctx) // get the network fee account arbOwnerPublic, err := precompilesgen.NewArbOwnerPublic(common.HexToAddress("0x6b"), l2client) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index 8eb4c8444c..4d32b2baeb 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -197,10 +197,10 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool) { conf.InboxReader.CheckDelay = time.Second rollupAddresses := DeployOnTestL1(t, ctx, l1Info, l1Backend, chainConfig.ChainID) - deployerTxOpts := l1Info.GetDefaultTransactOpts("deployer") - sequencerTxOpts := l1Info.GetDefaultTransactOpts("sequencer") - asserterTxOpts := l1Info.GetDefaultTransactOpts("asserter") - challengerTxOpts := l1Info.GetDefaultTransactOpts("challenger") + deployerTxOpts := l1Info.GetDefaultTransactOpts("deployer", ctx) + sequencerTxOpts := l1Info.GetDefaultTransactOpts("sequencer", ctx) + asserterTxOpts := l1Info.GetDefaultTransactOpts("asserter", ctx) + challengerTxOpts := l1Info.GetDefaultTransactOpts("challenger", ctx) delayedBridge, tx, _, err := mocksgen.DeployBridgeStub(&deployerTxOpts, l1Backend) Require(t, err) _, err = EnsureTxSucceeded(context.Background(), l1Backend, tx) diff --git a/system_tests/outbox_test.go b/system_tests/outbox_test.go index c31d312bce..105842a29c 100644 --- a/system_tests/outbox_test.go +++ b/system_tests/outbox_test.go @@ -35,7 +35,7 @@ func TestOutboxProofs(t *testing.T) { merkleTopic := arbSysAbi.Events["SendMerkleUpdate"].ID l2info, _, client := CreateTestL2(t, ctx) - auth := l2info.GetDefaultTransactOpts("Owner") + auth := l2info.GetDefaultTransactOpts("Owner", ctx) arbSys, err := precompilesgen.NewArbSys(types.ArbSysAddress, client) Require(t, err) diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 284be0b01b..f15180cf03 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -67,6 +67,18 @@ func retryableSetup(t *testing.T) ( TransferBalance(t, "Faucet", "Burn", discard, l2info, l2client, ctx) teardown := func() { + + // check the integrity of the RPC + blockNum, err := l2client.BlockNumber(ctx) + Require(t, err, "failed to get L2 block number") + for number := uint64(0); number < blockNum; number++ { + block, err := l2client.BlockByNumber(ctx, arbmath.UintToBig(number)) + Require(t, err, "failed to get L2 block", number, "of", blockNum) + if block.Number().Uint64() != number { + Fail(t, "block number mismatch", number, block.Number().Uint64()) + } + } + cancel() stack.Close() } @@ -100,7 +112,7 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { Require(t, err, "failed to deploy NodeInterface") // estimate the gas needed to auto-redeem the retryable - usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet") + usertxoptsL2 := l2info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL2.NoSend = true usertxoptsL2.GasMargin = 0 tx, err := nodeInterface.EstimateRetryableTicket( @@ -118,7 +130,7 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { colors.PrintBlue("estimate: ", estimate) // submit & auto-redeem the retryable using the gas estimate - usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet") + usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) usertxoptsL1.Value = deposit l1tx, err := delayedInbox.CreateRetryableTicket( &usertxoptsL1, @@ -159,8 +171,8 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { l2info, l1info, l2client, l1client, delayedInbox, lookupSubmitRetryableL2TxHash, ctx, teardown := retryableSetup(t) defer teardown() - ownerTxOpts := l2info.GetDefaultTransactOpts("Owner") - usertxopts := l1info.GetDefaultTransactOpts("Faucet") + ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) simpleAddr, _, simple, err := mocksgen.DeploySimple(&ownerTxOpts, l2client) @@ -238,7 +250,7 @@ func TestSubmissionGasCosts(t *testing.T) { l2info, l1info, l2client, l1client, delayedInbox, _, ctx, teardown := retryableSetup(t) defer teardown() - usertxopts := l1info.GetDefaultTransactOpts("Faucet") + usertxopts := l1info.GetDefaultTransactOpts("Faucet", ctx) usertxopts.Value = arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) l2info.GenerateAccount("Refund") diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index d54a28a392..619630cc6a 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -55,7 +55,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { seqInbox, err := bridgegen.NewSequencerInbox(l1Info.GetAddress("SequencerInbox"), l1Client) Require(t, err) - seqOpts := l1Info.GetDefaultTransactOpts("Sequencer") + seqOpts := l1Info.GetDefaultTransactOpts("Sequencer", ctx) ownerAddress := l2Info.GetAddress("Owner") var startL2BlockNumber uint64 = 0 diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 6d6f2857ba..d5529581cb 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -75,17 +75,17 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) } } - deployAuth := l1info.GetDefaultTransactOpts("RollupOwner") + deployAuth := l1info.GetDefaultTransactOpts("RollupOwner", ctx) balance := big.NewInt(params.Ether) balance.Mul(balance, big.NewInt(100)) l1info.GenerateAccount("ValidatorA") TransferBalance(t, "Faucet", "ValidatorA", balance, l1info, l1client, ctx) - l1authA := l1info.GetDefaultTransactOpts("ValidatorA") + l1authA := l1info.GetDefaultTransactOpts("ValidatorA", ctx) l1info.GenerateAccount("ValidatorB") TransferBalance(t, "Faucet", "ValidatorB", balance, l1info, l1client, ctx) - l1authB := l1info.GetDefaultTransactOpts("ValidatorB") + l1authB := l1info.GetDefaultTransactOpts("ValidatorB", ctx) valWalletAddrA, err := validator.CreateValidatorWallet(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader) Require(t, err) diff --git a/system_tests/test_info.go b/system_tests/test_info.go index 41d0b5b5f2..48b5824973 100644 --- a/system_tests/test_info.go +++ b/system_tests/test_info.go @@ -5,13 +5,15 @@ package arbtest import ( "bytes" + "context" "crypto/ecdsa" "errors" - "github.com/offchainlabs/nitro/arbos/l2pricing" - "github.com/offchainlabs/nitro/util" "math/big" "testing" + "github.com/offchainlabs/nitro/arbos/l2pricing" + "github.com/offchainlabs/nitro/util" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -152,7 +154,7 @@ func (b *BlockchainTestInfo) GetInfoWithPrivKey(name string) *AccountInfo { return info } -func (b *BlockchainTestInfo) GetDefaultTransactOpts(name string) bind.TransactOpts { +func (b *BlockchainTestInfo) GetDefaultTransactOpts(name string, ctx context.Context) bind.TransactOpts { b.T.Helper() info := b.GetInfoWithPrivKey(name) return bind.TransactOpts{ @@ -169,12 +171,13 @@ func (b *BlockchainTestInfo) GetDefaultTransactOpts(name string) bind.TransactOp return tx.WithSignature(b.Signer, signature) }, GasMargin: 2000, // adjust by 20% + Context: ctx, } } -func (b *BlockchainTestInfo) GetDefaultCallOpts(name string) *bind.CallOpts { +func (b *BlockchainTestInfo) GetDefaultCallOpts(name string, ctx context.Context) *bind.CallOpts { b.T.Helper() - auth := b.GetDefaultTransactOpts(name) + auth := b.GetDefaultTransactOpts(name, ctx) return &bind.CallOpts{ From: auth.From, } diff --git a/util/merkletree/common_test.go b/util/merkletree/common_test.go index 02762a5e47..6c05a6f6ea 100644 --- a/util/merkletree/common_test.go +++ b/util/merkletree/common_test.go @@ -9,9 +9,9 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/util/testhelpers/testhelpers.go b/util/testhelpers/testhelpers.go index 2ef694da0f..347757d9e0 100644 --- a/util/testhelpers/testhelpers.go +++ b/util/testhelpers/testhelpers.go @@ -12,10 +12,10 @@ import ( ) // Fail a test should an error occur -func RequireImpl(t *testing.T, err error, text ...string) { +func RequireImpl(t *testing.T, err error, printables ...interface{}) { t.Helper() if err != nil { - t.Fatal(colors.Red, text, err, colors.Clear) + t.Fatal(colors.Red, printables, err, colors.Clear) } } diff --git a/validator/block_validator.go b/validator/block_validator.go index 1d53461a5a..e6c46ee4e1 100644 --- a/validator/block_validator.go +++ b/validator/block_validator.go @@ -333,7 +333,9 @@ func (v *BlockValidator) validate(ctx context.Context, validationStatus *validat log.Info("starting validation for block", "blockNr", entry.BlockNumber) gsEnd, delayedMsg, err := v.executeBlock(ctx, entry, preimages, seqMsg, v.validateWasmModuleRoot) if err != nil { - log.Error("Validation of block failed", "err", err) + if !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) { + log.Error("Validation of block failed", "err", err) + } return } gsExpected := entry.expectedEnd() diff --git a/validator/common_test.go b/validator/common_test.go index ca1ea439ae..61a6e3b936 100644 --- a/validator/common_test.go +++ b/validator/common_test.go @@ -9,9 +9,9 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) { diff --git a/validator/stateless_block_validator.go b/validator/stateless_block_validator.go index 8b9615b45c..9a50801c17 100644 --- a/validator/stateless_block_validator.go +++ b/validator/stateless_block_validator.go @@ -346,10 +346,6 @@ func (v *StatelessBlockValidator) executeBlock(ctx context.Context, entry *valid log.Info("validation", "block", entry.BlockNumber, "steps", steps) } if err != nil { - if !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) { - log.Error("running machine failed", "err", err) - panic("Failed to run machine: " + err.Error()) - } return GoGlobalState{}, nil, fmt.Errorf("machine execution failed with error: %w", err) } steps += count diff --git a/zeroheavy/common_test.go b/zeroheavy/common_test.go index b7023d05cb..03ab9320fc 100644 --- a/zeroheavy/common_test.go +++ b/zeroheavy/common_test.go @@ -9,9 +9,9 @@ import ( "github.com/offchainlabs/nitro/util/testhelpers" ) -func Require(t *testing.T, err error, text ...string) { +func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() - testhelpers.RequireImpl(t, err, text...) + testhelpers.RequireImpl(t, err, printables...) } func Fail(t *testing.T, printables ...interface{}) {