Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

EIP-2718: Typed Transaction Envelope + EIP-2930 #21502

Merged
merged 83 commits into from
Feb 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
cb87b43
all: implement EIP-2718 + EIP-2930
lightclient Sep 4, 2020
1a70454
core/types, core/tx_pool: if access list not provided, set to empty l…
lightclient Nov 11, 2020
4ea3eeb
core/types: tests for accesslist transactions
holiman Nov 10, 2020
a457ae9
accounts/keystore, internal/ethapi: implement ethapi support for acl …
holiman Jan 12, 2021
b35f4d9
core/types, cmd/evm: integrate acl-tx into evm t8n + examples
holiman Jan 21, 2021
03ce4d8
core/types: rename tx json marshaller
lightclient Jan 22, 2021
27139df
cmd/evm: make evm t8n output block body (optional)
holiman Jan 23, 2021
5ae76df
eth: properly handle 2930 in api tracer
holiman Jan 24, 2021
ab662a8
core, eth, internal, light: fix rebase issues yolov2 -> yolov3
holiman Jan 29, 2021
a990187
cmd/geth, utils, params: re-enable --yolov3 switch + fix datadir + co…
holiman Jan 29, 2021
4b27811
internal/ethapi: add access list tx fields to RPC responses + fix sen…
holiman Jan 29, 2021
3871a11
core: remove json blockchain tests, fix unused imports
lightclient Jan 30, 2021
9a0b788
internal/t8ntool: output block body as hex-encoded string, same outpu…
holiman Feb 1, 2021
6efe70d
all: refactor access list handling + fix flaw in t8n
holiman Feb 3, 2021
68bfe72
cmd/geth: correct log output on yolov3
holiman Feb 4, 2021
ba9db21
core/types: update tx signing hash according to https://github.com/et…
holiman Feb 9, 2021
852ffce
core/types: add test for input to derivesha
holiman Feb 10, 2021
4d236b1
core/types: use switch
fjl Feb 11, 2021
ee783aa
core/types: clean up encoder
fjl Feb 11, 2021
11468ed
core/types: clean up WithSignature
fjl Feb 11, 2021
c6d1881
core/types: implement DeriveSha in a diffent way
fjl Feb 11, 2021
27b8e16
core/types: rename inner -> innerTx and remove docs
fjl Feb 11, 2021
e3afa34
core/types: use encoder buffer pool in EncodeRLP
fjl Feb 11, 2021
00bd0f1
core/types: add DeriveSha tests from StackTrie
fjl Feb 12, 2021
c980866
core/types: fix ineffectual assignment
fjl Feb 12, 2021
a25bc38
core/types: update receipt RLP handling
fjl Feb 12, 2021
27f966f
core/types: fix crash when decoding empty typed tx / receipt
fjl Feb 12, 2021
94feb0f
core/types: add missing tests
fjl Feb 12, 2021
c0b5059
core/types: add methods for EIP2718 canon encoding
fjl Feb 12, 2021
90eccc7
core/types: use encodeTyped in one more place
fjl Feb 12, 2021
0a59de2
internal/ethapi: canon format in fillTransaction and sendRawTransaction
fjl Feb 12, 2021
6e94273
internal/ethapi: fixup
fjl Feb 12, 2021
a3e4006
core/types: group simple tx accessors
fjl Feb 12, 2021
7d85a1d
core/types: rename tx type enum values
fjl Feb 12, 2021
c97925e
core/types: rename transaction types
fjl Feb 12, 2021
e8d48ea
core/types: remove CheckNonce of Transaction
fjl Feb 12, 2021
29cd03e
core/types: remove CheckNonce from innerTx
fjl Feb 12, 2021
4df70a5
internal/ethapi: use MarshallBinary in a few more places
holiman Feb 12, 2021
fb9517a
all: use Marshall/UnmarshallBinary over rlp for transactions
holiman Feb 12, 2021
0509791
core, params, cmd/utils: redefine yolov3 as yolov3x
holiman Feb 13, 2021
3a053a8
core: fix panic in prefetcher, due to 2930-access list not having bee…
holiman Feb 14, 2021
c1ebe42
core/types: fix decoding error due to shadowing
holiman Feb 14, 2021
1013bb4
core/types: fix flaw in receipt test
holiman Feb 15, 2021
54718c3
internal/ethapi: Fix use correct signer in GetTransactionReceipt
ryanschneider Feb 17, 2021
9bdc7ab
core/types: improve transaction JSON handling
fjl Feb 17, 2021
4a28669
core/types: use switch in new signer
fjl Feb 18, 2021
cdabbb0
core/types: reject typed transactions in legacy signers
fjl Feb 18, 2021
6eeeccd
core: remove extra checks for tx type
fjl Feb 18, 2021
52359ac
cmd/evm/internal/t8ntool: remove check for tx type
fjl Feb 18, 2021
ced016e
core: move access list setup into ApplyMessage
fjl Feb 18, 2021
02c1cbf
core: remove extra check for tx type in txpool
fjl Feb 18, 2021
5da8a0f
core: ensure there is only one error for unsupported tx type
fjl Feb 18, 2021
389f039
core/types: clean up innerTx accessors
fjl Feb 19, 2021
68e304b
core/types: remove tx.typ
fjl Feb 19, 2021
81a5bdc
core/types: document transaction accessors
fjl Feb 19, 2021
a05771d
core/types, miner, params: fix signer-flaw/crash in miner, add yolov3…
holiman Feb 19, 2021
ec78fe9
core/types: add NewTx constructor
fjl Feb 19, 2021
f02d1d1
core/types: add MustSignNewTx
fjl Feb 19, 2021
6e99680
miner: fix tests
fjl Feb 19, 2021
3f316e7
miner: use MakeSigner
fjl Feb 19, 2021
59fcaf8
internal/ethapi: use MakeSigner in getTransactionReceipt
fjl Feb 19, 2021
3b92b59
internal/ethapi: fix compile flaw
holiman Feb 21, 2021
dc796a4
internal/ethapi: use EIP2718 signer
fjl Feb 22, 2021
068899b
internal/ethapi: set "type" for all transactions
fjl Feb 22, 2021
3cde545
core/types: make access list optional in JSON
fjl Feb 22, 2021
c0743fe
internal/ethapi: always return tx type, part 2
fjl Feb 22, 2021
d866788
core/types: un-pointer access lists
fjl Feb 22, 2021
857123f
core/types: add documentation for access list transaction types
fjl Feb 22, 2021
f5af3c4
core/types: use copy() in WithSignature
fjl Feb 22, 2021
0fbc048
core/types: add documentation comment for LegacyTx
fjl Feb 22, 2021
fa857ea
core/types: remove AccessList.Addresses
fjl Feb 22, 2021
130c1e5
cmd/evm: fix t8ntool receipt root hash
holiman Feb 23, 2021
0578680
core: simplify receipt logic in state processor
holiman Feb 23, 2021
131c388
core/types: remove NewEIP2718Receipt
fjl Feb 23, 2021
b744467
core/types: rename LegacyTx/AccessListTx fields
fjl Feb 23, 2021
20b14c6
core/types: add API to get the latest signer
fjl Feb 23, 2021
406af1b
core/types: rename and unexport EIP2718Signer
fjl Feb 23, 2021
ee66c67
miner: fix test
fjl Feb 23, 2021
559cb21
core/types: make the receipt-type 0x-prefixed string in json
holiman Feb 24, 2021
dd2483c
core/types: fix chain ID handling in eip2930Signer
fjl Feb 24, 2021
dfba23b
ethclient: fix signer
fjl Feb 24, 2021
8f1528e
core/types: fix check in tx decoder
fjl Feb 25, 2021
9750e9b
core: move tx type check earlier
fjl Feb 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions accounts/abi/bind/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accou
if chainID == nil {
return nil, ErrNoChainID
}
signer := types.NewEIP155Signer(chainID)
signer := types.LatestSignerForChainID(chainID)
return &TransactOpts{
From: account.Address,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
Expand All @@ -143,7 +143,7 @@ func NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *big.Int) (*Tr
if chainID == nil {
return nil, ErrNoChainID
}
signer := types.NewEIP155Signer(chainID)
signer := types.LatestSignerForChainID(chainID)
return &TransactOpts{
From: keyAddr,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
Expand Down
25 changes: 15 additions & 10 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,10 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
b.mu.Lock()
defer b.mu.Unlock()

sender, err := types.Sender(types.NewEIP155Signer(b.config.ChainID), tx)
// Check transaction validity.
block := b.blockchain.CurrentBlock()
signer := types.MakeSigner(b.blockchain.Config(), block.Number())
sender, err := types.Sender(signer, tx)
if err != nil {
panic(fmt.Errorf("invalid transaction: %v", err))
}
Expand All @@ -568,7 +571,8 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce))
}

blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
// Include tx in chain.
blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
for _, tx := range b.pendingBlock.Transactions() {
block.AddTxWithChain(b.blockchain, tx)
}
Expand Down Expand Up @@ -707,14 +711,15 @@ type callMsg struct {
ethereum.CallMsg
}

func (m callMsg) From() common.Address { return m.CallMsg.From }
func (m callMsg) Nonce() uint64 { return 0 }
func (m callMsg) CheckNonce() bool { return false }
func (m callMsg) To() *common.Address { return m.CallMsg.To }
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callMsg) Data() []byte { return m.CallMsg.Data }
func (m callMsg) From() common.Address { return m.CallMsg.From }
func (m callMsg) Nonce() uint64 { return 0 }
func (m callMsg) CheckNonce() bool { return false }
func (m callMsg) To() *common.Address { return m.CallMsg.To }
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callMsg) Data() []byte { return m.CallMsg.Data }
func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList }

// filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account.
Expand Down
17 changes: 6 additions & 11 deletions accounts/keystore/keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,9 @@ func (ks *KeyStore) SignTx(a accounts.Account, tx *types.Transaction, chainID *b
if !found {
return nil, ErrLocked
}
// Depending on the presence of the chain ID, sign with EIP155 or homestead
if chainID != nil {
return types.SignTx(tx, types.NewEIP155Signer(chainID), unlockedKey.PrivateKey)
}
return types.SignTx(tx, types.HomesteadSigner{}, unlockedKey.PrivateKey)
// Depending on the presence of the chain ID, sign with 2718 or homestead
signer := types.LatestSignerForChainID(chainID)
return types.SignTx(tx, signer, unlockedKey.PrivateKey)
}

// SignHashWithPassphrase signs hash if the private key matching the given address
Expand All @@ -310,12 +308,9 @@ func (ks *KeyStore) SignTxWithPassphrase(a accounts.Account, passphrase string,
return nil, err
}
defer zeroKey(key.PrivateKey)

// Depending on the presence of the chain ID, sign with EIP155 or homestead
if chainID != nil {
return types.SignTx(tx, types.NewEIP155Signer(chainID), key.PrivateKey)
}
return types.SignTx(tx, types.HomesteadSigner{}, key.PrivateKey)
// Depending on the presence of the chain ID, sign with or without replay protection.
signer := types.LatestSignerForChainID(chainID)
return types.SignTx(tx, signer, key.PrivateKey)
}

// Unlock unlocks the given account indefinitely.
Expand Down
2 changes: 1 addition & 1 deletion accounts/scwallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ func (w *Wallet) signHash(account accounts.Account, hash []byte) ([]byte, error)
// the needed details via SignTxWithPassphrase, or by other means (e.g. unlock
// the account in a keystore).
func (w *Wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
signer := types.NewEIP155Signer(chainID)
signer := types.LatestSignerForChainID(chainID)
hash := signer.Hash(tx)
sig, err := w.signHash(account, hash[:])
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions accounts/usbwallet/trezor.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,11 @@ func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction
if chainID == nil {
signer = new(types.HomesteadSigner)
} else {
// Trezor backend does not support typed transactions yet.
signer = types.NewEIP155Signer(chainID)
signature[64] -= byte(chainID.Uint64()*2 + 35)
}

// Inject the final signature into the transaction and sanity check the sender
signed, err := tx.WithSignature(signer, signature)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/clef/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ func GenDoc(ctx *cli.Context) {

rlpdata := common.FromHex("0xf85d640101948a8eafb1cf62bfbeb1741769dae1a9dd47996192018026a0716bd90515acb1e68e5ac5867aa11a1e65399c3349d479f5fb698554ebc6f293a04e8a4ebfff434e971e0ef12c5bf3a881b06fd04fc3f8b8a7291fb67a26a1d4ed")
var tx types.Transaction
rlp.DecodeBytes(rlpdata, &tx)
tx.UnmarshalBinary(rlpdata)
add("OnApproved - SignTransactionResult", desc, &ethapi.SignTransactionResult{Raw: rlpdata, Tx: &tx})

}
Expand Down
17 changes: 8 additions & 9 deletions cmd/evm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Command line params that has to be supported are
--trace.nomemory Disable full memory dump in traces
--trace.nostack Disable stack output in traces
--trace.noreturndata Disable return data output in traces
--output.basedir value Specifies where output files are placed. Will be created if it does not exist. (default: ".")
--output.basedir value Specifies where output files are placed. Will be created if it does not exist.
--output.alloc alloc Determines where to put the alloc of the post-state.
`stdout` - into the stdout output
`stderr` - into the stderr output
Expand Down Expand Up @@ -237,10 +237,10 @@ Example where blockhashes are provided:
cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
```
```
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"STOP","error":""}
{"output":"","gasUsed":"0x17","time":112885}
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"STOP","error":""}
{"output":"","gasUsed":"0x17","time":142709}
```

In this example, the caller has not provided the required blockhash:
Expand All @@ -256,9 +256,9 @@ Error code: 4
Another thing that can be done, is to chain invocations:
```
./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --output.alloc=stdout | ./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json
INFO [08-03|15:25:15.168] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
INFO [08-03|15:25:15.169] rejected tx index=0 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
INFO [08-03|15:25:15.169] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
INFO [01-21|22:41:22.963] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
INFO [01-21|22:41:22.966] rejected tx index=0 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
INFO [01-21|22:41:22.967] rejected tx index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"

```
What happened here, is that we first applied two identical transactions, so the second one was rejected.
Expand All @@ -267,4 +267,3 @@ the same two transactions: this time, both failed due to too low nonce.

In order to meaningfully chain invocations, one would need to provide meaningful new `env`, otherwise the
actual blocknumber (exposed to the EVM) would not increase.

37 changes: 19 additions & 18 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
vmConfig.Debug = (tracer != nil)
statedb.Prepare(tx.Hash(), blockHash, txIndex)
txContext := core.NewEVMTxContext(msg)

evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig)
if chainConfig.IsYoloV3(vmContext.BlockNumber) {
statedb.AddAddressToAccessList(msg.From())
if dst := msg.To(); dst != nil {
statedb.AddAddressToAccessList(*dst)
// If it's a create-tx, the destination will be added inside evm.create
}
for _, addr := range evm.ActivePrecompiles() {
statedb.AddAddressToAccessList(addr)
}
}
snapshot := statedb.Snapshot()
evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig)

// (ret []byte, usedGas uint64, failed bool, err error)
msgResult, err := core.ApplyMessage(evm, msg, gaspool)
if err != nil {
Expand All @@ -169,7 +159,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return nil, nil, NewError(ErrorMissingBlockhash, hashError)
}
gasUsed += msgResult.UsedGas
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx

// Receipt:
{
var root []byte
if chainConfig.IsByzantium(vmContext.BlockNumber) {
Expand All @@ -178,22 +169,32 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
root = statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber)).Bytes()
}

receipt := types.NewReceipt(root, msgResult.Failed(), gasUsed)
// Create a new receipt for the transaction, storing the intermediate root and
// gas used by the tx.
receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: gasUsed}
if msgResult.Failed() {
receipt.Status = types.ReceiptStatusFailed
} else {
receipt.Status = types.ReceiptStatusSuccessful
}
receipt.TxHash = tx.Hash()
receipt.GasUsed = msgResult.UsedGas
// if the transaction created a contract, store the creation address in the receipt.

// If the transaction created a contract, store the creation address in the receipt.
if msg.To() == nil {
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
}
// Set the receipt logs and create a bloom for filtering

// Set the receipt logs and create the bloom filter.
receipt.Logs = statedb.GetLogs(tx.Hash())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
// These three are non-consensus fields
// These three are non-consensus fields:
//receipt.BlockHash
//receipt.BlockNumber =
//receipt.BlockNumber
receipt.TransactionIndex = uint(txIndex)
receipts = append(receipts, receipt)
}

txIndex++
}
statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber))
Expand Down
5 changes: 5 additions & 0 deletions cmd/evm/internal/t8ntool/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ var (
Usage: "Specifies where output files are placed. Will be created if it does not exist.",
Value: "",
}
OutputBodyFlag = cli.StringFlag{
Name: "output.body",
Usage: "If set, the RLP of the transactions (block body) will be written to this file.",
Value: "",
}
OutputAllocFlag = cli.StringFlag{
Name: "output.alloc",
Usage: "Determines where to put the `alloc` of the post-state.\n" +
Expand Down
Loading