github.com/ethereum-optimism/optimism@v1.7.2/op-node/rollup/derive/payload_util.go (about) 1 package derive 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 7 "github.com/ethereum/go-ethereum/core/types" 8 9 "github.com/ethereum-optimism/optimism/op-node/rollup" 10 "github.com/ethereum-optimism/optimism/op-service/eth" 11 ) 12 13 // PayloadToBlockRef extracts the essential L2BlockRef information from an execution payload, 14 // falling back to genesis information if necessary. 15 func PayloadToBlockRef(rollupCfg *rollup.Config, payload *eth.ExecutionPayload) (eth.L2BlockRef, error) { 16 genesis := &rollupCfg.Genesis 17 var l1Origin eth.BlockID 18 var sequenceNumber uint64 19 if uint64(payload.BlockNumber) == genesis.L2.Number { 20 if payload.BlockHash != genesis.L2.Hash { 21 return eth.L2BlockRef{}, fmt.Errorf("expected L2 genesis hash to match L2 block at genesis block number %d: %s <> %s", genesis.L2.Number, payload.BlockHash, genesis.L2.Hash) 22 } 23 l1Origin = genesis.L1 24 sequenceNumber = 0 25 } else { 26 if len(payload.Transactions) == 0 { 27 return eth.L2BlockRef{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", payload.BlockHash) 28 } 29 var tx types.Transaction 30 if err := tx.UnmarshalBinary(payload.Transactions[0]); err != nil { 31 return eth.L2BlockRef{}, fmt.Errorf("failed to decode first tx to read l1 info from: %w", err) 32 } 33 if tx.Type() != types.DepositTxType { 34 return eth.L2BlockRef{}, fmt.Errorf("first payload tx has unexpected tx type: %d", tx.Type()) 35 } 36 info, err := L1BlockInfoFromBytes(rollupCfg, uint64(payload.Timestamp), tx.Data()) 37 if err != nil { 38 return eth.L2BlockRef{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %w", err) 39 } 40 l1Origin = eth.BlockID{Hash: info.BlockHash, Number: info.Number} 41 sequenceNumber = info.SequenceNumber 42 } 43 44 return eth.L2BlockRef{ 45 Hash: payload.BlockHash, 46 Number: uint64(payload.BlockNumber), 47 ParentHash: payload.ParentHash, 48 Time: uint64(payload.Timestamp), 49 L1Origin: l1Origin, 50 SequenceNumber: sequenceNumber, 51 }, nil 52 } 53 54 func PayloadToSystemConfig(rollupCfg *rollup.Config, payload *eth.ExecutionPayload) (eth.SystemConfig, error) { 55 if uint64(payload.BlockNumber) == rollupCfg.Genesis.L2.Number { 56 if payload.BlockHash != rollupCfg.Genesis.L2.Hash { 57 return eth.SystemConfig{}, fmt.Errorf( 58 "expected L2 genesis hash to match L2 block at genesis block number %d: %s <> %s", 59 rollupCfg.Genesis.L2.Number, payload.BlockHash, rollupCfg.Genesis.L2.Hash) 60 } 61 return rollupCfg.Genesis.SystemConfig, nil 62 } else { 63 if len(payload.Transactions) == 0 { 64 return eth.SystemConfig{}, fmt.Errorf("l2 block is missing L1 info deposit tx, block hash: %s", payload.BlockHash) 65 } 66 var tx types.Transaction 67 if err := tx.UnmarshalBinary(payload.Transactions[0]); err != nil { 68 return eth.SystemConfig{}, fmt.Errorf("failed to decode first tx to read l1 info from: %w", err) 69 } 70 if tx.Type() != types.DepositTxType { 71 return eth.SystemConfig{}, fmt.Errorf("first payload tx has unexpected tx type: %d", tx.Type()) 72 } 73 info, err := L1BlockInfoFromBytes(rollupCfg, uint64(payload.Timestamp), tx.Data()) 74 if err != nil { 75 return eth.SystemConfig{}, fmt.Errorf("failed to parse L1 info deposit tx from L2 block: %w", err) 76 } 77 if isEcotoneButNotFirstBlock(rollupCfg, uint64(payload.Timestamp)) { 78 // Translate Ecotone values back into encoded scalar if needed. 79 // We do not know if it was derived from a v0 or v1 scalar, 80 // but v1 is fine, a 0 blob base fee has the same effect. 81 info.L1FeeScalar[0] = 1 82 binary.BigEndian.PutUint32(info.L1FeeScalar[24:28], info.BlobBaseFeeScalar) 83 binary.BigEndian.PutUint32(info.L1FeeScalar[28:32], info.BaseFeeScalar) 84 } 85 return eth.SystemConfig{ 86 BatcherAddr: info.BatcherAddr, 87 Overhead: info.L1FeeOverhead, 88 Scalar: info.L1FeeScalar, 89 GasLimit: uint64(payload.GasLimit), 90 }, err 91 } 92 }