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

Cancun RLP #81

Merged
merged 2 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
73 changes: 73 additions & 0 deletions rlp/berlin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package rlp

import (
"math/big"

"github.com/Fantom-foundation/Substate/types"
)

const berlinBlock = 37_455_223
cabrador marked this conversation as resolved.
Show resolved Hide resolved

// IsBerlinFork returns true if block is part of the berlin fork block range
func IsBerlinFork(block uint64) bool {
return block >= berlinBlock && block < londonBlock
}

// berlinRLP represents legacy RLP structure between Berlin and London fork starting at berlinBlock ending at londonBlock
type berlinRLP struct {
InputAlloc WorldState
OutputAlloc WorldState
Env *legacyEnv
Message *berlinMessage
Result *Result
}

// toRLP transforms r into RLP format which is compatible with the currently used Geth fork.
func (r berlinRLP) toRLP() *RLP {
return &RLP{
InputSubstate: r.InputAlloc,
OutputSubstate: r.OutputAlloc,
Env: r.Env.toEnv(),
Message: r.Message.toMessage(),
Result: r.Result,
}

}

type berlinMessage struct {
Nonce uint64
CheckNonce bool
GasPrice *big.Int
Gas uint64

From types.Address
To *types.Address `rlp:"nil"` // nil means contract creation
Value *big.Int
Data []byte

InitCodeHash *types.Hash `rlp:"nil"` // NOT nil for contract creation

AccessList types.AccessList // missing in substate DB from Geth v1.9.x
}

// toMessage transforms m into RLP format which is compatible with the currently used Geth fork.
func (m berlinMessage) toMessage() *Message {
return &Message{
londonMessage: londonMessage{
cabrador marked this conversation as resolved.
Show resolved Hide resolved
Nonce: m.Nonce,
CheckNonce: m.CheckNonce,
GasPrice: m.GasPrice,
Gas: m.Gas,
From: m.From,
To: m.To,
Value: new(big.Int).Set(m.Value),
Data: m.Data,
InitCodeHash: m.InitCodeHash,
AccessList: m.AccessList,

// Same behavior as AccessListTx.gasFeeCap() and AccessListTx.gasTipCap()
GasFeeCap: m.GasPrice,
GasTipCap: m.GasPrice,
},
}
}
127 changes: 32 additions & 95 deletions rlp/legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,6 @@ import (
"github.com/Fantom-foundation/Substate/types"
)

const (
berlinBlock = 37_455_223
londonBlock = 37_534_833
)

// IsLondonFork returns true if block is part of the london fork block range
func IsLondonFork(block uint64) bool {
return block >= londonBlock
}

// IsBerlinFork returns true if block is part of the berlin fork block range
func IsBerlinFork(block uint64) bool {
return block >= berlinBlock && block < londonBlock
}

// legacySubstateRLP represents legacy RLP structure between before Berlin fork thus before berlinBlock
type legacySubstateRLP struct {
InputAlloc WorldState
Expand All @@ -30,12 +15,13 @@ type legacySubstateRLP struct {
Result *Result
}

func (r legacySubstateRLP) toLondon() *RLP {
// toRLP transforms r into RLP format which is compatible with the currently used Geth fork.
func (r legacySubstateRLP) toRLP() *RLP {
return &RLP{
InputSubstate: r.InputAlloc,
OutputSubstate: r.OutputAlloc,
Env: r.Env.toLondon(),
Message: r.Message.toLondon(),
Env: r.Env.toEnv(),
Message: r.Message.toMessage(),
Result: r.Result,
}
}
Expand All @@ -54,22 +40,25 @@ type legacyMessage struct {
InitCodeHash *types.Hash `rlp:"nil"` // NOT nil for contract creation
}

func (m legacyMessage) toLondon() *Message {
// toMessage transforms m into RLP format which is compatible with the currently used Geth fork.
func (m legacyMessage) toMessage() *Message {
return &Message{
Nonce: m.Nonce,
CheckNonce: m.CheckNonce,
GasPrice: m.GasPrice,
Gas: m.Gas,
From: m.From,
To: m.To,
Value: new(big.Int).Set(m.Value),
Data: m.Data,
InitCodeHash: m.InitCodeHash,
AccessList: nil, // access list was not present before berlin fork?

// Same behavior as AccessListTx.gasFeeCap() and AccessListTx.gasTipCap()
GasFeeCap: m.GasPrice,
GasTipCap: m.GasPrice,
londonMessage: londonMessage{
Nonce: m.Nonce,
CheckNonce: m.CheckNonce,
GasPrice: m.GasPrice,
Gas: m.Gas,
From: m.From,
To: m.To,
Value: new(big.Int).Set(m.Value),
Data: m.Data,
InitCodeHash: m.InitCodeHash,
AccessList: nil, // access list was not present before berlin fork?

// Same behavior as AccessListTx.gasFeeCap() and AccessListTx.gasTipCap()
GasFeeCap: m.GasPrice,
GasTipCap: m.GasPrice,
},
}
}

Expand All @@ -82,68 +71,16 @@ type legacyEnv struct {
BlockHashes [][2]types.Hash
}

func (e legacyEnv) toLondon() *Env {
// toEnv transforms e into RLP format which is compatible with the currently used Geth fork.
func (e legacyEnv) toEnv() *Env {
return &Env{
Coinbase: e.Coinbase,
Difficulty: e.Difficulty,
GasLimit: e.GasLimit,
Number: e.Number,
Timestamp: e.Timestamp,
BlockHashes: e.BlockHashes,
}
}

// berlinRLP represents legacy RLP structure between Berlin and London fork starting at berlinBlock ending at londonBlock
type berlinRLP struct {
InputAlloc WorldState
OutputAlloc WorldState
Env *legacyEnv
Message *berlinMessage
Result *Result
}

func (r berlinRLP) toLondon() *RLP {
return &RLP{
InputSubstate: r.InputAlloc,
OutputSubstate: r.OutputAlloc,
Env: r.Env.toLondon(),
Message: r.Message.toLondon(),
Result: r.Result,
}

}

type berlinMessage struct {
Nonce uint64
CheckNonce bool
GasPrice *big.Int
Gas uint64

From types.Address
To *types.Address `rlp:"nil"` // nil means contract creation
Value *big.Int
Data []byte

InitCodeHash *types.Hash `rlp:"nil"` // NOT nil for contract creation

AccessList types.AccessList // missing in substate DB from Geth v1.9.x
}

func (m berlinMessage) toLondon() *Message {
return &Message{
Nonce: m.Nonce,
CheckNonce: m.CheckNonce,
GasPrice: m.GasPrice,
Gas: m.Gas,
From: m.From,
To: m.To,
Value: new(big.Int).Set(m.Value),
Data: m.Data,
InitCodeHash: m.InitCodeHash,
AccessList: m.AccessList,

// Same behavior as AccessListTx.gasFeeCap() and AccessListTx.gasTipCap()
GasFeeCap: m.GasPrice,
GasTipCap: m.GasPrice,
londonEnv: londonEnv{
Coinbase: e.Coinbase,
Difficulty: e.Difficulty,
GasLimit: e.GasLimit,
Number: e.Number,
Timestamp: e.Timestamp,
BlockHashes: e.BlockHashes,
},
}
}
145 changes: 145 additions & 0 deletions rlp/london.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package rlp

import (
"math/big"

"github.com/Fantom-foundation/Substate/substate"
"github.com/Fantom-foundation/Substate/types"
)

const londonBlock = 37_534_833

// IsLondonFork returns true if block is part of the london fork block range
func IsLondonFork(block uint64) bool {
return block >= londonBlock
cabrador marked this conversation as resolved.
Show resolved Hide resolved
}

func NewLondonRLP(substate *substate.Substate) *londonRLP {
return &londonRLP{
InputSubstate: NewWorldState(substate.InputSubstate),
OutputSubstate: NewWorldState(substate.OutputSubstate),
Env: newLondonEnv(substate.Env),
Message: newLondonMessage(substate.Message),
Result: NewResult(substate.Result),
}
}

// londonRLP represents RLP structure after londonBlock and before cancun fork.
type londonRLP struct {
InputSubstate WorldState
OutputSubstate WorldState
Env londonEnv
Message londonMessage
Result *Result
}

// toRLP transforms r into RLP format which is compatible with the currently used Geth fork.
func (r londonRLP) toRLP() *RLP {
return &RLP{
InputSubstate: r.InputSubstate,
OutputSubstate: r.OutputSubstate,
Env: r.Env.toEnv(),
Message: r.Message.toMessage(),
Result: r.Result,
}
}

func newLondonEnv(env *substate.Env) londonEnv {
e := londonEnv{
Coinbase: env.Coinbase,
Difficulty: env.Difficulty,
GasLimit: env.GasLimit,
Number: env.Number,
Timestamp: env.Timestamp,
}

var sortedNum64 []uint64
for num64 := range env.BlockHashes {
sortedNum64 = append(sortedNum64, num64)
}

for _, num64 := range sortedNum64 {
num := types.BigToHash(new(big.Int).SetUint64(num64))
blockHash := env.BlockHashes[num64]
pair := [2]types.Hash{num, blockHash}
e.BlockHashes = append(e.BlockHashes, pair)
}

e.BaseFee = nil
if env.BaseFee != nil {
baseFeeHash := types.BigToHash(env.BaseFee)
e.BaseFee = &baseFeeHash
}

return e
}

type londonEnv struct {
Coinbase types.Address
Difficulty *big.Int
GasLimit uint64
Number uint64
Timestamp uint64
BlockHashes [][2]types.Hash

BaseFee *types.Hash `rlp:"nil"` // missing in substate DB from Geth <= v1.10.3
}

// toEnv transforms m into RLP format which is compatible with the currently used Geth fork.
func (e londonEnv) toEnv() *Env {
return &Env{
londonEnv: e,
}
}

func newLondonMessage(message *substate.Message) londonMessage {
m := londonMessage{
Nonce: message.Nonce,
CheckNonce: message.CheckNonce,
GasPrice: message.GasPrice,
Gas: message.Gas,
From: message.From,
To: message.To,
Value: new(big.Int).Set(message.Value),
Data: message.Data,
InitCodeHash: nil,
AccessList: message.AccessList,
GasFeeCap: message.GasFeeCap,
GasTipCap: message.GasTipCap,
}

if m.To == nil {
// put contract creation init code into codeDB
dataHash := message.DataHash()
m.InitCodeHash = &dataHash
m.Data = nil
}

return m
}

type londonMessage struct {
Nonce uint64
CheckNonce bool
GasPrice *big.Int
Gas uint64

From types.Address
To *types.Address `rlp:"nil"` // nil means contract creation
Value *big.Int
Data []byte

InitCodeHash *types.Hash `rlp:"nil"` // NOT nil for contract creation

AccessList types.AccessList // missing in substate DB from Geth v1.9.x

GasFeeCap *big.Int // missing in substate DB from Geth <= v1.10.3
GasTipCap *big.Int // missing in substate DB from Geth <= v1.10.3
}

// toMessage transforms m into RLP format which is compatible with the currently used Geth fork.
func (m londonMessage) toMessage() *Message {
return &Message{
londonMessage: m,
}
}
Loading
Loading