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

[PoC] cmd/evm: malicious bloated 1559 transactions poc #22963

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions cmd/evm/internal/t8ntool/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ var (
Value: "env.json",
}
InputTxsFlag = cli.StringFlag{
Name: "input.txs",
Usage: "`stdin` or file name of where to find the transactions to apply.",
Name: "input.txs",
Usage: "`stdin` or file name of where to find the transactions to apply. " +
"If the file prefix is '.rlp', then the data is interpreted as an RLP list of signed transactions." +
"The '.rlp' format is identical to the output.body format.",
Value: "txs.json",
}
RewardFlag = cli.Int64Flag{
Expand Down
24 changes: 22 additions & 2 deletions cmd/evm/internal/t8ntool/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"math/big"
"os"
"path"
"strings"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand Down Expand Up @@ -199,8 +200,25 @@ func Main(ctx *cli.Context) error {
}
defer inFile.Close()
decoder := json.NewDecoder(inFile)
if err := decoder.Decode(&txsWithKeys); err != nil {
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
if strings.HasSuffix(txStr, ".rlp") {
var body hexutil.Bytes
if err := decoder.Decode(&body); err != nil {
return err
}
var txs types.Transactions
if err := rlp.DecodeBytes(body, &txs); err != nil {
return err
}
for _, tx := range txs {
txsWithKeys = append(txsWithKeys, &txWithKey{
key: nil,
tx: tx,
})
}
} else {
if err := decoder.Decode(&txsWithKeys); err != nil {
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
}
}
} else {
txsWithKeys = inputData.Txs
Expand Down Expand Up @@ -365,13 +383,15 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
}
os.Stdout.Write(b)
os.Stdout.Write([]byte("\n"))
}
if len(stdErrObject) > 0 {
b, err := json.MarshalIndent(stdErrObject, "", " ")
if err != nil {
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
}
os.Stderr.Write(b)
os.Stderr.Write([]byte("\n"))
}
return nil
}
23 changes: 23 additions & 0 deletions cmd/evm/testdata/12/alloc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"0x1111111111111111111111111111111111111111" : {
"balance" : "0x010000000000",
"code" : "0xfe",
"nonce" : "0x01",
"storage" : {
}
},
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x010000000000",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
},
"0xd02d72e067e77158444ef2020ff2d325f929b363" : {
"balance" : "0x01000000000000",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
}
}
12 changes: 12 additions & 0 deletions cmd/evm/testdata/12/env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x020000",
"currentNumber" : "0x01",
"currentTimestamp" : "0x079e",
"previousHash" : "0xcb23ee65a163121f640673b41788ee94633941405f95009999b502eedfbbfd4f",
"currentGasLimit" : "0x40000000",
"currentBaseFee" : "0x036b",
"blockHashes" : {
"0" : "0xcb23ee65a163121f640673b41788ee94633941405f95009999b502eedfbbfd4f"
}
}
70 changes: 70 additions & 0 deletions cmd/evm/testdata/12/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
## EIP-1559 malicious bloat

This test contains testcases for EIP-1559, which tests an attack where transactions are bloated.
The transactions uses a `1Mb`-sized integer to specify either `max_priority_fee_per_gas` or `max_fee_per_gas`.

What they actually pay is

priority_fee_per_gas = min(transaction.max_priority_fee_per_gas, transaction.max_fee_per_gas - block.base_fee_per_gas)

So it is possible to dump huge amount of data into one of the fields.
A user can maliciously bombard blocks with no penalty, and a miner can create basically arbitrary large blocks.

There are two transactions in `txs.rlp`, the first one with `512K` `max_fee_per_gas` (a.k.a `feeCap`), the second with `512K` `max_priority_fee_per_gas` (a.k.a `tip`).
The `txs.json` is what was used to generate the two malicious ones.

This attack is a bit hard to pull off, even on a testnet. In various json-conversions, go-ethereum does not allow
marshallling integers above `256` bits. Further, the txpool rejects oversized transactions, and is also erroneously
calculating the `cost` of a transaction.

This PoC shows that the _consensus engine_ accepts such bloated transactions. This means that a valid block, post 1559, can be arbitrarily
large, _without_ that extra bloat costing anything (except for the miner who increases the chance to be uncled).


```
$ dir=./testdata/12 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.rlp --input.env=$dir/env.json --output.result=stdout --verbosity 5
INFO [05-28|09:32:06.392] Trie dumping started root=12d94e..ef3b17
INFO [05-28|09:32:06.392] Trie dumping complete accounts=4 elapsed="282.184µs"
INFO [05-28|09:32:06.392] Wrote file file=alloc.json
```
Output:
```json
{
"result": {
"stateRoot": "0x12d94ef874c8ae6aaf016f24398f2ba5344b07d787038afb17d54432e8ef3b17",
"txRoot": "0x0037cd520bc14053499608731ebb11974ae4ca10150f2f9f4caa76e478cb56d8",
"receiptRoot": "0xa532a08aa9f62431d6fe5d924951b8efb86ed3c54d06fee77788c3767dd13420",
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"receipts": [
{
"type": "0x2",
"root": "0x",
"status": "0x0",
"cumulativeGasUsed": "0x84d0",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"logs": null,
"transactionHash": "0x5dd0bd036f9d2dfdc92bb94377194fd13c6ae55b022d546942b1b3e60e46a2c2",
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x84d0",
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"transactionIndex": "0x0"
},
{
"type": "0x2",
"root": "0x",
"status": "0x0",
"cumulativeGasUsed": "0x109a0",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"logs": null,
"transactionHash": "0x493a42e091d6b01e5df82238933fb4429b582f6b62b339db2062ab69092bce19",
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x84d0",
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"transactionIndex": "0x1"
}
]
}
}
```

34 changes: 34 additions & 0 deletions cmd/evm/testdata/12/txs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"input" : "0x",
"gas" : "0x84d0",
"nonce" : "0x1",
"to" : "0x1111111111111111111111111111111111111111",
"value" : "0x0",
"v" : "0x0",
"r" : "0x0",
"s" : "0x0",
"secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298",
"chainId" : "0x1",
"type" : "0x2",
"feeCap" : "0xfa0",
"tip" : "0x0",
"accessList" : []
},
{
"input" : "0x",
"gas" : "0x84d0",
"nonce" : "0x2",
"to" : "0x1111111111111111111111111111111111111111",
"value" : "0x0",
"v" : "0x0",
"r" : "0x0",
"s" : "0x0",
"secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298",
"chainId" : "0x1",
"type" : "0x2",
"feeCap" : "0xfa0",
"tip" : "0x0",
"accessList" : []
}
]
1 change: 1 addition & 0 deletions cmd/evm/testdata/12/txs.rlp

Large diffs are not rendered by default.