Skip to content

Commit

Permalink
fix tests and incorporate feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
sudeepdino008 committed Jul 9, 2024
1 parent b668b57 commit 7f6416e
Show file tree
Hide file tree
Showing 24 changed files with 8,782 additions and 86 deletions.
10 changes: 7 additions & 3 deletions core/state/intra_block_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -803,10 +803,9 @@ func (sdb *IntraBlockState) clearJournalAndRefund() {
// Cancun fork:
// - Reset transient storage (EIP-1153)
func (sdb *IntraBlockState) Prepare(rules *chain.Rules, sender, coinbase libcommon.Address, dst *libcommon.Address,
precompiles []libcommon.Address, list types2.AccessList,
) {
precompiles []libcommon.Address, list types2.AccessList, authorities []libcommon.Address) {
if sdb.trace {
fmt.Printf("ibs.Prepare %x, %x, %x, %x, %v, %v\n", sender, coinbase, dst, precompiles, list, rules)
fmt.Printf("ibs.Prepare %x, %x, %x, %x, %v, %v, %v\n", sender, coinbase, dst, precompiles, list, rules, authorities)
}
if rules.IsBerlin {
// Clear out any leftover from previous executions
Expand All @@ -833,6 +832,11 @@ func (sdb *IntraBlockState) Prepare(rules *chain.Rules, sender, coinbase libcomm
al.AddAddress(coinbase)
}
}
if rules.IsPrague {
for _, addr := range authorities {
sdb.accessList.AddAddress(addr)
}
}
// Reset transient storage at the beginning of transaction execution
sdb.transientStorage = newTransientStorage()
}
Expand Down
47 changes: 29 additions & 18 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import (
"fmt"

"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon-lib/log/v3"

"github.com/ledgerwatch/erigon-lib/common"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg"
types2 "github.com/ledgerwatch/erigon-lib/types"
Expand Down Expand Up @@ -350,50 +352,59 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtype

// set code tx
auths := msg.Authorizations()
verifiedAuthorities := make([]common.Address, 0)
if len(auths) > 0 {
var b [33]byte
data := bytes.NewBuffer(nil)
for _, auth := range auths {

// 2. chainId check
if auth.ChainID != 0 && auth.ChainID != st.evm.ChainRules().ChainID.Uint64() {
continue
//TODO: should these errors be recorded somewhere? perhaps tracer or logs
//return nil, fmt.Errorf("invalid chainID %d", auth.ChainID)
}
for i, auth := range auths {
data.Reset()

// 1. authority recover
authorityPtr, err := auth.RecoverSigner(data, b[:])
if err != nil {
log.Debug("authority recover failed, skipping", "err", err, "auth index", i)
continue
//return nil, fmt.Errorf("authority recover failed")
}
authority := *authorityPtr

// 2. chainId check
if auth.ChainID != nil && auth.ChainID.Uint64() != 0 && auth.ChainID.Uint64() != st.evm.ChainRules().ChainID.Uint64() {
log.Debug("invalid chainID, skipping", "chainId", auth.ChainID, "auth index", i)
continue
}

// 3. authority code should be empty
if codeHash := st.state.GetCodeHash(authority); codeHash != emptyCodeHash && codeHash != (libcommon.Hash{}) {
log.Debug("authority code is not empty, skipping", "auth index", i)
continue
//return nil, fmt.Errorf("authority code is not empty")
}

// 4. nonce check
if auth.Nonce != nil && st.state.GetNonce(authority) != auth.Nonce.Uint64() {
if len(auth.Nonce) > 0 && st.state.GetNonce(authority) != auth.Nonce[0] {
log.Debug("invalid nonce, skipping", "auth index", i)
continue
//return nil, fmt.Errorf("invalid nonce")
}

// 5. set code of authority to code associated with address
st.state.SetCode(authority, st.state.GetCode(auth.Address))
defer st.state.SetCode(authority, nil) // reset code after execution

// 6. add authority account to accesses_addresses
if !accessTuples.HasAddr(authority) {
accessTuples = append(accessTuples, types2.AccessTuple{Address: authority, StorageKeys: nil})
verifiedAuthorities = append(verifiedAuthorities, authority)
// authority is added to acceessed_address in prepare step
}
}

if len(verifiedAuthorities) > 0 {
oldPostApplyMessage := st.evm.Context.PostApplyMessage
st.evm.Context.PostApplyMessage = func(ibs evmtypes.IntraBlockState, sender common.Address, coinbase common.Address, result *evmtypes.ExecutionResult) {
for _, authority := range verifiedAuthorities {
ibs.SetCode(authority, nil)
}

data.Reset()
if oldPostApplyMessage != nil {
oldPostApplyMessage(ibs, sender, coinbase, result)
}
}

}

// Check clauses 4-5, subtract intrinsic gas if everything is correct
Expand Down Expand Up @@ -422,7 +433,7 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtype
// Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin)
// - reset transient storage(eip 1153)
st.state.Prepare(rules, msg.From(), coinbase, msg.To(), vm.ActivePrecompiles(rules), accessTuples)
st.state.Prepare(rules, msg.From(), coinbase, msg.To(), vm.ActivePrecompiles(rules), accessTuples, verifiedAuthorities)

var (
ret []byte
Expand Down
2 changes: 1 addition & 1 deletion core/types/access_list_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func encodeAccessList(al types2.AccessList, w io.Writer, b []byte) error {
if err := EncodeStructSizePrefix(tupleLen, w, b); err != nil {
return err
}
if err := rlp.EncodeAddress(&tuple.Address, w, b); err != nil {
if err := rlp.EncodeOptionalAddress(&tuple.Address, w, b); err != nil {
return err
}
if err := EncodeStructSizePrefix(storageLen, w, b); err != nil {
Expand Down
136 changes: 90 additions & 46 deletions core/types/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import (
)

type Authorization struct {
ChainID uint64 `json:"chainId"`
ChainID *uint256.Int `json:"chainId"`
Address libcommon.Address `json:"address"`
Nonce *uint256.Int `json:"nonce,omitempty"`
Nonce []uint64 `json:"nonce"`
V uint256.Int `json:"v"`
R uint256.Int `json:"r"`
S uint256.Int `json:"s"`
Expand All @@ -35,60 +35,80 @@ func (ath *Authorization) copy() *Authorization {
}

if ath.Nonce != nil {
cpy.Nonce = ath.Nonce.Clone()
cpy.Nonce = ath.Nonce
}

return cpy
}

func (ath *Authorization) RecoverSigner(data *bytes.Buffer, b []byte) (*libcommon.Address, error) {
authLen := rlp2.U64Len(ath.ChainID)
authLen := 1 + rlp.Uint256LenExcludingHead(ath.ChainID)
authLen += (1 + length.Addr)
authLen += 1 // nonce
if ath.Nonce != nil {
authLen += rlp.Uint256LenExcludingHead(ath.Nonce)
var nonceSize int
if len(ath.Nonce) == 0 {
// if empty array, treat as encoding nil
authLen += 1
} else {
nonceSize = noncesSize(ath.Nonce)
authLen += rlp2.ListPrefixLen(nonceSize) + nonceSize
}

if err := rlp.EncodeStringSizePrefix(authLen, data, b[:]); err != nil {
if err := EncodeStructSizePrefix(authLen, data, b); err != nil {
return nil, err
}

// chainId, address, nonce
if err := rlp.EncodeInt(ath.ChainID, data, b[:]); err != nil {
if err := ath.ChainID.EncodeRLP(data); err != nil {
return nil, err
}

if err := rlp.EncodeAddress(&ath.Address, data, b[:]); err != nil {
if err := rlp.EncodeOptionalAddress(&ath.Address, data, b); err != nil {
return nil, err
}

if err := ath.Nonce.EncodeRLP(data); err != nil {
return nil, err
if len(ath.Nonce) == 0 {
if err := rlp.EncodeString(nil, data, b); err != nil {
return nil, err
}
} else {
if err := EncodeStructSizePrefix(nonceSize, data, b); err != nil {
return nil, err
}

for _, nonce := range ath.Nonce {
if err := rlp.EncodeInt(nonce, data, b); err != nil {
return nil, err
}
}
}

hashData := []byte{params.SetCodeMagicPrefix} //data.Bytes()
hashData := []byte{params.SetCodeMagicPrefix}
hashData = append(hashData, data.Bytes()...)
hash := crypto.Keccak256Hash(hashData)

var sig [65]byte
var arr [32]byte

ath.R.WriteToArray32(&arr)
copy(sig[:32], arr[:])

ath.S.WriteToArray32(&arr)
copy(sig[32:], arr[:])
r := ath.R.Bytes()
s := ath.S.Bytes()
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)

if ath.V.Eq(u256.Num0) || ath.V.Eq(u256.Num1) {
sig[64] = byte(ath.V.Uint64())
} else {
return nil, fmt.Errorf("invalid V value: %d", ath.V.Uint64())
}

if !crypto.ValidateSignatureValues(sig[64], &ath.R, &ath.S, false) {
return nil, fmt.Errorf("invalid signature")
}

pubkey, err := crypto.Ecrecover(hash.Bytes(), sig[:])
if err != nil {
return nil, err
}
if len(pubkey) == 0 || pubkey[0] != 4 {
return nil, errors.New("invalid public key")
}

var authority libcommon.Address
copy(authority[:], crypto.Keccak256(pubkey[1:])[12:])
Expand All @@ -99,16 +119,14 @@ func authorizationsSize(authorizations []Authorization) int {
totalSize := 0
// ChainID uint64
// Address common.Address
// Nonce *uint256.Int
// Nonce []uint256.Int
// V, R, S uint256.Int // signature values
for _, auth := range authorizations {
size := rlp2.U64Len(auth.ChainID) // chainId
size += 1 + length.Addr // address
size := 1 + rlp.Uint256LenExcludingHead(auth.ChainID)
size += 1 + length.Addr // address

size++
if auth.Nonce != nil {
size += rlp.Uint256LenExcludingHead(auth.Nonce)
}
noncesSize := noncesSize(auth.Nonce)
size += rlp2.ListPrefixLen(noncesSize) + noncesSize

size++
size += rlp.Uint256LenExcludingHead(&auth.V)
Expand All @@ -133,9 +151,10 @@ func decodeAuthorizations(auths *[]Authorization, s *rlp.Stream) error {
i := 0
for _, err = s.List(); err == nil; _, err = s.List() {
auth := Authorization{}
if auth.ChainID, err = s.Uint(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return err
}
auth.ChainID = new(uint256.Int).SetBytes(b)

if b, err = s.Bytes(); err != nil {
return err
Expand All @@ -145,13 +164,9 @@ func decodeAuthorizations(auths *[]Authorization, s *rlp.Stream) error {
return fmt.Errorf("wrong size for Address: %d", len(b))
}
auth.Address = libcommon.BytesToAddress(b)

if b, err = s.Uint256Bytes(); err != nil {
if auth.Nonce, err = decodeNonces(s); err != nil {
return err
}
if len(b) > 0 {
auth.Nonce = new(uint256.Int).SetBytes(b)
}

if b, err = s.Uint256Bytes(); err != nil {
return err
Expand Down Expand Up @@ -185,19 +200,12 @@ func decodeAuthorizations(auths *[]Authorization, s *rlp.Stream) error {
}

func encodeAuthorizations(authorizations []Authorization, w io.Writer, b []byte) error {
// Authorization:
// ChainID uint64
// Address common.Address
// Nonce *uint256.Int
// V, R, S uint256.Int
for _, auth := range authorizations {
// 0. encode length of individual Authorization
authLen := rlp2.U64Len(auth.ChainID)
authLen := 1 + rlp.Uint256LenExcludingHead(auth.ChainID)
authLen += (1 + length.Addr)
authLen += 1 // nonce prefix
if auth.Nonce != nil {
authLen += rlp.Uint256LenExcludingHead(auth.Nonce)
}
noncesSize := noncesSize(auth.Nonce)
authLen += rlp2.ListPrefixLen(noncesSize) + noncesSize

authLen += (1 + rlp.Uint256LenExcludingHead(&auth.V)) + (1 + rlp.Uint256LenExcludingHead(&auth.R)) + (1 + rlp.Uint256LenExcludingHead(&auth.S))

Expand All @@ -206,17 +214,24 @@ func encodeAuthorizations(authorizations []Authorization, w io.Writer, b []byte)
}

// 1. encode ChainId
if err := rlp.EncodeInt(auth.ChainID, w, b); err != nil {
if err := auth.ChainID.EncodeRLP(w); err != nil {
return err
}
// 2. encode Address
if err := rlp.EncodeAddress(&auth.Address, w, b); err != nil {
if err := rlp.EncodeOptionalAddress(&auth.Address, w, b); err != nil {
return err
}
// 3. encode Nonce
if err := auth.Nonce.EncodeRLP(w); err != nil {
if err := EncodeStructSizePrefix(noncesSize, w, b); err != nil {
return err
}

for _, nonce := range auth.Nonce {
if err := rlp.EncodeInt(nonce, w, b); err != nil {
return err
}
}

// 4. encode V, R, S
if err := auth.V.EncodeRLP(w); err != nil {
return err
Expand All @@ -231,3 +246,32 @@ func encodeAuthorizations(authorizations []Authorization, w io.Writer, b []byte)

return nil
}

func noncesSize(nonce []uint64) int {
totalSize := 0
for _, n := range nonce {
totalSize += rlp.IntLenExcludingHead(n) + 1
}
return totalSize
}

func decodeNonces(s *rlp.Stream) ([]uint64, error) {
_, err := s.List()
if err != nil {
return nil, fmt.Errorf("open nonce: %w", err)
}
nonces := make([]uint64, 0)
var b uint64
i := 0
for b, err = s.Uint(); err == nil; b, err = s.Uint() {
nonces = append(nonces, b)
i++
}
if !errors.Is(err, rlp.EOL) {
return nil, fmt.Errorf("open nonce: %d %w", i, err)
}
if err = s.ListEnd(); err != nil {
return nil, fmt.Errorf("close nonce: %w", err)
}
return nonces, nil
}
2 changes: 1 addition & 1 deletion core/types/dynamic_fee_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func (tx *DynamicFeeTransaction) encodePayload(w io.Writer, b []byte, payloadSiz
return err
}
// encode To
if err := rlp.EncodeAddress(tx.To, w, b); err != nil {
if err := rlp.EncodeOptionalAddress(tx.To, w, b); err != nil {
return err
}
// encode Value
Expand Down
Loading

0 comments on commit 7f6416e

Please sign in to comment.