diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 09f8007611..691087f631 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -7,10 +7,12 @@ import ( "bytes" "context" "fmt" - "github.com/offchainlabs/nitro/util/headerreader" "math/big" "time" + "github.com/offchainlabs/nitro/arbos" + "github.com/offchainlabs/nitro/util/headerreader" + "github.com/andybalholm/brotli" "github.com/pkg/errors" flag "github.com/spf13/pflag" @@ -341,24 +343,30 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context, timeSinceBatc return nil, err } forcePostBatch := timeSinceBatchPosted >= b.config.MaxBatchPostInterval + haveUsefulMessage := false for b.building.msgCount < msgCount { msg, err := b.streamer.GetMessage(b.building.msgCount) if err != nil { log.Error("error getting message from streamer", "error", err) break } + if msg.Message.Header.Kind != arbos.L1MessageType_BatchPostingReport { + haveUsefulMessage = true + } success, err := b.building.segments.AddMessage(&msg) if err != nil { log.Error("error adding message to batch", "error", err) break } if !success { - forcePostBatch = true // this batch is full + // this batch is full + forcePostBatch = true + haveUsefulMessage = true break } b.building.msgCount++ } - if !forcePostBatch { + if !forcePostBatch || !haveUsefulMessage { // the batch isn't full yet and we've posted a batch recently // don't post anything for now return nil, nil diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index 1ea14ae286..b535f58d3a 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -92,11 +92,25 @@ func testBlockValidatorSimple(t *testing.T, dasModeString string, expensiveTx bo Fail(t, "Unexpected balance:", l2balance) } - lastBlockHeader, err := l2clientB.HeaderByNumber(ctx, nil) + lastBlock, err := l2clientB.BlockByNumber(ctx, nil) Require(t, err) + for { + usefulBlock := false + for _, tx := range lastBlock.Transactions() { + if tx.Type() != types.ArbitrumInternalTxType { + usefulBlock = true + break + } + } + if usefulBlock { + break + } + lastBlock, err = l2clientB.BlockByHash(ctx, lastBlock.ParentHash()) + Require(t, err) + } testDeadLine, _ := t.Deadline() nodeA.StopAndWait() - if !nodeB.BlockValidator.WaitForBlock(lastBlockHeader.Number.Uint64(), time.Until(testDeadLine)-time.Second*10) { + if !nodeB.BlockValidator.WaitForBlock(lastBlock.NumberU64(), time.Until(testDeadLine)-time.Second*10) { Fail(t, "did not validate all blocks") } nodeB.StopAndWait() diff --git a/validator/challenge_manager.go b/validator/challenge_manager.go index e585ea38c8..02fa735b2f 100644 --- a/validator/challenge_manager.go +++ b/validator/challenge_manager.go @@ -420,7 +420,7 @@ func (m *ChallengeManager) createInitialMachine(ctx context.Context, blockNum in var batchInfo []BatchInfo if tooFar { // Just record the part of block creation before the message is read - _, preimages, readBatchInfo, err := RecordBlockCreation(ctx, m.blockchain, m.inboxReader, blockHeader, nil) + _, preimages, readBatchInfo, err := RecordBlockCreation(ctx, m.blockchain, m.inboxReader, blockHeader, nil, true) if err != nil { return err } diff --git a/validator/stateless_block_validator.go b/validator/stateless_block_validator.go index a18965c032..08a8a59546 100644 --- a/validator/stateless_block_validator.go +++ b/validator/stateless_block_validator.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" @@ -222,10 +223,26 @@ type BatchInfo struct { } // If msg is nil, this will record block creation up to the point where message would be accessed (for a "too far" proof) -func RecordBlockCreation(ctx context.Context, blockchain *core.BlockChain, inboxReader InboxReaderInterface, prevHeader *types.Header, msg *arbstate.MessageWithMetadata) (common.Hash, map[common.Hash][]byte, []BatchInfo, error) { - recordingdb, chaincontext, recordingKV, err := arbitrum.PrepareRecording(blockchain, prevHeader) - if err != nil { - return common.Hash{}, nil, nil, err +func RecordBlockCreation(ctx context.Context, blockchain *core.BlockChain, inboxReader InboxReaderInterface, prevHeader *types.Header, msg *arbstate.MessageWithMetadata, producePreimages bool) (common.Hash, map[common.Hash][]byte, []BatchInfo, error) { + var recordingdb *state.StateDB + var chaincontext core.ChainContext + var recordingKV *arbitrum.RecordingKV + var err error + if producePreimages { + recordingdb, chaincontext, recordingKV, err = arbitrum.PrepareRecording(blockchain, prevHeader) + if err != nil { + return common.Hash{}, nil, nil, err + } + } else { + var prevRoot common.Hash + if prevHeader != nil { + prevRoot = prevHeader.Root + } + recordingdb, err = blockchain.StateAt(prevRoot) + if err != nil { + return common.Hash{}, nil, nil, err + } + chaincontext = blockchain } chainConfig := blockchain.Config() @@ -275,7 +292,13 @@ func RecordBlockCreation(ctx context.Context, blockchain *core.BlockChain, inbox blockHash = block.Hash() } - preimages, err := arbitrum.PreimagesFromRecording(chaincontext, recordingKV) + var preimages map[common.Hash][]byte + if recordingKV != nil { + preimages, err = arbitrum.PreimagesFromRecording(chaincontext, recordingKV) + if err != nil { + return common.Hash{}, nil, nil, err + } + } return blockHash, preimages, readBatchInfo, err } @@ -289,9 +312,9 @@ func BlockDataForValidation(ctx context.Context, blockchain *core.BlockChain, in return } - if prevHeader != nil && producePreimages { + if prevHeader != nil { var blockhash common.Hash - blockhash, preimages, readBatchInfo, err = RecordBlockCreation(ctx, blockchain, inboxReader, prevHeader, &msg) + blockhash, preimages, readBatchInfo, err = RecordBlockCreation(ctx, blockchain, inboxReader, prevHeader, &msg, producePreimages) if err != nil { return } @@ -319,7 +342,7 @@ func SetMachinePreimageResolver(ctx context.Context, mach *ArbitratorMachine, pr } for _, batch := range batchInfo { - if arbstate.IsDASMessageHeaderByte(batch.Data[40]) { + if len(batch.Data) >= 41 && arbstate.IsDASMessageHeaderByte(batch.Data[40]) { if das == nil { log.Error("No DAS configured, but sequencer message found with DAS header") if bc.Config().ArbitrumChainParams.DataAvailabilityCommittee {