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

all: implement eip-1559 #22837

Merged
merged 19 commits into from
May 17, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,8 @@ 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) FeeCap() *big.Int { return m.CallMsg.FeeCap }
func (m callMsg) Tip() *big.Int { return m.CallMsg.Tip }
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 }
Expand Down
38 changes: 20 additions & 18 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,15 @@ type ommer struct {
Address common.Address `json:"address"`
}

//go:generate gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
type stEnv struct {
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
Difficulty *big.Int `json:"currentDifficulty" gencodec:"required"`
GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
Number uint64 `json:"currentNumber" gencodec:"required"`
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
Ommers []ommer `json:"ommers,omitempty"`
}

type stEnvMarshaling struct {
Coinbase common.UnprefixedAddress
Difficulty *math.HexOrDecimal256
GasLimit math.HexOrDecimal64
Number math.HexOrDecimal64
Timestamp math.HexOrDecimal64
Coinbase common.Address
Difficulty *big.Int
GasLimit uint64
BaseFee *big.Int
Number uint64
Timestamp uint64
BlockHashes map[math.HexOrDecimal64]common.Hash
Ommers []ommer
}

// Apply applies a set of transactions to a pre-state
Expand Down Expand Up @@ -109,7 +101,13 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
receipts = make(types.Receipts, 0)
txIndex = 0
)
gaspool.AddGas(pre.Env.GasLimit)

if chainConfig.IsLondon(new(big.Int).SetUint64(pre.Env.Number)) {
holiman marked this conversation as resolved.
Show resolved Hide resolved
gaspool.AddGas(pre.Env.GasLimit * params.ElasticityMultiplier)
} else {
gaspool.AddGas(pre.Env.GasLimit)
}

vmContext := vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
Expand All @@ -120,6 +118,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
GasLimit: pre.Env.GasLimit,
GetHash: getHash,
}
// If currentBaseFee is defined, add it to the vmContext.
if pre.Env.BaseFee != nil {
vmContext.BaseFee = new(big.Int).Set(pre.Env.BaseFee)
}
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
// done in StateProcessor.Process(block, ...), right before transactions are applied.
if chainConfig.DAOForkSupport &&
Expand All @@ -129,7 +131,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
}

for i, tx := range txs {
msg, err := tx.AsMessage(signer)
msg, err := tx.AsMessage(signer, pre.Env.BaseFee)
if err != nil {
log.Info("rejected tx", "index", i, "hash", tx.Hash(), "error", err)
rejectedTxs = append(rejectedTxs, i)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.

package t8ntool

import (
Expand All @@ -11,38 +9,16 @@ import (
"github.com/ethereum/go-ethereum/common/math"
)

var _ = (*stEnvMarshaling)(nil)

// MarshalJSON marshals as JSON.
func (s stEnv) MarshalJSON() ([]byte, error) {
type stEnv struct {
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
Ommers []ommer `json:"ommers,omitempty"`
}
var enc stEnv
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty)
enc.GasLimit = math.HexOrDecimal64(s.GasLimit)
enc.Number = math.HexOrDecimal64(s.Number)
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
enc.BlockHashes = s.BlockHashes
enc.Ommers = s.Ommers
return json.Marshal(&enc)
}

// UnmarshalJSON unmarshals from JSON.
func (s *stEnv) UnmarshalJSON(input []byte) error {
type stEnv struct {
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
Coinbase *common.UnprefixedAddress `json:"currentCoinbase"`
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
GasLimit *math.HexOrDecimal64 `json:"currentGasLimit"`
GasTarget *math.HexOrDecimal64 `json:"currentGasTarget"`
holiman marked this conversation as resolved.
Show resolved Hide resolved
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
Number *math.HexOrDecimal64 `json:"currentNumber"`
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp"`
BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
Ommers []ommer `json:"ommers,omitempty"`
}
Expand All @@ -58,10 +34,19 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'currentDifficulty' for stEnv")
}
s.Difficulty = (*big.Int)(dec.Difficulty)
if dec.GasLimit == nil {
return errors.New("missing required field 'currentGasLimit' for stEnv")
switch {
case dec.GasLimit == nil && dec.GasTarget == nil:
return errors.New("at least one of 'currentGasLimit' or 'currentGasTarget' must be defined")
case dec.GasLimit != nil && dec.GasTarget != nil:
return errors.New("only one of 'currentGasLimit' or 'currentGasTarget' may be defined")
case dec.GasLimit != nil && dec.GasTarget == nil:
s.GasLimit = uint64(*dec.GasLimit)
case dec.GasLimit == nil && dec.GasTarget != nil:
s.GasLimit = uint64(*dec.GasTarget)
}
if dec.BaseFee != nil {
s.BaseFee = (*big.Int)(dec.BaseFee)
}
s.GasLimit = uint64(*dec.GasLimit)
if dec.Number == nil {
return errors.New("missing required field 'currentNumber' for stEnv")
}
Expand Down
23 changes: 0 additions & 23 deletions cmd/evm/poststate.json

This file was deleted.

11 changes: 11 additions & 0 deletions cmd/evm/testdata/9/alloc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"0x000000000000000000000000000000000000aaaa": {
"balance": "0x03",
"code": "0x58585454",
"nonce": "0x1"
},
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"balance": "0x100000000000000",
"nonce": "0x00"
}
}
8 changes: 8 additions & 0 deletions cmd/evm/testdata/9/env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty": "0x20000",
"currentGasTarget": "0x1000000000",
"currentBaseFee": "0x3B9ACA00",
"currentNumber": "0x1000000",
"currentTimestamp": "0x04"
}
75 changes: 75 additions & 0 deletions cmd/evm/testdata/9/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
## EIP-1559 testing

This test contains testcases for EIP-1559, which uses an new transaction type and has a new block parameter.

### Prestate

The alloc portion contains one contract (`0x000000000000000000000000000000000000aaaa`), containing the
following code: `0x58585454`: `PC; PC; SLOAD; SLOAD`.

Essentialy, this contract does `SLOAD(0)` and `SLOAD(1)`.

The alloc also contains some funds on `0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b`.

## Transactions

There are two transactions, each invokes the contract above.

1. EIP-1559 ACL-transaction, which contains the `0x0` slot for `0xaaaa`
2. Legacy transaction

## Execution

Running it yields:
```
$ dir=./testdata/9 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --trace && cat trace-* | grep SLOAD
{"pc":2,"op":84,"gas":"0x48c28","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0","0x1"],"returnStack":null,"returnD
ata":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""}
{"pc":3,"op":84,"gas":"0x483f4","gasCost":"0x64","memory":"0x","memSize":0,"stack":["0x0","0x0"],"returnStack":null,"returnDa
ta":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""}
{"pc":2,"op":84,"gas":"0x49cf4","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0","0x1"],"returnStack":null,"returnD
ata":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""}
{"pc":3,"op":84,"gas":"0x494c0","gasCost":"0x834","memory":"0x","memSize":0,"stack":["0x0","0x0"],"returnStack":null,"returnD
ata":"0x","depth":1,"refund":0,"opName":"SLOAD","error":""}
```

We can also get the post-alloc:
```
$ dir=./testdata/9 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout
{
"alloc": {
"0x000000000000000000000000000000000000aaaa": {
"code": "0x58585454",
"balance": "0x3",
"nonce": "0x1"
},
"0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": {
"balance": "0xbfc02677a000"
},
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"balance": "0xff104fcfea7800",
"nonce": "0x2"
}
}
}
```

If we try to execute it on older rules:
```
dir=./testdata/9 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout
ERROR(10): Failed signing transactions: ERROR(10): Tx 0: failed to sign tx: transaction type not supported
```

It fails, due to the `evm t8n` cannot sign them in with the given signer. We can bypass that, however,
by feeding it presigned transactions, located in `txs_signed.json`.

```
dir=./testdata/9 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json --input.txs=$dir/txs_signed.json --input.env=$dir/env.json
INFO [05-07|12:28:42.072] rejected tx index=0 hash=b4821e..536819 error="transaction type not supported"
INFO [05-07|12:28:42.072] rejected tx index=1 hash=a9c6c6..fa4036 from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="nonce too high: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B, tx: 1 state: 0"
INFO [05-07|12:28:42.073] Wrote file file=alloc.json
INFO [05-07|12:28:42.073] Wrote file file=result.json
```

Number `0` is not applicable, and therefore number `1` has wrong nonce, and both are rejected.

37 changes: 37 additions & 0 deletions cmd/evm/testdata/9/txs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"gas": "0x4ef00",
"tip": "0x2",
"feeCap": "0x12A05F200",
"chainId": "0x1",
"input": "0x",
"nonce": "0x0",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"type" : "0x2",
"accessList": [
{"address": "0x000000000000000000000000000000000000aaaa",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
}
],
"v": "0x0",
"r": "0x0",
"s": "0x0",
"secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"
},
{
"gas": "0x4ef00",
"gasPrice": "0x12A05F200",
"chainId": "0x1",
"input": "0x",
"nonce": "0x1",
"to": "0x000000000000000000000000000000000000aaaa",
"value": "0x0",
"v": "0x0",
"r": "0x0",
"s": "0x0",
"secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"
}
]
27 changes: 20 additions & 7 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,6 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
if header.GasLimit > cap {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
}
// Verify that the gasUsed is <= gasLimit
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
// If all checks passed, validate any special fields for hard forks
if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil {
return err
Expand Down Expand Up @@ -334,12 +330,26 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header
if parent.Time+c.config.Period > header.Time {
return errInvalidTimestamp
}
// Verify that the gasUsed is <= gasLimit
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
if !chain.Config().IsLondon(header.Number) {
// Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee)
}
} else if err := misc.VerifyEip1559Header(chain.Config(), parent, header); err != nil {
// Verify the header's EIP-1559 attributes.
return err
}
// Verify that the gas limit remains within allowed bounds
diff := int64(parent.GasLimit) - int64(header.GasLimit)
if diff < 0 {
diff *= -1
}
limit := parent.GasLimit / params.GasLimitBoundDivisor

if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
}
Expand Down Expand Up @@ -725,7 +735,7 @@ func CliqueRLP(header *types.Header) []byte {
}

func encodeSigHeader(w io.Writer, header *types.Header) {
err := rlp.Encode(w, []interface{}{
enc := []interface{}{
holiman marked this conversation as resolved.
Show resolved Hide resolved
header.ParentHash,
header.UncleHash,
header.Coinbase,
Expand All @@ -741,8 +751,11 @@ func encodeSigHeader(w io.Writer, header *types.Header) {
header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short
header.MixDigest,
header.Nonce,
})
if err != nil {
}
if header.BaseFee != nil {
enc = append(enc, header.BaseFee)
}
if err := rlp.Encode(w, enc); err != nil {
panic("can't encode: " + err.Error())
}
}
Loading