From 17199daa76590b581dfcc28d500fcbb6105c7e69 Mon Sep 17 00:00:00 2001 From: Shude Li Date: Mon, 20 Jan 2025 17:12:36 +0800 Subject: [PATCH 1/9] core/types: correct chainId check for pragueSigner (#31032) Use zero value check for the pragueSigner This aligns with cancunSigner and londonSigner as well. --- core/types/transaction_signing.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 4d70f37bd3..030fc472a0 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -219,7 +219,7 @@ func (s pragueSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big } // Check that chain ID of tx matches the signer. We also accept ID zero here, // because it indicates that the chain ID was not specified in the tx. - if txdata.ChainID != nil && txdata.ChainID.CmpBig(s.chainId) != 0 { + if txdata.ChainID.Sign() != 0 && txdata.ChainID.CmpBig(s.chainId) != 0 { return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId) } R, S, _ = decodeSignature(sig) @@ -287,7 +287,7 @@ func (s cancunSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big } // Check that chain ID of tx matches the signer. We also accept ID zero here, // because it indicates that the chain ID was not specified in the tx. - if txdata.ChainID.Sign() != 0 && txdata.ChainID.ToBig().Cmp(s.chainId) != 0 { + if txdata.ChainID.Sign() != 0 && txdata.ChainID.CmpBig(s.chainId) != 0 { return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId) } R, S, _ = decodeSignature(sig) From 448e16ad543e9b9be244b1bfdad3cdc009cbd6f0 Mon Sep 17 00:00:00 2001 From: levisyin Date: Tue, 21 Jan 2025 00:04:29 +0800 Subject: [PATCH 2/9] build: upgrade -dlgo version to Go 1.23.5 (#31037) --- build/checksums.txt | 98 ++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/build/checksums.txt b/build/checksums.txt index b0b7a73a3b..7270492ec9 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -5,56 +5,56 @@ # https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/ ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz -# version:golang 1.23.4 +# version:golang 1.23.5 # https://go.dev/dl/ -ad345ac421e90814293a9699cca19dd5238251c3f687980bbcae28495b263531 go1.23.4.src.tar.gz -459a09504f7ebf2cbcee6ac282c8f34f97651217b1feae64557dcdd392b9bb62 go1.23.4.aix-ppc64.tar.gz -0f4e569b2d38cb75cb2efcaf56beb42778ab5e46d89318fef39060fe36d7b9b7 go1.23.4.darwin-amd64.pkg -6700067389a53a1607d30aa8d6e01d198230397029faa0b109e89bc871ab5a0e go1.23.4.darwin-amd64.tar.gz -19c054eaf40c5fac65b027f7443c01382e493d3c8c42cf8b2504832ebddce037 go1.23.4.darwin-arm64.pkg -87d2bb0ad4fe24d2a0685a55df321e0efe4296419a9b3de03369dbe60b8acd3a go1.23.4.darwin-arm64.tar.gz -5e73dc89b44626677ec9d9aa4257d6d2ef1245502bc36a99385284910d0ade0a go1.23.4.dragonfly-amd64.tar.gz -8df26b1e71234756c1f0e82cfffba3f427c5a91a251844ada2c7694a6986c546 go1.23.4.freebsd-386.tar.gz -7de078d94d2af50ee9506ef7df85e4d12d4018b23e0b2cbcbc61d686f549b41a go1.23.4.freebsd-amd64.tar.gz -3f23e0a01cfe24e4160124cd7ab02bdd188264652074abdbce401c93f41e58a4 go1.23.4.freebsd-arm.tar.gz -986a20e7c94431f03b44b3c415abc698c7b4edc2ae8431f7ecae1c2429d4cfa2 go1.23.4.freebsd-arm64.tar.gz -25e39f005f977778ce963fc43089510fe7514f3cfc0358eab584de4ce9f181fb go1.23.4.freebsd-riscv64.tar.gz -7e1d52f93da68c3bab39e3d83f89944d7d151208e54fdc30b0eda2a3812661d7 go1.23.4.illumos-amd64.tar.gz -4a4a0e7587ef8c8a326439b957027f2791795e2d29d4ae3885b4091a48f843bc go1.23.4.linux-386.tar.gz -6924efde5de86fe277676e929dc9917d466efa02fb934197bc2eba35d5680971 go1.23.4.linux-amd64.tar.gz -16e5017863a7f6071363782b1b8042eb12c6ca4f4cd71528b2123f0a1275b13e go1.23.4.linux-arm64.tar.gz -1f1dda0dc7ce0b2295f57258ec5ef0803fd31b9ed0aa20e2e9222334e5755de1 go1.23.4.linux-armv6l.tar.gz -4f469179a335a1a7bb9f991ad0c567f3d3eeb9b412ecd192206ab5c3e1a52b5a go1.23.4.linux-loong64.tar.gz -86b68185bcc43ea07190e95137c3442f062acc7ae10c3f1cf900fbe23e07df24 go1.23.4.linux-mips.tar.gz -3a19245eec76533b3d01c90f3a40a38d63684028f0fd54d442dc9a9d03197891 go1.23.4.linux-mips64.tar.gz -b53a06fc8455f6a875329e8d2e24d39db298122c9cce6e948117022191f6c613 go1.23.4.linux-mips64le.tar.gz -66120a8105b8ba6559f4e6a13b1e39b433fb8032df9d1744e4486876fa1723ce go1.23.4.linux-mipsle.tar.gz -33be2bfb27f2821a65e9f6aba744c85ea7c5e233e16bac27bb3ec253bcd4e970 go1.23.4.linux-ppc64.tar.gz -65a303ef51e48ff77e004a6a5b4db6ce59495cd59c6af51b54bf4f786c01a1b9 go1.23.4.linux-ppc64le.tar.gz -7c40e9e0d722cef14ede765159ba297f4c6e3093bb106f10fbccf8564780049a go1.23.4.linux-riscv64.tar.gz -74aab82bf4eca7c26c830a5b0e2a31d193a4d5ba47045526b92473cc7188d7d7 go1.23.4.linux-s390x.tar.gz -dba009d8bf9928cb5a1e31fcbe0eb41335cce4fe63755d95cef6b5987df4ed5a go1.23.4.netbsd-386.tar.gz -54b081cc36355aa5ecb6db9544cf7e77366a7b08ce96cb98a45d043e393660c7 go1.23.4.netbsd-amd64.tar.gz -f05fec348c7c9f07e1ad4e436db4122e98de99ebcfbf6ac6176869785f334a02 go1.23.4.netbsd-arm.tar.gz -317878da2bface5a57a8eaf5c1fe2b40b1c82d8172a10453ad3eea36f6946bdb go1.23.4.netbsd-arm64.tar.gz -0d84350dfd72c505c6ad474e51676b04e95ffb748c614bd5bf8510026873059b go1.23.4.openbsd-386.tar.gz -cc62f5a14ea3d573d8edbce1833f70a8f99ca048a9db0fcc9e738fd48e950505 go1.23.4.openbsd-amd64.tar.gz -326aba6cf5bb9348fa3e41217abd2c84eac92608684e2fe8c5474fdab23a0db9 go1.23.4.openbsd-arm.tar.gz -51ea2a2588bf3da8e1476f3e2bd4d6724d74126e99f9c6ea9af4ebe389e64de6 go1.23.4.openbsd-arm64.tar.gz -44c5c82ab23e40225b2ba1e7d19150a5973ea58e93b4931e426e6e6f0d108872 go1.23.4.openbsd-ppc64.tar.gz -5fa31fc13d1e3c123a5e96ba38683fa2c947baed23ac9c7c341afcfe007c8993 go1.23.4.openbsd-riscv64.tar.gz -e5952fc93eeaa0094ef09a0e72a9f06f0621ce841a39f9637fb5b9062e77d67a go1.23.4.plan9-386.tar.gz -fb2a9ee3ae5a77e734862e257a9395b43e707ac45e060dfa84c5a40688e73170 go1.23.4.plan9-amd64.tar.gz -e1b95563b19fdebd6ea0d20c07641e69580976fa754e586c831ad7a3ae987140 go1.23.4.plan9-arm.tar.gz -088c282509fc9e1a8f29fc0dd16fe486854d05b8ceba08d077d17d11d6979a41 go1.23.4.solaris-amd64.tar.gz -e5865c1bfc3fee5d003819b2e2c800f598fe9994931bac63f573e8d05a10d91f go1.23.4.windows-386.msi -e544e0e356147ba998e267002bd0f2c4bf3370d495467a55baf2c63595a2026d go1.23.4.windows-386.zip -5f8cc5991eb8f4f96b6c611d839453cd11c9a2c3f23672a4188342c97ee159fa go1.23.4.windows-amd64.msi -16c59ac9196b63afb872ce9b47f945b9821a3e1542ec125f16f6085a1c0f3c39 go1.23.4.windows-amd64.zip -fc77c0531406d092c5356167e45c05a22d16bea84e3fa555e0f03af085c11763 go1.23.4.windows-arm.msi -1012cfd8ca7241c2beecb5c345dd61f01897c6f6baca80ea1bfed357035c868a go1.23.4.windows-arm.zip -8347c1aa4e1e67954d12830f88dbe44bd7ac0ec134bb472783dbfb5a3a8865d0 go1.23.4.windows-arm64.msi -db69cae5006753c785345c3215ad941f8b6224e2f81fec471c42d6857bee0e6f go1.23.4.windows-arm64.zip +a6f3f4bbd3e6bdd626f79b668f212fbb5649daf75084fb79b678a0ae4d97423b go1.23.5.src.tar.gz +8d8bc7d1b362dd91426da9352741db298ff73e3e0a3ccbe6f607f80ba17647a4 go1.23.5.aix-ppc64.tar.gz +d8b310b0b6bd6a630307579165cfac8a37571483c7d6804a10dd73bbefb0827f go1.23.5.darwin-amd64.tar.gz +d2b06bf0b8299e0187dfe2d8ad39bd3dd96a6d93fe4d1cfd42c7872452f4a0a2 go1.23.5.darwin-amd64.pkg +047bfce4fbd0da6426bd30cd19716b35a466b1c15a45525ce65b9824acb33285 go1.23.5.darwin-arm64.tar.gz +f819ed94939e08a5016b9a607ec84ebbde6cb3fe59750c59d97aa300c3fd02df go1.23.5.darwin-arm64.pkg +2dec52821e1f04a538d00b2cafe70fa506f2eea94a551bfe3ce1238f1bd4966f go1.23.5.dragonfly-amd64.tar.gz +7204e7bc62913b12f18c61afe0bc1a92fd192c0e45a54125978592296cb84e49 go1.23.5.freebsd-386.tar.gz +90a119995ebc3e36082874df5fa8fe6da194946679d01ae8bef33c87aab99391 go1.23.5.freebsd-amd64.tar.gz +255d26d873e41ff2fc278013bb2e5f25cf2ebe8d0ec84c07e3bb1436216020d3 go1.23.5.freebsd-arm.tar.gz +2785d9122654980b59ca38305a11b34f2a1e12d9f7eb41d52efc137c1fc29e61 go1.23.5.freebsd-arm64.tar.gz +8f66a94018ab666d56868f61c579aa81e549ac9700979ce6004445d315be2d37 go1.23.5.freebsd-riscv64.tar.gz +4b7a69928385ec512a4e77a547e24118adbb92301d2be36187ff0852ba9e6303 go1.23.5.illumos-amd64.tar.gz +6ecf6a41d0925358905fa2641db0e1c9037aa5b5bcd26ca6734caf50d9196417 go1.23.5.linux-386.tar.gz +cbcad4a6482107c7c7926df1608106c189417163428200ce357695cc7e01d091 go1.23.5.linux-amd64.tar.gz +47c84d332123883653b70da2db7dd57d2a865921ba4724efcdf56b5da7021db0 go1.23.5.linux-arm64.tar.gz +04e0b5cf5c216f0aa1bf8204d49312ad0845800ab0702dfe4357c0b1241027a3 go1.23.5.linux-armv6l.tar.gz +e1d14ac2207c78d52b76ba086da18a004c70aeb58cba72cd9bef0da7d1602786 go1.23.5.linux-loong64.tar.gz +d9e937f2fac4fc863850fb4cc31ae76d5495029a62858ef09c78604472d354c0 go1.23.5.linux-mips.tar.gz +59710d0782abafd47e40d1cf96aafa596bbdee09ac7c61062404604f49bd523e go1.23.5.linux-mips64.tar.gz +bc528cd836b4aa6701a42093ed390ef9929639a0e2818759887dc5539e517cab go1.23.5.linux-mips64le.tar.gz +a0404764ea1fd4a175dc5193622b15be6ed1ab59cbfa478f5ae24531bafb6cbd go1.23.5.linux-mipsle.tar.gz +db110284a0c91d4545273f210ca95b9f89f6e3ac90f39eb819033a6b96f25897 go1.23.5.linux-ppc64.tar.gz +db268bf5710b5b1b82ab38722ba6e4427d9e4942aed78c7d09195a9dff329613 go1.23.5.linux-ppc64le.tar.gz +d9da15778442464f32acfa777ac731fd4d47362b233b83a0932380cb6d2d5dc8 go1.23.5.linux-riscv64.tar.gz +14924b917d35311eb130e263f34931043d4f9dc65f20684301bf8f60a72edcdf go1.23.5.linux-s390x.tar.gz +7b8074102e7f039bd6473c44f58cb323c98dcda48df98ad1f78aaa2664769c8f go1.23.5.netbsd-386.tar.gz +1a466b9c8900e66664b15c07548ecb156e8274cf1028ac5da84134728e6dbbed go1.23.5.netbsd-amd64.tar.gz +901c9e72038926e37a4dbde8f03d1d81fcb9992850901a3da1da5a25ef93e65b go1.23.5.netbsd-arm.tar.gz +221f69a7c3a920e3666633ee0b4e5c810176982e74339ba4693226996dc636e4 go1.23.5.netbsd-arm64.tar.gz +42e46cbf73febb8e6ddf848765ce1c39573736383b132402cdc487eb6be3ad06 go1.23.5.openbsd-386.tar.gz +f49e81fce17aab21800fab7c4b10c97ab02f8a9c807fdf8641ccf2f87d69289f go1.23.5.openbsd-amd64.tar.gz +d8bd7269d4670a46e702b64822254a654824347c35923ef1c444d2e8687381ea go1.23.5.openbsd-arm.tar.gz +9cb259adff431d4d28b18e3348e26fe07ea10380675051dcfd740934b5e8b9f2 go1.23.5.openbsd-arm64.tar.gz +72a03223c98fcecfb06e57c3edd584f99fb7f6574a42f59348473f354be1f379 go1.23.5.openbsd-ppc64.tar.gz +c06432b859afb36657207382b7bac03f961b8fafc18176b501d239575a9ace64 go1.23.5.openbsd-riscv64.tar.gz +b1f9b12b269ab5cd4aa7ae3dd3075c2407c1ea8bb1211e6835261f98931201cc go1.23.5.plan9-386.tar.gz +45b4026a103e2f6cd436e2b7ad24b24a40dd22c9903519b98b45c535574fa01a go1.23.5.plan9-amd64.tar.gz +6e28e26f8c1e8620006490260aa5743198843aa0003c400cb65cbf5e743b21c7 go1.23.5.plan9-arm.tar.gz +0496c9969f208bd597f3e63fb27068ce1c7ed776618da1007fcc1c8be83ca413 go1.23.5.solaris-amd64.tar.gz +8441605a005ea74c28d8c02ca5f2708c17b4df7e91796148b9f8760caafb05c1 go1.23.5.windows-386.zip +39962346d8d0cb0cc8716489ee33b08d7a220c24a9e45423487876dd4acbdac6 go1.23.5.windows-386.msi +96d74945d7daeeb98a7978d0cf099321d7eb821b45f5c510373d545162d39c20 go1.23.5.windows-amd64.zip +03e11a988a18ad7e3f9038cef836330af72ba0a454a502cda7b7faee07a0dd8a go1.23.5.windows-amd64.msi +0005b31dcf9732c280a5cceb6aa1c5ab8284bc2541d0256c221256080acf2a09 go1.23.5.windows-arm.zip +a8442de35cbac230db8c4b20e363055671f2295dc4d6b2b2dfec66b89a3c4bce go1.23.5.windows-arm.msi +4f20c2d8a5a387c227e3ef48c5506b22906139d8afd8d66a78ef3de8dda1d1c3 go1.23.5.windows-arm64.zip +6f54fb46b669345c734936c521f7e0f55555e63ed6e11efbbaaed06f9514773c go1.23.5.windows-arm64.msi # version:golangci 1.63.4 # https://github.com/golangci/golangci-lint/releases/ From 530adfc8e3ef9c8b6356facecdec10b30fb81d7d Mon Sep 17 00:00:00 2001 From: Shude Li Date: Tue, 21 Jan 2025 00:06:39 +0800 Subject: [PATCH 3/9] core/types: initialize ChainID in SetCodeTx copy method (#31054) --- core/types/tx_setcode.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/types/tx_setcode.go b/core/types/tx_setcode.go index 0fb5362c26..894bac10a3 100644 --- a/core/types/tx_setcode.go +++ b/core/types/tx_setcode.go @@ -148,7 +148,7 @@ func (tx *SetCodeTx) copy() TxData { AccessList: make(AccessList, len(tx.AccessList)), AuthList: make([]SetCodeAuthorization, len(tx.AuthList)), Value: new(uint256.Int), - ChainID: tx.ChainID, + ChainID: new(uint256.Int), GasTipCap: new(uint256.Int), GasFeeCap: new(uint256.Int), V: new(uint256.Int), @@ -160,6 +160,9 @@ func (tx *SetCodeTx) copy() TxData { if tx.Value != nil { cpy.Value.Set(tx.Value) } + if tx.ChainID != nil { + cpy.ChainID.Set(tx.ChainID) + } if tx.GasTipCap != nil { cpy.GasTipCap.Set(tx.GasTipCap) } From e25cedf16debb0ab76adaf376f6df808aee8f029 Mon Sep 17 00:00:00 2001 From: jwasinger Date: Tue, 21 Jan 2025 11:42:05 +0800 Subject: [PATCH 4/9] core/txpool: terminate subpool reset goroutine if pool was closed (#31030) if the pool terminates before `resetDone` can be read, then the go-routine will hang. --- core/txpool/txpool.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index d54cf4968b..182706d63c 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -224,7 +224,10 @@ func (p *TxPool) loop(head *types.Header, chain BlockChain) { for _, subpool := range p.subpools { subpool.Reset(oldHead, newHead) } - resetDone <- newHead + select { + case resetDone <- newHead: + case <-p.term: + } }(oldHead, newHead) // If the reset operation was explicitly requested, consider it From 2bf4a8ff73fc387592383dcba4175c422825b6b9 Mon Sep 17 00:00:00 2001 From: Martin HS Date: Tue, 21 Jan 2025 08:35:03 +0100 Subject: [PATCH 5/9] cmd/evm: refactor handling output-files for `t8n` (#30854) As part of trying to make the inputs and outputs of the evm subcommands more streamlined and aligned, this PR modifies how `evm t8n` manages output-files. Previously, we do a kind of wonky thing where between each transaction, we invoke a `getTracer` closure. In that closure, we create a new output-file, a tracer, and then make the tracer stream output to the file. We also fiddle a bit to ensure that the file becomes properly closed. It is a kind of hacky solution we have in place. This PR changes it, so that from the execution-pipeline point of view, we have just a regular tracer. No fiddling with re-setting it or closing files. That particular tracer, however, is a bit special: it takes care of creating new files per transaction (in the tx-start-hook) and closing (on tx-end-hook). Also instantiating the right type of underlying tracer, which can be a json-logger or a custom tracer. --------- Co-authored-by: Gary Rong --- cmd/evm/internal/t8ntool/execution.go | 52 +----- cmd/evm/internal/t8ntool/file_tracer.go | 152 ++++++++++++++++++ cmd/evm/internal/t8ntool/transaction.go | 6 +- cmd/evm/internal/t8ntool/transition.go | 77 ++++----- cmd/evm/main.go | 4 +- cmd/evm/t8n_test.go | 32 ++-- cmd/evm/testdata/31/README.md | 10 ++ ...47543268a5aaf2a6b32a69d2c6d978c45dcfb.json | 2 +- ...3641ef5a8bbdb10ac69f466083a6789c77fb8.json | 1 + ...641ef5a8bbdb10ac69f466083a6789c77fb8.jsonl | 6 + ...86f5a9a08f7ef183da72c23bb3b2374530128.json | 1 + ...6f5a9a08f7ef183da72c23bb3b2374530128.jsonl | 6 + cmd/evm/testdata/31/txs.json | 24 +++ core/vm/evm.go | 5 - 14 files changed, 260 insertions(+), 118 deletions(-) create mode 100644 cmd/evm/internal/t8ntool/file_tracer.go create mode 100644 cmd/evm/testdata/31/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.json create mode 100644 cmd/evm/testdata/31/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.jsonl create mode 100644 cmd/evm/testdata/31/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.json create mode 100644 cmd/evm/testdata/31/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.jsonl diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 7c17a251f0..9ff5a05290 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -17,9 +17,7 @@ package t8ntool import ( - "encoding/json" "fmt" - "io" "math/big" "github.com/ethereum/go-ethereum/common" @@ -35,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -130,9 +127,7 @@ type rejectedTx struct { } // Apply applies a set of transactions to a pre-state -func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, - txIt txIterator, miningReward int64, - getTracerFn func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error)) (*state.StateDB, *ExecutionResult, []byte, error) { +func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, txIt txIterator, miningReward int64) (*state.StateDB, *ExecutionResult, []byte, error) { // Capture errors for BLOCKHASH operation, if we haven't been supplied the // required blockhashes var hashError error @@ -241,23 +236,13 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, continue } } - tracer, traceOutput, err := getTracerFn(txIndex, tx.Hash(), chainConfig) - if err != nil { - return nil, nil, nil, err - } - // TODO (rjl493456442) it's a bit weird to reset the tracer in the - // middle of block execution, please improve it somehow. - if tracer != nil { - evm.SetTracer(tracer.Hooks) - } statedb.SetTxContext(tx.Hash(), txIndex) - var ( snapshot = statedb.Snapshot() prevGas = gaspool.Gas() ) - if tracer != nil && tracer.OnTxStart != nil { - tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) + if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxStart != nil { + evm.Config.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) } // (ret []byte, usedGas uint64, failed bool, err error) msgResult, err := core.ApplyMessage(evm, msg, gaspool) @@ -266,13 +251,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) gaspool.SetGas(prevGas) - if tracer != nil { - if tracer.OnTxEnd != nil { - tracer.OnTxEnd(nil, err) - } - if err := writeTraceResult(tracer, traceOutput); err != nil { - log.Warn("Error writing tracer output", "err", err) - } + if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxEnd != nil { + evm.Config.Tracer.OnTxEnd(nil, err) } continue } @@ -316,13 +296,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, //receipt.BlockNumber receipt.TransactionIndex = uint(txIndex) receipts = append(receipts, receipt) - if tracer != nil { - if tracer.Hooks.OnTxEnd != nil { - tracer.Hooks.OnTxEnd(receipt, nil) - } - if err = writeTraceResult(tracer, traceOutput); err != nil { - log.Warn("Error writing tracer output", "err", err) - } + if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxEnd != nil { + evm.Config.Tracer.OnTxEnd(receipt, nil) } } @@ -468,16 +443,3 @@ func calcDifficulty(config *params.ChainConfig, number, currentTime, parentTime } return ethash.CalcDifficulty(config, currentTime, parent) } - -func writeTraceResult(tracer *tracers.Tracer, f io.WriteCloser) error { - defer f.Close() - result, err := tracer.GetResult() - if err != nil || result == nil { - return err - } - err = json.NewEncoder(f).Encode(result) - if err != nil { - return err - } - return nil -} diff --git a/cmd/evm/internal/t8ntool/file_tracer.go b/cmd/evm/internal/t8ntool/file_tracer.go new file mode 100644 index 0000000000..38fc35bd32 --- /dev/null +++ b/cmd/evm/internal/t8ntool/file_tracer.go @@ -0,0 +1,152 @@ +// Copyright 2024 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . + +package t8ntool + +import ( + "encoding/json" + "fmt" + "io" + "math/big" + "os" + "path/filepath" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/log" +) + +// fileWritingTracer wraps either a tracer or a logger. On tx start, +// it instantiates a tracer/logger, creates a new file to direct output to, +// and on tx end it closes the file. +type fileWritingTracer struct { + txIndex int // transaction counter + inner *tracing.Hooks // inner hooks + destination io.WriteCloser // the currently open file (if any) + baseDir string // baseDir to write output-files to + suffix string // suffix is the suffix to use when creating files + + // for custom tracing + getResult func() (json.RawMessage, error) +} + +func (l *fileWritingTracer) Write(p []byte) (n int, err error) { + if l.destination != nil { + return l.destination.Write(p) + } + log.Warn("Tracer wrote to non-existing output") + // It is tempting to return an error here, however, the json encoder + // will no retry writing to an io.Writer once it has returned an error once. + // Therefore, we must squash the error. + return n, nil +} + +// newFileWriter creates a set of hooks which wraps inner hooks (typically a logger), +// and writes the output to a file, one file per transaction. +func newFileWriter(baseDir string, innerFn func(out io.Writer) *tracing.Hooks) *tracing.Hooks { + t := &fileWritingTracer{ + baseDir: baseDir, + suffix: "jsonl", + } + t.inner = innerFn(t) // instantiate the inner tracer + return t.hooks() +} + +// newResultWriter creates a set of hooks wraps and invokes an underlying tracer, +// and writes the result (getResult-output) to file, one per transaction. +func newResultWriter(baseDir string, tracer *tracers.Tracer) *tracing.Hooks { + t := &fileWritingTracer{ + baseDir: baseDir, + getResult: tracer.GetResult, + inner: tracer.Hooks, + suffix: "json", + } + return t.hooks() +} + +// OnTxStart creates a new output-file specific for this transaction, and invokes +// the inner OnTxStart handler. +func (l *fileWritingTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { + // Open a new file, or print a warning log if it's failed + fname := filepath.Join(l.baseDir, fmt.Sprintf("trace-%d-%v.%v", l.txIndex, tx.Hash().String(), l.suffix)) + traceFile, err := os.Create(fname) + if err != nil { + log.Warn("Failed creating trace-file", "err", err) + } else { + log.Info("Created tracing-file", "path", fname) + l.destination = traceFile + } + if l.inner != nil && l.inner.OnTxStart != nil { + l.inner.OnTxStart(env, tx, from) + } +} + +// OnTxEnd writes result (if getResult exist), closes any currently open output-file, +// and invokes the inner OnTxEnd handler. +func (l *fileWritingTracer) OnTxEnd(receipt *types.Receipt, err error) { + if l.inner != nil && l.inner.OnTxEnd != nil { + l.inner.OnTxEnd(receipt, err) + } + if l.getResult != nil && l.destination != nil { + if result, err := l.getResult(); result != nil { + json.NewEncoder(l.destination).Encode(result) + } else { + log.Warn("Error obtaining tracer result", "err", err) + } + l.destination.Close() + l.destination = nil + } + l.txIndex++ +} + +func (l *fileWritingTracer) hooks() *tracing.Hooks { + return &tracing.Hooks{ + OnTxStart: l.OnTxStart, + OnTxEnd: l.OnTxEnd, + OnEnter: func(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if l.inner != nil && l.inner.OnEnter != nil { + l.inner.OnEnter(depth, typ, from, to, input, gas, value) + } + }, + OnExit: func(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + if l.inner != nil && l.inner.OnExit != nil { + l.inner.OnExit(depth, output, gasUsed, err, reverted) + } + }, + OnOpcode: func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { + if l.inner != nil && l.inner.OnOpcode != nil { + l.inner.OnOpcode(pc, op, gas, cost, scope, rData, depth, err) + } + }, + OnFault: func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, depth int, err error) { + if l.inner != nil && l.inner.OnFault != nil { + l.inner.OnFault(pc, op, gas, cost, scope, depth, err) + } + }, + OnSystemCallStart: func() { + if l.inner != nil && l.inner.OnSystemCallStart != nil { + l.inner.OnSystemCallStart() + } + }, + OnSystemCallEnd: func() { + if l.inner != nil && l.inner.OnSystemCallEnd != nil { + l.inner.OnSystemCallEnd() + } + }, + } +} diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 6dac4301dd..d8650beca6 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -64,12 +64,10 @@ func (r *result) MarshalJSON() ([]byte, error) { } func Transaction(ctx *cli.Context) error { - var ( - err error - ) // We need to load the transactions. May be either in stdin input or in files. // Check if anything needs to be read from stdin var ( + err error txStr = ctx.String(InputTxsFlag.Name) inputData = &input{} chainConfig *params.ChainConfig @@ -82,6 +80,7 @@ func Transaction(ctx *cli.Context) error { } // Set the chain id chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name)) + var body hexutil.Bytes if txStr == stdinSelector { decoder := json.NewDecoder(os.Stdin) @@ -107,6 +106,7 @@ func Transaction(ctx *cli.Context) error { } } signer := types.MakeSigner(chainConfig, new(big.Int), 0) + // We now have the transactions in 'body', which is supposed to be an // rlp list of transactions it, err := rlp.NewListIterator([]byte(body)) diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index 231576fa42..e946ccddd5 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -82,58 +82,10 @@ type input struct { } func Transition(ctx *cli.Context) error { - var getTracer = func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) { - return nil, nil, nil - } - baseDir, err := createBasedir(ctx) if err != nil { return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err)) } - - if ctx.Bool(TraceFlag.Name) { // JSON opcode tracing - // Configure the EVM logger - logConfig := &logger.Config{ - DisableStack: ctx.Bool(TraceDisableStackFlag.Name), - EnableMemory: ctx.Bool(TraceEnableMemoryFlag.Name), - EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name), - } - getTracer = func(txIndex int, txHash common.Hash, _ *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) { - traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String()))) - if err != nil { - return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err)) - } - var l *tracing.Hooks - if ctx.Bool(TraceEnableCallFramesFlag.Name) { - l = logger.NewJSONLoggerWithCallFrames(logConfig, traceFile) - } else { - l = logger.NewJSONLogger(logConfig, traceFile) - } - tracer := &tracers.Tracer{ - Hooks: l, - // jsonLogger streams out result to file. - GetResult: func() (json.RawMessage, error) { return nil, nil }, - Stop: func(err error) {}, - } - return tracer, traceFile, nil - } - } else if ctx.IsSet(TraceTracerFlag.Name) { - var config json.RawMessage - if ctx.IsSet(TraceTracerConfigFlag.Name) { - config = []byte(ctx.String(TraceTracerConfigFlag.Name)) - } - getTracer = func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) { - traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String()))) - if err != nil { - return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err)) - } - tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config, chainConfig) - if err != nil { - return nil, nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err)) - } - return tracer, traceFile, nil - } - } // We need to load three things: alloc, env and transactions. May be either in // stdin input or in files. // Check if anything needs to be read from stdin @@ -179,6 +131,7 @@ func Transition(ctx *cli.Context) error { chainConfig = cConf vmConfig.ExtraEips = extraEips } + // Set the chain id chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name)) @@ -197,8 +150,34 @@ func Transition(ctx *cli.Context) error { if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil { return err } + + // Configure tracer + if ctx.IsSet(TraceTracerFlag.Name) { // Custom tracing + config := json.RawMessage(ctx.String(TraceTracerConfigFlag.Name)) + tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), + nil, config, chainConfig) + if err != nil { + return NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %v", err)) + } + vmConfig.Tracer = newResultWriter(baseDir, tracer) + } else if ctx.Bool(TraceFlag.Name) { // JSON opcode tracing + logConfig := &logger.Config{ + DisableStack: ctx.Bool(TraceDisableStackFlag.Name), + EnableMemory: ctx.Bool(TraceEnableMemoryFlag.Name), + EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name), + } + if ctx.Bool(TraceEnableCallFramesFlag.Name) { + vmConfig.Tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks { + return logger.NewJSONLoggerWithCallFrames(logConfig, out) + }) + } else { + vmConfig.Tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks { + return logger.NewJSONLogger(logConfig, out) + }) + } + } // Run the test and aggregate the result - s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name), getTracer) + s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name)) if err != nil { return err } diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 2079425416..61e46aa50e 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -83,8 +83,8 @@ var ( } TraceFormatFlag = &cli.StringFlag{ Name: "trace.format", - Usage: "Trace output format to use (struct|json)", - Value: "struct", + Usage: "Trace output format to use (json|struct|md)", + Value: "json", Category: traceCategory, } TraceDisableMemoryFlag = &cli.BoolFlag{ diff --git a/cmd/evm/t8n_test.go b/cmd/evm/t8n_test.go index 27c6c43164..985dac968d 100644 --- a/cmd/evm/t8n_test.go +++ b/cmd/evm/t8n_test.go @@ -606,18 +606,18 @@ func TestEvmRun(t *testing.T) { wantStdout: "./testdata/evmrun/1.out.1.txt", wantStderr: "./testdata/evmrun/1.out.2.txt", }, - { // default tracing (struct) - input: []string{"run", "--trace", "0x6040"}, + { // Struct tracing + input: []string{"run", "--trace", "--trace.format=struct", "0x6040"}, wantStdout: "./testdata/evmrun/2.out.1.txt", wantStderr: "./testdata/evmrun/2.out.2.txt", }, - { // default tracing (struct), plus alloc-dump - input: []string{"run", "--trace", "--dump", "0x6040"}, + { // struct-tracing, plus alloc-dump + input: []string{"run", "--trace", "--trace.format=struct", "--dump", "0x6040"}, wantStdout: "./testdata/evmrun/3.out.1.txt", //wantStderr: "./testdata/evmrun/3.out.2.txt", }, - { // json-tracing, plus alloc-dump - input: []string{"run", "--trace", "--trace.format=json", "--dump", "0x6040"}, + { // json-tracing (default), plus alloc-dump + input: []string{"run", "--trace", "--dump", "0x6040"}, wantStdout: "./testdata/evmrun/4.out.1.txt", //wantStderr: "./testdata/evmrun/4.out.2.txt", }, @@ -698,7 +698,10 @@ func TestEVMTracing(t *testing.T) { "--input.env=./testdata/31/env.json", "--state.fork=Cancun", "--trace", }, - expectedTraces: []string{"trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.jsonl"}, + //expectedTraces: []string{"trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.jsonl"}, + expectedTraces: []string{"trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.jsonl", + "trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.jsonl", + "trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.jsonl"}, }, { base: "./testdata/31", @@ -706,14 +709,17 @@ func TestEVMTracing(t *testing.T) { "--input.alloc=./testdata/31/alloc.json", "--input.txs=./testdata/31/txs.json", "--input.env=./testdata/31/env.json", "--state.fork=Cancun", "--trace.tracer", ` -{ - result: function(){ - return "hello world" - }, - fault: function(){} +{ count: 0, + result: function(){ + this.count = this.count + 1; + return "hello world " + this.count + }, + fault: function(){} }`, }, - expectedTraces: []string{"trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.json"}, + expectedTraces: []string{"trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.json", + "trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.json", + "trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.json"}, }, { base: "./testdata/32", diff --git a/cmd/evm/testdata/31/README.md b/cmd/evm/testdata/31/README.md index 305e4f52da..b337c1eb62 100644 --- a/cmd/evm/testdata/31/README.md +++ b/cmd/evm/testdata/31/README.md @@ -1 +1,11 @@ This test does some EVM execution, and can be used to test the tracers and trace-outputs. +This test should yield three output-traces, in separate files + +For example: +``` +[user@work evm]$ go run . t8n --input.alloc ./testdata/31/alloc.json --input.txs ./testdata/31/txs.json --input.env ./testdata/31/env.json --state.fork Cancun --output.basedir /tmp --trace +INFO [12-06|09:53:32.123] Created tracing-file path=/tmp/trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.jsonl +INFO [12-06|09:53:32.124] Created tracing-file path=/tmp/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.jsonl +INFO [12-06|09:53:32.125] Created tracing-file path=/tmp/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.jsonl +``` + diff --git a/cmd/evm/testdata/31/trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.json b/cmd/evm/testdata/31/trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.json index cd4bc1ab64..dfa1d7c7cb 100644 --- a/cmd/evm/testdata/31/trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.json +++ b/cmd/evm/testdata/31/trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.json @@ -1 +1 @@ -"hello world" +"hello world 1" diff --git a/cmd/evm/testdata/31/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.json b/cmd/evm/testdata/31/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.json new file mode 100644 index 0000000000..25980291c7 --- /dev/null +++ b/cmd/evm/testdata/31/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.json @@ -0,0 +1 @@ +"hello world 2" diff --git a/cmd/evm/testdata/31/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.jsonl b/cmd/evm/testdata/31/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.jsonl new file mode 100644 index 0000000000..26e5c7ee4e --- /dev/null +++ b/cmd/evm/testdata/31/trace-1-0x03a7b0a91e61a170d64ea94b8263641ef5a8bbdb10ac69f466083a6789c77fb8.jsonl @@ -0,0 +1,6 @@ +{"pc":0,"op":96,"gas":"0x13498","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} +{"pc":2,"op":96,"gas":"0x13495","gasCost":"0x3","memSize":0,"stack":["0x40"],"depth":1,"refund":0,"opName":"PUSH1"} +{"pc":4,"op":96,"gas":"0x13492","gasCost":"0x3","memSize":0,"stack":["0x40","0x40"],"depth":1,"refund":0,"opName":"PUSH1"} +{"pc":6,"op":96,"gas":"0x1348f","gasCost":"0x3","memSize":0,"stack":["0x40","0x40","0x40"],"depth":1,"refund":0,"opName":"PUSH1"} +{"pc":8,"op":0,"gas":"0x1348c","gasCost":"0x0","memSize":0,"stack":["0x40","0x40","0x40","0x40"],"depth":1,"refund":0,"opName":"STOP"} +{"output":"","gasUsed":"0xc"} diff --git a/cmd/evm/testdata/31/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.json b/cmd/evm/testdata/31/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.json new file mode 100644 index 0000000000..242587bd83 --- /dev/null +++ b/cmd/evm/testdata/31/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.json @@ -0,0 +1 @@ +"hello world 3" diff --git a/cmd/evm/testdata/31/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.jsonl b/cmd/evm/testdata/31/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.jsonl new file mode 100644 index 0000000000..26e5c7ee4e --- /dev/null +++ b/cmd/evm/testdata/31/trace-2-0xd96e0ce6418ee3360e11d3c7b6886f5a9a08f7ef183da72c23bb3b2374530128.jsonl @@ -0,0 +1,6 @@ +{"pc":0,"op":96,"gas":"0x13498","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} +{"pc":2,"op":96,"gas":"0x13495","gasCost":"0x3","memSize":0,"stack":["0x40"],"depth":1,"refund":0,"opName":"PUSH1"} +{"pc":4,"op":96,"gas":"0x13492","gasCost":"0x3","memSize":0,"stack":["0x40","0x40"],"depth":1,"refund":0,"opName":"PUSH1"} +{"pc":6,"op":96,"gas":"0x1348f","gasCost":"0x3","memSize":0,"stack":["0x40","0x40","0x40"],"depth":1,"refund":0,"opName":"PUSH1"} +{"pc":8,"op":0,"gas":"0x1348c","gasCost":"0x0","memSize":0,"stack":["0x40","0x40","0x40","0x40"],"depth":1,"refund":0,"opName":"STOP"} +{"output":"","gasUsed":"0xc"} diff --git a/cmd/evm/testdata/31/txs.json b/cmd/evm/testdata/31/txs.json index 473c1526f4..da8f5761f6 100644 --- a/cmd/evm/testdata/31/txs.json +++ b/cmd/evm/testdata/31/txs.json @@ -10,5 +10,29 @@ "r" : "0x0", "s" : "0x0", "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" + }, + { + "gas": "0x186a0", + "gasPrice": "0x600", + "input": "0x", + "nonce": "0x1", + "to": "0x1111111111111111111111111111111111111111", + "value": "0x1", + "v" : "0x0", + "r" : "0x0", + "s" : "0x0", + "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" + }, + { + "gas": "0x186a0", + "gasPrice": "0x600", + "input": "0x", + "nonce": "0x2", + "to": "0x1111111111111111111111111111111111111111", + "value": "0x1", + "v" : "0x0", + "r" : "0x0", + "s" : "0x0", + "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" } ] diff --git a/core/vm/evm.go b/core/vm/evm.go index 1a0215459c..1e52215b7e 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -133,11 +133,6 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon return evm } -// SetTracer sets the tracer for following state transition. -func (evm *EVM) SetTracer(tracer *tracing.Hooks) { - evm.Config.Tracer = tracer -} - // SetPrecompiles sets the precompiled contracts for the EVM. // This method is only used through RPC calls. // It is not thread-safe. From 6c10996bf5664ea2a7f7020bcb4d97a848dbf48a Mon Sep 17 00:00:00 2001 From: jwasinger Date: Tue, 21 Jan 2025 20:11:05 +0800 Subject: [PATCH 6/9] eth/filters: ensure API timeoutLoop terminates with event system (#31056) Discovered from failing test introduced https://github.com/ethereum/go-ethereum/pull/31033 . We should ensure `timeoutLoop` terminates if the filter event system is terminated. --- eth/filters/api.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/eth/filters/api.go b/eth/filters/api.go index f46dd39dd8..e3057a2af2 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -90,7 +90,11 @@ func (api *FilterAPI) timeoutLoop(timeout time.Duration) { ticker := time.NewTicker(timeout) defer ticker.Stop() for { - <-ticker.C + select { + case <-ticker.C: + case <-api.events.chainSub.Err(): + return + } api.filtersMu.Lock() for id, f := range api.filters { select { From 4af9af419d71bd4510e7e4257c05e4ce41131096 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 21 Jan 2025 22:23:46 +0100 Subject: [PATCH 7/9] go.mod: remove toolchain line (#31057) We have our own system for downloading the toolchain, and really don't want Go's to get in the way of that. We may switch to Go's builtin toolchain support, but not now. --- go.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.mod b/go.mod index 35018fbe08..20526956df 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/ethereum/go-ethereum go 1.22 -toolchain go1.22.0 - require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 github.com/Microsoft/go-winio v0.6.2 From c43faa3d9d88337824e8210e1835cfd82c15cd96 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 21 Jan 2025 15:02:17 -0700 Subject: [PATCH 8/9] cmd/evm: restore --bench flag to evm statetest (#31055) Refactoring of the `evm` command moved where some commands were valid. One command, `--bench`, used to work in `evm statetest`. The pluming is still in place. This PR puts the `--bench` flag in the place the trace flags were moved, and adds tests to validate the bench flag operates in `run` and `statetest` --------- Co-authored-by: Felix Lange --- cmd/evm/staterunner.go | 1 + cmd/evm/t8n_test.go | 56 ++++++++++++++++++++++++++++ cmd/evm/testdata/evmrun/10.out.1.txt | 15 ++++++++ cmd/evm/testdata/evmrun/10.out.2.txt | 0 cmd/evm/testdata/evmrun/9.out.1.txt | 0 cmd/evm/testdata/evmrun/9.out.2.txt | 4 ++ 6 files changed, 76 insertions(+) create mode 100644 cmd/evm/testdata/evmrun/10.out.1.txt create mode 100644 cmd/evm/testdata/evmrun/10.out.2.txt create mode 100644 cmd/evm/testdata/evmrun/9.out.1.txt create mode 100644 cmd/evm/testdata/evmrun/9.out.2.txt diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go index 4c2dfeabc6..8f81a95315 100644 --- a/cmd/evm/staterunner.go +++ b/cmd/evm/staterunner.go @@ -51,6 +51,7 @@ var stateTestCommand = &cli.Command{ Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).", ArgsUsage: "", Flags: slices.Concat([]cli.Flag{ + BenchFlag, DumpFlag, HumanReadableFlag, RunFlag, diff --git a/cmd/evm/t8n_test.go b/cmd/evm/t8n_test.go index 985dac968d..46146be787 100644 --- a/cmd/evm/t8n_test.go +++ b/cmd/evm/t8n_test.go @@ -24,6 +24,7 @@ import ( "os" "path/filepath" "reflect" + "regexp" "strings" "testing" @@ -670,6 +671,61 @@ func TestEvmRun(t *testing.T) { } } +func TestEvmRunRegEx(t *testing.T) { + t.Parallel() + tt := cmdtest.NewTestCmd(t, nil) + for i, tc := range []struct { + input []string + wantStdout string + wantStderr string + }{ + { // json tracing + input: []string{"run", "--bench", "6040"}, + wantStdout: "./testdata/evmrun/9.out.1.txt", + wantStderr: "./testdata/evmrun/9.out.2.txt", + }, + { // statetest subcommand + input: []string{"statetest", "--bench", "./testdata/statetest.json"}, + wantStdout: "./testdata/evmrun/10.out.1.txt", + wantStderr: "./testdata/evmrun/10.out.2.txt", + }, + } { + tt.Logf("args: go run ./cmd/evm %v\n", strings.Join(tc.input, " ")) + tt.Run("evm-test", tc.input...) + + haveStdOut := tt.Output() + tt.WaitExit() + haveStdErr := tt.StderrText() + + if have, wantFile := haveStdOut, tc.wantStdout; wantFile != "" { + want, err := os.ReadFile(wantFile) + if err != nil { + t.Fatalf("test %d: could not read expected output: %v", i, err) + } + re, err := regexp.Compile(string(want)) + if err != nil { + t.Fatalf("test %d: could not compile regular expression: %v", i, err) + } + if !re.Match(have) { + t.Fatalf("test %d, output wrong, have \n%v\nwant\n%v\n", i, string(have), re) + } + } + if have, wantFile := haveStdErr, tc.wantStderr; wantFile != "" { + want, err := os.ReadFile(wantFile) + if err != nil { + t.Fatalf("test %d: could not read expected output: %v", i, err) + } + re, err := regexp.Compile(string(want)) + if err != nil { + t.Fatalf("test %d: could not compile regular expression: %v", i, err) + } + if !re.MatchString(have) { + t.Fatalf("test %d, output wrong, have \n%v\nwant\n%v\n", i, have, re) + } + } + } +} + // cmpJson compares the JSON in two byte slices. func cmpJson(a, b []byte) (bool, error) { var j, j2 interface{} diff --git a/cmd/evm/testdata/evmrun/10.out.1.txt b/cmd/evm/testdata/evmrun/10.out.1.txt new file mode 100644 index 0000000000..5f94bdd261 --- /dev/null +++ b/cmd/evm/testdata/evmrun/10.out.1.txt @@ -0,0 +1,15 @@ +\[ + \{ + "name": "00000006-naivefuzz-0", + "pass": false, + "stateRoot": "0xad1024c87b5548e77c937aa50f72b6cb620d278f4dd79bae7f78f71ff75af458", + "fork": "London", + "error": "post state root mismatch: got ad1024c87b5548e77c937aa50f72b6cb620d278f4dd79bae7f78f71ff75af458, want 0000000000000000000000000000000000000000000000000000000000000000", + "benchStats": \{ + "time": \d+, + "allocs": \d+, + "bytesAllocated": \d+, + "gasUsed": \d+ + \} + \} +\] \ No newline at end of file diff --git a/cmd/evm/testdata/evmrun/10.out.2.txt b/cmd/evm/testdata/evmrun/10.out.2.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cmd/evm/testdata/evmrun/9.out.1.txt b/cmd/evm/testdata/evmrun/9.out.1.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cmd/evm/testdata/evmrun/9.out.2.txt b/cmd/evm/testdata/evmrun/9.out.2.txt new file mode 100644 index 0000000000..90def283e0 --- /dev/null +++ b/cmd/evm/testdata/evmrun/9.out.2.txt @@ -0,0 +1,4 @@ +EVM gas used: \d+ +execution time: \d+\.\d+.s +allocations: \d+ +allocated bytes: \d+ From 218b697f053b3e09c4a60d27feeb32af30acab58 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 22 Jan 2025 09:29:34 +0100 Subject: [PATCH 9/9] p2p: support configuring NAT in TOML file (#31041) This is an alternative for #27407 with a solution based on gencodec. With the PR, one can now configure like this: ``` # config.toml [Node.P2P] NAT = "extip:33.33.33.33" ``` ```shell $ geth --config config.toml ... INFO [01-17|16:37:31.436] Started P2P networking self=enode://2290...ab@33.33.33.33:30303 ``` --- go.mod | 14 ++-- go.sum | 24 +++---- p2p/config.go | 144 +++++++++++++++++++++++++++++++++++++++ p2p/config_toml.go | 165 +++++++++++++++++++++++++++++++++++++++++++++ p2p/nat/nat.go | 15 +++-- p2p/nat/natpmp.go | 4 ++ p2p/server.go | 99 --------------------------- 7 files changed, 342 insertions(+), 123 deletions(-) create mode 100644 p2p/config.go create mode 100644 p2p/config_toml.go diff --git a/go.mod b/go.mod index 20526956df..51f9f1bda7 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ethereum/go-ethereum -go 1.22 +go 1.22.0 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 @@ -25,7 +25,7 @@ require ( github.com/ethereum/go-verkle v0.2.2 github.com/fatih/color v1.16.0 github.com/ferranbt/fastssz v0.1.2 - github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e + github.com/fjl/gencodec v0.0.0-20250117152317-bc3e1c7619d4 github.com/fsnotify/fsnotify v1.6.0 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff github.com/gofrs/flock v0.8.1 @@ -62,13 +62,13 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/urfave/cli/v2 v2.25.7 go.uber.org/automaxprocs v1.5.2 - golang.org/x/crypto v0.31.0 + golang.org/x/crypto v0.32.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.10.0 - golang.org/x/sys v0.28.0 + golang.org/x/sys v0.29.0 golang.org/x/text v0.21.0 golang.org/x/time v0.5.0 - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d + golang.org/x/tools v0.29.0 google.golang.org/protobuf v1.34.2 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v3 v3.0.1 @@ -138,8 +138,8 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.25.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.34.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index ded07f4867..8a280398d0 100644 --- a/go.sum +++ b/go.sum @@ -172,8 +172,8 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk= github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= -github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY= -github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= +github.com/fjl/gencodec v0.0.0-20250117152317-bc3e1c7619d4 h1:HhaRPDFEB1BrvBF+UCUnhyY9y5dtuBxy0myn+7sFjAw= +github.com/fjl/gencodec v0.0.0-20250117152317-bc3e1c7619d4/go.mod h1:Um1dFHPONZGTHog1qD1NaWjXJW/SPB38wPv0O8uZ2fI= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -528,8 +528,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -563,8 +563,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -601,8 +601,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -684,8 +684,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -750,8 +750,8 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/p2p/config.go b/p2p/config.go new file mode 100644 index 0000000000..14492a2e55 --- /dev/null +++ b/p2p/config.go @@ -0,0 +1,144 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . +package p2p + +import ( + "crypto/ecdsa" + "fmt" + + "github.com/ethereum/go-ethereum/common/mclock" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/nat" + "github.com/ethereum/go-ethereum/p2p/netutil" +) + +//go:generate go run github.com/fjl/gencodec -type Config -field-override configMarshaling -formats toml -out config_toml.go + +// Config holds Server options. +type Config struct { + // This field must be set to a valid secp256k1 private key. + PrivateKey *ecdsa.PrivateKey `toml:"-"` + + // MaxPeers is the maximum number of peers that can be + // connected. It must be greater than zero. + MaxPeers int + + // MaxPendingPeers is the maximum number of peers that can be pending in the + // handshake phase, counted separately for inbound and outbound connections. + // Zero defaults to preset values. + MaxPendingPeers int `toml:",omitempty"` + + // DialRatio controls the ratio of inbound to dialed connections. + // Example: a DialRatio of 2 allows 1/2 of connections to be dialed. + // Setting DialRatio to zero defaults it to 3. + DialRatio int `toml:",omitempty"` + + // NoDiscovery can be used to disable the peer discovery mechanism. + // Disabling is useful for protocol debugging (manual topology). + NoDiscovery bool + + // DiscoveryV4 specifies whether V4 discovery should be started. + DiscoveryV4 bool `toml:",omitempty"` + + // DiscoveryV5 specifies whether the new topic-discovery based V5 discovery + // protocol should be started or not. + DiscoveryV5 bool `toml:",omitempty"` + + // Name sets the node name of this server. + Name string `toml:"-"` + + // BootstrapNodes are used to establish connectivity + // with the rest of the network. + BootstrapNodes []*enode.Node + + // BootstrapNodesV5 are used to establish connectivity + // with the rest of the network using the V5 discovery + // protocol. + BootstrapNodesV5 []*enode.Node `toml:",omitempty"` + + // Static nodes are used as pre-configured connections which are always + // maintained and re-connected on disconnects. + StaticNodes []*enode.Node + + // Trusted nodes are used as pre-configured connections which are always + // allowed to connect, even above the peer limit. + TrustedNodes []*enode.Node + + // Connectivity can be restricted to certain IP networks. + // If this option is set to a non-nil value, only hosts which match one of the + // IP networks contained in the list are considered. + NetRestrict *netutil.Netlist `toml:",omitempty"` + + // NodeDatabase is the path to the database containing the previously seen + // live nodes in the network. + NodeDatabase string `toml:",omitempty"` + + // Protocols should contain the protocols supported + // by the server. Matching protocols are launched for + // each peer. + Protocols []Protocol `toml:"-" json:"-"` + + // If ListenAddr is set to a non-nil address, the server + // will listen for incoming connections. + // + // If the port is zero, the operating system will pick a port. The + // ListenAddr field will be updated with the actual address when + // the server is started. + ListenAddr string + + // If DiscAddr is set to a non-nil value, the server will use ListenAddr + // for TCP and DiscAddr for the UDP discovery protocol. + DiscAddr string + + // If set to a non-nil value, the given NAT port mapper + // is used to make the listening port available to the + // Internet. + NAT nat.Interface `toml:",omitempty"` + + // If Dialer is set to a non-nil value, the given Dialer + // is used to dial outbound peer connections. + Dialer NodeDialer `toml:"-"` + + // If NoDial is true, the server will not dial any peers. + NoDial bool `toml:",omitempty"` + + // If EnableMsgEvents is set then the server will emit PeerEvents + // whenever a message is sent to or received from a peer + EnableMsgEvents bool + + // Logger is a custom logger to use with the p2p.Server. + Logger log.Logger `toml:"-"` + + clock mclock.Clock +} + +type configMarshaling struct { + NAT configNAT +} + +type configNAT struct { + nat.Interface +} + +func (w *configNAT) UnmarshalText(input []byte) error { + n, err := nat.Parse(string(input)) + if err != nil { + return fmt.Errorf("invalid NAT specification: %v", err) + } + w.Interface = n + return nil +} diff --git a/p2p/config_toml.go b/p2p/config_toml.go new file mode 100644 index 0000000000..8a255e62fb --- /dev/null +++ b/p2p/config_toml.go @@ -0,0 +1,165 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package p2p + +import ( + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/nat" + "github.com/ethereum/go-ethereum/p2p/netutil" +) + +var _ = (*configMarshaling)(nil) + +// MarshalTOML marshals as TOML. +func (c Config) MarshalTOML() (interface{}, error) { + type Config struct { + PrivateKey *ecdsa.PrivateKey `toml:"-"` + MaxPeers int + MaxPendingPeers int `toml:",omitempty"` + DialRatio int `toml:",omitempty"` + NoDiscovery bool + DiscoveryV4 bool `toml:",omitempty"` + DiscoveryV5 bool `toml:",omitempty"` + Name string `toml:"-"` + BootstrapNodes []*enode.Node + BootstrapNodesV5 []*enode.Node `toml:",omitempty"` + StaticNodes []*enode.Node + TrustedNodes []*enode.Node + NetRestrict *netutil.Netlist `toml:",omitempty"` + NodeDatabase string `toml:",omitempty"` + Protocols []Protocol `toml:"-" json:"-"` + ListenAddr string + DiscAddr string + NAT nat.Interface `toml:",omitempty"` + Dialer NodeDialer `toml:"-"` + NoDial bool `toml:",omitempty"` + EnableMsgEvents bool + Logger log.Logger `toml:"-"` + } + var enc Config + enc.PrivateKey = c.PrivateKey + enc.MaxPeers = c.MaxPeers + enc.MaxPendingPeers = c.MaxPendingPeers + enc.DialRatio = c.DialRatio + enc.NoDiscovery = c.NoDiscovery + enc.DiscoveryV4 = c.DiscoveryV4 + enc.DiscoveryV5 = c.DiscoveryV5 + enc.Name = c.Name + enc.BootstrapNodes = c.BootstrapNodes + enc.BootstrapNodesV5 = c.BootstrapNodesV5 + enc.StaticNodes = c.StaticNodes + enc.TrustedNodes = c.TrustedNodes + enc.NetRestrict = c.NetRestrict + enc.NodeDatabase = c.NodeDatabase + enc.Protocols = c.Protocols + enc.ListenAddr = c.ListenAddr + enc.DiscAddr = c.DiscAddr + enc.NAT = c.NAT + enc.Dialer = c.Dialer + enc.NoDial = c.NoDial + enc.EnableMsgEvents = c.EnableMsgEvents + enc.Logger = c.Logger + return &enc, nil +} + +// UnmarshalTOML unmarshals from TOML. +func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { + type Config struct { + PrivateKey *ecdsa.PrivateKey `toml:"-"` + MaxPeers *int + MaxPendingPeers *int `toml:",omitempty"` + DialRatio *int `toml:",omitempty"` + NoDiscovery *bool + DiscoveryV4 *bool `toml:",omitempty"` + DiscoveryV5 *bool `toml:",omitempty"` + Name *string `toml:"-"` + BootstrapNodes []*enode.Node + BootstrapNodesV5 []*enode.Node `toml:",omitempty"` + StaticNodes []*enode.Node + TrustedNodes []*enode.Node + NetRestrict *netutil.Netlist `toml:",omitempty"` + NodeDatabase *string `toml:",omitempty"` + Protocols []Protocol `toml:"-" json:"-"` + ListenAddr *string + DiscAddr *string + NAT *configNAT `toml:",omitempty"` + Dialer NodeDialer `toml:"-"` + NoDial *bool `toml:",omitempty"` + EnableMsgEvents *bool + Logger log.Logger `toml:"-"` + } + var dec Config + if err := unmarshal(&dec); err != nil { + return err + } + if dec.PrivateKey != nil { + c.PrivateKey = dec.PrivateKey + } + if dec.MaxPeers != nil { + c.MaxPeers = *dec.MaxPeers + } + if dec.MaxPendingPeers != nil { + c.MaxPendingPeers = *dec.MaxPendingPeers + } + if dec.DialRatio != nil { + c.DialRatio = *dec.DialRatio + } + if dec.NoDiscovery != nil { + c.NoDiscovery = *dec.NoDiscovery + } + if dec.DiscoveryV4 != nil { + c.DiscoveryV4 = *dec.DiscoveryV4 + } + if dec.DiscoveryV5 != nil { + c.DiscoveryV5 = *dec.DiscoveryV5 + } + if dec.Name != nil { + c.Name = *dec.Name + } + if dec.BootstrapNodes != nil { + c.BootstrapNodes = dec.BootstrapNodes + } + if dec.BootstrapNodesV5 != nil { + c.BootstrapNodesV5 = dec.BootstrapNodesV5 + } + if dec.StaticNodes != nil { + c.StaticNodes = dec.StaticNodes + } + if dec.TrustedNodes != nil { + c.TrustedNodes = dec.TrustedNodes + } + if dec.NetRestrict != nil { + c.NetRestrict = dec.NetRestrict + } + if dec.NodeDatabase != nil { + c.NodeDatabase = *dec.NodeDatabase + } + if dec.Protocols != nil { + c.Protocols = dec.Protocols + } + if dec.ListenAddr != nil { + c.ListenAddr = *dec.ListenAddr + } + if dec.DiscAddr != nil { + c.DiscAddr = *dec.DiscAddr + } + if dec.NAT != nil { + c.NAT = dec.NAT + } + if dec.Dialer != nil { + c.Dialer = dec.Dialer + } + if dec.NoDial != nil { + c.NoDial = *dec.NoDial + } + if dec.EnableMsgEvents != nil { + c.EnableMsgEvents = *dec.EnableMsgEvents + } + if dec.Logger != nil { + c.Logger = dec.Logger + } + return nil +} diff --git a/p2p/nat/nat.go b/p2p/nat/nat.go index c656044268..f7fe8196c9 100644 --- a/p2p/nat/nat.go +++ b/p2p/nat/nat.go @@ -133,8 +133,9 @@ func Map(m Interface, c <-chan struct{}, protocol string, extport, intport int, // Mapping operations will not return an error but won't actually do anything. type ExtIP net.IP -func (n ExtIP) ExternalIP() (net.IP, error) { return net.IP(n), nil } -func (n ExtIP) String() string { return fmt.Sprintf("ExtIP(%v)", net.IP(n)) } +func (n ExtIP) ExternalIP() (net.IP, error) { return net.IP(n), nil } +func (n ExtIP) String() string { return fmt.Sprintf("ExtIP(%v)", net.IP(n)) } +func (n ExtIP) MarshalText() ([]byte, error) { return []byte(fmt.Sprintf("extip:%v", net.IP(n))), nil } // These do nothing. @@ -148,7 +149,7 @@ func (ExtIP) DeleteMapping(string, int, int) error { return nil } func Any() Interface { // TODO: attempt to discover whether the local machine has an // Internet-class address. Return ExtIP in this case. - return startautodisc("UPnP or NAT-PMP", func() Interface { + return startautodisc("any", func() Interface { found := make(chan Interface, 2) go func() { found <- discoverUPnP() }() go func() { found <- discoverPMP() }() @@ -164,7 +165,7 @@ func Any() Interface { // UPnP returns a port mapper that uses UPnP. It will attempt to // discover the address of your router using UDP broadcasts. func UPnP() Interface { - return startautodisc("UPnP", discoverUPnP) + return startautodisc("upnp", discoverUPnP) } // PMP returns a port mapper that uses NAT-PMP. The provided gateway @@ -174,7 +175,7 @@ func PMP(gateway net.IP) Interface { if gateway != nil { return &pmp{gw: gateway, c: natpmp.NewClient(gateway)} } - return startautodisc("NAT-PMP", discoverPMP) + return startautodisc("natpmp", discoverPMP) } // autodisc represents a port mapping mechanism that is still being @@ -228,6 +229,10 @@ func (n *autodisc) String() string { return n.found.String() } +func (n *autodisc) MarshalText() ([]byte, error) { + return []byte(n.what), nil +} + // wait blocks until auto-discovery has been performed. func (n *autodisc) wait() error { n.once.Do(func() { diff --git a/p2p/nat/natpmp.go b/p2p/nat/natpmp.go index 94ef1f4b68..b8f59ee890 100644 --- a/p2p/nat/natpmp.go +++ b/p2p/nat/natpmp.go @@ -70,6 +70,10 @@ func (n *pmp) DeleteMapping(protocol string, extport, intport int) (err error) { return err } +func (n *pmp) MarshalText() ([]byte, error) { + return []byte(fmt.Sprintf("natpmp:%v", n.gw)), nil +} + func discoverPMP() Interface { // run external address lookups on all potential gateways gws := potentialGateways() diff --git a/p2p/server.go b/p2p/server.go index 172f0667eb..c1564352e5 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -39,7 +39,6 @@ import ( "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" - "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/netutil" ) @@ -72,104 +71,6 @@ var ( errProtoHandshakeError = errors.New("rlpx proto error") ) -// Config holds Server options. -type Config struct { - // This field must be set to a valid secp256k1 private key. - PrivateKey *ecdsa.PrivateKey `toml:"-"` - - // MaxPeers is the maximum number of peers that can be - // connected. It must be greater than zero. - MaxPeers int - - // MaxPendingPeers is the maximum number of peers that can be pending in the - // handshake phase, counted separately for inbound and outbound connections. - // Zero defaults to preset values. - MaxPendingPeers int `toml:",omitempty"` - - // DialRatio controls the ratio of inbound to dialed connections. - // Example: a DialRatio of 2 allows 1/2 of connections to be dialed. - // Setting DialRatio to zero defaults it to 3. - DialRatio int `toml:",omitempty"` - - // NoDiscovery can be used to disable the peer discovery mechanism. - // Disabling is useful for protocol debugging (manual topology). - NoDiscovery bool - - // DiscoveryV4 specifies whether V4 discovery should be started. - DiscoveryV4 bool `toml:",omitempty"` - - // DiscoveryV5 specifies whether the new topic-discovery based V5 discovery - // protocol should be started or not. - DiscoveryV5 bool `toml:",omitempty"` - - // Name sets the node name of this server. - Name string `toml:"-"` - - // BootstrapNodes are used to establish connectivity - // with the rest of the network. - BootstrapNodes []*enode.Node - - // BootstrapNodesV5 are used to establish connectivity - // with the rest of the network using the V5 discovery - // protocol. - BootstrapNodesV5 []*enode.Node `toml:",omitempty"` - - // Static nodes are used as pre-configured connections which are always - // maintained and re-connected on disconnects. - StaticNodes []*enode.Node - - // Trusted nodes are used as pre-configured connections which are always - // allowed to connect, even above the peer limit. - TrustedNodes []*enode.Node - - // Connectivity can be restricted to certain IP networks. - // If this option is set to a non-nil value, only hosts which match one of the - // IP networks contained in the list are considered. - NetRestrict *netutil.Netlist `toml:",omitempty"` - - // NodeDatabase is the path to the database containing the previously seen - // live nodes in the network. - NodeDatabase string `toml:",omitempty"` - - // Protocols should contain the protocols supported - // by the server. Matching protocols are launched for - // each peer. - Protocols []Protocol `toml:"-" json:"-"` - - // If ListenAddr is set to a non-nil address, the server - // will listen for incoming connections. - // - // If the port is zero, the operating system will pick a port. The - // ListenAddr field will be updated with the actual address when - // the server is started. - ListenAddr string - - // If DiscAddr is set to a non-nil value, the server will use ListenAddr - // for TCP and DiscAddr for the UDP discovery protocol. - DiscAddr string - - // If set to a non-nil value, the given NAT port mapper - // is used to make the listening port available to the - // Internet. - NAT nat.Interface `toml:",omitempty"` - - // If Dialer is set to a non-nil value, the given Dialer - // is used to dial outbound peer connections. - Dialer NodeDialer `toml:"-"` - - // If NoDial is true, the server will not dial any peers. - NoDial bool `toml:",omitempty"` - - // If EnableMsgEvents is set then the server will emit PeerEvents - // whenever a message is sent to or received from a peer - EnableMsgEvents bool - - // Logger is a custom logger to use with the p2p.Server. - Logger log.Logger `toml:",omitempty"` - - clock mclock.Clock -} - // Server manages all peer connections. type Server struct { // Config fields may not be modified while the server is running.