Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse the initial data cost out of the init message #1704

Merged
merged 5 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
5 changes: 2 additions & 3 deletions arbos/l1pricing/l1pricing.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,14 @@ const (
const (
InitialInertia = 10
InitialPerUnitReward = 10
InitialPricePerUnitWei = 50 * params.GWei
InitialPerBatchGasCostV6 = 100000
)

// one minute at 100000 bytes / sec
var InitialEquilibrationUnitsV0 = arbmath.UintToBig(60 * params.TxDataNonZeroGasEIP2028 * 100000)
var InitialEquilibrationUnitsV6 = arbmath.UintToBig(params.TxDataNonZeroGasEIP2028 * 10000000)

func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient common.Address) error {
func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient common.Address, initialL1BaseFee *big.Int) error {
bptStorage := sto.OpenSubStorage(BatchPosterTableKey)
if err := InitializeBatchPostersTable(bptStorage); err != nil {
return err
Expand All @@ -109,7 +108,7 @@ func InitializeL1PricingState(sto *storage.Storage, initialRewardsRecipient comm
return err
}
pricePerUnit := sto.OpenStorageBackedBigInt(pricePerUnitOffset)
if err := pricePerUnit.SetByUint(InitialPricePerUnitWei); err != nil {
if err := pricePerUnit.SetSaturatingWithWarning(initialL1BaseFee, "initial L1 base fee (storing in price per unit)"); err != nil {
return err
}
return nil
Expand Down
8 changes: 4 additions & 4 deletions arbos/l1pricing/l1pricing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@
package l1pricing

import (
"math/big"
"testing"

am "github.com/offchainlabs/nitro/util/arbmath"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/offchainlabs/nitro/arbos/burn"
"github.com/offchainlabs/nitro/arbos/storage"
)

func TestL1PriceUpdate(t *testing.T) {
sto := storage.NewMemoryBacked(burn.NewSystemBurner(nil, false))
err := InitializeL1PricingState(sto, common.Address{})
initialPriceEstimate := big.NewInt(123 * params.GWei)
err := InitializeL1PricingState(sto, common.Address{}, initialPriceEstimate)
Require(t, err)
ps := OpenL1PricingState(sto)

Expand All @@ -25,7 +26,6 @@ func TestL1PriceUpdate(t *testing.T) {
Fail(t)
}

initialPriceEstimate := am.UintToBig(InitialPricePerUnitWei)
priceEstimate, err := ps.PricePerUnit()
Require(t, err)
if priceEstimate.Cmp(initialPriceEstimate) != 0 {
Expand Down
8 changes: 8 additions & 0 deletions arbos/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ func HashFromReader(rd io.Reader) (common.Hash, error) {
return common.BytesToHash(buf), nil
}

func Uint256FromReader(rd io.Reader) (*big.Int, error) {
asHash, err := HashFromReader(rd)
if err != nil {
return nil, err
}
return asHash.Big(), nil
}

func HashToWriter(val common.Hash, wr io.Writer) error {
_, err := wr.Write(val.Bytes())
return err
Expand Down
28 changes: 16 additions & 12 deletions cmd/nitro/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo
if config.Init.ThenQuit {
cacheConfig.SnapshotWait = true
}
var serializedChainConfig []byte
var parsedInitMessage *arbostypes.ParsedInitMessage
if config.Node.L1Reader.Enable {
delayedBridge, err := arbnode.NewDelayedBridge(l1Client, rollupAddrs.Bridge, rollupAddrs.DeployedAt)
if err != nil {
Expand All @@ -596,30 +596,34 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo
if initMessage == nil {
return chainDb, nil, fmt.Errorf("failed to get init message while attempting to get serialized chain config")
}
var initChainConfig *params.ChainConfig
var initChainId *big.Int
initChainId, initChainConfig, serializedChainConfig, err = initMessage.ParseInitMessage()
parsedInitMessage, err = initMessage.ParseInitMessage()
if err != nil {
return chainDb, nil, err
}
if initChainId.Cmp(chainId) != 0 {
return chainDb, nil, fmt.Errorf("expected L2 chain ID %v but read L2 chain ID %v from init message in L1 inbox", chainId, initChainId)
if parsedInitMessage.ChainId.Cmp(chainId) != 0 {
return chainDb, nil, fmt.Errorf("expected L2 chain ID %v but read L2 chain ID %v from init message in L1 inbox", chainId, parsedInitMessage.ChainId)
}
if initChainConfig != nil {
if err := initChainConfig.CheckCompatible(chainConfig, chainConfig.ArbitrumChainParams.GenesisBlockNum, 0); err != nil {
if parsedInitMessage.ChainConfig != nil {
if err := parsedInitMessage.ChainConfig.CheckCompatible(chainConfig, chainConfig.ArbitrumChainParams.GenesisBlockNum, 0); err != nil {
return chainDb, nil, fmt.Errorf("incompatible chain config read from init message in L1 inbox: %w", err)
}
}
log.Info("Read serialized chain config from init message", "json", string(serializedChainConfig))
log.Info("Read serialized chain config from init message", "json", string(parsedInitMessage.SerializedChainConfig))
} else {
serializedChainConfig, err = json.Marshal(chainConfig)
serializedChainConfig, err := json.Marshal(chainConfig)
if err != nil {
return chainDb, nil, err
}
log.Warn("Serialized chain config as L1Reader is disabled and serialized chain config from init message is not available", "json", string(serializedChainConfig))
parsedInitMessage = &arbostypes.ParsedInitMessage{
ChainId: chainConfig.ChainID,
InitialL1BaseFee: arbostypes.DefaultInitialL1BaseFee,
ChainConfig: chainConfig,
SerializedChainConfig: serializedChainConfig,
}
log.Warn("Created fake init message as L1Reader is disabled and serialized chain config from init message is not available", "json", string(serializedChainConfig))
}

l2BlockChain, err = execution.WriteOrTestBlockChain(chainDb, cacheConfig, initDataReader, chainConfig, serializedChainConfig, config.Node.TxLookupLimit, config.Init.AccountsPerSync)
l2BlockChain, err = execution.WriteOrTestBlockChain(chainDb, cacheConfig, initDataReader, chainConfig, parsedInitMessage, config.Node.TxLookupLimit, config.Init.AccountsPerSync)
if err != nil {
return chainDb, nil, err
}
Expand Down
Loading
Loading