Skip to content

Commit

Permalink
Merge branch 'seq-maintenance-lock' of github.com:OffchainLabs/nitro …
Browse files Browse the repository at this point in the history
…into seq-maintenance-lock
  • Loading branch information
anodar committed Jun 21, 2023
2 parents 90b4fb5 + b6e2aca commit cb97e97
Show file tree
Hide file tree
Showing 21 changed files with 167 additions and 131 deletions.
9 changes: 5 additions & 4 deletions arbnode/execution/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/offchainlabs/nitro/arbos"
"github.com/offchainlabs/nitro/arbos/arbosState"
"github.com/offchainlabs/nitro/arbos/arbostypes"
"github.com/offchainlabs/nitro/gethhook"
"github.com/offchainlabs/nitro/statetransfer"
)
Expand Down Expand Up @@ -82,7 +83,7 @@ func DefaultCacheConfigFor(stack *node.Node, cachingConfig *CachingConfig) *core
}
}

func WriteOrTestGenblock(chainDb ethdb.Database, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, serializedChainConfig []byte, accountsPerSync uint) error {
func WriteOrTestGenblock(chainDb ethdb.Database, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, accountsPerSync uint) error {
EmptyHash := common.Hash{}
prevHash := EmptyHash
prevDifficulty := big.NewInt(0)
Expand All @@ -103,7 +104,7 @@ func WriteOrTestGenblock(chainDb ethdb.Database, initData statetransfer.InitData
}
timestamp = prevHeader.Time
}
stateRoot, err := arbosState.InitializeArbosInDatabase(chainDb, initData, chainConfig, serializedChainConfig, timestamp, accountsPerSync)
stateRoot, err := arbosState.InitializeArbosInDatabase(chainDb, initData, chainConfig, initMessage, timestamp, accountsPerSync)
if err != nil {
return err
}
Expand Down Expand Up @@ -170,8 +171,8 @@ func GetBlockChain(chainDb ethdb.Database, cacheConfig *core.CacheConfig, chainC
return core.NewBlockChain(chainDb, cacheConfig, chainConfig, nil, nil, engine, vmConfig, shouldPreserveFalse, &txLookupLimit)
}

func WriteOrTestBlockChain(chainDb ethdb.Database, cacheConfig *core.CacheConfig, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, serializedChainConfig []byte, txLookupLimit uint64, accountsPerSync uint) (*core.BlockChain, error) {
err := WriteOrTestGenblock(chainDb, initData, chainConfig, serializedChainConfig, accountsPerSync)
func WriteOrTestBlockChain(chainDb ethdb.Database, cacheConfig *core.CacheConfig, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, txLookupLimit uint64, accountsPerSync uint) (*core.BlockChain, error) {
err := WriteOrTestGenblock(chainDb, initData, chainConfig, initMessage, accountsPerSync)
if err != nil {
return nil, err
}
Expand Down
10 changes: 5 additions & 5 deletions arbnode/inbox_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,17 @@ func (r *InboxReader) Start(ctxIn context.Context) error {
if err != nil {
return err
}
initChainId, initChainConfig, _, err := message.ParseInitMessage()
initMessage, err := message.ParseInitMessage()
if err != nil {
return err
}
chainConfig := r.tracker.txStreamer.chainConfig
configChainId := chainConfig.ChainID
if initChainId.Cmp(configChainId) != 0 {
return fmt.Errorf("expected L2 chain ID %v but read L2 chain ID %v from init message in L1 inbox", configChainId, initChainId)
if initMessage.ChainId.Cmp(configChainId) != 0 {
return fmt.Errorf("expected L2 chain ID %v but read L2 chain ID %v from init message in L1 inbox", configChainId, initMessage.ChainId)
}
if initChainConfig != nil {
if err := initChainConfig.CheckCompatible(chainConfig, chainConfig.ArbitrumChainParams.GenesisBlockNum, 0); err != nil {
if initMessage.ChainConfig != nil {
if err := initMessage.ChainConfig.CheckCompatible(chainConfig, chainConfig.ArbitrumChainParams.GenesisBlockNum, 0); err != nil {
return fmt.Errorf("incompatible chain config read from init message in L1 inbox: %w", err)
}
}
Expand Down
7 changes: 1 addition & 6 deletions arbnode/inbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package arbnode
import (
"context"
"encoding/binary"
"encoding/json"
"math/big"
"math/rand"
"testing"
Expand All @@ -33,10 +32,6 @@ import (

func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (*execution.ExecutionEngine, *TransactionStreamer, ethdb.Database, *core.BlockChain) {
chainConfig := params.ArbitrumDevTestChainConfig()
serializedChainConfig, err := json.Marshal(chainConfig)
if err != nil {
Fail(t, err)
}

initData := statetransfer.ArbosInitializationInfo{
Accounts: []statetransfer.AccountInitializationInfo{
Expand All @@ -51,7 +46,7 @@ func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (*
arbDb := rawdb.NewMemoryDatabase()
initReader := statetransfer.NewMemoryInitDataReader(&initData)

bc, err := execution.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, serializedChainConfig, ConfigDefaultL2Test().TxLookupLimit, 0)
bc, err := execution.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, arbostypes.TestInitMessage, ConfigDefaultL2Test().TxLookupLimit, 0)

if err != nil {
Fail(t, err)
Expand Down
12 changes: 6 additions & 6 deletions arbnode/message_pruner.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ func (m *MessagePruner) prune(ctx context.Context) time.Duration {
BlockNumber: big.NewInt(int64(rpc.FinalizedBlockNumber)),
})
if err != nil {
log.Error("error getting latest confirmed node: %w", err)
log.Error("error getting latest confirmed node", "err", err)
return m.config().MessagePruneInterval
}
nodeInfo, err := m.staker.Rollup().LookupNode(ctx, latestConfirmedNode)
if err != nil {
log.Error("error getting latest confirmed node info: %w", err)
log.Error("error getting latest confirmed node info", "node", latestConfirmedNode, "err", err)
return m.config().MessagePruneInterval
}
endBatchCount := nodeInfo.Assertion.AfterState.GlobalState.Batch
Expand All @@ -81,7 +81,7 @@ func (m *MessagePruner) prune(ctx context.Context) time.Duration {
}
endBatchMetadata, err := m.inboxTracker.GetBatchMetadata(endBatchCount - 1)
if err != nil {
log.Error("error getting last batch metadata: %w", err)
log.Error("error getting last batch metadata", "batch", endBatchCount-1, "err", err)
return m.config().MessagePruneInterval
}
deleteOldMessageFromDB(endBatchCount, endBatchMetadata, m.inboxTracker.db, m.transactionStreamer.db)
Expand All @@ -91,7 +91,7 @@ func (m *MessagePruner) prune(ctx context.Context) time.Duration {
func deleteOldMessageFromDB(endBatchCount uint64, endBatchMetadata BatchMetadata, inboxTrackerDb ethdb.Database, transactionStreamerDb ethdb.Database) {
prunedKeysRange, err := deleteFromLastPrunedUptoEndKey(inboxTrackerDb, sequencerBatchMetaPrefix, endBatchCount)
if err != nil {
log.Error("error deleting batch metadata: %w", err)
log.Error("error deleting batch metadata", "err", err)
return
}
if len(prunedKeysRange) > 0 {
Expand All @@ -100,7 +100,7 @@ func deleteOldMessageFromDB(endBatchCount uint64, endBatchMetadata BatchMetadata

prunedKeysRange, err = deleteFromLastPrunedUptoEndKey(transactionStreamerDb, messagePrefix, uint64(endBatchMetadata.MessageCount))
if err != nil {
log.Error("error deleting last batch messages: %w", err)
log.Error("error deleting last batch messages", "err", err)
return
}
if len(prunedKeysRange) > 0 {
Expand All @@ -109,7 +109,7 @@ func deleteOldMessageFromDB(endBatchCount uint64, endBatchMetadata BatchMetadata

prunedKeysRange, err = deleteFromLastPrunedUptoEndKey(inboxTrackerDb, rlpDelayedMessagePrefix, endBatchMetadata.DelayedMessageCount)
if err != nil {
log.Error("error deleting last batch delayed messages: %w", err)
log.Error("error deleting last batch delayed messages", "err", err)
return
}
if len(prunedKeysRange) > 0 {
Expand Down
14 changes: 5 additions & 9 deletions arbos/arbosState/arbosstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package arbosState

import (
"encoding/json"
"errors"
"fmt"
"math/big"
Expand All @@ -19,6 +18,7 @@ import (

"github.com/offchainlabs/nitro/arbos/addressSet"
"github.com/offchainlabs/nitro/arbos/addressTable"
"github.com/offchainlabs/nitro/arbos/arbostypes"
"github.com/offchainlabs/nitro/arbos/blockhash"
"github.com/offchainlabs/nitro/arbos/burn"
"github.com/offchainlabs/nitro/arbos/l1pricing"
Expand Down Expand Up @@ -112,11 +112,7 @@ func NewArbosMemoryBackedArbOSState() (*ArbosState, *state.StateDB) {
}
burner := burn.NewSystemBurner(nil, false)
chainConfig := params.ArbitrumDevTestChainConfig()
serializedChainConfig, err := json.Marshal(chainConfig)
if err != nil {
log.Crit("failed to serialize chain config", "error", err)
}
newState, err := InitializeArbosState(statedb, burner, chainConfig, serializedChainConfig)
newState, err := InitializeArbosState(statedb, burner, chainConfig, arbostypes.TestInitMessage)
if err != nil {
log.Crit("failed to open the ArbOS state", "error", err)
}
Expand Down Expand Up @@ -183,7 +179,7 @@ func getArbitrumOnlyGenesisPrecompiles(chainConfig *params.ChainConfig) []common
// start running long-lived chains, every change to the storage format will require defining a new version and
// providing upgrade code.

func InitializeArbosState(stateDB vm.StateDB, burner burn.Burner, chainConfig *params.ChainConfig, serializedChainConfig []byte) (*ArbosState, error) {
func InitializeArbosState(stateDB vm.StateDB, burner burn.Burner, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage) (*ArbosState, error) {
sto := storage.NewGeth(stateDB, burner)
arbosVersion, err := sto.GetUint64ByUint64(uint64(versionOffset))
if err != nil {
Expand Down Expand Up @@ -217,14 +213,14 @@ func InitializeArbosState(stateDB vm.StateDB, burner burn.Burner, chainConfig *p
}
_ = sto.SetByUint64(uint64(chainIdOffset), common.BigToHash(chainConfig.ChainID))
chainConfigStorage := sto.OpenStorageBackedBytes(chainConfigSubspace)
_ = chainConfigStorage.Set(serializedChainConfig)
_ = chainConfigStorage.Set(initMessage.SerializedChainConfig)
_ = sto.SetUint64ByUint64(uint64(genesisBlockNumOffset), chainConfig.ArbitrumChainParams.GenesisBlockNum)

initialRewardsRecipient := l1pricing.BatchPosterAddress
if desiredArbosVersion >= 2 {
initialRewardsRecipient = initialChainOwner
}
_ = l1pricing.InitializeL1PricingState(sto.OpenSubStorage(l1PricingSubspace), initialRewardsRecipient)
_ = l1pricing.InitializeL1PricingState(sto.OpenSubStorage(l1PricingSubspace), initialRewardsRecipient, initMessage.InitialL1BaseFee)
_ = l2pricing.InitializeL2PricingState(sto.OpenSubStorage(l2PricingSubspace))
_ = retryables.InitializeRetryableState(sto.OpenSubStorage(retryablesSubspace))
addressTable.Initialize(sto.OpenSubStorage(addressTableSubspace))
Expand Down
8 changes: 2 additions & 6 deletions arbos/arbosState/initialization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/offchainlabs/nitro/arbos/arbostypes"
"github.com/offchainlabs/nitro/arbos/burn"
"github.com/offchainlabs/nitro/statetransfer"
"github.com/offchainlabs/nitro/util/testhelpers"
Expand Down Expand Up @@ -60,11 +60,7 @@ func tryMarshalUnmarshal(input *statetransfer.ArbosInitializationInfo, t *testin

initReader := statetransfer.NewMemoryInitDataReader(&initData)
chainConfig := params.ArbitrumDevTestChainConfig()
serializedChainConfig, err := json.Marshal(chainConfig)
if err != nil {
log.Crit("failed to serialize chain config", "error", err)
}
stateroot, err := InitializeArbosInDatabase(raw, initReader, chainConfig, serializedChainConfig, 0, 0)
stateroot, err := InitializeArbosInDatabase(raw, initReader, chainConfig, arbostypes.TestInitMessage, 0, 0)
Require(t, err)

stateDb, err := state.New(stateroot, state.NewDatabase(raw), nil)
Expand Down
5 changes: 3 additions & 2 deletions arbos/arbosState/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/offchainlabs/nitro/arbos/arbostypes"
"github.com/offchainlabs/nitro/arbos/burn"
"github.com/offchainlabs/nitro/arbos/l2pricing"
"github.com/offchainlabs/nitro/arbos/retryables"
Expand Down Expand Up @@ -49,7 +50,7 @@ func MakeGenesisBlock(parentHash common.Hash, blockNumber uint64, timestamp uint
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil))
}

func InitializeArbosInDatabase(db ethdb.Database, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, serializedChainConfig []byte, timestamp uint64, accountsPerSync uint) (common.Hash, error) {
func InitializeArbosInDatabase(db ethdb.Database, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, timestamp uint64, accountsPerSync uint) (common.Hash, error) {
stateDatabase := state.NewDatabase(db)
statedb, err := state.New(common.Hash{}, stateDatabase, nil)
if err != nil {
Expand All @@ -73,7 +74,7 @@ func InitializeArbosInDatabase(db ethdb.Database, initData statetransfer.InitDat
}

burner := burn.NewSystemBurner(nil, false)
arbosState, err := InitializeArbosState(statedb, burner, chainConfig, serializedChainConfig)
arbosState, err := InitializeArbosState(statedb, burner, chainConfig, initMessage)
if err != nil {
log.Crit("failed to open the ArbOS state", "error", err)
}
Expand Down
48 changes: 39 additions & 9 deletions arbos/arbostypes/incomingmessage.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,30 +234,60 @@ func ParseIncomingL1Message(rd io.Reader, batchFetcher FallibleBatchFetcher) (*L

type FallibleBatchFetcher func(batchNum uint64) ([]byte, error)

type ParsedInitMessage struct {
ChainId *big.Int
InitialL1BaseFee *big.Int

// These may be nil
ChainConfig *params.ChainConfig
SerializedChainConfig []byte
}

// The initial L1 pricing basefee starts at 50 GWei unless set in the init message
var DefaultInitialL1BaseFee = big.NewInt(50 * params.GWei)

var TestInitMessage = &ParsedInitMessage{
ChainId: params.ArbitrumDevTestChainConfig().ChainID,
InitialL1BaseFee: DefaultInitialL1BaseFee,
}

// ParseInitMessage returns the chain id on success
func (msg *L1IncomingMessage) ParseInitMessage() (*big.Int, *params.ChainConfig, []byte, error) {
func (msg *L1IncomingMessage) ParseInitMessage() (*ParsedInitMessage, error) {
if msg.Header.Kind != L1MessageType_Initialize {
return nil, nil, nil, fmt.Errorf("invalid init message kind %v", msg.Header.Kind)
return nil, fmt.Errorf("invalid init message kind %v", msg.Header.Kind)
}
basefee := new(big.Int).Set(DefaultInitialL1BaseFee)
var chainConfig params.ChainConfig
var chainId *big.Int
if len(msg.L2msg) == 32 {
chainId = new(big.Int).SetBytes(msg.L2msg[:32])
return chainId, nil, nil, nil
return &ParsedInitMessage{chainId, basefee, nil, nil}, nil
}
if len(msg.L2msg) > 32 {
chainId = new(big.Int).SetBytes(msg.L2msg[:32])
version := msg.L2msg[32]
if version == 0 && len(msg.L2msg) > 33 {
serializedChainConfig := msg.L2msg[33:]
err := json.Unmarshal(serializedChainConfig, &chainConfig)
reader := bytes.NewReader(msg.L2msg[33:])
switch version {
case 1:
var err error
basefee, err = util.Uint256FromReader(reader)
if err != nil {
return nil, err
}
fallthrough
case 0:
serializedChainConfig, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
err = json.Unmarshal(serializedChainConfig, &chainConfig)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to parse init message, err: %w, message data: %v", err, string(msg.L2msg))
return nil, fmt.Errorf("failed to parse init message, err: %w, message data: %v", err, string(msg.L2msg))
}
return chainId, &chainConfig, serializedChainConfig, nil
return &ParsedInitMessage{chainId, basefee, &chainConfig, serializedChainConfig}, nil
}
}
return nil, nil, nil, fmt.Errorf("invalid init message data %v", string(msg.L2msg))
return nil, fmt.Errorf("invalid init message data %v", string(msg.L2msg))
}

func ParseBatchPostingReportMessageFields(rd io.Reader) (*big.Int, common.Address, common.Hash, uint64, *big.Int, error) {
Expand Down
34 changes: 7 additions & 27 deletions arbos/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (info *L1Info) L1BlockNumber() uint64 {
return info.l1BlockNumber
}

func createNewHeader(prevHeader *types.Header, l1info *L1Info, state *arbosState.ArbosState, chainConfig *params.ChainConfig, updateHeaderWithInfo bool) *types.Header {
func createNewHeader(prevHeader *types.Header, l1info *L1Info, state *arbosState.ArbosState, chainConfig *params.ChainConfig) *types.Header {
l2Pricing := state.L2PricingState()
baseFee, err := l2Pricing.BaseFeeWei()
state.Restrict(err)
Expand Down Expand Up @@ -96,30 +96,6 @@ func createNewHeader(prevHeader *types.Header, l1info *L1Info, state *arbosState
Nonce: [8]byte{}, // Filled in later; post-merge Ethereum will require this to be zero
BaseFee: baseFee,
}

if updateHeaderWithInfo {
var sendRoot common.Hash
var sendCount uint64
var nextL1BlockNumber uint64
var arbosVersion uint64

if blockNumber.Uint64() == chainConfig.ArbitrumChainParams.GenesisBlockNum {
arbosVersion = chainConfig.ArbitrumChainParams.InitialArbOSVersion
} else {
acc := state.SendMerkleAccumulator()
sendRoot, _ = acc.Root()
sendCount, _ = acc.Size()
nextL1BlockNumber, _ = state.Blockhashes().L1BlockNumber()
arbosVersion = state.ArbOSVersion()
}
arbitrumHeader := types.HeaderInfo{
SendRoot: sendRoot,
SendCount: sendCount,
L1BlockNumber: nextL1BlockNumber,
ArbOSFormatVersion: arbosVersion,
}
arbitrumHeader.UpdateHeaderWithInfo(header)
}
return header
}

Expand Down Expand Up @@ -213,7 +189,7 @@ func ProduceBlockAdvanced(
l1Timestamp: l1Header.Timestamp,
}

header := createNewHeader(lastBlockHeader, l1Info, state, chainConfig, false)
header := createNewHeader(lastBlockHeader, l1Info, state, chainConfig)
signer := types.MakeSigner(chainConfig, header.Number)
// Note: blockGasLeft will diverge from the actual gas left during execution in the event of invalid txs,
// but it's only used as block-local representation limiting the amount of work done in a block.
Expand Down Expand Up @@ -349,11 +325,15 @@ func ProduceBlockAdvanced(
})()

if tx.Type() == types.ArbitrumInternalTxType {
// ArbOS might have upgraded to a new version, so we need to refresh our state
state, err = arbosState.OpenSystemArbosState(statedb, nil, true)
if err != nil {
return nil, nil, err
}
header = createNewHeader(lastBlockHeader, l1Info, state, chainConfig, true)
// Update the ArbOS version in the header (if it changed)
extraInfo := types.DeserializeHeaderExtraInformation(header)
extraInfo.ArbOSFormatVersion = state.ArbOSVersion()
extraInfo.UpdateHeaderWithInfo(header)
}

// append the err, even if it is nil
Expand Down
Loading

0 comments on commit cb97e97

Please sign in to comment.