Merge remote-tracking branch 'laconic/receipt-encoding-updates' into laconic-merge
This commit is contained in:
commit
f5884db6fb
1
go.mod
1
go.mod
@ -16,6 +16,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -17,6 +17,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -1,21 +1,12 @@
|
|||||||
package bls12381
|
package bls12381
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fromHex(s string) []byte {
|
|
||||||
b, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *G1) one() *PointG1 {
|
func (g *G1) one() *PointG1 {
|
||||||
one, _ := g.fromBytesUnchecked(
|
one, _ := g.fromBytesUnchecked(
|
||||||
fromHex("" +
|
fromHex("" +
|
||||||
|
@ -17,15 +17,34 @@
|
|||||||
package bls12381
|
package bls12381
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
func bigFromHex(hex string) *big.Int {
|
// fromHex returns the bytes represented by the hexadecimal string s.
|
||||||
b, _ := hex.DecodeString(strings.TrimPrefix(hex, "0x"))
|
// s may be prefixed with "0x".
|
||||||
return new(big.Int).SetBytes(b)
|
func fromHex(s string) []byte {
|
||||||
|
if has0xPrefix(s) {
|
||||||
|
s = s[2:]
|
||||||
|
}
|
||||||
|
if len(s)%2 == 1 {
|
||||||
|
s = "0" + s
|
||||||
|
}
|
||||||
|
h, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// has0xPrefix validates str begins with '0x' or '0X'.
|
||||||
|
func has0xPrefix(str string) bool {
|
||||||
|
return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')
|
||||||
|
}
|
||||||
|
|
||||||
|
func bigFromHex(s string) *big.Int {
|
||||||
|
return new(big.Int).SetBytes(fromHex(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeFieldElement expects 64 byte input with zero top 16 bytes,
|
// decodeFieldElement expects 64 byte input with zero top 16 bytes,
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
package hasher
|
package hasher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ func returnToPool(st *StackTrie) {
|
|||||||
// in order. Once it determines that a subtree will no longer be inserted
|
// in order. Once it determines that a subtree will no longer be inserted
|
||||||
// into, it will hash it and free up the memory it uses.
|
// into, it will hash it and free up the memory it uses.
|
||||||
type StackTrie struct {
|
type StackTrie struct {
|
||||||
owner core.Hash // the owner of the trie
|
owner core.Hash // the owner of the trie
|
||||||
nodeType uint8 // node type (as in branch, ext, leaf)
|
nodeType uint8 // node type (as in branch, ext, leaf)
|
||||||
val []byte // value contained by this node if it's a leaf
|
val []byte // value contained by this node if it's a leaf
|
||||||
key []byte // key chunk covered by this (leaf|ext) node
|
key []byte // key chunk covered by this (leaf|ext) node
|
||||||
@ -214,7 +214,7 @@ func (st *StackTrie) TryUpdate(key, value []byte) error {
|
|||||||
|
|
||||||
func (st *StackTrie) Update(key, value []byte) {
|
func (st *StackTrie) Update(key, value []byte) {
|
||||||
if err := st.TryUpdate(key, value); err != nil {
|
if err := st.TryUpdate(key, value); err != nil {
|
||||||
fmt.Errorf("Unhandled trie error in StackTrie.Update", "err", err)
|
fmt.Println("Unhandled trie error in StackTrie.Update:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,13 +34,43 @@ var (
|
|||||||
CalaverasGenesisHash = core.HexToHash("0xeb9233d066c275efcdfed8037f4fc082770176aefdbcb7691c71da412a5670f2")
|
CalaverasGenesisHash = core.HexToHash("0xeb9233d066c275efcdfed8037f4fc082770176aefdbcb7691c71da412a5670f2")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// TestChainConfig contains every protocol change (EIPs) introduced
|
||||||
|
// and accepted by the Ethereum core developers for testing proposes.
|
||||||
|
TestChainConfig = &ChainConfig{
|
||||||
|
ChainID: big.NewInt(1),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
DAOForkBlock: nil,
|
||||||
|
DAOForkSupport: false,
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
ArrowGlacierBlock: big.NewInt(0),
|
||||||
|
GrayGlacierBlock: big.NewInt(0),
|
||||||
|
MergeNetsplitBlock: nil,
|
||||||
|
ShanghaiTime: nil,
|
||||||
|
CancunTime: nil,
|
||||||
|
PragueTime: nil,
|
||||||
|
TerminalTotalDifficulty: nil,
|
||||||
|
TerminalTotalDifficultyPassed: false,
|
||||||
|
Ethash: new(EthashConfig),
|
||||||
|
Clique: nil,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
|
// TrustedCheckpoint represents a set of post-processed trie roots (CHT and
|
||||||
// BloomTrie) associated with the appropriate section index and head hash. It is
|
// BloomTrie) associated with the appropriate section index and head hash. It is
|
||||||
// used to start light syncing from this checkpoint and avoid downloading the
|
// used to start light syncing from this checkpoint and avoid downloading the
|
||||||
// entire header chain while still being able to securely access old headers/logs.
|
// entire header chain while still being able to securely access old headers/logs.
|
||||||
type TrustedCheckpoint struct {
|
type TrustedCheckpoint struct {
|
||||||
SectionIndex uint64 `json:"sectionIndex"`
|
SectionIndex uint64 `json:"sectionIndex"`
|
||||||
SectionHead core.Hash `json:"sectionHead"`
|
SectionHead core.Hash `json:"sectionHead"`
|
||||||
CHTRoot core.Hash `json:"chtRoot"`
|
CHTRoot core.Hash `json:"chtRoot"`
|
||||||
BloomRoot core.Hash `json:"bloomRoot"`
|
BloomRoot core.Hash `json:"bloomRoot"`
|
||||||
@ -80,7 +110,7 @@ func (c *TrustedCheckpoint) Empty() bool {
|
|||||||
type CheckpointOracleConfig struct {
|
type CheckpointOracleConfig struct {
|
||||||
Address core.Address `json:"address"`
|
Address core.Address `json:"address"`
|
||||||
Signers []core.Address `json:"signers"`
|
Signers []core.Address `json:"signers"`
|
||||||
Threshold uint64 `json:"threshold"`
|
Threshold uint64 `json:"threshold"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChainConfig is the core config which determines the blockchain settings.
|
// ChainConfig is the core config which determines the blockchain settings.
|
||||||
@ -97,7 +127,7 @@ type ChainConfig struct {
|
|||||||
DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
|
DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
|
||||||
|
|
||||||
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
|
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
|
||||||
EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
|
EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
|
||||||
EIP150Hash core.Hash `json:"eip150Hash,omitempty"` // EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
EIP150Hash core.Hash `json:"eip150Hash,omitempty"` // EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
||||||
|
|
||||||
EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
|
EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
|
||||||
@ -111,9 +141,9 @@ type ChainConfig struct {
|
|||||||
BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin)
|
BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin)
|
||||||
LondonBlock *big.Int `json:"londonBlock,omitempty"` // London switch block (nil = no fork, 0 = already on london)
|
LondonBlock *big.Int `json:"londonBlock,omitempty"` // London switch block (nil = no fork, 0 = already on london)
|
||||||
|
|
||||||
ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||||
GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` // Eip-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` // Eip-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||||
MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter
|
MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter
|
||||||
|
|
||||||
// Fork scheduling was switched from blocks to timestamps here
|
// Fork scheduling was switched from blocks to timestamps here
|
||||||
|
|
||||||
|
@ -22,6 +22,37 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
|
||||||
|
// and accepted by the Ethereum core developers into the Ethash consensus.
|
||||||
|
AllEthashProtocolChanges = &ChainConfig{
|
||||||
|
ChainID: big.NewInt(1337),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
DAOForkBlock: nil,
|
||||||
|
DAOForkSupport: false,
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
ArrowGlacierBlock: big.NewInt(0),
|
||||||
|
GrayGlacierBlock: big.NewInt(0),
|
||||||
|
MergeNetsplitBlock: nil,
|
||||||
|
ShanghaiTime: nil,
|
||||||
|
CancunTime: nil,
|
||||||
|
PragueTime: nil,
|
||||||
|
TerminalTotalDifficulty: nil,
|
||||||
|
TerminalTotalDifficultyPassed: false,
|
||||||
|
Ethash: new(EthashConfig),
|
||||||
|
Clique: nil,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func TestCheckCompatible(t *testing.T) {
|
func TestCheckCompatible(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
stored, new *ChainConfig
|
stored, new *ChainConfig
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020 The go-ethereum Authors
|
// Copyright 2021 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
@ -22,7 +22,7 @@ import (
|
|||||||
"github.com/openrelayxyz/plugeth-utils/core"
|
"github.com/openrelayxyz/plugeth-utils/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate gencodec -type AccessTuple -out gen_access_tuple.go
|
//go:generate go run github.com/fjl/gencodec -type AccessTuple -out gen_access_tuple.go
|
||||||
|
|
||||||
// AccessList is an EIP-2930 access list.
|
// AccessList is an EIP-2930 access list.
|
||||||
type AccessList []AccessTuple
|
type AccessList []AccessTuple
|
||||||
@ -44,22 +44,22 @@ func (al AccessList) StorageKeys() int {
|
|||||||
|
|
||||||
// AccessListTx is the data of EIP-2930 access list transactions.
|
// AccessListTx is the data of EIP-2930 access list transactions.
|
||||||
type AccessListTx struct {
|
type AccessListTx struct {
|
||||||
ChainID *big.Int // destination chain ID
|
ChainID *big.Int // destination chain ID
|
||||||
Nonce uint64 // nonce of sender account
|
Nonce uint64 // nonce of sender account
|
||||||
GasPrice *big.Int // wei per gas
|
GasPrice *big.Int // wei per gas
|
||||||
Gas uint64 // gas limit
|
Gas uint64 // gas limit
|
||||||
To *core.Address `rlp:"nil"` // nil means contract creation
|
To *core.Address `rlp:"nil"` // nil means contract creation
|
||||||
Value *big.Int // wei amount
|
Value *big.Int // wei amount
|
||||||
Data []byte // contract invocation input data
|
Data []byte // contract invocation input data
|
||||||
AccessList AccessList // EIP-2930 access list
|
AccessList AccessList // EIP-2930 access list
|
||||||
V, R, S *big.Int // signature values
|
V, R, S *big.Int // signature values
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy creates a deep copy of the transaction data and initializes all fields.
|
// copy creates a deep copy of the transaction data and initializes all fields.
|
||||||
func (tx *AccessListTx) copy() TxData {
|
func (tx *AccessListTx) copy() TxData {
|
||||||
cpy := &AccessListTx{
|
cpy := &AccessListTx{
|
||||||
Nonce: tx.Nonce,
|
Nonce: tx.Nonce,
|
||||||
To: tx.To, // TODO: copy pointed-to address
|
To: copyAddressPtr(tx.To),
|
||||||
Data: core.CopyBytes(tx.Data),
|
Data: core.CopyBytes(tx.Data),
|
||||||
Gas: tx.Gas,
|
Gas: tx.Gas,
|
||||||
// These are copied below.
|
// These are copied below.
|
||||||
@ -96,7 +96,6 @@ func (tx *AccessListTx) copy() TxData {
|
|||||||
// accessors for innerTx.
|
// accessors for innerTx.
|
||||||
func (tx *AccessListTx) txType() byte { return AccessListTxType }
|
func (tx *AccessListTx) txType() byte { return AccessListTxType }
|
||||||
func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID }
|
func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID }
|
||||||
func (tx *AccessListTx) protected() bool { return true }
|
|
||||||
func (tx *AccessListTx) accessList() AccessList { return tx.AccessList }
|
func (tx *AccessListTx) accessList() AccessList { return tx.AccessList }
|
||||||
func (tx *AccessListTx) data() []byte { return tx.Data }
|
func (tx *AccessListTx) data() []byte { return tx.Data }
|
||||||
func (tx *AccessListTx) gas() uint64 { return tx.Gas }
|
func (tx *AccessListTx) gas() uint64 { return tx.Gas }
|
||||||
@ -105,7 +104,11 @@ func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice }
|
|||||||
func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice }
|
func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice }
|
||||||
func (tx *AccessListTx) value() *big.Int { return tx.Value }
|
func (tx *AccessListTx) value() *big.Int { return tx.Value }
|
||||||
func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
|
func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
|
||||||
func (tx *AccessListTx) to() *core.Address { return tx.To }
|
func (tx *AccessListTx) to() *core.Address { return tx.To }
|
||||||
|
|
||||||
|
func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||||
|
return dst.Set(tx.GasPrice)
|
||||||
|
}
|
||||||
|
|
||||||
func (tx *AccessListTx) rawSignatureValues() (v, r, s *big.Int) {
|
func (tx *AccessListTx) rawSignatureValues() (v, r, s *big.Int) {
|
||||||
return tx.V, tx.R, tx.S
|
return tx.V, tx.R, tx.S
|
||||||
|
@ -25,8 +25,8 @@ import (
|
|||||||
type DynamicFeeTx struct {
|
type DynamicFeeTx struct {
|
||||||
ChainID *big.Int
|
ChainID *big.Int
|
||||||
Nonce uint64
|
Nonce uint64
|
||||||
GasTipCap *big.Int
|
GasTipCap *big.Int // a.k.a. maxPriorityFeePerGas
|
||||||
GasFeeCap *big.Int
|
GasFeeCap *big.Int // a.k.a. maxFeePerGas
|
||||||
Gas uint64
|
Gas uint64
|
||||||
To *core.Address `rlp:"nil"` // nil means contract creation
|
To *core.Address `rlp:"nil"` // nil means contract creation
|
||||||
Value *big.Int
|
Value *big.Int
|
||||||
@ -43,7 +43,7 @@ type DynamicFeeTx struct {
|
|||||||
func (tx *DynamicFeeTx) copy() TxData {
|
func (tx *DynamicFeeTx) copy() TxData {
|
||||||
cpy := &DynamicFeeTx{
|
cpy := &DynamicFeeTx{
|
||||||
Nonce: tx.Nonce,
|
Nonce: tx.Nonce,
|
||||||
To: tx.To, // TODO: copy pointed-to address
|
To: copyAddressPtr(tx.To),
|
||||||
Data: core.CopyBytes(tx.Data),
|
Data: core.CopyBytes(tx.Data),
|
||||||
Gas: tx.Gas,
|
Gas: tx.Gas,
|
||||||
// These are copied below.
|
// These are copied below.
|
||||||
@ -84,7 +84,6 @@ func (tx *DynamicFeeTx) copy() TxData {
|
|||||||
// accessors for innerTx.
|
// accessors for innerTx.
|
||||||
func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType }
|
func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType }
|
||||||
func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID }
|
func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID }
|
||||||
func (tx *DynamicFeeTx) protected() bool { return true }
|
|
||||||
func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList }
|
func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList }
|
||||||
func (tx *DynamicFeeTx) data() []byte { return tx.Data }
|
func (tx *DynamicFeeTx) data() []byte { return tx.Data }
|
||||||
func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas }
|
func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas }
|
||||||
@ -93,7 +92,18 @@ func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap }
|
|||||||
func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap }
|
func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap }
|
||||||
func (tx *DynamicFeeTx) value() *big.Int { return tx.Value }
|
func (tx *DynamicFeeTx) value() *big.Int { return tx.Value }
|
||||||
func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce }
|
func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce }
|
||||||
func (tx *DynamicFeeTx) to() *core.Address { return tx.To }
|
func (tx *DynamicFeeTx) to() *core.Address { return tx.To }
|
||||||
|
|
||||||
|
func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||||
|
if baseFee == nil {
|
||||||
|
return dst.Set(tx.GasFeeCap)
|
||||||
|
}
|
||||||
|
tip := dst.Sub(tx.GasFeeCap, baseFee)
|
||||||
|
if tip.Cmp(tx.GasTipCap) > 0 {
|
||||||
|
tip.Set(tx.GasTipCap)
|
||||||
|
}
|
||||||
|
return tip.Add(tip, baseFee)
|
||||||
|
}
|
||||||
|
|
||||||
func (tx *DynamicFeeTx) rawSignatureValues() (v, r, s *big.Int) {
|
func (tx *DynamicFeeTx) rawSignatureValues() (v, r, s *big.Int) {
|
||||||
return tx.V, tx.R, tx.S
|
return tx.V, tx.R, tx.S
|
||||||
|
@ -22,10 +22,11 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
|
|||||||
CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
|
CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
|
||||||
Bloom Bloom `json:"logsBloom" gencodec:"required"`
|
Bloom Bloom `json:"logsBloom" gencodec:"required"`
|
||||||
Logs []*Log `json:"logs" gencodec:"required"`
|
Logs []*Log `json:"logs" gencodec:"required"`
|
||||||
TxHash core.Hash `json:"transactionHash" gencodec:"required"`
|
TxHash core.Hash `json:"transactionHash" gencodec:"required"`
|
||||||
ContractAddress core.Address `json:"contractAddress"`
|
ContractAddress core.Address `json:"contractAddress"`
|
||||||
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||||
BlockHash core.Hash `json:"blockHash,omitempty"`
|
EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice"`
|
||||||
|
BlockHash core.Hash `json:"blockHash,omitempty"`
|
||||||
BlockNumber *hexutil.Big `json:"blockNumber,omitempty"`
|
BlockNumber *hexutil.Big `json:"blockNumber,omitempty"`
|
||||||
TransactionIndex hexutil.Uint `json:"transactionIndex"`
|
TransactionIndex hexutil.Uint `json:"transactionIndex"`
|
||||||
}
|
}
|
||||||
@ -39,6 +40,7 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
|
|||||||
enc.TxHash = r.TxHash
|
enc.TxHash = r.TxHash
|
||||||
enc.ContractAddress = r.ContractAddress
|
enc.ContractAddress = r.ContractAddress
|
||||||
enc.GasUsed = hexutil.Uint64(r.GasUsed)
|
enc.GasUsed = hexutil.Uint64(r.GasUsed)
|
||||||
|
enc.EffectiveGasPrice = (*hexutil.Big)(r.EffectiveGasPrice)
|
||||||
enc.BlockHash = r.BlockHash
|
enc.BlockHash = r.BlockHash
|
||||||
enc.BlockNumber = (*hexutil.Big)(r.BlockNumber)
|
enc.BlockNumber = (*hexutil.Big)(r.BlockNumber)
|
||||||
enc.TransactionIndex = hexutil.Uint(r.TransactionIndex)
|
enc.TransactionIndex = hexutil.Uint(r.TransactionIndex)
|
||||||
@ -54,10 +56,11 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
|
|||||||
CumulativeGasUsed *hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
|
CumulativeGasUsed *hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
|
||||||
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
|
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
|
||||||
Logs []*Log `json:"logs" gencodec:"required"`
|
Logs []*Log `json:"logs" gencodec:"required"`
|
||||||
TxHash *core.Hash `json:"transactionHash" gencodec:"required"`
|
TxHash *core.Hash `json:"transactionHash" gencodec:"required"`
|
||||||
ContractAddress *core.Address `json:"contractAddress"`
|
ContractAddress *core.Address `json:"contractAddress"`
|
||||||
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||||
BlockHash *core.Hash `json:"blockHash,omitempty"`
|
EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice"`
|
||||||
|
BlockHash *core.Hash `json:"blockHash,omitempty"`
|
||||||
BlockNumber *hexutil.Big `json:"blockNumber,omitempty"`
|
BlockNumber *hexutil.Big `json:"blockNumber,omitempty"`
|
||||||
TransactionIndex *hexutil.Uint `json:"transactionIndex"`
|
TransactionIndex *hexutil.Uint `json:"transactionIndex"`
|
||||||
}
|
}
|
||||||
@ -97,6 +100,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
|
|||||||
return errors.New("missing required field 'gasUsed' for Receipt")
|
return errors.New("missing required field 'gasUsed' for Receipt")
|
||||||
}
|
}
|
||||||
r.GasUsed = uint64(*dec.GasUsed)
|
r.GasUsed = uint64(*dec.GasUsed)
|
||||||
|
if dec.EffectiveGasPrice != nil {
|
||||||
|
r.EffectiveGasPrice = (*big.Int)(dec.EffectiveGasPrice)
|
||||||
|
}
|
||||||
if dec.BlockHash != nil {
|
if dec.BlockHash != nil {
|
||||||
r.BlockHash = *dec.BlockHash
|
r.BlockHash = *dec.BlockHash
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func prefixedRlpHash(prefix byte, x interface{}) (h core.Hash) {
|
|||||||
// This is internal, do not use.
|
// This is internal, do not use.
|
||||||
type TrieHasher interface {
|
type TrieHasher interface {
|
||||||
Reset()
|
Reset()
|
||||||
Update([]byte, []byte)
|
Update([]byte, []byte) error
|
||||||
Hash() core.Hash
|
Hash() core.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,10 +26,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/openrelayxyz/plugeth-utils/core"
|
"github.com/openrelayxyz/plugeth-utils/core"
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/hexutil"
|
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/types"
|
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/crypto"
|
"github.com/openrelayxyz/plugeth-utils/restricted/crypto"
|
||||||
|
"github.com/openrelayxyz/plugeth-utils/restricted/hexutil"
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/rlp"
|
"github.com/openrelayxyz/plugeth-utils/restricted/rlp"
|
||||||
|
"github.com/openrelayxyz/plugeth-utils/restricted/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fromHex(data string) []byte {
|
func fromHex(data string) []byte {
|
||||||
@ -136,9 +136,10 @@ func (d *hashToHumanReadable) Reset() {
|
|||||||
d.data = make([]byte, 0)
|
d.data = make([]byte, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *hashToHumanReadable) Update(i []byte, i2 []byte) {
|
func (d *hashToHumanReadable) Update(i []byte, i2 []byte) error {
|
||||||
l := fmt.Sprintf("%x %x\n", i, i2)
|
l := fmt.Sprintf("%x %x\n", i, i2)
|
||||||
d.data = append(d.data, []byte(l)...)
|
d.data = append(d.data, []byte(l)...)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *hashToHumanReadable) Hash() core.Hash {
|
func (d *hashToHumanReadable) Hash() core.Hash {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020 The go-ethereum Authors
|
// Copyright 2021 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
@ -24,13 +24,13 @@ import (
|
|||||||
|
|
||||||
// LegacyTx is the transaction data of regular Ethereum transactions.
|
// LegacyTx is the transaction data of regular Ethereum transactions.
|
||||||
type LegacyTx struct {
|
type LegacyTx struct {
|
||||||
Nonce uint64 // nonce of sender account
|
Nonce uint64 // nonce of sender account
|
||||||
GasPrice *big.Int // wei per gas
|
GasPrice *big.Int // wei per gas
|
||||||
Gas uint64 // gas limit
|
Gas uint64 // gas limit
|
||||||
To *core.Address `rlp:"nil"` // nil means contract creation
|
To *core.Address `rlp:"nil"` // nil means contract creation
|
||||||
Value *big.Int // wei amount
|
Value *big.Int // wei amount
|
||||||
Data []byte // contract invocation input data
|
Data []byte // contract invocation input data
|
||||||
V, R, S *big.Int // signature values
|
V, R, S *big.Int // signature values
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTransaction creates an unsigned legacy transaction.
|
// NewTransaction creates an unsigned legacy transaction.
|
||||||
@ -62,7 +62,7 @@ func NewContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPric
|
|||||||
func (tx *LegacyTx) copy() TxData {
|
func (tx *LegacyTx) copy() TxData {
|
||||||
cpy := &LegacyTx{
|
cpy := &LegacyTx{
|
||||||
Nonce: tx.Nonce,
|
Nonce: tx.Nonce,
|
||||||
To: tx.To, // TODO: copy pointed-to address
|
To: copyAddressPtr(tx.To),
|
||||||
Data: core.CopyBytes(tx.Data),
|
Data: core.CopyBytes(tx.Data),
|
||||||
Gas: tx.Gas,
|
Gas: tx.Gas,
|
||||||
// These are initialized below.
|
// These are initialized below.
|
||||||
@ -101,7 +101,11 @@ func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice }
|
|||||||
func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice }
|
func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice }
|
||||||
func (tx *LegacyTx) value() *big.Int { return tx.Value }
|
func (tx *LegacyTx) value() *big.Int { return tx.Value }
|
||||||
func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
|
func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
|
||||||
func (tx *LegacyTx) to() *core.Address { return tx.To }
|
func (tx *LegacyTx) to() *core.Address { return tx.To }
|
||||||
|
|
||||||
|
func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
|
||||||
|
return dst.Set(tx.GasPrice)
|
||||||
|
}
|
||||||
|
|
||||||
func (tx *LegacyTx) rawSignatureValues() (v, r, s *big.Int) {
|
func (tx *LegacyTx) rawSignatureValues() (v, r, s *big.Int) {
|
||||||
return tx.V, tx.R, tx.S
|
return tx.V, tx.R, tx.S
|
||||||
|
@ -25,13 +25,13 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/openrelayxyz/plugeth-utils/core"
|
"github.com/openrelayxyz/plugeth-utils/core"
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/hexutil"
|
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/crypto"
|
"github.com/openrelayxyz/plugeth-utils/restricted/crypto"
|
||||||
|
"github.com/openrelayxyz/plugeth-utils/restricted/hexutil"
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/params"
|
"github.com/openrelayxyz/plugeth-utils/restricted/params"
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/rlp"
|
"github.com/openrelayxyz/plugeth-utils/restricted/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go
|
//go:generate go run github.com/fjl/gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go
|
||||||
|
|
||||||
var (
|
var (
|
||||||
receiptStatusFailedRLP = []byte{}
|
receiptStatusFailedRLP = []byte{}
|
||||||
@ -60,16 +60,16 @@ type Receipt struct {
|
|||||||
Logs []*Log `json:"logs" gencodec:"required"`
|
Logs []*Log `json:"logs" gencodec:"required"`
|
||||||
|
|
||||||
// Implementation fields: These fields are added by geth when processing a transaction.
|
// Implementation fields: These fields are added by geth when processing a transaction.
|
||||||
// They are stored in the chain database.
|
TxHash core.Hash `json:"transactionHash" gencodec:"required"`
|
||||||
TxHash core.Hash `json:"transactionHash" gencodec:"required"`
|
ContractAddress core.Address `json:"contractAddress"`
|
||||||
ContractAddress core.Address `json:"contractAddress"`
|
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
||||||
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
EffectiveGasPrice *big.Int `json:"effectiveGasPrice"` // required, but tag omitted for backwards compatibility
|
||||||
|
|
||||||
// Inclusion information: These fields provide information about the inclusion of the
|
// Inclusion information: These fields provide information about the inclusion of the
|
||||||
// transaction corresponding to this receipt.
|
// transaction corresponding to this receipt.
|
||||||
BlockHash core.Hash `json:"blockHash,omitempty"`
|
BlockHash core.Hash `json:"blockHash,omitempty"`
|
||||||
BlockNumber *big.Int `json:"blockNumber,omitempty"`
|
BlockNumber *big.Int `json:"blockNumber,omitempty"`
|
||||||
TransactionIndex uint `json:"transactionIndex"`
|
TransactionIndex uint `json:"transactionIndex"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type receiptMarshaling struct {
|
type receiptMarshaling struct {
|
||||||
@ -78,6 +78,7 @@ type receiptMarshaling struct {
|
|||||||
Status hexutil.Uint64
|
Status hexutil.Uint64
|
||||||
CumulativeGasUsed hexutil.Uint64
|
CumulativeGasUsed hexutil.Uint64
|
||||||
GasUsed hexutil.Uint64
|
GasUsed hexutil.Uint64
|
||||||
|
EffectiveGasPrice *hexutil.Big
|
||||||
BlockNumber *hexutil.Big
|
BlockNumber *hexutil.Big
|
||||||
TransactionIndex hexutil.Uint
|
TransactionIndex hexutil.Uint
|
||||||
}
|
}
|
||||||
@ -115,6 +116,9 @@ func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt {
|
|||||||
|
|
||||||
// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt
|
// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt
|
||||||
// into an RLP stream. If no post state is present, byzantium fork is assumed.
|
// into an RLP stream. If no post state is present, byzantium fork is assumed.
|
||||||
|
// For a legacy Receipt this returns RLP([PostStateOrStatus, CumulativeGasUsed, Bloom, Logs])
|
||||||
|
// For a EIP-2718 Receipt this returns RLP(TxType || ReceiptPayload)
|
||||||
|
// For a EIP-2930 Receipt, TxType == 0x01 and ReceiptPayload == RLP([PostStateOrStatus, CumulativeGasUsed, Bloom, Logs])
|
||||||
func (r *Receipt) EncodeRLP(w io.Writer) error {
|
func (r *Receipt) EncodeRLP(w io.Writer) error {
|
||||||
data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs}
|
data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs}
|
||||||
if r.Type == LegacyTxType {
|
if r.Type == LegacyTxType {
|
||||||
@ -123,13 +127,29 @@ func (r *Receipt) EncodeRLP(w io.Writer) error {
|
|||||||
buf := encodeBufferPool.Get().(*bytes.Buffer)
|
buf := encodeBufferPool.Get().(*bytes.Buffer)
|
||||||
defer encodeBufferPool.Put(buf)
|
defer encodeBufferPool.Put(buf)
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
buf.WriteByte(r.Type)
|
if err := r.encodeTyped(data, buf); err != nil {
|
||||||
if err := rlp.Encode(buf, data); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return rlp.Encode(w, buf.Bytes())
|
return rlp.Encode(w, buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// encodeTyped writes the canonical encoding of a typed receipt to w.
|
||||||
|
func (r *Receipt) encodeTyped(data *receiptRLP, w *bytes.Buffer) error {
|
||||||
|
w.WriteByte(r.Type)
|
||||||
|
return rlp.Encode(w, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary returns the consensus encoding of the receipt.
|
||||||
|
func (r *Receipt) MarshalBinary() ([]byte, error) {
|
||||||
|
if r.Type == LegacyTxType {
|
||||||
|
return rlp.EncodeToBytes(r)
|
||||||
|
}
|
||||||
|
data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := r.encodeTyped(data, &buf)
|
||||||
|
return buf.Bytes(), err
|
||||||
|
}
|
||||||
|
|
||||||
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
|
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
|
||||||
// from an RLP stream.
|
// from an RLP stream.
|
||||||
func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||||
@ -145,26 +165,49 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
|||||||
}
|
}
|
||||||
r.Type = LegacyTxType
|
r.Type = LegacyTxType
|
||||||
return r.setFromRLP(dec)
|
return r.setFromRLP(dec)
|
||||||
case kind == rlp.String:
|
default:
|
||||||
// It's an EIP-2718 typed tx receipt.
|
// It's an EIP-2718 typed tx receipt.
|
||||||
b, err := s.Bytes()
|
b, err := s.Bytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(b) == 0 {
|
return r.decodeTyped(b)
|
||||||
return errEmptyTypedReceipt
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary decodes the consensus encoding of receipts.
|
||||||
|
// It supports legacy RLP receipts and EIP-2718 typed receipts.
|
||||||
|
func (r *Receipt) UnmarshalBinary(b []byte) error {
|
||||||
|
if len(b) > 0 && b[0] > 0x7f {
|
||||||
|
// It's a legacy receipt decode the RLP
|
||||||
|
var data receiptRLP
|
||||||
|
err := rlp.DecodeBytes(b, &data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Type = LegacyTxType
|
||||||
|
return r.setFromRLP(data)
|
||||||
|
}
|
||||||
|
// It's an EIP2718 typed transaction envelope.
|
||||||
|
return r.decodeTyped(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeTyped decodes a typed receipt from the canonical format.
|
||||||
|
func (r *Receipt) decodeTyped(b []byte) error {
|
||||||
|
if len(b) <= 1 {
|
||||||
|
return errEmptyTypedReceipt
|
||||||
|
}
|
||||||
|
switch b[0] {
|
||||||
|
case DynamicFeeTxType, AccessListTxType:
|
||||||
|
var data receiptRLP
|
||||||
|
err := rlp.DecodeBytes(b[1:], &data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
r.Type = b[0]
|
r.Type = b[0]
|
||||||
if r.Type == AccessListTxType || r.Type == DynamicFeeTxType {
|
return r.setFromRLP(data)
|
||||||
var dec receiptRLP
|
|
||||||
if err := rlp.DecodeBytes(b[1:], &dec); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return r.setFromRLP(dec)
|
|
||||||
}
|
|
||||||
return ErrTxTypeNotSupported
|
|
||||||
default:
|
default:
|
||||||
return rlp.ErrExpectedList
|
return ErrTxTypeNotSupported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,8 +251,8 @@ func (r *Receipt) Size() float64 {
|
|||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReceiptForStorage is a wrapper around a Receipt that flattens and parses the
|
// ReceiptForStorage is a wrapper around a Receipt with RLP serialization
|
||||||
// entire content of a receipt, as opposed to only the consensus fields originally.
|
// that omits the Bloom field and deserialization that re-computes it.
|
||||||
type ReceiptForStorage Receipt
|
type ReceiptForStorage Receipt
|
||||||
|
|
||||||
// EncodeRLP implements rlp.Encoder.
|
// EncodeRLP implements rlp.Encoder.
|
||||||
@ -222,7 +265,8 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
|
|||||||
return rlp.Encode(w, enc)
|
return rlp.Encode(w, enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeRLP implements rlp.Decoder.
|
// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
|
||||||
|
// fields of a receipt from an RLP stream.
|
||||||
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
||||||
var stored storedReceiptRLP
|
var stored storedReceiptRLP
|
||||||
if err := s.Decode(&stored); err != nil {
|
if err := s.Decode(&stored); err != nil {
|
||||||
@ -234,6 +278,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
|
|||||||
r.CumulativeGasUsed = stored.CumulativeGasUsed
|
r.CumulativeGasUsed = stored.CumulativeGasUsed
|
||||||
r.Logs = stored.Logs
|
r.Logs = stored.Logs
|
||||||
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
|
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,42 +310,48 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
|
|||||||
|
|
||||||
// DeriveFields fills the receipts with their computed fields based on consensus
|
// DeriveFields fills the receipts with their computed fields based on consensus
|
||||||
// data and contextual infos like containing block and transactions.
|
// data and contextual infos like containing block and transactions.
|
||||||
func (r Receipts) DeriveFields(config *params.ChainConfig, hash core.Hash, number uint64, txs Transactions) error {
|
func (rs Receipts) DeriveFields(config *params.ChainConfig, hash core.Hash, number uint64, baseFee *big.Int, txs []*Transaction) error {
|
||||||
signer := MakeSigner(config, new(big.Int).SetUint64(number))
|
signer := MakeSigner(config, new(big.Int).SetUint64(number))
|
||||||
|
|
||||||
logIndex := uint(0)
|
logIndex := uint(0)
|
||||||
if len(txs) != len(r) {
|
if len(txs) != len(rs) {
|
||||||
return errors.New("transaction and receipt count mismatch")
|
return errors.New("transaction and receipt count mismatch")
|
||||||
}
|
}
|
||||||
for i := 0; i < len(r); i++ {
|
for i := 0; i < len(rs); i++ {
|
||||||
// The transaction type and hash can be retrieved from the transaction itself
|
// The transaction type and hash can be retrieved from the transaction itself
|
||||||
r[i].Type = txs[i].Type()
|
rs[i].Type = txs[i].Type()
|
||||||
r[i].TxHash = txs[i].Hash()
|
rs[i].TxHash = txs[i].Hash()
|
||||||
|
|
||||||
|
rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), baseFee)
|
||||||
|
|
||||||
// block location fields
|
// block location fields
|
||||||
r[i].BlockHash = hash
|
rs[i].BlockHash = hash
|
||||||
r[i].BlockNumber = new(big.Int).SetUint64(number)
|
rs[i].BlockNumber = new(big.Int).SetUint64(number)
|
||||||
r[i].TransactionIndex = uint(i)
|
rs[i].TransactionIndex = uint(i)
|
||||||
|
|
||||||
// The contract address can be derived from the transaction itself
|
// The contract address can be derived from the transaction itself
|
||||||
if txs[i].To() == nil {
|
if txs[i].To() == nil {
|
||||||
// Deriving the signer is expensive, only do if it's actually needed
|
// Deriving the signer is expensive, only do if it's actually needed
|
||||||
from, _ := Sender(signer, txs[i])
|
from, _ := Sender(signer, txs[i])
|
||||||
r[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce())
|
rs[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce())
|
||||||
|
} else {
|
||||||
|
rs[i].ContractAddress = core.Address{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The used gas can be calculated based on previous r
|
// The used gas can be calculated based on previous r
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
r[i].GasUsed = r[i].CumulativeGasUsed
|
rs[i].GasUsed = rs[i].CumulativeGasUsed
|
||||||
} else {
|
} else {
|
||||||
r[i].GasUsed = r[i].CumulativeGasUsed - r[i-1].CumulativeGasUsed
|
rs[i].GasUsed = rs[i].CumulativeGasUsed - rs[i-1].CumulativeGasUsed
|
||||||
}
|
}
|
||||||
|
|
||||||
// The derived log fields can simply be set from the block and transaction
|
// The derived log fields can simply be set from the block and transaction
|
||||||
for j := 0; j < len(r[i].Logs); j++ {
|
for j := 0; j < len(rs[i].Logs); j++ {
|
||||||
r[i].Logs[j].BlockNumber = number
|
rs[i].Logs[j].BlockNumber = number
|
||||||
r[i].Logs[j].BlockHash = hash
|
rs[i].Logs[j].BlockHash = hash
|
||||||
r[i].Logs[j].TxHash = r[i].TxHash
|
rs[i].Logs[j].TxHash = rs[i].TxHash
|
||||||
r[i].Logs[j].TxIndex = uint(i)
|
rs[i].Logs[j].TxIndex = uint(i)
|
||||||
r[i].Logs[j].Index = logIndex
|
rs[i].Logs[j].Index = logIndex
|
||||||
logIndex++
|
logIndex++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,233 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"encoding/hex"
|
|
||||||
|
"github.com/kylelemons/godebug/diff"
|
||||||
|
|
||||||
"github.com/openrelayxyz/plugeth-utils/core"
|
"github.com/openrelayxyz/plugeth-utils/core"
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/crypto"
|
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/params"
|
"github.com/openrelayxyz/plugeth-utils/restricted/params"
|
||||||
"github.com/openrelayxyz/plugeth-utils/restricted/rlp"
|
"github.com/openrelayxyz/plugeth-utils/restricted/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
legacyReceipt = &Receipt{
|
||||||
|
Status: ReceiptStatusFailed,
|
||||||
|
CumulativeGasUsed: 1,
|
||||||
|
Logs: []*Log{
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x11}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
Data: []byte{0x01, 0x00, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x01, 0x11}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
Data: []byte{0x01, 0x00, 0xff},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
accessListReceipt = &Receipt{
|
||||||
|
Status: ReceiptStatusFailed,
|
||||||
|
CumulativeGasUsed: 1,
|
||||||
|
Logs: []*Log{
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x11}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
Data: []byte{0x01, 0x00, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x01, 0x11}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
Data: []byte{0x01, 0x00, 0xff},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: AccessListTxType,
|
||||||
|
}
|
||||||
|
eip1559Receipt = &Receipt{
|
||||||
|
Status: ReceiptStatusFailed,
|
||||||
|
CumulativeGasUsed: 1,
|
||||||
|
Logs: []*Log{
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x11}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
Data: []byte{0x01, 0x00, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x01, 0x11}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
Data: []byte{0x01, 0x00, 0xff},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: DynamicFeeTxType,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a few transactions to have receipts for
|
||||||
|
to2 = core.HexToAddress("0x2")
|
||||||
|
to3 = core.HexToAddress("0x3")
|
||||||
|
to4 = core.HexToAddress("0x4")
|
||||||
|
to5 = core.HexToAddress("0x5")
|
||||||
|
to6 = core.HexToAddress("0x6")
|
||||||
|
to7 = core.HexToAddress("0x7")
|
||||||
|
txs = Transactions{
|
||||||
|
NewTx(&LegacyTx{
|
||||||
|
Nonce: 1,
|
||||||
|
Value: big.NewInt(1),
|
||||||
|
Gas: 1,
|
||||||
|
GasPrice: big.NewInt(11),
|
||||||
|
}),
|
||||||
|
NewTx(&LegacyTx{
|
||||||
|
To: &to2,
|
||||||
|
Nonce: 2,
|
||||||
|
Value: big.NewInt(2),
|
||||||
|
Gas: 2,
|
||||||
|
GasPrice: big.NewInt(22),
|
||||||
|
}),
|
||||||
|
NewTx(&AccessListTx{
|
||||||
|
To: &to3,
|
||||||
|
Nonce: 3,
|
||||||
|
Value: big.NewInt(3),
|
||||||
|
Gas: 3,
|
||||||
|
GasPrice: big.NewInt(33),
|
||||||
|
}),
|
||||||
|
// EIP-1559 transactions.
|
||||||
|
NewTx(&DynamicFeeTx{
|
||||||
|
To: &to4,
|
||||||
|
Nonce: 4,
|
||||||
|
Value: big.NewInt(4),
|
||||||
|
Gas: 4,
|
||||||
|
GasTipCap: big.NewInt(44),
|
||||||
|
GasFeeCap: big.NewInt(1045),
|
||||||
|
}),
|
||||||
|
NewTx(&DynamicFeeTx{
|
||||||
|
To: &to5,
|
||||||
|
Nonce: 5,
|
||||||
|
Value: big.NewInt(5),
|
||||||
|
Gas: 5,
|
||||||
|
GasTipCap: big.NewInt(56),
|
||||||
|
GasFeeCap: big.NewInt(1055),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
blockNumber = big.NewInt(1)
|
||||||
|
blockHash = core.BytesToHash([]byte{0x03, 0x14})
|
||||||
|
|
||||||
|
// Create the corresponding receipts
|
||||||
|
receipts = Receipts{
|
||||||
|
&Receipt{
|
||||||
|
Status: ReceiptStatusFailed,
|
||||||
|
CumulativeGasUsed: 1,
|
||||||
|
Logs: []*Log{
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x11}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
// derived fields:
|
||||||
|
BlockNumber: blockNumber.Uint64(),
|
||||||
|
TxHash: txs[0].Hash(),
|
||||||
|
TxIndex: 0,
|
||||||
|
BlockHash: blockHash,
|
||||||
|
Index: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x01, 0x11}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
// derived fields:
|
||||||
|
BlockNumber: blockNumber.Uint64(),
|
||||||
|
TxHash: txs[0].Hash(),
|
||||||
|
TxIndex: 0,
|
||||||
|
BlockHash: blockHash,
|
||||||
|
Index: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// derived fields:
|
||||||
|
TxHash: txs[0].Hash(),
|
||||||
|
ContractAddress: core.HexToAddress("0x5a443704dd4b594b382c22a083e2bd3090a6fef3"),
|
||||||
|
GasUsed: 1,
|
||||||
|
EffectiveGasPrice: big.NewInt(11),
|
||||||
|
BlockHash: blockHash,
|
||||||
|
BlockNumber: blockNumber,
|
||||||
|
TransactionIndex: 0,
|
||||||
|
},
|
||||||
|
&Receipt{
|
||||||
|
PostState: core.Hash{2}.Bytes(),
|
||||||
|
CumulativeGasUsed: 3,
|
||||||
|
Logs: []*Log{
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x22}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
// derived fields:
|
||||||
|
BlockNumber: blockNumber.Uint64(),
|
||||||
|
TxHash: txs[1].Hash(),
|
||||||
|
TxIndex: 1,
|
||||||
|
BlockHash: blockHash,
|
||||||
|
Index: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: core.BytesToAddress([]byte{0x02, 0x22}),
|
||||||
|
Topics: []core.Hash{core.HexToHash("dead"), core.HexToHash("beef")},
|
||||||
|
// derived fields:
|
||||||
|
BlockNumber: blockNumber.Uint64(),
|
||||||
|
TxHash: txs[1].Hash(),
|
||||||
|
TxIndex: 1,
|
||||||
|
BlockHash: blockHash,
|
||||||
|
Index: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// derived fields:
|
||||||
|
TxHash: txs[1].Hash(),
|
||||||
|
GasUsed: 2,
|
||||||
|
EffectiveGasPrice: big.NewInt(22),
|
||||||
|
BlockHash: blockHash,
|
||||||
|
BlockNumber: blockNumber,
|
||||||
|
TransactionIndex: 1,
|
||||||
|
},
|
||||||
|
&Receipt{
|
||||||
|
Type: AccessListTxType,
|
||||||
|
PostState: core.Hash{3}.Bytes(),
|
||||||
|
CumulativeGasUsed: 6,
|
||||||
|
Logs: []*Log{},
|
||||||
|
// derived fields:
|
||||||
|
TxHash: txs[2].Hash(),
|
||||||
|
GasUsed: 3,
|
||||||
|
EffectiveGasPrice: big.NewInt(33),
|
||||||
|
BlockHash: blockHash,
|
||||||
|
BlockNumber: blockNumber,
|
||||||
|
TransactionIndex: 2,
|
||||||
|
},
|
||||||
|
&Receipt{
|
||||||
|
Type: DynamicFeeTxType,
|
||||||
|
PostState: core.Hash{4}.Bytes(),
|
||||||
|
CumulativeGasUsed: 10,
|
||||||
|
Logs: []*Log{},
|
||||||
|
// derived fields:
|
||||||
|
TxHash: txs[3].Hash(),
|
||||||
|
GasUsed: 4,
|
||||||
|
EffectiveGasPrice: big.NewInt(1044),
|
||||||
|
BlockHash: blockHash,
|
||||||
|
BlockNumber: blockNumber,
|
||||||
|
TransactionIndex: 3,
|
||||||
|
},
|
||||||
|
&Receipt{
|
||||||
|
Type: DynamicFeeTxType,
|
||||||
|
PostState: core.Hash{5}.Bytes(),
|
||||||
|
CumulativeGasUsed: 15,
|
||||||
|
Logs: []*Log{},
|
||||||
|
// derived fields:
|
||||||
|
TxHash: txs[4].Hash(),
|
||||||
|
GasUsed: 5,
|
||||||
|
EffectiveGasPrice: big.NewInt(1055),
|
||||||
|
BlockHash: blockHash,
|
||||||
|
BlockNumber: blockNumber,
|
||||||
|
TransactionIndex: 4,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func TestDecodeEmptyTypedReceipt(t *testing.T) {
|
func TestDecodeEmptyTypedReceipt(t *testing.T) {
|
||||||
input := []byte{0x80}
|
input := []byte{0x80}
|
||||||
var r Receipt
|
var r Receipt
|
||||||
@ -40,131 +256,62 @@ func TestDecodeEmptyTypedReceipt(t *testing.T) {
|
|||||||
|
|
||||||
// Tests that receipt data can be correctly derived from the contextual infos
|
// Tests that receipt data can be correctly derived from the contextual infos
|
||||||
func TestDeriveFields(t *testing.T) {
|
func TestDeriveFields(t *testing.T) {
|
||||||
// Create a few transactions to have receipts for
|
// Re-derive receipts.
|
||||||
to2 := core.HexToAddress("0x2")
|
basefee := big.NewInt(1000)
|
||||||
to3 := core.HexToAddress("0x3")
|
derivedReceipts := clearComputedFieldsOnReceipts(receipts)
|
||||||
txs := Transactions{
|
err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), basefee, txs)
|
||||||
NewTx(&LegacyTx{
|
if err != nil {
|
||||||
Nonce: 1,
|
|
||||||
Value: big.NewInt(1),
|
|
||||||
Gas: 1,
|
|
||||||
GasPrice: big.NewInt(1),
|
|
||||||
}),
|
|
||||||
NewTx(&LegacyTx{
|
|
||||||
To: &to2,
|
|
||||||
Nonce: 2,
|
|
||||||
Value: big.NewInt(2),
|
|
||||||
Gas: 2,
|
|
||||||
GasPrice: big.NewInt(2),
|
|
||||||
}),
|
|
||||||
NewTx(&AccessListTx{
|
|
||||||
To: &to3,
|
|
||||||
Nonce: 3,
|
|
||||||
Value: big.NewInt(3),
|
|
||||||
Gas: 3,
|
|
||||||
GasPrice: big.NewInt(3),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
// Create the corresponding receipts
|
|
||||||
receipts := Receipts{
|
|
||||||
&Receipt{
|
|
||||||
Status: ReceiptStatusFailed,
|
|
||||||
CumulativeGasUsed: 1,
|
|
||||||
Logs: []*Log{
|
|
||||||
{Address: core.BytesToAddress([]byte{0x11})},
|
|
||||||
{Address: core.BytesToAddress([]byte{0x01, 0x11})},
|
|
||||||
},
|
|
||||||
TxHash: txs[0].Hash(),
|
|
||||||
ContractAddress: core.BytesToAddress([]byte{0x01, 0x11, 0x11}),
|
|
||||||
GasUsed: 1,
|
|
||||||
},
|
|
||||||
&Receipt{
|
|
||||||
PostState: core.Hash{2}.Bytes(),
|
|
||||||
CumulativeGasUsed: 3,
|
|
||||||
Logs: []*Log{
|
|
||||||
{Address: core.BytesToAddress([]byte{0x22})},
|
|
||||||
{Address: core.BytesToAddress([]byte{0x02, 0x22})},
|
|
||||||
},
|
|
||||||
TxHash: txs[1].Hash(),
|
|
||||||
ContractAddress: core.BytesToAddress([]byte{0x02, 0x22, 0x22}),
|
|
||||||
GasUsed: 2,
|
|
||||||
},
|
|
||||||
&Receipt{
|
|
||||||
Type: AccessListTxType,
|
|
||||||
PostState: core.Hash{3}.Bytes(),
|
|
||||||
CumulativeGasUsed: 6,
|
|
||||||
Logs: []*Log{
|
|
||||||
{Address: core.BytesToAddress([]byte{0x33})},
|
|
||||||
{Address: core.BytesToAddress([]byte{0x03, 0x33})},
|
|
||||||
},
|
|
||||||
TxHash: txs[2].Hash(),
|
|
||||||
ContractAddress: core.BytesToAddress([]byte{0x03, 0x33, 0x33}),
|
|
||||||
GasUsed: 3,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// Clear all the computed fields and re-derive them
|
|
||||||
number := big.NewInt(1)
|
|
||||||
hash := core.BytesToHash([]byte{0x03, 0x14})
|
|
||||||
|
|
||||||
clearComputedFieldsOnReceipts(t, receipts)
|
|
||||||
if err := receipts.DeriveFields(params.TestChainConfig, hash, number.Uint64(), txs); err != nil {
|
|
||||||
t.Fatalf("DeriveFields(...) = %v, want <nil>", err)
|
t.Fatalf("DeriveFields(...) = %v, want <nil>", err)
|
||||||
}
|
}
|
||||||
// Iterate over all the computed fields and check that they're correct
|
|
||||||
signer := MakeSigner(params.TestChainConfig, number)
|
|
||||||
|
|
||||||
logIndex := uint(0)
|
// Check diff of receipts against derivedReceipts.
|
||||||
|
r1, err := json.MarshalIndent(receipts, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("error marshaling input receipts:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r2, err := json.MarshalIndent(derivedReceipts, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("error marshaling derived receipts:", err)
|
||||||
|
}
|
||||||
|
d := diff.Diff(string(r1), string(r2))
|
||||||
|
if d != "" {
|
||||||
|
t.Fatal("receipts differ:", d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that we can marshal/unmarshal receipts to/from json without errors.
|
||||||
|
// This also confirms that our test receipts contain all the required fields.
|
||||||
|
func TestReceiptJSON(t *testing.T) {
|
||||||
for i := range receipts {
|
for i := range receipts {
|
||||||
if receipts[i].Type != txs[i].Type() {
|
b, err := receipts[i].MarshalJSON()
|
||||||
t.Errorf("receipts[%d].Type = %d, want %d", i, receipts[i].Type, txs[i].Type())
|
if err != nil {
|
||||||
|
t.Fatal("error marshaling receipt to json:", err)
|
||||||
}
|
}
|
||||||
if receipts[i].TxHash != txs[i].Hash() {
|
r := Receipt{}
|
||||||
t.Errorf("receipts[%d].TxHash = %s, want %s", i, receipts[i].TxHash.String(), txs[i].Hash().String())
|
err = r.UnmarshalJSON(b)
|
||||||
}
|
if err != nil {
|
||||||
if receipts[i].BlockHash != hash {
|
t.Fatal("error unmarshaling receipt from json:", err)
|
||||||
t.Errorf("receipts[%d].BlockHash = %s, want %s", i, receipts[i].BlockHash.String(), hash.String())
|
|
||||||
}
|
|
||||||
if receipts[i].BlockNumber.Cmp(number) != 0 {
|
|
||||||
t.Errorf("receipts[%c].BlockNumber = %s, want %s", i, receipts[i].BlockNumber.String(), number.String())
|
|
||||||
}
|
|
||||||
if receipts[i].TransactionIndex != uint(i) {
|
|
||||||
t.Errorf("receipts[%d].TransactionIndex = %d, want %d", i, receipts[i].TransactionIndex, i)
|
|
||||||
}
|
|
||||||
if receipts[i].GasUsed != txs[i].Gas() {
|
|
||||||
t.Errorf("receipts[%d].GasUsed = %d, want %d", i, receipts[i].GasUsed, txs[i].Gas())
|
|
||||||
}
|
|
||||||
if txs[i].To() != nil && receipts[i].ContractAddress != (core.Address{}) {
|
|
||||||
t.Errorf("receipts[%d].ContractAddress = %s, want %s", i, receipts[i].ContractAddress.String(), (core.Address{}).String())
|
|
||||||
}
|
|
||||||
from, _ := Sender(signer, txs[i])
|
|
||||||
contractAddress := crypto.CreateAddress(from, txs[i].Nonce())
|
|
||||||
if txs[i].To() == nil && receipts[i].ContractAddress != contractAddress {
|
|
||||||
t.Errorf("receipts[%d].ContractAddress = %s, want %s", i, receipts[i].ContractAddress.String(), contractAddress.String())
|
|
||||||
}
|
|
||||||
for j := range receipts[i].Logs {
|
|
||||||
if receipts[i].Logs[j].BlockNumber != number.Uint64() {
|
|
||||||
t.Errorf("receipts[%d].Logs[%d].BlockNumber = %d, want %d", i, j, receipts[i].Logs[j].BlockNumber, number.Uint64())
|
|
||||||
}
|
|
||||||
if receipts[i].Logs[j].BlockHash != hash {
|
|
||||||
t.Errorf("receipts[%d].Logs[%d].BlockHash = %s, want %s", i, j, receipts[i].Logs[j].BlockHash.String(), hash.String())
|
|
||||||
}
|
|
||||||
if receipts[i].Logs[j].TxHash != txs[i].Hash() {
|
|
||||||
t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String())
|
|
||||||
}
|
|
||||||
if receipts[i].Logs[j].TxHash != txs[i].Hash() {
|
|
||||||
t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String())
|
|
||||||
}
|
|
||||||
if receipts[i].Logs[j].TxIndex != uint(i) {
|
|
||||||
t.Errorf("receipts[%d].Logs[%d].TransactionIndex = %d, want %d", i, j, receipts[i].Logs[j].TxIndex, i)
|
|
||||||
}
|
|
||||||
if receipts[i].Logs[j].Index != logIndex {
|
|
||||||
t.Errorf("receipts[%d].Logs[%d].Index = %d, want %d", i, j, receipts[i].Logs[j].Index, logIndex)
|
|
||||||
}
|
|
||||||
logIndex++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test we can still parse receipt without EffectiveGasPrice for backwards compatibility, even
|
||||||
|
// though it is required per the spec.
|
||||||
|
func TestEffectiveGasPriceNotRequired(t *testing.T) {
|
||||||
|
r := *receipts[0]
|
||||||
|
r.EffectiveGasPrice = nil
|
||||||
|
b, err := r.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("error marshaling receipt to json:", err)
|
||||||
|
}
|
||||||
|
r2 := Receipt{}
|
||||||
|
err = r2.UnmarshalJSON(b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("error unmarshaling receipt from json:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestTypedReceiptEncodingDecoding reproduces a flaw that existed in the receipt
|
// TestTypedReceiptEncodingDecoding reproduces a flaw that existed in the receipt
|
||||||
// rlp decoder, which failed due to a shadowing error.
|
// rlp decoder, which failed due to a shadowing error.
|
||||||
func TestTypedReceiptEncodingDecoding(t *testing.T) {
|
func TestTypedReceiptEncodingDecoding(t *testing.T) {
|
||||||
@ -193,41 +340,135 @@ func TestTypedReceiptEncodingDecoding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearComputedFieldsOnReceipts(t *testing.T, receipts Receipts) {
|
func TestReceiptMarshalBinary(t *testing.T) {
|
||||||
t.Helper()
|
// Legacy Receipt
|
||||||
|
legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt})
|
||||||
|
have, err := legacyReceipt.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal binary error: %v", err)
|
||||||
|
}
|
||||||
|
legacyReceipts := Receipts{legacyReceipt}
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
legacyReceipts.EncodeIndex(0, buf)
|
||||||
|
haveEncodeIndex := buf.Bytes()
|
||||||
|
if !bytes.Equal(have, haveEncodeIndex) {
|
||||||
|
t.Errorf("BinaryMarshal and EncodeIndex mismatch, got %x want %x", have, haveEncodeIndex)
|
||||||
|
}
|
||||||
|
buf.Reset()
|
||||||
|
if err := legacyReceipt.EncodeRLP(buf); err != nil {
|
||||||
|
t.Fatalf("encode rlp error: %v", err)
|
||||||
|
}
|
||||||
|
haveRLPEncode := buf.Bytes()
|
||||||
|
if !bytes.Equal(have, haveRLPEncode) {
|
||||||
|
t.Errorf("BinaryMarshal and EncodeRLP mismatch for legacy tx, got %x want %x", have, haveRLPEncode)
|
||||||
|
}
|
||||||
|
legacyWant, _ := hex.DecodeString("f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff")
|
||||||
|
if !bytes.Equal(have, legacyWant) {
|
||||||
|
t.Errorf("encoded RLP mismatch, got %x want %x", have, legacyWant)
|
||||||
|
}
|
||||||
|
|
||||||
for _, receipt := range receipts {
|
// 2930 Receipt
|
||||||
clearComputedFieldsOnReceipt(t, receipt)
|
buf.Reset()
|
||||||
|
accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt})
|
||||||
|
have, err = accessListReceipt.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal binary error: %v", err)
|
||||||
|
}
|
||||||
|
accessListReceipts := Receipts{accessListReceipt}
|
||||||
|
accessListReceipts.EncodeIndex(0, buf)
|
||||||
|
haveEncodeIndex = buf.Bytes()
|
||||||
|
if !bytes.Equal(have, haveEncodeIndex) {
|
||||||
|
t.Errorf("BinaryMarshal and EncodeIndex mismatch, got %x want %x", have, haveEncodeIndex)
|
||||||
|
}
|
||||||
|
accessListWant, _ := hex.DecodeString("01f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff")
|
||||||
|
if !bytes.Equal(have, accessListWant) {
|
||||||
|
t.Errorf("encoded RLP mismatch, got %x want %x", have, accessListWant)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1559 Receipt
|
||||||
|
buf.Reset()
|
||||||
|
eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt})
|
||||||
|
have, err = eip1559Receipt.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal binary error: %v", err)
|
||||||
|
}
|
||||||
|
eip1559Receipts := Receipts{eip1559Receipt}
|
||||||
|
eip1559Receipts.EncodeIndex(0, buf)
|
||||||
|
haveEncodeIndex = buf.Bytes()
|
||||||
|
if !bytes.Equal(have, haveEncodeIndex) {
|
||||||
|
t.Errorf("BinaryMarshal and EncodeIndex mismatch, got %x want %x", have, haveEncodeIndex)
|
||||||
|
}
|
||||||
|
eip1559Want, _ := hex.DecodeString("02f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff")
|
||||||
|
if !bytes.Equal(have, eip1559Want) {
|
||||||
|
t.Errorf("encoded RLP mismatch, got %x want %x", have, eip1559Want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearComputedFieldsOnReceipt(t *testing.T, receipt *Receipt) {
|
func TestReceiptUnmarshalBinary(t *testing.T) {
|
||||||
t.Helper()
|
// Legacy Receipt
|
||||||
|
legacyBinary, _ := hex.DecodeString("f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff")
|
||||||
|
gotLegacyReceipt := new(Receipt)
|
||||||
|
if err := gotLegacyReceipt.UnmarshalBinary(legacyBinary); err != nil {
|
||||||
|
t.Fatalf("unmarshal binary error: %v", err)
|
||||||
|
}
|
||||||
|
legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt})
|
||||||
|
if !reflect.DeepEqual(gotLegacyReceipt, legacyReceipt) {
|
||||||
|
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotLegacyReceipt, legacyReceipt)
|
||||||
|
}
|
||||||
|
|
||||||
receipt.TxHash = core.Hash{}
|
// 2930 Receipt
|
||||||
receipt.BlockHash = core.Hash{}
|
accessListBinary, _ := hex.DecodeString("01f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff")
|
||||||
receipt.BlockNumber = big.NewInt(math.MaxUint32)
|
gotAccessListReceipt := new(Receipt)
|
||||||
receipt.TransactionIndex = math.MaxUint32
|
if err := gotAccessListReceipt.UnmarshalBinary(accessListBinary); err != nil {
|
||||||
receipt.ContractAddress = core.Address{}
|
t.Fatalf("unmarshal binary error: %v", err)
|
||||||
receipt.GasUsed = 0
|
}
|
||||||
|
accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt})
|
||||||
|
if !reflect.DeepEqual(gotAccessListReceipt, accessListReceipt) {
|
||||||
|
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotAccessListReceipt, accessListReceipt)
|
||||||
|
}
|
||||||
|
|
||||||
clearComputedFieldsOnLogs(t, receipt.Logs)
|
// 1559 Receipt
|
||||||
}
|
eip1559RctBinary, _ := hex.DecodeString("02f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff")
|
||||||
|
got1559Receipt := new(Receipt)
|
||||||
func clearComputedFieldsOnLogs(t *testing.T, logs []*Log) {
|
if err := got1559Receipt.UnmarshalBinary(eip1559RctBinary); err != nil {
|
||||||
t.Helper()
|
t.Fatalf("unmarshal binary error: %v", err)
|
||||||
|
}
|
||||||
for _, log := range logs {
|
eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt})
|
||||||
clearComputedFieldsOnLog(t, log)
|
if !reflect.DeepEqual(got1559Receipt, eip1559Receipt) {
|
||||||
|
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", got1559Receipt, eip1559Receipt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearComputedFieldsOnLog(t *testing.T, log *Log) {
|
func clearComputedFieldsOnReceipts(receipts []*Receipt) []*Receipt {
|
||||||
t.Helper()
|
r := make([]*Receipt, len(receipts))
|
||||||
|
for i, receipt := range receipts {
|
||||||
log.BlockNumber = math.MaxUint32
|
r[i] = clearComputedFieldsOnReceipt(receipt)
|
||||||
log.BlockHash = core.Hash{}
|
}
|
||||||
log.TxHash = core.Hash{}
|
return r
|
||||||
log.TxIndex = math.MaxUint32
|
}
|
||||||
log.Index = math.MaxUint32
|
|
||||||
|
func clearComputedFieldsOnReceipt(receipt *Receipt) *Receipt {
|
||||||
|
cpy := *receipt
|
||||||
|
cpy.TxHash = core.Hash{0xff, 0xff, 0x11}
|
||||||
|
cpy.BlockHash = core.Hash{0xff, 0xff, 0x22}
|
||||||
|
cpy.BlockNumber = big.NewInt(math.MaxUint32)
|
||||||
|
cpy.TransactionIndex = math.MaxUint32
|
||||||
|
cpy.ContractAddress = core.Address{0xff, 0xff, 0x33}
|
||||||
|
cpy.GasUsed = 0xffffffff
|
||||||
|
cpy.Logs = clearComputedFieldsOnLogs(receipt.Logs)
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearComputedFieldsOnLogs(logs []*Log) []*Log {
|
||||||
|
l := make([]*Log, len(logs))
|
||||||
|
for i, log := range logs {
|
||||||
|
cpy := *log
|
||||||
|
cpy.BlockNumber = math.MaxUint32
|
||||||
|
cpy.BlockHash = core.Hash{}
|
||||||
|
cpy.TxHash = core.Hash{}
|
||||||
|
cpy.TxIndex = math.MaxUint32
|
||||||
|
cpy.Index = math.MaxUint32
|
||||||
|
l[i] = &cpy
|
||||||
|
}
|
||||||
|
return l
|
||||||
}
|
}
|
||||||
|
@ -89,9 +89,20 @@ type TxData interface {
|
|||||||
|
|
||||||
rawSignatureValues() (v, r, s *big.Int)
|
rawSignatureValues() (v, r, s *big.Int)
|
||||||
setSignatureValues(chainID, v, r, s *big.Int)
|
setSignatureValues(chainID, v, r, s *big.Int)
|
||||||
|
|
||||||
|
// effectiveGasPrice computes the gas price paid by the transaction, given
|
||||||
|
// the inclusion block baseFee.
|
||||||
|
//
|
||||||
|
// Unlike other TxData methods, the returned *big.Int should be an independent
|
||||||
|
// copy of the computed value, i.e. callers are allowed to mutate the result.
|
||||||
|
// Method implementations can use 'dst' to store the result.
|
||||||
|
effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeRLP implements rlp.Encoder
|
// EncodeRLP implements rlp.Encoder
|
||||||
|
// For a legacy Transaction this returns RLP([AccountNonce, GasPrice, GasLimit, Recipient, Amount, Data, V, R, S])
|
||||||
|
// For a EIP-2718 Transaction this returns RLP(TxType || TxPayload)
|
||||||
|
// For a EIP-2930 Transaction, TxType == 0x01 and TxPayload == RLP([ChainID, AccountNonce, GasPrice, GasLimit, Recipient, Amount, Data, AccessList, V, R, S]
|
||||||
func (tx *Transaction) EncodeRLP(w io.Writer) error {
|
func (tx *Transaction) EncodeRLP(w io.Writer) error {
|
||||||
if tx.Type() == LegacyTxType {
|
if tx.Type() == LegacyTxType {
|
||||||
return rlp.Encode(w, tx.inner)
|
return rlp.Encode(w, tx.inner)
|
||||||
@ -112,9 +123,10 @@ func (tx *Transaction) encodeTyped(w *bytes.Buffer) error {
|
|||||||
return rlp.Encode(w, tx.inner)
|
return rlp.Encode(w, tx.inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalBinary returns the canonical encoding of the transaction.
|
// MarshalBinary returns the canonical consensus encoding of the transaction.
|
||||||
// For legacy transactions, it returns the RLP encoding. For EIP-2718 typed
|
// For a legacy Transaction this returns RLP([AccountNonce, GasPrice, GasLimit, Recipient, Amount, Data, V, R, S])
|
||||||
// transactions, it returns the type and payload.
|
// For a EIP-2718 Transaction this returns TxType || TxPayload
|
||||||
|
// For a EIP-2930 Transaction, TxType == 0x01 and TxPayload == RLP([ChainID, AccountNonce, GasPrice, GasLimit, Recipient, Amount, Data, AccessList, V, R, S]
|
||||||
func (tx *Transaction) MarshalBinary() ([]byte, error) {
|
func (tx *Transaction) MarshalBinary() ([]byte, error) {
|
||||||
if tx.Type() == LegacyTxType {
|
if tx.Type() == LegacyTxType {
|
||||||
return rlp.EncodeToBytes(tx.inner)
|
return rlp.EncodeToBytes(tx.inner)
|
||||||
@ -135,10 +147,10 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
|
|||||||
var inner LegacyTx
|
var inner LegacyTx
|
||||||
err := s.Decode(&inner)
|
err := s.Decode(&inner)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tx.setDecoded(&inner, int(rlp.ListSize(size)))
|
tx.setDecoded(&inner, rlp.ListSize(size))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
case kind == rlp.String:
|
default:
|
||||||
// It's an EIP-2718 typed TX envelope.
|
// It's an EIP-2718 typed TX envelope.
|
||||||
var b []byte
|
var b []byte
|
||||||
if b, err = s.Bytes(); err != nil {
|
if b, err = s.Bytes(); err != nil {
|
||||||
@ -146,11 +158,9 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
|
|||||||
}
|
}
|
||||||
inner, err := tx.decodeTyped(b)
|
inner, err := tx.decodeTyped(b)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tx.setDecoded(inner, len(b))
|
tx.setDecoded(inner, uint64(len(b)))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
default:
|
|
||||||
return rlp.ErrExpectedList
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +174,7 @@ func (tx *Transaction) UnmarshalBinary(b []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tx.setDecoded(&data, len(b))
|
tx.setDecoded(&data, uint64(len(b)))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// It's an EIP2718 typed transaction envelope.
|
// It's an EIP2718 typed transaction envelope.
|
||||||
@ -172,13 +182,13 @@ func (tx *Transaction) UnmarshalBinary(b []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tx.setDecoded(inner, len(b))
|
tx.setDecoded(inner, uint64(len(b)))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeTyped decodes a typed transaction from the canonical format.
|
// decodeTyped decodes a typed transaction from the canonical format.
|
||||||
func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
||||||
if len(b) == 0 {
|
if len(b) <= 1 {
|
||||||
return nil, errEmptyTypedTx
|
return nil, errEmptyTypedTx
|
||||||
}
|
}
|
||||||
switch b[0] {
|
switch b[0] {
|
||||||
@ -196,11 +206,11 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setDecoded sets the inner transaction and size after decoding.
|
// setDecoded sets the inner transaction and size after decoding.
|
||||||
func (tx *Transaction) setDecoded(inner TxData, size int) {
|
func (tx *Transaction) setDecoded(inner TxData, size uint64) {
|
||||||
tx.inner = inner
|
tx.inner = inner
|
||||||
tx.time = time.Now()
|
tx.time = time.Now()
|
||||||
if size > 0 {
|
if size > 0 {
|
||||||
tx.size.Store(float64(size))
|
tx.size.Store(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,13 +298,7 @@ func (tx *Transaction) Nonce() uint64 { return tx.inner.nonce() }
|
|||||||
// To returns the recipient address of the transaction.
|
// To returns the recipient address of the transaction.
|
||||||
// For contract-creation transactions, To returns nil.
|
// For contract-creation transactions, To returns nil.
|
||||||
func (tx *Transaction) To() *core.Address {
|
func (tx *Transaction) To() *core.Address {
|
||||||
// Copy the pointed-to address.
|
return copyAddressPtr(tx.inner.to())
|
||||||
ito := tx.inner.to()
|
|
||||||
if ito == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
cpy := *ito
|
|
||||||
return &cpy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cost returns gas * gasPrice + value.
|
// Cost returns gas * gasPrice + value.
|
||||||
@ -384,16 +388,21 @@ func (tx *Transaction) Hash() core.Hash {
|
|||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the true RLP encoded storage size of the transaction, either by
|
// Size returns the true encoded storage size of the transaction, either by encoding
|
||||||
// encoding and returning it, or returning a previously cached value.
|
// and returning it, or returning a previously cached value.
|
||||||
func (tx *Transaction) Size() float64 {
|
func (tx *Transaction) Size() uint64 {
|
||||||
if size := tx.size.Load(); size != nil {
|
if size := tx.size.Load(); size != nil {
|
||||||
return size.(float64)
|
return size.(uint64)
|
||||||
}
|
}
|
||||||
c := writeCounter(0)
|
c := writeCounter(0)
|
||||||
rlp.Encode(&c, &tx.inner)
|
rlp.Encode(&c, &tx.inner)
|
||||||
tx.size.Store(float64(c))
|
|
||||||
return float64(c)
|
size := uint64(c)
|
||||||
|
if tx.Type() != LegacyTxType {
|
||||||
|
size += 1 // type byte
|
||||||
|
}
|
||||||
|
tx.size.Store(size)
|
||||||
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithSignature returns a new transaction with the given signature.
|
// WithSignature returns a new transaction with the given signature.
|
||||||
@ -444,6 +453,24 @@ func TxDifference(a, b Transactions) Transactions {
|
|||||||
return keep
|
return keep
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HashDifference returns a new set which is the difference between a and b.
|
||||||
|
func HashDifference(a, b []core.Hash) []core.Hash {
|
||||||
|
keep := make([]core.Hash, 0, len(a))
|
||||||
|
|
||||||
|
remove := make(map[core.Hash]struct{})
|
||||||
|
for _, hash := range b {
|
||||||
|
remove[hash] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, hash := range a {
|
||||||
|
if _, ok := remove[hash]; !ok {
|
||||||
|
keep = append(keep, hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keep
|
||||||
|
}
|
||||||
|
|
||||||
// TxByNonce implements the sort interface to allow sorting a list of transactions
|
// TxByNonce implements the sort interface to allow sorting a list of transactions
|
||||||
// by their nonces. This is usually only useful for sorting transactions from a
|
// by their nonces. This is usually only useful for sorting transactions from a
|
||||||
// single account, otherwise a nonce comparison doesn't make much sense.
|
// single account, otherwise a nonce comparison doesn't make much sense.
|
||||||
@ -497,6 +524,7 @@ func (s *TxByPriceAndTime) Pop() interface{} {
|
|||||||
old := *s
|
old := *s
|
||||||
n := len(old)
|
n := len(old)
|
||||||
x := old[n-1]
|
x := old[n-1]
|
||||||
|
old[n-1] = nil
|
||||||
*s = old[0 : n-1]
|
*s = old[0 : n-1]
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
@ -506,9 +534,9 @@ func (s *TxByPriceAndTime) Pop() interface{} {
|
|||||||
// entire batches of transactions for non-executable accounts.
|
// entire batches of transactions for non-executable accounts.
|
||||||
type TransactionsByPriceAndNonce struct {
|
type TransactionsByPriceAndNonce struct {
|
||||||
txs map[core.Address]Transactions // Per account nonce-sorted list of transactions
|
txs map[core.Address]Transactions // Per account nonce-sorted list of transactions
|
||||||
heads TxByPriceAndTime // Next transaction for each unique account (price heap)
|
heads TxByPriceAndTime // Next transaction for each unique account (price heap)
|
||||||
signer Signer // Signer for the set of transactions
|
signer Signer // Signer for the set of transactions
|
||||||
baseFee *big.Int // Current base fee
|
baseFee *big.Int // Current base fee
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTransactionsByPriceAndNonce creates a transaction set that can retrieve
|
// NewTransactionsByPriceAndNonce creates a transaction set that can retrieve
|
||||||
@ -569,70 +597,11 @@ func (t *TransactionsByPriceAndNonce) Pop() {
|
|||||||
heap.Pop(&t.heads)
|
heap.Pop(&t.heads)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message is a fully derived transaction and implements core.Message
|
// copyAddressPtr copies an address.
|
||||||
//
|
func copyAddressPtr(a *core.Address) *core.Address {
|
||||||
// NOTE: In a future PR this will be removed.
|
if a == nil {
|
||||||
type Message struct {
|
return nil
|
||||||
to *core.Address
|
|
||||||
from core.Address
|
|
||||||
nonce uint64
|
|
||||||
amount *big.Int
|
|
||||||
gasLimit uint64
|
|
||||||
gasPrice *big.Int
|
|
||||||
gasFeeCap *big.Int
|
|
||||||
gasTipCap *big.Int
|
|
||||||
data []byte
|
|
||||||
accessList AccessList
|
|
||||||
checkNonce bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMessage(from core.Address, to *core.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, data []byte, accessList AccessList, checkNonce bool) Message {
|
|
||||||
return Message{
|
|
||||||
from: from,
|
|
||||||
to: to,
|
|
||||||
nonce: nonce,
|
|
||||||
amount: amount,
|
|
||||||
gasLimit: gasLimit,
|
|
||||||
gasPrice: gasPrice,
|
|
||||||
gasFeeCap: gasFeeCap,
|
|
||||||
gasTipCap: gasTipCap,
|
|
||||||
data: data,
|
|
||||||
accessList: accessList,
|
|
||||||
checkNonce: checkNonce,
|
|
||||||
}
|
}
|
||||||
|
cpy := *a
|
||||||
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsMessage returns the transaction as a core.Message.
|
|
||||||
func (tx *Transaction) AsMessage(s Signer, baseFee *big.Int) (Message, error) {
|
|
||||||
msg := Message{
|
|
||||||
nonce: tx.Nonce(),
|
|
||||||
gasLimit: tx.Gas(),
|
|
||||||
gasPrice: new(big.Int).Set(tx.GasPrice()),
|
|
||||||
gasFeeCap: new(big.Int).Set(tx.GasFeeCap()),
|
|
||||||
gasTipCap: new(big.Int).Set(tx.GasTipCap()),
|
|
||||||
to: tx.To(),
|
|
||||||
amount: tx.Value(),
|
|
||||||
data: tx.Data(),
|
|
||||||
accessList: tx.AccessList(),
|
|
||||||
checkNonce: true,
|
|
||||||
}
|
|
||||||
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
|
||||||
if baseFee != nil {
|
|
||||||
msg.gasPrice = bigMin(msg.gasPrice.Add(msg.gasTipCap, baseFee), msg.gasFeeCap)
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
msg.from, err = Sender(s, tx)
|
|
||||||
return msg, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m Message) From() core.Address { return m.from }
|
|
||||||
func (m Message) To() *core.Address { return m.to }
|
|
||||||
func (m Message) GasPrice() *big.Int { return m.gasPrice }
|
|
||||||
func (m Message) GasFeeCap() *big.Int { return m.gasFeeCap }
|
|
||||||
func (m Message) GasTipCap() *big.Int { return m.gasTipCap }
|
|
||||||
func (m Message) Value() *big.Int { return m.amount }
|
|
||||||
func (m Message) Gas() uint64 { return m.gasLimit }
|
|
||||||
func (m Message) Nonce() uint64 { return m.nonce }
|
|
||||||
func (m Message) Data() []byte { return m.data }
|
|
||||||
func (m Message) AccessList() AccessList { return m.accessList }
|
|
||||||
func (m Message) CheckNonce() bool { return m.checkNonce }
|
|
||||||
|
Loading…
Reference in New Issue
Block a user