mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-03-01 00:53:47 +00:00
Compare commits
No commits in common. "master" and "v1.17.0" have entirely different histories.
120 changed files with 1117 additions and 3178 deletions
4
.github/workflows/go.yml
vendored
4
.github/workflows/go.yml
vendored
|
|
@ -69,8 +69,8 @@ jobs:
|
|||
|
||||
- name: Install cross toolchain
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
|
||||
apt-get update
|
||||
apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
|
||||
|
||||
- name: Build
|
||||
run: go run build/ci.go test -arch 386 -short -p 8
|
||||
|
|
|
|||
98
AGENTS.md
98
AGENTS.md
|
|
@ -1,98 +0,0 @@
|
|||
# AGENTS
|
||||
|
||||
## Guidelines
|
||||
|
||||
- **Keep changes minimal and focused.** Only modify code directly related to the task at hand. Do not refactor unrelated code, rename existing variables or functions for style, or bundle unrelated fixes into the same commit or PR.
|
||||
- **Do not add, remove, or update dependencies** unless the task explicitly requires it.
|
||||
|
||||
## Pre-Commit Checklist
|
||||
|
||||
Before every commit, run **all** of the following checks and ensure they pass:
|
||||
|
||||
### 1. Formatting
|
||||
|
||||
Before committing, always run `gofmt` and `goimports` on all modified files:
|
||||
|
||||
```sh
|
||||
gofmt -w <modified files>
|
||||
goimports -w <modified files>
|
||||
```
|
||||
|
||||
### 2. Build All Commands
|
||||
|
||||
Verify that all tools compile successfully:
|
||||
|
||||
```sh
|
||||
make all
|
||||
```
|
||||
|
||||
This builds all executables under `cmd/`, including `keeper` which has special build requirements.
|
||||
|
||||
### 3. Tests
|
||||
|
||||
While iterating during development, use `-short` for faster feedback:
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go test -short
|
||||
```
|
||||
|
||||
Before committing, run the full test suite **without** `-short` to ensure all tests pass, including the Ethereum execution-spec tests and all state/block test permutations:
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go test
|
||||
```
|
||||
|
||||
### 4. Linting
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go lint
|
||||
```
|
||||
|
||||
This runs additional style checks. Fix any issues before committing.
|
||||
|
||||
### 5. Generated Code
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go check_generate
|
||||
```
|
||||
|
||||
Ensures that all generated files (e.g., `gen_*.go`) are up to date. If this fails, first install the required code generators by running `make devtools`, then run the appropriate `go generate` commands and include the updated files in your commit.
|
||||
|
||||
### 6. Dependency Hygiene
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go check_baddeps
|
||||
```
|
||||
|
||||
Verifies that no forbidden dependencies have been introduced.
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
Commit messages must be prefixed with the package(s) they modify, followed by a short lowercase description:
|
||||
|
||||
```
|
||||
<package(s)>: description
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `core/vm: fix stack overflow in PUSH instruction`
|
||||
- `eth, rpc: make trace configs optional`
|
||||
- `cmd/geth: add new flag for sync mode`
|
||||
|
||||
Use comma-separated package names when multiple areas are affected. Keep the description concise.
|
||||
|
||||
## Pull Request Title Format
|
||||
|
||||
PR titles follow the same convention as commit messages:
|
||||
|
||||
```
|
||||
<list of modified paths>: description
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `core/vm: fix stack overflow in PUSH instruction`
|
||||
- `core, eth: add arena allocator support`
|
||||
- `cmd/geth, internal/ethapi: refactor transaction args`
|
||||
- `trie/archiver: streaming subtree archival to fix OOM`
|
||||
|
||||
Use the top-level package paths, comma-separated if multiple areas are affected. Only mention the directories with functional changes, interface changes that trickle all over the codebase should not generate an exhaustive list. The description should be a short, lowercase summary of the change.
|
||||
|
|
@ -4,7 +4,7 @@ ARG VERSION=""
|
|||
ARG BUILDNUM=""
|
||||
|
||||
# Build Geth in a stock Go builder container
|
||||
FROM golang:1.26-alpine AS builder
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache gcc musl-dev linux-headers git
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ ARG VERSION=""
|
|||
ARG BUILDNUM=""
|
||||
|
||||
# Build Geth in a stock Go builder container
|
||||
FROM golang:1.26-alpine AS builder
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache gcc musl-dev linux-headers git
|
||||
|
||||
|
|
|
|||
|
|
@ -87,10 +87,6 @@ func (ec *engineClient) updateLoop(headCh <-chan types.ChainHeadEvent) {
|
|||
if status, err := ec.callForkchoiceUpdated(forkName, event); err == nil {
|
||||
log.Info("Successful ForkchoiceUpdated", "head", event.Block.Hash(), "status", status)
|
||||
} else {
|
||||
if err.Error() == "beacon syncer reorging" {
|
||||
log.Debug("Failed ForkchoiceUpdated", "head", event.Block.Hash(), "error", err)
|
||||
continue // ignore beacon syncer reorging errors, this error can occur if the blsync is skipping a block
|
||||
}
|
||||
log.Error("Failed ForkchoiceUpdated", "head", event.Block.Hash(), "error", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
|||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
|
||||
}
|
||||
var enc PayloadAttributes
|
||||
enc.Timestamp = hexutil.Uint64(p.Timestamp)
|
||||
|
|
@ -29,7 +28,6 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
|||
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
|
||||
enc.Withdrawals = p.Withdrawals
|
||||
enc.BeaconRoot = p.BeaconRoot
|
||||
enc.SlotNumber = (*hexutil.Uint64)(p.SlotNumber)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +39,6 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
|||
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
|
||||
}
|
||||
var dec PayloadAttributes
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -65,8 +62,5 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
|||
if dec.BeaconRoot != nil {
|
||||
p.BeaconRoot = dec.BeaconRoot
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
p.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
|||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
|
||||
}
|
||||
var enc ExecutableData
|
||||
enc.ParentHash = e.ParentHash
|
||||
|
|
@ -59,7 +58,6 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
|||
enc.Withdrawals = e.Withdrawals
|
||||
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
||||
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
||||
enc.SlotNumber = (*hexutil.Uint64)(e.SlotNumber)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +81,6 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
|||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
|
||||
}
|
||||
var dec ExecutableData
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -157,8 +154,5 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
|||
if dec.ExcessBlobGas != nil {
|
||||
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
e.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,13 +50,6 @@ var (
|
|||
// ExecutionPayloadV3 has the syntax of ExecutionPayloadV2 and appends the new
|
||||
// fields: blobGasUsed and excessBlobGas.
|
||||
PayloadV3 PayloadVersion = 0x3
|
||||
|
||||
// PayloadV4 is the identifier of ExecutionPayloadV4 introduced in amsterdam fork.
|
||||
//
|
||||
// https://github.com/ethereum/execution-apis/blob/main/src/engine/amsterdam.md#executionpayloadv4
|
||||
// ExecutionPayloadV4 has the syntax of ExecutionPayloadV3 and appends the new
|
||||
// field slotNumber.
|
||||
PayloadV4 PayloadVersion = 0x4
|
||||
)
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
||||
|
|
@ -69,13 +62,11 @@ type PayloadAttributes struct {
|
|||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *uint64 `json:"slotNumber"`
|
||||
}
|
||||
|
||||
// JSON type overrides for PayloadAttributes.
|
||||
type payloadAttributesMarshaling struct {
|
||||
Timestamp hexutil.Uint64
|
||||
SlotNumber *hexutil.Uint64
|
||||
Timestamp hexutil.Uint64
|
||||
}
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go
|
||||
|
|
@ -99,7 +90,6 @@ type ExecutableData struct {
|
|||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||
SlotNumber *uint64 `json:"slotNumber"`
|
||||
}
|
||||
|
||||
// JSON type overrides for executableData.
|
||||
|
|
@ -114,7 +104,6 @@ type executableDataMarshaling struct {
|
|||
Transactions []hexutil.Bytes
|
||||
BlobGasUsed *hexutil.Uint64
|
||||
ExcessBlobGas *hexutil.Uint64
|
||||
SlotNumber *hexutil.Uint64
|
||||
}
|
||||
|
||||
// StatelessPayloadStatusV1 is the result of a stateless payload execution.
|
||||
|
|
@ -224,7 +213,7 @@ func encodeTransactions(txs []*types.Transaction) [][]byte {
|
|||
return enc
|
||||
}
|
||||
|
||||
func DecodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
||||
func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
||||
var txs = make([]*types.Transaction, len(enc))
|
||||
for i, encTx := range enc {
|
||||
var tx types.Transaction
|
||||
|
|
@ -262,7 +251,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
|||
// for stateless execution, so it skips checking if the executable data hashes to
|
||||
// the requested hash (stateless has to *compute* the root hash, it's not given).
|
||||
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
|
||||
txs, err := DecodeTransactions(data.Transactions)
|
||||
txs, err := decodeTransactions(data.Transactions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -324,7 +313,6 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
|||
BlobGasUsed: data.BlobGasUsed,
|
||||
ParentBeaconRoot: beaconRoot,
|
||||
RequestsHash: requestsHash,
|
||||
SlotNumber: data.SlotNumber,
|
||||
}
|
||||
return types.NewBlockWithHeader(header).
|
||||
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}),
|
||||
|
|
@ -352,7 +340,6 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
|||
Withdrawals: block.Withdrawals(),
|
||||
BlobGasUsed: block.BlobGasUsed(),
|
||||
ExcessBlobGas: block.ExcessBlobGas(),
|
||||
SlotNumber: block.SlotNumber(),
|
||||
}
|
||||
|
||||
// Add blobs.
|
||||
|
|
|
|||
|
|
@ -5,102 +5,81 @@
|
|||
# https://github.com/ethereum/execution-spec-tests/releases/download/v5.1.0
|
||||
a3192784375acec7eaec492799d5c5d0c47a2909a3cc40178898e4ecd20cc416 fixtures_develop.tar.gz
|
||||
|
||||
# version:golang 1.25.7
|
||||
# version:golang 1.25.1
|
||||
# https://go.dev/dl/
|
||||
178f2832820274b43e177d32f06a3ebb0129e427dd20a5e4c88df2c1763cf10a go1.25.7.src.tar.gz
|
||||
81bf2a1f20633f62d55d826d82dde3b0570cf1408a91e15781b266037299285b go1.25.7.aix-ppc64.tar.gz
|
||||
bf5050a2152f4053837b886e8d9640c829dbacbc3370f913351eb0904cb706f5 go1.25.7.darwin-amd64.tar.gz
|
||||
ff18369ffad05c57d5bed888b660b31385f3c913670a83ef557cdfd98ea9ae1b go1.25.7.darwin-arm64.tar.gz
|
||||
c5dccd7f192dd7b305dc209fb316ac1917776d74bd8e4d532ef2772f305bf42a go1.25.7.dragonfly-amd64.tar.gz
|
||||
a2de97c8ac74bf64b0ae73fe9d379e61af530e061bc7f8f825044172ffe61a8b go1.25.7.freebsd-386.tar.gz
|
||||
055f9e138787dcafa81eb0314c8ff70c6dd0f6dba1e8a6957fef5d5efd1ab8fd go1.25.7.freebsd-amd64.tar.gz
|
||||
60e7f7a7c990f0b9539ac8ed668155746997d404643a4eecd47b3dee1b7e710b go1.25.7.freebsd-arm.tar.gz
|
||||
631e03d5fd4c526e2f499154d8c6bf4cb081afb2fff171c428722afc9539d53a go1.25.7.freebsd-arm64.tar.gz
|
||||
8a264fd685823808140672812e3ad9c43f6ad59444c0dc14cdd3a1351839ddd5 go1.25.7.freebsd-riscv64.tar.gz
|
||||
57c672447d906a1bcab98f2b11492d54521a791aacbb4994a25169e59cbe289a go1.25.7.illumos-amd64.tar.gz
|
||||
2866517e9ca81e6a2e85a930e9b11bc8a05cfeb2fc6dc6cb2765e7fb3c14b715 go1.25.7.linux-386.tar.gz
|
||||
12e6d6a191091ae27dc31f6efc630e3a3b8ba409baf3573d955b196fdf086005 go1.25.7.linux-amd64.tar.gz
|
||||
ba611a53534135a81067240eff9508cd7e256c560edd5d8c2fef54f083c07129 go1.25.7.linux-arm64.tar.gz
|
||||
1ba07e0eb86b839e72467f4b5c7a5597d07f30bcf5563c951410454f7cda5266 go1.25.7.linux-armv6l.tar.gz
|
||||
775753fc5952a334c415f08768df2f0b73a3228a16e8f5f63d545daacb4e3357 go1.25.7.linux-loong64.tar.gz
|
||||
1a023bb367c5fbb4c637a2f6dc23ff17c6591ad929ce16ea88c74d857153b307 go1.25.7.linux-mips.tar.gz
|
||||
a8e97223d8aa6fdfd45f132a4784d2f536bbac5f3d63a24b63d33b6bfe1549af go1.25.7.linux-mips64.tar.gz
|
||||
eb9edb6223330d5e20275667c65dea076b064c08e595fe4eba5d7d6055cfaccf go1.25.7.linux-mips64le.tar.gz
|
||||
9c1e693552a5f9bb9e0012d1c5e01456ecefbc59bef53a77305222ce10aba368 go1.25.7.linux-mipsle.tar.gz
|
||||
28a788798e7329acbbc0ac2caa5e4368b1e5ede646cc24429c991214cfb45c63 go1.25.7.linux-ppc64.tar.gz
|
||||
42124c0edc92464e2b37b2d7fcd3658f0c47ebd6a098732415a522be8cb88e3f go1.25.7.linux-ppc64le.tar.gz
|
||||
88d59c6893c8425875d6eef8e3434bc2fa2552e5ad4c058c6cd8cd710a0301c8 go1.25.7.linux-riscv64.tar.gz
|
||||
c6b77facf666dc68195ecab05dbf0ebb4e755b2a8b7734c759880557f1c29b0c go1.25.7.linux-s390x.tar.gz
|
||||
f14c184d9ade0ee04c7735d4071257b90896ecbde1b32adae84135f055e6399b go1.25.7.netbsd-386.tar.gz
|
||||
7e7389e404dca1088c31f0fc07f1dd60891d7182bcd621469c14f7e79eceb3ff go1.25.7.netbsd-amd64.tar.gz
|
||||
70388bb3ef2f03dbf1357e9056bd09034a67e018262557354f8cf549766b3f9d go1.25.7.netbsd-arm.tar.gz
|
||||
8c1cda9d25bfc9b18d24d5f95fc23949dd3ff99fa408a6cfa40e2cf12b07e362 go1.25.7.netbsd-arm64.tar.gz
|
||||
42f0d1bfbe39b8401cccb84dd66b30795b97bfc9620dfdc17c5cd4fcf6495cb0 go1.25.7.openbsd-386.tar.gz
|
||||
e514879c0a28bc32123cd52c4c093de912477fe83f36a6d07517d066ef55391a go1.25.7.openbsd-amd64.tar.gz
|
||||
8cd22530695a0218232bf7efea8f162df1697a3106942ac4129b8c3de39ce4ef go1.25.7.openbsd-arm.tar.gz
|
||||
938720f6ebc0d1c53d7840321d3a31f29fd02496e84a6538f442a9311dc1cc9a go1.25.7.openbsd-arm64.tar.gz
|
||||
a4c378b73b98f89a3596c2ef51aabbb28783d9ca29f7e317d8ca07939660ce6f go1.25.7.openbsd-ppc64.tar.gz
|
||||
937b58734fbeaa8c7941a0e4285e7e84b7885396e8d11c23f9ab1a8ff10ff20e go1.25.7.openbsd-riscv64.tar.gz
|
||||
61a093c8c5244916f25740316386bb9f141545dcf01b06a79d1c78ece488403e go1.25.7.plan9-386.tar.gz
|
||||
7fc8f6689c9de8ccb7689d2278035fa83c2d601409101840df6ddfe09ba58699 go1.25.7.plan9-amd64.tar.gz
|
||||
9661dff8eaeeb62f1c3aadbc5ff189a2e6744e1ec885e32dbcb438f58a34def5 go1.25.7.plan9-arm.tar.gz
|
||||
28ecba0e1d7950c8b29a4a04962dd49c3bf5221f55a44f17d98f369f82859cf4 go1.25.7.solaris-amd64.tar.gz
|
||||
baa6b488291801642fa620026169e38bec2da2ac187cd3ae2145721cf826bbc3 go1.25.7.windows-386.zip
|
||||
c75e5f4ff62d085cc0017be3ad19d5536f46825fa05db06ec468941f847e3228 go1.25.7.windows-amd64.zip
|
||||
807033f85931bc4a589ca8497535dcbeb1f30d506e47fa200f5f04c4a71c3d9f go1.25.7.windows-arm64.zip
|
||||
d010c109cee94d80efe681eab46bdea491ac906bf46583c32e9f0dbb0bd1a594 go1.25.1.src.tar.gz
|
||||
1d622468f767a1b9fe1e1e67bd6ce6744d04e0c68712adc689748bbeccb126bb go1.25.1.darwin-amd64.tar.gz
|
||||
68deebb214f39d542e518ebb0598a406ab1b5a22bba8ec9ade9f55fb4dd94a6c go1.25.1.darwin-arm64.tar.gz
|
||||
d03cdcbc9bd8baf5cf028de390478e9e2b3e4d0afe5a6582dedc19bfe6a263b2 go1.25.1.linux-386.tar.gz
|
||||
7716a0d940a0f6ae8e1f3b3f4f36299dc53e31b16840dbd171254312c41ca12e go1.25.1.linux-amd64.tar.gz
|
||||
65a3e34fb2126f55b34e1edfc709121660e1be2dee6bdf405fc399a63a95a87d go1.25.1.linux-arm64.tar.gz
|
||||
eb949be683e82a99e9861dafd7057e31ea40b161eae6c4cd18fdc0e8c4ae6225 go1.25.1.linux-armv6l.tar.gz
|
||||
be13d5479b8c75438f2efcaa8c191fba3af684b3228abc9c99c7aa8502f34424 go1.25.1.windows-386.zip
|
||||
4a974de310e7ee1d523d2fcedb114ba5fa75408c98eb3652023e55ccf3fa7cab go1.25.1.windows-amd64.zip
|
||||
45ab4290adbd6ee9e7f18f0d57eaa9008fdbef590882778ed93eac3c8cca06c5 go1.25.1.aix-ppc64.tar.gz
|
||||
2e3c1549bed3124763774d648f291ac42611232f48320ebbd23517c909c09b81 go1.25.1.dragonfly-amd64.tar.gz
|
||||
dc0198dd4ec520e13f26798def8750544edf6448d8e9c43fd2a814e4885932af go1.25.1.freebsd-386.tar.gz
|
||||
c4f1a7e7b258406e6f3b677ecdbd97bbb23ff9c0d44be4eb238a07d360f69ac8 go1.25.1.freebsd-amd64.tar.gz
|
||||
7772fc5ff71ed39297ec0c1599fc54e399642c9b848eac989601040923b0de9c go1.25.1.freebsd-arm.tar.gz
|
||||
5bb011d5d5b6218b12189f07aa0be618ab2002662fff1ca40afba7389735c207 go1.25.1.freebsd-arm64.tar.gz
|
||||
ccac716240cb049bebfafcb7eebc3758512178a4c51fc26da9cc032035d850c8 go1.25.1.freebsd-riscv64.tar.gz
|
||||
cc53910ffb9fcfdd988a9fa25b5423bae1cfa01b19616be646700e1f5453b466 go1.25.1.illumos-amd64.tar.gz
|
||||
efe809f923bcedab44bf7be2b3af8d182b512b1bf9c07d302e0c45d26c8f56f3 go1.25.1.linux-loong64.tar.gz
|
||||
c0de33679f6ed68991dc42dc4a602e74a666e3e166c1748ee1b5d1a7ea2ffbb2 go1.25.1.linux-mips.tar.gz
|
||||
c270f7b0c0bdfbcd54fef4481227c40d41bb518f9ae38ee930870f04a0a6a589 go1.25.1.linux-mips64.tar.gz
|
||||
80be871ba9c944f34d1868cdf5047e1cf2e1289fe08cdb90e2453d2f0d6965ae go1.25.1.linux-mips64le.tar.gz
|
||||
9f09defa9bb22ebf2cde76162f40958564e57ce5c2b3649bc063bebcbc9294c1 go1.25.1.linux-mipsle.tar.gz
|
||||
2c76b7d278c1d43ad19d478ad3f0f05e7b782b64b90870701b314fa48b5f43c6 go1.25.1.linux-ppc64.tar.gz
|
||||
8b0c8d3ee5b1b5c28b6bd63dc4438792012e01d03b4bf7a61d985c87edab7d1f go1.25.1.linux-ppc64le.tar.gz
|
||||
22fe934a9d0c9c57275716c55b92d46ebd887cec3177c9140705efa9f84ba1e2 go1.25.1.linux-riscv64.tar.gz
|
||||
9cfe517ba423f59f3738ca5c3d907c103253cffbbcc2987142f79c5de8c1bf93 go1.25.1.linux-s390x.tar.gz
|
||||
6af8a08353e76205d5b743dd7a3f0126684f96f62be0a31b75daf9837e512c46 go1.25.1.netbsd-386.tar.gz
|
||||
e5d534ff362edb1bd8c8e10892b6a027c4c1482454245d1529167676498684c7 go1.25.1.netbsd-amd64.tar.gz
|
||||
88bcf39254fdcea6a199c1c27d787831b652427ce60851ae9e41a3d7eb477f45 go1.25.1.netbsd-arm.tar.gz
|
||||
d7c2eabe1d04ee47bcaea2816fdd90dbd25d90d4dfa756faa9786c788e4f3a4e go1.25.1.netbsd-arm64.tar.gz
|
||||
14a2845977eb4dde11d929858c437a043467c427db87899935e90cee04a38d72 go1.25.1.openbsd-386.tar.gz
|
||||
d27ac54b38a13a09c81e67c82ac70d387037341c85c3399291c73e13e83fdd8c go1.25.1.openbsd-amd64.tar.gz
|
||||
0f4ab5f02500afa4befd51fed1e8b45e4d07ca050f641cc3acc76eaa4027b2c3 go1.25.1.openbsd-arm.tar.gz
|
||||
d46c3bd156843656f7f3cb0dec27ea51cd926ec3f7b80744bf8156e67c1c812f go1.25.1.openbsd-arm64.tar.gz
|
||||
c550514c67f22e409be10e40eace761e2e43069f4ef086ae6e60aac736c2b679 go1.25.1.openbsd-ppc64.tar.gz
|
||||
8a09a8714a2556eb13fc1f10b7ce2553fcea4971e3330fc3be0efd24aab45734 go1.25.1.openbsd-riscv64.tar.gz
|
||||
b0e1fefaf0c7abd71f139a54eee9767944aff5f0bc9d69c968234804884e552f go1.25.1.plan9-386.tar.gz
|
||||
e94732c94f149690aa0ab11c26090577211b4a988137cb2c03ec0b54e750402e go1.25.1.plan9-amd64.tar.gz
|
||||
7eb80e9de1e817d9089a54e8c7c5c8d8ed9e5fb4d4a012fc0f18fc422a484f0c go1.25.1.plan9-arm.tar.gz
|
||||
1261dfad7c4953c0ab90381bc1242dc54e394db7485c59349428d532b2273343 go1.25.1.solaris-amd64.tar.gz
|
||||
04bc3c078e9e904c4d58d6ac2532a5bdd402bd36a9ff0b5949b3c5e6006a05ee go1.25.1.windows-arm64.zip
|
||||
|
||||
# version:golangci 2.10.1
|
||||
# version:golangci 2.4.0
|
||||
# https://github.com/golangci/golangci-lint/releases/
|
||||
# https://github.com/golangci/golangci-lint/releases/download/v2.10.1
|
||||
66fb0da81b8033b477f97eea420d4b46b230ca172b8bb87c6610109f3772b6b6 golangci-lint-2.10.1-darwin-amd64.tar.gz
|
||||
03bfadf67e52b441b7ec21305e501c717df93c959836d66c7f97312654acb297 golangci-lint-2.10.1-darwin-arm64.tar.gz
|
||||
c9a44658ccc8f7b8dbbd4ae6020ba91c1a5d3987f4d91ced0f7d2bea013e57ca golangci-lint-2.10.1-freebsd-386.tar.gz
|
||||
a513c5cb4e0f5bd5767001af9d5e97e7868cfc2d9c46739a4df93e713cfb24af golangci-lint-2.10.1-freebsd-amd64.tar.gz
|
||||
2ef38eefc4b5cee2febacb75a30579526e5656c16338a921d80e59a8e87d4425 golangci-lint-2.10.1-freebsd-arm64.tar.gz
|
||||
8fea6766318b4829e766bbe325f10191d75297dcc44ae35bf374816037878e38 golangci-lint-2.10.1-freebsd-armv6.tar.gz
|
||||
30b629870574d6254f3e8804e5a74b34f98e1263c9d55465830d739c88b862ed golangci-lint-2.10.1-freebsd-armv7.tar.gz
|
||||
c0db839f866ce80b1b6c96167aa101cfe50d9c936f42d942a3c1cbdc1801af68 golangci-lint-2.10.1-illumos-amd64.tar.gz
|
||||
280eb56636e9175f671cd7b755d7d67f628ae2ed00a164d1e443c43c112034e5 golangci-lint-2.10.1-linux-386.deb
|
||||
065a7d99da61dc7dfbfef2e2d7053dd3fa6672598f2747117aa4bb5f45e7df7f golangci-lint-2.10.1-linux-386.rpm
|
||||
a55918c03bb413b2662287653ab2ae2fef4e37428b247dad6348724adde9d770 golangci-lint-2.10.1-linux-386.tar.gz
|
||||
8aa9b3aa14f39745eeb7fc7ff50bcac683e785397d1e4bc9afd2184b12c4ce86 golangci-lint-2.10.1-linux-amd64.deb
|
||||
62a111688e9e305032334a2cbc84f4d971b64bb3bffc99d3f80081d57fb25e32 golangci-lint-2.10.1-linux-amd64.rpm
|
||||
dfa775874cf0561b404a02a8f4481fc69b28091da95aa697259820d429b09c99 golangci-lint-2.10.1-linux-amd64.tar.gz
|
||||
b3f36937e8ea1660739dc0f5c892ea59c9c21ed4e75a91a25957c561f7f79a55 golangci-lint-2.10.1-linux-arm64.deb
|
||||
36d50314d53683b1f1a2a6cedfb5a9468451b481c64ab9e97a8e843ea088074d golangci-lint-2.10.1-linux-arm64.rpm
|
||||
6652b42ae02915eb2f9cb2a2e0cac99514c8eded8388d88ae3e06e1a52c00de8 golangci-lint-2.10.1-linux-arm64.tar.gz
|
||||
a32d8d318e803496812dd3461f250e52ccc7f53c47b95ce404a9cf55778ceb6a golangci-lint-2.10.1-linux-armv6.deb
|
||||
41d065f4c8ea165a1531abea644988ee2e973e4f0b49f9725ed3b979dac45112 golangci-lint-2.10.1-linux-armv6.rpm
|
||||
59159a4df03aabbde69d15c7b7b3df143363cbb41f4bd4b200caffb8e34fb734 golangci-lint-2.10.1-linux-armv6.tar.gz
|
||||
b2e8ec0e050a1e2251dfe1561434999d202f5a3f9fa47ce94378b0fd1662ea5a golangci-lint-2.10.1-linux-armv7.deb
|
||||
28c9331429a497da27e9c77846063bd0e8275e878ffedb4eb9e9f21d24771cc0 golangci-lint-2.10.1-linux-armv7.rpm
|
||||
818f33e95b273e3769284b25563b51ef6a294e9e25acf140fda5830c075a1a59 golangci-lint-2.10.1-linux-armv7.tar.gz
|
||||
6b6b85ed4b7c27f51097dd681523000409dde835e86e6e314e87be4bb013e2ab golangci-lint-2.10.1-linux-loong64.deb
|
||||
94050a0cf06169e2ae44afb307dcaafa7d7c3b38c0c23b5652cf9cb60f0c337f golangci-lint-2.10.1-linux-loong64.rpm
|
||||
25820300fccb8c961c1cdcb1f77928040c079e04c43a3a5ceb34b1cb4a1c5c8d golangci-lint-2.10.1-linux-loong64.tar.gz
|
||||
98bf39d10139fdcaa37f94950e9bbb8888660ae468847ae0bf1cb5bf67c1f68b golangci-lint-2.10.1-linux-mips64.deb
|
||||
df3ce5f03808dcceaa8b683d1d06e95c885f09b59dc8e15deb840fbe2b3e3299 golangci-lint-2.10.1-linux-mips64.rpm
|
||||
972508dda523067e6e6a1c8e6609d63bc7c4153819c11b947d439235cf17bac2 golangci-lint-2.10.1-linux-mips64.tar.gz
|
||||
1d37f2919e183b5bf8b1777ed8c4b163d3b491d0158355a7999d647655cbbeb6 golangci-lint-2.10.1-linux-mips64le.deb
|
||||
e341d031002cd09a416329ed40f674231051a38544b8f94deb2d1708ce1f4a6f golangci-lint-2.10.1-linux-mips64le.rpm
|
||||
393560122b9cb5538df0c357d30eb27b6ee563533fbb9b138c8db4fd264002af golangci-lint-2.10.1-linux-mips64le.tar.gz
|
||||
21ca46b6a96442e8957677a3ca059c6b93674a68a01b1c71f4e5df0ea2e96d19 golangci-lint-2.10.1-linux-ppc64le.deb
|
||||
57fe0cbca0a9bbdf1547c5e8aa7d278e6896b438d72a541bae6bc62c38b43d1e golangci-lint-2.10.1-linux-ppc64le.rpm
|
||||
e2883db9fa51584e5e203c64456f29993550a7faadc84e3faccdb48f0669992e golangci-lint-2.10.1-linux-ppc64le.tar.gz
|
||||
aa6da0e98ab0ba3bb7582e112174c349907d5edfeff90a551dca3c6eecf92fc0 golangci-lint-2.10.1-linux-riscv64.deb
|
||||
3c68d76cd884a7aad206223a980b9c20bb9ea74b560fa27ed02baf2389189234 golangci-lint-2.10.1-linux-riscv64.rpm
|
||||
3bca11bfac4197205639cbd4676a5415054e629ac6c12ea10fcbe33ef852d9c3 golangci-lint-2.10.1-linux-riscv64.tar.gz
|
||||
0c6aed2ce49db2586adbac72c80d871f06feb1caf4c0763a5ca98fec809a8f0b golangci-lint-2.10.1-linux-s390x.deb
|
||||
16c285adfe1061d69dd8e503be69f87c7202857c6f4add74ac02e3571158fbec golangci-lint-2.10.1-linux-s390x.rpm
|
||||
21011ad368eb04f024201b832095c6b5f96d0888de194cca5bfe4d9307d6364b golangci-lint-2.10.1-linux-s390x.tar.gz
|
||||
7b5191e77a70485918712e31ed55159956323e4911bab1b67569c9d86e1b75eb golangci-lint-2.10.1-netbsd-386.tar.gz
|
||||
07801fd38d293ebad10826f8285525a39ea91ce5ddad77d05bfa90bda9c884a9 golangci-lint-2.10.1-netbsd-amd64.tar.gz
|
||||
7e7219d71c1bf33b98c328c93dc0560706dd896a1c43c44696e5222fc9d7446e golangci-lint-2.10.1-netbsd-arm64.tar.gz
|
||||
92fbc90b9eec0e572269b0f5492a2895c426b086a68372fde49b7e4d4020863e golangci-lint-2.10.1-netbsd-armv6.tar.gz
|
||||
f67b3ae1f47caeefa507a4ebb0c8336958a19011fe48766443212030f75d004b golangci-lint-2.10.1-netbsd-armv7.tar.gz
|
||||
a40bc091c10cea84eaee1a90b84b65f5e8652113b0a600bb099e4e4d9d7caddb golangci-lint-2.10.1-windows-386.zip
|
||||
c60c87695e79db8e320f0e5be885059859de52bb5ee5f11be5577828570bc2a3 golangci-lint-2.10.1-windows-amd64.zip
|
||||
636ab790c8dcea8034aa34aba6031ca3893d68f7eda000460ab534341fadbab1 golangci-lint-2.10.1-windows-arm64.zip
|
||||
# https://github.com/golangci/golangci-lint/releases/download/v2.4.0/
|
||||
7904ce63f79db44934939cf7a063086ea0ea98e9b19eba0a9d52ccdd0d21951c golangci-lint-2.4.0-darwin-amd64.tar.gz
|
||||
cd4dd53fa09b6646baff5fd22b8c64d91db02c21c7496df27992d75d34feec59 golangci-lint-2.4.0-darwin-arm64.tar.gz
|
||||
d58f426ebe14cc257e81562b4bf37a488ffb4ffbbb3ec73041eb3b38bb25c0e1 golangci-lint-2.4.0-freebsd-386.tar.gz
|
||||
6ec4a6177fc6c0dd541fbcb3a7612845266d020d35cc6fa92959220cdf64ca39 golangci-lint-2.4.0-freebsd-amd64.tar.gz
|
||||
4d473e3e71c01feaa915a0604fb35758b41284fb976cdeac3f842118d9ee7e17 golangci-lint-2.4.0-freebsd-armv6.tar.gz
|
||||
58727746c6530801a3f9a702a5945556a5eb7e88809222536dd9f9d54cafaeff golangci-lint-2.4.0-freebsd-armv7.tar.gz
|
||||
fbf28c662760e24c32f82f8d16dffdb4a82de7726a52ba1fad94f890c22997ea golangci-lint-2.4.0-illumos-amd64.tar.gz
|
||||
a15a000a8981ef665e971e0f67e2acda9066a9e37a59344393b7351d8fb49c81 golangci-lint-2.4.0-linux-386.tar.gz
|
||||
fae792524c04424c0ac369f5b8076f04b45cf29fc945a370e55d369a8dc11840 golangci-lint-2.4.0-linux-amd64.tar.gz
|
||||
70ac11f55b80ec78fd3a879249cc9255121b8dfd7f7ed4fc46ed137f4abf17e7 golangci-lint-2.4.0-linux-arm64.tar.gz
|
||||
4acdc40e5cebe99e4e7ced358a05b2e71789f409b41cb4f39bbb86ccfa14b1dc golangci-lint-2.4.0-linux-armv6.tar.gz
|
||||
2a68749568fa22b4a97cb88dbea655595563c795076536aa6c087f7968784bf3 golangci-lint-2.4.0-linux-armv7.tar.gz
|
||||
9e3369afb023711036dcb0b4f45c9fe2792af962fa1df050c9f6ac101a6c5d73 golangci-lint-2.4.0-linux-loong64.tar.gz
|
||||
bb9143d6329be2c4dbfffef9564078e7da7d88e7dde6c829b6263d98e072229e golangci-lint-2.4.0-linux-mips64.tar.gz
|
||||
5ad1765b40d56cd04d4afd805b3ba6f4bfd9b36181da93c31e9b17e483d8608d golangci-lint-2.4.0-linux-mips64le.tar.gz
|
||||
918936fb9c0d5ba96bef03cf4348b03938634cfcced49be1e9bb29cb5094fa73 golangci-lint-2.4.0-linux-ppc64le.tar.gz
|
||||
f7474c638e1fb67ebbdc654b55ca0125377ea0bc88e8fee8d964a4f24eacf828 golangci-lint-2.4.0-linux-riscv64.tar.gz
|
||||
b617a9543997c8bfceaffa88a75d4e595030c6add69fba800c1e4d8f5fe253dd golangci-lint-2.4.0-linux-s390x.tar.gz
|
||||
7db027b03a9ba328f795215b04f594036837bc7dd0dd7cd16776b02a6167981c golangci-lint-2.4.0-netbsd-386.tar.gz
|
||||
52d8f9393f4313df0a62b752c37775e3af0b818e43e8dd28954351542d7c60bc golangci-lint-2.4.0-netbsd-amd64.tar.gz
|
||||
5c0086027fb5a4af3829e530c8115db4b35d11afe1914322eef528eb8cd38c69 golangci-lint-2.4.0-netbsd-arm64.tar.gz
|
||||
6b779d6ed1aed87cefe195cc11759902b97a76551b593312c6833f2635a3488f golangci-lint-2.4.0-netbsd-armv6.tar.gz
|
||||
f00d1f4b7ec3468a0f9fffd0d9ea036248b029b7621cbc9a59c449ef94356d09 golangci-lint-2.4.0-netbsd-armv7.tar.gz
|
||||
3ce671b0b42b58e35066493aab75a7e2826c9e079988f1ba5d814a4029faaf87 golangci-lint-2.4.0-windows-386.zip
|
||||
003112f7a56746feaabf20b744054bf9acdf900c9e77176383623c4b1d76aaa9 golangci-lint-2.4.0-windows-amd64.zip
|
||||
dc0c2092af5d47fc2cd31a1dfe7b4c7e765fab22de98bd21ef2ffcc53ad9f54f golangci-lint-2.4.0-windows-arm64.zip
|
||||
0263d23e20a260cb1592d35e12a388f99efe2c51b3611fdc66fbd9db1fce664d golangci-lint-2.4.0-windows-armv6.zip
|
||||
9403c03bf648e6313036e0273149d44bad1b9ad53889b6d00e4ccb842ba3c058 golangci-lint-2.4.0-windows-armv7.zip
|
||||
|
||||
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
|
||||
#
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@ var (
|
|||
"focal", // 20.04, EOL: 04/2030
|
||||
"jammy", // 22.04, EOL: 04/2032
|
||||
"noble", // 24.04, EOL: 04/2034
|
||||
"oracular", // 24.10, EOL: 07/2025
|
||||
"plucky", // 25.04, EOL: 01/2026
|
||||
}
|
||||
|
||||
// This is where the tests should be unpacked.
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ func (c *Conn) ReadEth() (any, error) {
|
|||
var msg any
|
||||
switch int(code) {
|
||||
case eth.StatusMsg:
|
||||
msg = new(eth.StatusPacket)
|
||||
msg = new(eth.StatusPacket69)
|
||||
case eth.GetBlockHeadersMsg:
|
||||
msg = new(eth.GetBlockHeadersPacket)
|
||||
case eth.BlockHeadersMsg:
|
||||
|
|
@ -164,6 +164,10 @@ func (c *Conn) ReadEth() (any, error) {
|
|||
msg = new(eth.GetBlockBodiesPacket)
|
||||
case eth.BlockBodiesMsg:
|
||||
msg = new(eth.BlockBodiesPacket)
|
||||
case eth.NewBlockMsg:
|
||||
msg = new(eth.NewBlockPacket)
|
||||
case eth.NewBlockHashesMsg:
|
||||
msg = new(eth.NewBlockHashesPacket)
|
||||
case eth.TransactionsMsg:
|
||||
msg = new(eth.TransactionsPacket)
|
||||
case eth.NewPooledTransactionHashesMsg:
|
||||
|
|
@ -225,7 +229,7 @@ func (c *Conn) ReadSnap() (any, error) {
|
|||
}
|
||||
|
||||
// dialAndPeer creates a peer connection and runs the handshake.
|
||||
func (s *Suite) dialAndPeer(status *eth.StatusPacket) (*Conn, error) {
|
||||
func (s *Suite) dialAndPeer(status *eth.StatusPacket69) (*Conn, error) {
|
||||
c, err := s.dial()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -238,7 +242,7 @@ func (s *Suite) dialAndPeer(status *eth.StatusPacket) (*Conn, error) {
|
|||
|
||||
// peer performs both the protocol handshake and the status message
|
||||
// exchange with the node in order to peer with it.
|
||||
func (c *Conn) peer(chain *Chain, status *eth.StatusPacket) error {
|
||||
func (c *Conn) peer(chain *Chain, status *eth.StatusPacket69) error {
|
||||
if err := c.handshake(); err != nil {
|
||||
return fmt.Errorf("handshake failed: %v", err)
|
||||
}
|
||||
|
|
@ -311,7 +315,7 @@ func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) {
|
|||
}
|
||||
|
||||
// statusExchange performs a `Status` message exchange with the given node.
|
||||
func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket) error {
|
||||
func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket69) error {
|
||||
loop:
|
||||
for {
|
||||
code, data, err := c.Read()
|
||||
|
|
@ -320,7 +324,7 @@ loop:
|
|||
}
|
||||
switch code {
|
||||
case eth.StatusMsg + protoOffset(ethProto):
|
||||
msg := new(eth.StatusPacket)
|
||||
msg := new(eth.StatusPacket69)
|
||||
if err := rlp.DecodeBytes(data, &msg); err != nil {
|
||||
return fmt.Errorf("error decoding status packet: %w", err)
|
||||
}
|
||||
|
|
@ -359,7 +363,7 @@ loop:
|
|||
}
|
||||
if status == nil {
|
||||
// default status message
|
||||
status = ð.StatusPacket{
|
||||
status = ð.StatusPacket69{
|
||||
ProtocolVersion: uint32(c.negotiatedProtoVersion),
|
||||
NetworkID: chain.config.ChainID.Uint64(),
|
||||
Genesis: chain.blocks[0].Hash(),
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ func (s *Suite) TestGetReceipts(t *utesting.T) {
|
|||
t.Fatalf("could not write to connection: %v", err)
|
||||
}
|
||||
// Wait for response.
|
||||
resp := new(eth.ReceiptsPacket)
|
||||
resp := new(eth.ReceiptsPacket[*eth.ReceiptList69])
|
||||
if err := conn.ReadMsg(ethProto, eth.ReceiptsMsg, &resp); err != nil {
|
||||
t.Fatalf("error reading block bodies msg: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func (s *Suite) AllTests() []utesting.Test {
|
|||
{Name: "Ping", Fn: s.TestPing},
|
||||
{Name: "PingLargeRequestID", Fn: s.TestPingLargeRequestID},
|
||||
{Name: "PingMultiIP", Fn: s.TestPingMultiIP},
|
||||
{Name: "HandshakeResend", Fn: s.TestHandshakeResend},
|
||||
{Name: "PingHandshakeInterrupted", Fn: s.TestPingHandshakeInterrupted},
|
||||
{Name: "TalkRequest", Fn: s.TestTalkRequest},
|
||||
{Name: "FindnodeZeroDistance", Fn: s.TestFindnodeZeroDistance},
|
||||
{Name: "FindnodeResults", Fn: s.TestFindnodeResults},
|
||||
|
|
@ -158,20 +158,22 @@ the attempt from a different IP.`)
|
|||
}
|
||||
}
|
||||
|
||||
// TestHandshakeResend starts a handshake, but doesn't finish it and sends a second ordinary message
|
||||
// packet instead of a handshake message packet. The remote node should repeat the previous WHOAREYOU
|
||||
// challenge for the first PING.
|
||||
func (s *Suite) TestHandshakeResend(t *utesting.T) {
|
||||
// TestPingHandshakeInterrupted starts a handshake, but doesn't finish it and sends a second ordinary message
|
||||
// packet instead of a handshake message packet. The remote node should respond with
|
||||
// another WHOAREYOU challenge for the second packet.
|
||||
func (s *Suite) TestPingHandshakeInterrupted(t *utesting.T) {
|
||||
t.Log(`TestPingHandshakeInterrupted starts a handshake, but doesn't finish it and sends a second ordinary message
|
||||
packet instead of a handshake message packet. The remote node should respond with
|
||||
another WHOAREYOU challenge for the second packet.`)
|
||||
|
||||
conn, l1 := s.listen1(t)
|
||||
defer conn.close()
|
||||
|
||||
// First PING triggers challenge.
|
||||
ping := &v5wire.Ping{ReqID: conn.nextReqID()}
|
||||
conn.write(l1, ping, nil)
|
||||
var challenge1 *v5wire.Whoareyou
|
||||
switch resp := conn.read(l1).(type) {
|
||||
case *v5wire.Whoareyou:
|
||||
challenge1 = resp
|
||||
t.Logf("got WHOAREYOU for PING")
|
||||
default:
|
||||
t.Fatal("expected WHOAREYOU, got", resp)
|
||||
|
|
@ -179,16 +181,9 @@ func (s *Suite) TestHandshakeResend(t *utesting.T) {
|
|||
|
||||
// Send second PING.
|
||||
ping2 := &v5wire.Ping{ReqID: conn.nextReqID()}
|
||||
conn.write(l1, ping2, nil)
|
||||
switch resp := conn.read(l1).(type) {
|
||||
case *v5wire.Whoareyou:
|
||||
if resp.Nonce != challenge1.Nonce {
|
||||
t.Fatalf("wrong nonce %x in WHOAREYOU (want %x)", resp.Nonce[:], challenge1.Nonce[:])
|
||||
}
|
||||
if !bytes.Equal(resp.ChallengeData, challenge1.ChallengeData) {
|
||||
t.Fatalf("wrong ChallengeData in resent WHOAREYOU (want %x)", resp.ChallengeData, challenge1.ChallengeData)
|
||||
}
|
||||
resp.Node = conn.remote
|
||||
switch resp := conn.reqresp(l1, ping2).(type) {
|
||||
case *v5wire.Pong:
|
||||
checkPong(t, resp, ping2, l1)
|
||||
default:
|
||||
t.Fatal("expected WHOAREYOU, got", resp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ type header struct {
|
|||
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`
|
||||
}
|
||||
|
||||
type headerMarshaling struct {
|
||||
|
|
@ -69,7 +68,6 @@ type headerMarshaling struct {
|
|||
BaseFee *math.HexOrDecimal256
|
||||
BlobGasUsed *math.HexOrDecimal64
|
||||
ExcessBlobGas *math.HexOrDecimal64
|
||||
SlotNumber *math.HexOrDecimal64
|
||||
}
|
||||
|
||||
type bbInput struct {
|
||||
|
|
@ -138,7 +136,6 @@ func (i *bbInput) ToBlock() *types.Block {
|
|||
BlobGasUsed: i.Header.BlobGasUsed,
|
||||
ExcessBlobGas: i.Header.ExcessBlobGas,
|
||||
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
|
||||
SlotNumber: i.Header.SlotNumber,
|
||||
}
|
||||
|
||||
// Fill optional values.
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ type stEnv struct {
|
|||
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
|
||||
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *uint64 `json:"slotNumber"`
|
||||
}
|
||||
|
||||
type stEnvMarshaling struct {
|
||||
|
|
@ -121,7 +120,6 @@ type stEnvMarshaling struct {
|
|||
ExcessBlobGas *math.HexOrDecimal64
|
||||
ParentExcessBlobGas *math.HexOrDecimal64
|
||||
ParentBlobGasUsed *math.HexOrDecimal64
|
||||
SlotNumber *math.HexOrDecimal64
|
||||
}
|
||||
|
||||
type rejectedTx struct {
|
||||
|
|
@ -197,7 +195,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
ExcessBlobGas: pre.Env.ParentExcessBlobGas,
|
||||
BlobGasUsed: pre.Env.ParentBlobGasUsed,
|
||||
BaseFee: pre.Env.ParentBaseFee,
|
||||
SlotNumber: pre.Env.SlotNumber,
|
||||
}
|
||||
header := &types.Header{
|
||||
Time: pre.Env.Timestamp,
|
||||
|
|
@ -268,9 +265,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
gaspool.SetGas(prevGas)
|
||||
continue
|
||||
}
|
||||
if receipt.Logs == nil {
|
||||
receipt.Logs = []*types.Log{}
|
||||
}
|
||||
includedTxs = append(includedTxs, tx)
|
||||
if hashError != nil {
|
||||
return nil, nil, nil, NewError(ErrorMissingBlockhash, hashError)
|
||||
|
|
|
|||
|
|
@ -56,35 +56,27 @@ func (l *fileWritingTracer) Write(p []byte) (n int, err error) {
|
|||
return n, nil
|
||||
}
|
||||
|
||||
// newFileWriter creates a tracer which wraps inner hooks (typically a logger),
|
||||
// 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) *tracers.Tracer {
|
||||
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 &tracers.Tracer{
|
||||
Hooks: t.hooks(),
|
||||
GetResult: func() (json.RawMessage, error) { return json.RawMessage("{}"), nil },
|
||||
Stop: func(err error) {},
|
||||
}
|
||||
return t.hooks()
|
||||
}
|
||||
|
||||
// newResultWriter creates a tracer that wraps and invokes an underlying tracer,
|
||||
// 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) *tracers.Tracer {
|
||||
func newResultWriter(baseDir string, tracer *tracers.Tracer) *tracing.Hooks {
|
||||
t := &fileWritingTracer{
|
||||
baseDir: baseDir,
|
||||
getResult: tracer.GetResult,
|
||||
inner: tracer.Hooks,
|
||||
suffix: "json",
|
||||
}
|
||||
return &tracers.Tracer{
|
||||
Hooks: t.hooks(),
|
||||
GetResult: func() (json.RawMessage, error) { return json.RawMessage("{}"), nil },
|
||||
Stop: func(err error) {},
|
||||
}
|
||||
return t.hooks()
|
||||
}
|
||||
|
||||
// OnTxStart creates a new output-file specific for this transaction, and invokes
|
||||
|
|
|
|||
|
|
@ -162,11 +162,6 @@ var (
|
|||
strings.Join(vm.ActivateableEips(), ", ")),
|
||||
Value: "GrayGlacier",
|
||||
}
|
||||
OpcodeCountFlag = &cli.StringFlag{
|
||||
Name: "opcode.count",
|
||||
Usage: "If set, opcode execution counts will be written to this file (relative to output.basedir).",
|
||||
Value: "",
|
||||
}
|
||||
VerbosityFlag = &cli.IntFlag{
|
||||
Name: "verbosity",
|
||||
Usage: "sets the verbosity level",
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ func (h header) MarshalJSON() ([]byte, error) {
|
|||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
SlotNumber *math.HexOrDecimal64 `json:"slotNumber" rlp:"optional"`
|
||||
}
|
||||
var enc header
|
||||
enc.ParentHash = h.ParentHash
|
||||
|
|
@ -61,7 +60,6 @@ func (h header) MarshalJSON() ([]byte, error) {
|
|||
enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed)
|
||||
enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas)
|
||||
enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot
|
||||
enc.SlotNumber = (*math.HexOrDecimal64)(h.SlotNumber)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +86,6 @@ func (h *header) UnmarshalJSON(input []byte) error {
|
|||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
SlotNumber *math.HexOrDecimal64 `json:"slotNumber" rlp:"optional"`
|
||||
}
|
||||
var dec header
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -158,8 +155,5 @@ func (h *header) UnmarshalJSON(input []byte) error {
|
|||
if dec.ParentBeaconBlockRoot != nil {
|
||||
h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
h.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *math.HexOrDecimal64 `json:"slotNumber"`
|
||||
}
|
||||
var enc stEnv
|
||||
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
||||
|
|
@ -60,7 +59,6 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
|
||||
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
|
||||
enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
|
||||
enc.SlotNumber = (*math.HexOrDecimal64)(s.SlotNumber)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +85,6 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
|||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *math.HexOrDecimal64 `json:"slotNumber"`
|
||||
}
|
||||
var dec stEnv
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -157,8 +154,5 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
|||
if dec.ParentBeaconBlockRoot != nil {
|
||||
s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
s.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/tests"
|
||||
|
|
@ -168,15 +167,14 @@ func Transition(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
// Configure tracer
|
||||
var tracer *tracers.Tracer
|
||||
if ctx.IsSet(TraceTracerFlag.Name) { // Custom tracing
|
||||
config := json.RawMessage(ctx.String(TraceTracerConfigFlag.Name))
|
||||
innerTracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.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))
|
||||
}
|
||||
tracer = newResultWriter(baseDir, innerTracer)
|
||||
vmConfig.Tracer = newResultWriter(baseDir, tracer)
|
||||
} else if ctx.Bool(TraceFlag.Name) { // JSON opcode tracing
|
||||
logConfig := &logger.Config{
|
||||
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
|
||||
|
|
@ -184,45 +182,20 @@ func Transition(ctx *cli.Context) error {
|
|||
EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
|
||||
}
|
||||
if ctx.Bool(TraceEnableCallFramesFlag.Name) {
|
||||
tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks {
|
||||
vmConfig.Tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks {
|
||||
return logger.NewJSONLoggerWithCallFrames(logConfig, out)
|
||||
})
|
||||
} else {
|
||||
tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks {
|
||||
vmConfig.Tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks {
|
||||
return logger.NewJSONLogger(logConfig, out)
|
||||
})
|
||||
}
|
||||
}
|
||||
// Configure opcode counter
|
||||
var opcodeTracer *tracers.Tracer
|
||||
if ctx.IsSet(OpcodeCountFlag.Name) && ctx.String(OpcodeCountFlag.Name) != "" {
|
||||
opcodeTracer = native.NewOpcodeCounter()
|
||||
if tracer != nil {
|
||||
// If we have an existing tracer, multiplex with the opcode tracer
|
||||
mux, _ := native.NewMuxTracer([]string{"trace", "opcode"}, []*tracers.Tracer{tracer, opcodeTracer})
|
||||
vmConfig.Tracer = mux.Hooks
|
||||
} else {
|
||||
vmConfig.Tracer = opcodeTracer.Hooks
|
||||
}
|
||||
} else if tracer != nil {
|
||||
vmConfig.Tracer = tracer.Hooks
|
||||
}
|
||||
// Run the test and aggregate the result
|
||||
s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write opcode counts if enabled
|
||||
if opcodeTracer != nil {
|
||||
fname := ctx.String(OpcodeCountFlag.Name)
|
||||
result, err := opcodeTracer.GetResult()
|
||||
if err != nil {
|
||||
return NewError(ErrorJson, fmt.Errorf("failed getting opcode counts: %v", err))
|
||||
}
|
||||
if err := saveFile(baseDir, fname, result); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Dump the execution result
|
||||
var (
|
||||
collector = make(Alloc)
|
||||
|
|
|
|||
|
|
@ -161,7 +161,6 @@ var (
|
|||
t8ntool.ForknameFlag,
|
||||
t8ntool.ChainIDFlag,
|
||||
t8ntool.RewardFlag,
|
||||
t8ntool.OpcodeCountFlag,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
2
cmd/evm/testdata/1/exp.json
vendored
2
cmd/evm/testdata/1/exp.json
vendored
|
|
@ -24,7 +24,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
|
|||
4
cmd/evm/testdata/13/exp2.json
vendored
4
cmd/evm/testdata/13/exp2.json
vendored
|
|
@ -12,7 +12,7 @@
|
|||
"status": "0x0",
|
||||
"cumulativeGasUsed": "0x84d0",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x84d0",
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
"status": "0x0",
|
||||
"cumulativeGasUsed": "0x109a0",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x84d0",
|
||||
|
|
|
|||
2
cmd/evm/testdata/23/exp.json
vendored
2
cmd/evm/testdata/23/exp.json
vendored
|
|
@ -11,7 +11,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x520b",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x520b",
|
||||
|
|
|
|||
4
cmd/evm/testdata/24/exp.json
vendored
4
cmd/evm/testdata/24/exp.json
vendored
|
|
@ -27,7 +27,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0xa861",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x92ea4a28224d033afb20e0cc2b290d4c7c2d61f6a4800a680e4e19ac962ee941",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0xa861",
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x10306",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x16b1d912f1d664f3f60f4e1b5f296f3c82a64a1a253117b4851d18bc03c4f1da",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5aa5",
|
||||
|
|
|
|||
2
cmd/evm/testdata/25/exp.json
vendored
2
cmd/evm/testdata/25/exp.json
vendored
|
|
@ -23,7 +23,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x92ea4a28224d033afb20e0cc2b290d4c7c2d61f6a4800a680e4e19ac962ee941",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
|
|||
2
cmd/evm/testdata/28/exp.json
vendored
2
cmd/evm/testdata/28/exp.json
vendored
|
|
@ -28,7 +28,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0xa865",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x7508d7139d002a4b3a26a4f12dec0d87cb46075c78bf77a38b569a133b509262",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0xa865",
|
||||
|
|
|
|||
2
cmd/evm/testdata/29/exp.json
vendored
2
cmd/evm/testdata/29/exp.json
vendored
|
|
@ -26,7 +26,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x84f70aba406a55628a0620f26d260f90aeb6ccc55fed6ec2ac13dd4f727032ed",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
|
|||
2
cmd/evm/testdata/3/exp.json
vendored
2
cmd/evm/testdata/3/exp.json
vendored
|
|
@ -24,7 +24,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x521f",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x521f",
|
||||
|
|
|
|||
4
cmd/evm/testdata/30/exp.json
vendored
4
cmd/evm/testdata/30/exp.json
vendored
|
|
@ -25,7 +25,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0xa410",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
|
|||
2
cmd/evm/testdata/33/exp.json
vendored
2
cmd/evm/testdata/33/exp.json
vendored
|
|
@ -44,7 +44,7 @@
|
|||
"root": "0x",
|
||||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x15fa9",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","logs": [],"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","logs": null,"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x15fa9",
|
||||
"effectiveGasPrice": null,
|
||||
|
|
|
|||
|
|
@ -111,7 +111,6 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
|
|||
utils.MetricsInfluxDBUsernameFlag,
|
||||
utils.MetricsInfluxDBPasswordFlag,
|
||||
utils.MetricsInfluxDBTagsFlag,
|
||||
utils.MetricsInfluxDBIntervalFlag,
|
||||
utils.MetricsInfluxDBTokenFlag,
|
||||
utils.MetricsInfluxDBBucketFlag,
|
||||
utils.MetricsInfluxDBOrganizationFlag,
|
||||
|
|
|
|||
|
|
@ -377,9 +377,6 @@ func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) {
|
|||
if ctx.IsSet(utils.MetricsInfluxDBTagsFlag.Name) {
|
||||
cfg.Metrics.InfluxDBTags = ctx.String(utils.MetricsInfluxDBTagsFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBIntervalFlag.Name) {
|
||||
cfg.Metrics.InfluxDBInterval = ctx.Duration(utils.MetricsInfluxDBIntervalFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsEnableInfluxDBV2Flag.Name) {
|
||||
cfg.Metrics.EnableInfluxDBV2 = ctx.Bool(utils.MetricsEnableInfluxDBV2Flag.Name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
ipcAPIs = "admin:1.0 debug:1.0 engine:1.0 eth:1.0 miner:1.0 net:1.0 rpc:1.0 testing:1.0 txpool:1.0 web3:1.0"
|
||||
ipcAPIs = "admin:1.0 debug:1.0 engine:1.0 eth:1.0 miner:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0"
|
||||
httpAPIs = "eth:1.0 net:1.0 rpc:1.0 web3:1.0"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
|
|
@ -38,7 +37,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/internal/tablewriter"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
|
|
@ -55,23 +53,6 @@ var (
|
|||
Name: "remove.chain",
|
||||
Usage: "If set, selects the state data for removal",
|
||||
}
|
||||
inspectTrieTopFlag = &cli.IntFlag{
|
||||
Name: "top",
|
||||
Usage: "Print the top N results per ranking category",
|
||||
Value: 10,
|
||||
}
|
||||
inspectTrieDumpPathFlag = &cli.StringFlag{
|
||||
Name: "dump-path",
|
||||
Usage: "Path for the trie statistics dump file",
|
||||
}
|
||||
inspectTrieSummarizeFlag = &cli.StringFlag{
|
||||
Name: "summarize",
|
||||
Usage: "Summarize an existing trie dump file (skip trie traversal)",
|
||||
}
|
||||
inspectTrieContractFlag = &cli.StringFlag{
|
||||
Name: "contract",
|
||||
Usage: "Inspect only the storage of the given contract address (skips full account trie walk)",
|
||||
}
|
||||
|
||||
removedbCommand = &cli.Command{
|
||||
Action: removeDB,
|
||||
|
|
@ -93,7 +74,6 @@ Remove blockchain and state databases`,
|
|||
dbCompactCmd,
|
||||
dbGetCmd,
|
||||
dbDeleteCmd,
|
||||
dbInspectTrieCmd,
|
||||
dbPutCmd,
|
||||
dbGetSlotsCmd,
|
||||
dbDumpFreezerIndex,
|
||||
|
|
@ -112,22 +92,6 @@ Remove blockchain and state databases`,
|
|||
Usage: "Inspect the storage size for each type of data in the database",
|
||||
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
||||
}
|
||||
dbInspectTrieCmd = &cli.Command{
|
||||
Action: inspectTrie,
|
||||
Name: "inspect-trie",
|
||||
ArgsUsage: "<blocknum>",
|
||||
Flags: slices.Concat([]cli.Flag{
|
||||
utils.ExcludeStorageFlag,
|
||||
inspectTrieTopFlag,
|
||||
utils.OutputFileFlag,
|
||||
inspectTrieDumpPathFlag,
|
||||
inspectTrieSummarizeFlag,
|
||||
inspectTrieContractFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||
Usage: "Print detailed trie information about the structure of account trie and storage tries.",
|
||||
Description: `This commands iterates the entrie trie-backed state. If the 'blocknum' is not specified,
|
||||
the latest block number will be used by default.`,
|
||||
}
|
||||
dbCheckStateContentCmd = &cli.Command{
|
||||
Action: checkStateContent,
|
||||
Name: "check-state-content",
|
||||
|
|
@ -421,88 +385,6 @@ func checkStateContent(ctx *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func inspectTrie(ctx *cli.Context) error {
|
||||
topN := ctx.Int(inspectTrieTopFlag.Name)
|
||||
if topN <= 0 {
|
||||
return fmt.Errorf("invalid --%s value %d (must be > 0)", inspectTrieTopFlag.Name, topN)
|
||||
}
|
||||
config := &trie.InspectConfig{
|
||||
NoStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
|
||||
TopN: topN,
|
||||
Path: ctx.String(utils.OutputFileFlag.Name),
|
||||
}
|
||||
|
||||
if summarizePath := ctx.String(inspectTrieSummarizeFlag.Name); summarizePath != "" {
|
||||
if ctx.NArg() > 0 {
|
||||
return fmt.Errorf("block number argument is not supported with --%s", inspectTrieSummarizeFlag.Name)
|
||||
}
|
||||
config.DumpPath = summarizePath
|
||||
log.Info("Summarizing trie dump", "path", summarizePath, "top", topN)
|
||||
return trie.Summarize(summarizePath, config)
|
||||
}
|
||||
if ctx.NArg() > 1 {
|
||||
return fmt.Errorf("excessive number of arguments: %v", ctx.Command.ArgsUsage)
|
||||
}
|
||||
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
db := utils.MakeChainDatabase(ctx, stack, false)
|
||||
defer stack.Close()
|
||||
defer db.Close()
|
||||
|
||||
var (
|
||||
trieRoot common.Hash
|
||||
hash common.Hash
|
||||
number uint64
|
||||
)
|
||||
switch {
|
||||
case ctx.NArg() == 0 || ctx.Args().Get(0) == "latest":
|
||||
head := rawdb.ReadHeadHeaderHash(db)
|
||||
n, ok := rawdb.ReadHeaderNumber(db, head)
|
||||
if !ok {
|
||||
return fmt.Errorf("could not load head block hash")
|
||||
}
|
||||
number = n
|
||||
case ctx.Args().Get(0) == "snapshot":
|
||||
trieRoot = rawdb.ReadSnapshotRoot(db)
|
||||
number = math.MaxUint64
|
||||
default:
|
||||
var err error
|
||||
number, err = strconv.ParseUint(ctx.Args().Get(0), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse blocknum, Args[0]: %v, err: %v", ctx.Args().Get(0), err)
|
||||
}
|
||||
}
|
||||
|
||||
if number != math.MaxUint64 {
|
||||
hash = rawdb.ReadCanonicalHash(db, number)
|
||||
if hash == (common.Hash{}) {
|
||||
return fmt.Errorf("canonical hash for block %d not found", number)
|
||||
}
|
||||
blockHeader := rawdb.ReadHeader(db, hash, number)
|
||||
trieRoot = blockHeader.Root
|
||||
}
|
||||
if trieRoot == (common.Hash{}) {
|
||||
log.Error("Empty root hash")
|
||||
}
|
||||
|
||||
config.DumpPath = ctx.String(inspectTrieDumpPathFlag.Name)
|
||||
if config.DumpPath == "" {
|
||||
config.DumpPath = stack.ResolvePath("trie-dump.bin")
|
||||
}
|
||||
|
||||
triedb := utils.MakeTrieDatabase(ctx, stack, db, false, true, false)
|
||||
defer triedb.Close()
|
||||
|
||||
if contractAddr := ctx.String(inspectTrieContractFlag.Name); contractAddr != "" {
|
||||
address := common.HexToAddress(contractAddr)
|
||||
log.Info("Inspecting contract", "address", address, "root", trieRoot, "block", number)
|
||||
return trie.InspectContract(triedb, db, trieRoot, address)
|
||||
}
|
||||
|
||||
log.Info("Inspecting trie", "root", trieRoot, "block", number, "dump", config.DumpPath, "top", topN)
|
||||
return trie.Inspect(triedb, trieRoot, config)
|
||||
}
|
||||
|
||||
func showDBStats(db ethdb.KeyValueStater) {
|
||||
stats, err := db.Stat()
|
||||
if err != nil {
|
||||
|
|
@ -877,7 +759,7 @@ func showMetaData(ctx *cli.Context) error {
|
|||
data = append(data, []string{"headHeader.Root", fmt.Sprintf("%v", h.Root)})
|
||||
data = append(data, []string{"headHeader.Number", fmt.Sprintf("%d (%#x)", h.Number, h.Number)})
|
||||
}
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table := rawdb.NewTableWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Field", "Value"})
|
||||
table.AppendBulk(data)
|
||||
table.Render()
|
||||
|
|
|
|||
|
|
@ -216,7 +216,6 @@ var (
|
|||
utils.MetricsInfluxDBUsernameFlag,
|
||||
utils.MetricsInfluxDBPasswordFlag,
|
||||
utils.MetricsInfluxDBTagsFlag,
|
||||
utils.MetricsInfluxDBIntervalFlag,
|
||||
utils.MetricsEnableInfluxDBV2Flag,
|
||||
utils.MetricsInfluxDBTokenFlag,
|
||||
utils.MetricsInfluxDBBucketFlag,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ require (
|
|||
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/emicklei/dot v1.6.2 // indirect
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.6 // indirect
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
|
||||
github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect
|
||||
github.com/ferranbt/fastssz v0.1.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
|
|
@ -31,7 +31,7 @@ require (
|
|||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||
github.com/supranational/blst v0.3.16 // indirect
|
||||
github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1
|
|||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||
github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
|
||||
github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.6 h1:xQymkKCT5E2Jiaoqf3v4wsNgjZLY0lRSkZn27fRjSls=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.6/go.mod h1:8HMkUZ5JRv4hpw/XUrYWSQNAUzhHMg2UDb/U+5m+XNw=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs=
|
||||
github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk=
|
||||
github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8=
|
||||
github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY=
|
||||
|
|
@ -111,8 +111,8 @@ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1
|
|||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/supranational/blst v0.3.16 h1:bTDadT+3fK497EvLdWRQEjiGnUtzJ7jjIUMF0jqwYhE=
|
||||
github.com/supranational/blst v0.3.16/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||
github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw=
|
||||
github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
|
|
|
|||
|
|
@ -218,16 +218,6 @@ var (
|
|||
Usage: "Max number of elements (0 = no limit)",
|
||||
Value: 0,
|
||||
}
|
||||
TopFlag = &cli.IntFlag{
|
||||
Name: "top",
|
||||
Usage: "Print the top N results",
|
||||
Value: 5,
|
||||
}
|
||||
OutputFileFlag = &cli.StringFlag{
|
||||
Name: "output",
|
||||
Usage: "Writes the result in json to the output",
|
||||
Value: "",
|
||||
}
|
||||
|
||||
SnapshotFlag = &cli.BoolFlag{
|
||||
Name: "snapshot",
|
||||
|
|
@ -1026,13 +1016,6 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
|||
Category: flags.MetricsCategory,
|
||||
}
|
||||
|
||||
MetricsInfluxDBIntervalFlag = &cli.DurationFlag{
|
||||
Name: "metrics.influxdb.interval",
|
||||
Usage: "Interval between metrics reports to InfluxDB (with time unit, e.g. 10s)",
|
||||
Value: metrics.DefaultConfig.InfluxDBInterval,
|
||||
Category: flags.MetricsCategory,
|
||||
}
|
||||
|
||||
MetricsEnableInfluxDBV2Flag = &cli.BoolFlag{
|
||||
Name: "metrics.influxdbv2",
|
||||
Usage: "Enable metrics export/push to an external InfluxDB v2 database",
|
||||
|
|
@ -2263,14 +2246,13 @@ func SetupMetrics(cfg *metrics.Config) {
|
|||
bucket = cfg.InfluxDBBucket
|
||||
organization = cfg.InfluxDBOrganization
|
||||
tagsMap = SplitTagsFlag(cfg.InfluxDBTags)
|
||||
interval = cfg.InfluxDBInterval
|
||||
)
|
||||
if enableExport {
|
||||
log.Info("Enabling metrics export to InfluxDB", "interval", interval)
|
||||
go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, interval, endpoint, database, username, password, "geth.", tagsMap)
|
||||
log.Info("Enabling metrics export to InfluxDB")
|
||||
go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
|
||||
} else if enableExportV2 {
|
||||
log.Info("Enabling metrics export to InfluxDB (v2)", "interval", interval)
|
||||
go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, interval, endpoint, token, bucket, organization, "geth.", tagsMap)
|
||||
log.Info("Enabling metrics export to InfluxDB (v2)")
|
||||
go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap)
|
||||
}
|
||||
|
||||
// Expvar exporter.
|
||||
|
|
|
|||
|
|
@ -272,14 +272,6 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
amsterdam := chain.Config().IsAmsterdam(header.Number, header.Time)
|
||||
if amsterdam && header.SlotNumber == nil {
|
||||
return errors.New("header is missing slotNumber")
|
||||
}
|
||||
if !amsterdam && header.SlotNumber != nil {
|
||||
return fmt.Errorf("invalid slotNumber: have %d, expected nil", *header.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -310,8 +310,6 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
|
|||
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", *header.BlobGasUsed)
|
||||
case header.ParentBeaconRoot != nil:
|
||||
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", *header.ParentBeaconRoot)
|
||||
case header.SlotNumber != nil:
|
||||
return fmt.Errorf("invalid slotNumber, have %#x, expected nil", *header.SlotNumber)
|
||||
}
|
||||
// All basic checks passed, verify cascading fields
|
||||
return c.verifyCascadingFields(chain, header, parents)
|
||||
|
|
@ -696,9 +694,6 @@ func encodeSigHeader(w io.Writer, header *types.Header) {
|
|||
if header.ParentBeaconRoot != nil {
|
||||
panic("unexpected parent beacon root value in clique")
|
||||
}
|
||||
if header.SlotNumber != nil {
|
||||
panic("unexpected slot number value in clique")
|
||||
}
|
||||
if err := rlp.Encode(w, enc); err != nil {
|
||||
panic("can't encode: " + err.Error())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,8 +283,6 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
|
|||
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", *header.BlobGasUsed)
|
||||
case header.ParentBeaconRoot != nil:
|
||||
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", *header.ParentBeaconRoot)
|
||||
case header.SlotNumber != nil:
|
||||
return fmt.Errorf("invalid slotNumber, have %#x, expected nil", *header.SlotNumber)
|
||||
}
|
||||
// Add some fake checks for tests
|
||||
if ethash.fakeDelay != nil {
|
||||
|
|
@ -561,9 +559,6 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
|
|||
if header.ParentBeaconRoot != nil {
|
||||
panic("parent beacon root set on ethash")
|
||||
}
|
||||
if header.SlotNumber != nil {
|
||||
panic("slot number set on ethash")
|
||||
}
|
||||
rlp.Encode(hasher, enc)
|
||||
hasher.Sum(hash[:0])
|
||||
return hash
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||
baseFee *big.Int
|
||||
blobBaseFee *big.Int
|
||||
random *common.Hash
|
||||
slotNum uint64
|
||||
)
|
||||
|
||||
// If we don't have an explicit author (i.e. not mining), extract from the header
|
||||
|
|
@ -62,10 +61,6 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||
if header.Difficulty.Sign() == 0 {
|
||||
random = &header.MixDigest
|
||||
}
|
||||
if header.SlotNumber != nil {
|
||||
slotNum = *header.SlotNumber
|
||||
}
|
||||
|
||||
return vm.BlockContext{
|
||||
CanTransfer: CanTransfer,
|
||||
Transfer: Transfer,
|
||||
|
|
@ -78,7 +73,6 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||
BlobBaseFee: blobBaseFee,
|
||||
GasLimit: header.GasLimit,
|
||||
Random: random,
|
||||
SlotNum: slotNum,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ func (g Genesis) MarshalJSON() ([]byte, error) {
|
|||
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
|
||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
|
||||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
|
||||
SlotNumber *uint64 `json:"slotNumber"`
|
||||
}
|
||||
var enc Genesis
|
||||
enc.Config = g.Config
|
||||
|
|
@ -57,7 +56,6 @@ func (g Genesis) MarshalJSON() ([]byte, error) {
|
|||
enc.BaseFee = (*math.HexOrDecimal256)(g.BaseFee)
|
||||
enc.ExcessBlobGas = (*math.HexOrDecimal64)(g.ExcessBlobGas)
|
||||
enc.BlobGasUsed = (*math.HexOrDecimal64)(g.BlobGasUsed)
|
||||
enc.SlotNumber = g.SlotNumber
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +77,6 @@ func (g *Genesis) UnmarshalJSON(input []byte) error {
|
|||
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
|
||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
|
||||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
|
||||
SlotNumber *uint64 `json:"slotNumber"`
|
||||
}
|
||||
var dec Genesis
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -136,8 +133,5 @@ func (g *Genesis) UnmarshalJSON(input []byte) error {
|
|||
if dec.BlobGasUsed != nil {
|
||||
g.BlobGasUsed = (*uint64)(dec.BlobGasUsed)
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
g.SlotNumber = dec.SlotNumber
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ type Genesis struct {
|
|||
BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas"` // EIP-4844
|
||||
BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844
|
||||
SlotNumber *uint64 `json:"slotNumber"` // EIP-7843
|
||||
}
|
||||
|
||||
// copy copies the genesis.
|
||||
|
|
@ -123,7 +122,6 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) {
|
|||
genesis.BaseFee = genesisHeader.BaseFee
|
||||
genesis.ExcessBlobGas = genesisHeader.ExcessBlobGas
|
||||
genesis.BlobGasUsed = genesisHeader.BlobGasUsed
|
||||
genesis.SlotNumber = genesisHeader.SlotNumber
|
||||
|
||||
return &genesis, nil
|
||||
}
|
||||
|
|
@ -549,12 +547,6 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
|||
if conf.IsPrague(num, g.Timestamp) {
|
||||
head.RequestsHash = &types.EmptyRequestsHash
|
||||
}
|
||||
if conf.IsAmsterdam(num, g.Timestamp) {
|
||||
head.SlotNumber = g.SlotNumber
|
||||
if head.SlotNumber == nil {
|
||||
head.SlotNumber = new(uint64)
|
||||
}
|
||||
}
|
||||
}
|
||||
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -424,7 +424,13 @@ func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp
|
|||
// HasBody verifies the existence of a block body corresponding to the hash.
|
||||
func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||
if isCanon(db, number, hash) {
|
||||
return true
|
||||
// Block is in ancient store, but bodies can be pruned.
|
||||
// Check if the block number is above the pruning tail.
|
||||
tail, _ := db.Tail()
|
||||
if number >= tail {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil {
|
||||
return false
|
||||
|
|
@ -466,7 +472,13 @@ func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
|||
// to a block.
|
||||
func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||
if isCanon(db, number, hash) {
|
||||
return true
|
||||
// Block is in ancient store, but receipts can be pruned.
|
||||
// Check if the block number is above the pruning tail.
|
||||
tail, _ := db.Tail()
|
||||
if number >= tail {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil {
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||
"github.com/ethereum/go-ethereum/internal/tablewriter"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
|
@ -664,7 +663,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
|||
total.Add(uint64(ancient.size()))
|
||||
}
|
||||
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table := NewTableWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Database", "Category", "Size", "Items"})
|
||||
table.SetFooter([]string{"", "Total", common.StorageSize(total.Load()).String(), fmt.Sprintf("%d", count.Load())})
|
||||
table.AppendBulk(stats)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
// Naive stub implementation for tablewriter
|
||||
|
||||
package tablewriter
|
||||
package rawdb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
|
@ -37,7 +37,7 @@ type Table struct {
|
|||
rows [][]string
|
||||
}
|
||||
|
||||
func NewWriter(w io.Writer) *Table {
|
||||
func NewTableWriter(w io.Writer) *Table {
|
||||
return &Table{out: w}
|
||||
}
|
||||
|
||||
|
|
@ -58,12 +58,12 @@ func (t *Table) SetFooter(footer []string) {
|
|||
t.footer = footer
|
||||
}
|
||||
|
||||
// AppendBulk appends one or more data rows to the table.
|
||||
// AppendBulk sets all data rows for the table at once, replacing any existing rows.
|
||||
//
|
||||
// Each row must have the same number of columns as the headers, or validation
|
||||
// will fail during Render().
|
||||
func (t *Table) AppendBulk(rows [][]string) {
|
||||
t.rows = append(t.rows, rows...)
|
||||
t.rows = rows
|
||||
}
|
||||
|
||||
// Render outputs the complete table to the configured writer. The table is rendered
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package tablewriter
|
||||
package rawdb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
func TestTableWriterTinyGo(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
table := NewWriter(&buf)
|
||||
table := NewTableWriter(&buf)
|
||||
|
||||
headers := []string{"Database", "Size", "Items", "Status"}
|
||||
rows := [][]string{
|
||||
|
|
@ -48,7 +48,7 @@ func TestTableWriterValidationErrors(t *testing.T) {
|
|||
// Test missing headers
|
||||
t.Run("MissingHeaders", func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
table := NewWriter(&buf)
|
||||
table := NewTableWriter(&buf)
|
||||
|
||||
rows := [][]string{{"x", "y", "z"}}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ func TestTableWriterValidationErrors(t *testing.T) {
|
|||
|
||||
t.Run("NotEnoughRowColumns", func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
table := NewWriter(&buf)
|
||||
table := NewTableWriter(&buf)
|
||||
|
||||
headers := []string{"A", "B", "C"}
|
||||
badRows := [][]string{
|
||||
|
|
@ -82,7 +82,7 @@ func TestTableWriterValidationErrors(t *testing.T) {
|
|||
|
||||
t.Run("TooManyRowColumns", func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
table := NewWriter(&buf)
|
||||
table := NewTableWriter(&buf)
|
||||
|
||||
headers := []string{"A", "B", "C"}
|
||||
badRows := [][]string{
|
||||
|
|
@ -102,7 +102,7 @@ func TestTableWriterValidationErrors(t *testing.T) {
|
|||
// Test mismatched footer columns
|
||||
t.Run("MismatchedFooterColumns", func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
table := NewWriter(&buf)
|
||||
table := NewTableWriter(&buf)
|
||||
|
||||
headers := []string{"A", "B", "C"}
|
||||
rows := [][]string{{"x", "y", "z"}}
|
||||
|
|
@ -195,19 +195,6 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
|||
// have been handles via pendingStorage above.
|
||||
// 2) we don't have new values, and can deliver empty response back
|
||||
if _, destructed := s.db.stateObjectsDestruct[s.address]; destructed {
|
||||
// Invoke the reader regardless and discard the returned value.
|
||||
// The returned value may not be empty, as it could belong to a
|
||||
// self-destructed contract.
|
||||
//
|
||||
// The read operation is still essential for correctly building
|
||||
// the block-level access list.
|
||||
//
|
||||
// TODO(rjl493456442) the reader interface can be extended with
|
||||
// Touch, recording the read access without the actual disk load.
|
||||
_, err := s.db.reader.Storage(s.address, key)
|
||||
if err != nil {
|
||||
s.db.setError(err)
|
||||
}
|
||||
s.originStorage[key] = common.Hash{} // track the empty slot as origin value
|
||||
return common.Hash{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -422,9 +422,6 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
|
|||
beaconRoot := common.HexToHash("0xbeac00")
|
||||
header.ParentBeaconRoot = &beaconRoot
|
||||
}
|
||||
if config.IsAmsterdam(header.Number, header.Time) {
|
||||
header.SlotNumber = new(uint64)
|
||||
}
|
||||
// Assemble and return the final block for sealing
|
||||
body := &types.Body{Transactions: txs}
|
||||
if config.IsShanghai(header.Number, header.Time) {
|
||||
|
|
|
|||
|
|
@ -177,9 +177,9 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
|
|||
msg := &Message{
|
||||
Nonce: tx.Nonce(),
|
||||
GasLimit: tx.Gas(),
|
||||
GasPrice: tx.GasPrice(),
|
||||
GasFeeCap: tx.GasFeeCap(),
|
||||
GasTipCap: tx.GasTipCap(),
|
||||
GasPrice: new(big.Int).Set(tx.GasPrice()),
|
||||
GasFeeCap: new(big.Int).Set(tx.GasFeeCap()),
|
||||
GasTipCap: new(big.Int).Set(tx.GasTipCap()),
|
||||
To: tx.To(),
|
||||
Value: tx.Value(),
|
||||
Data: tx.Data(),
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
var accountTrieLeavesAtDepth [16]*metrics.Counter
|
||||
|
|
@ -42,68 +41,59 @@ func init() {
|
|||
|
||||
// WitnessStats aggregates statistics for account and storage trie accesses.
|
||||
type WitnessStats struct {
|
||||
accountTrie *trie.LevelStats
|
||||
storageTrie *trie.LevelStats
|
||||
accountTrieLeaves [16]int64
|
||||
storageTrieLeaves [16]int64
|
||||
}
|
||||
|
||||
// NewWitnessStats creates a new WitnessStats collector.
|
||||
func NewWitnessStats() *WitnessStats {
|
||||
return &WitnessStats{
|
||||
accountTrie: trie.NewLevelStats(),
|
||||
storageTrie: trie.NewLevelStats(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *WitnessStats) init() {
|
||||
if s.accountTrie == nil {
|
||||
s.accountTrie = trie.NewLevelStats()
|
||||
}
|
||||
if s.storageTrie == nil {
|
||||
s.storageTrie = trie.NewLevelStats()
|
||||
}
|
||||
return &WitnessStats{}
|
||||
}
|
||||
|
||||
// Add records trie access depths from the given node paths.
|
||||
// If `owner` is the zero hash, accesses are attributed to the account trie;
|
||||
// otherwise, they are attributed to the storage trie of that account.
|
||||
func (s *WitnessStats) Add(nodes map[string][]byte, owner common.Hash) {
|
||||
s.init()
|
||||
|
||||
// Extract paths from the nodes map.
|
||||
// Extract paths from the nodes map
|
||||
paths := slices.Collect(maps.Keys(nodes))
|
||||
sort.Strings(paths)
|
||||
|
||||
ownerStat := s.accountTrie
|
||||
if owner != (common.Hash{}) {
|
||||
ownerStat = s.storageTrie
|
||||
}
|
||||
|
||||
for i, path := range paths {
|
||||
// If current path is a prefix of the next path, it's not a leaf.
|
||||
// The last path is always a leaf.
|
||||
if i == len(paths)-1 || !strings.HasPrefix(paths[i+1], paths[i]) {
|
||||
ownerStat.AddLeaf(len(path))
|
||||
depth := len(path)
|
||||
if owner == (common.Hash{}) {
|
||||
if depth >= len(s.accountTrieLeaves) {
|
||||
depth = len(s.accountTrieLeaves) - 1
|
||||
}
|
||||
s.accountTrieLeaves[depth] += 1
|
||||
} else {
|
||||
if depth >= len(s.storageTrieLeaves) {
|
||||
depth = len(s.storageTrieLeaves) - 1
|
||||
}
|
||||
s.storageTrieLeaves[depth] += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReportMetrics reports the collected statistics to the global metrics registry.
|
||||
func (s *WitnessStats) ReportMetrics(blockNumber uint64) {
|
||||
s.init()
|
||||
// Encode the metrics as JSON for easier consumption
|
||||
accountLeavesJson, _ := json.Marshal(s.accountTrieLeaves)
|
||||
storageLeavesJson, _ := json.Marshal(s.storageTrieLeaves)
|
||||
|
||||
accountTrieLeaves := s.accountTrie.LeafDepths()
|
||||
storageTrieLeaves := s.storageTrie.LeafDepths()
|
||||
// Log account trie depth statistics
|
||||
log.Info("Account trie depth stats",
|
||||
"block", blockNumber,
|
||||
"leavesAtDepth", string(accountLeavesJson))
|
||||
log.Info("Storage trie depth stats",
|
||||
"block", blockNumber,
|
||||
"leavesAtDepth", string(storageLeavesJson))
|
||||
|
||||
// Encode the metrics as JSON for easier consumption.
|
||||
accountLeavesJSON, _ := json.Marshal(accountTrieLeaves)
|
||||
storageLeavesJSON, _ := json.Marshal(storageTrieLeaves)
|
||||
|
||||
// Log account trie depth statistics.
|
||||
log.Info("Account trie depth stats", "block", blockNumber, "leavesAtDepth", string(accountLeavesJSON))
|
||||
log.Info("Storage trie depth stats", "block", blockNumber, "leavesAtDepth", string(storageLeavesJSON))
|
||||
|
||||
for i := 0; i < len(accountTrieLeavesAtDepth); i++ {
|
||||
accountTrieLeavesAtDepth[i].Inc(accountTrieLeaves[i])
|
||||
storageTrieLeavesAtDepth[i].Inc(storageTrieLeaves[i])
|
||||
for i := 0; i < 16; i++ {
|
||||
accountTrieLeavesAtDepth[i].Inc(s.accountTrieLeaves[i])
|
||||
storageTrieLeavesAtDepth[i].Inc(s.storageTrieLeaves[i])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,27 +17,18 @@
|
|||
package stateless
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func expectedLeaves(counts map[int]int64) [16]int64 {
|
||||
var leaves [16]int64
|
||||
for depth, count := range counts {
|
||||
leaves[depth] = count
|
||||
}
|
||||
return leaves
|
||||
}
|
||||
|
||||
func TestWitnessStatsAdd(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
nodes map[string][]byte
|
||||
owner common.Hash
|
||||
expectedAccountLeaves map[int]int64
|
||||
expectedStorageLeaves map[int]int64
|
||||
expectedAccountLeaves map[int64]int64
|
||||
expectedStorageLeaves map[int64]int64
|
||||
}{
|
||||
{
|
||||
name: "empty nodes",
|
||||
|
|
@ -50,7 +41,7 @@ func TestWitnessStatsAdd(t *testing.T) {
|
|||
"": []byte("data"),
|
||||
},
|
||||
owner: common.Hash{},
|
||||
expectedAccountLeaves: map[int]int64{0: 1},
|
||||
expectedAccountLeaves: map[int64]int64{0: 1},
|
||||
},
|
||||
{
|
||||
name: "single account trie leaf",
|
||||
|
|
@ -58,7 +49,7 @@ func TestWitnessStatsAdd(t *testing.T) {
|
|||
"abc": []byte("data"),
|
||||
},
|
||||
owner: common.Hash{},
|
||||
expectedAccountLeaves: map[int]int64{3: 1},
|
||||
expectedAccountLeaves: map[int64]int64{3: 1},
|
||||
},
|
||||
{
|
||||
name: "account trie with internal nodes",
|
||||
|
|
@ -68,7 +59,7 @@ func TestWitnessStatsAdd(t *testing.T) {
|
|||
"abc": []byte("data3"),
|
||||
},
|
||||
owner: common.Hash{},
|
||||
expectedAccountLeaves: map[int]int64{3: 1}, // Only "abc" is a leaf
|
||||
expectedAccountLeaves: map[int64]int64{3: 1}, // Only "abc" is a leaf
|
||||
},
|
||||
{
|
||||
name: "multiple account trie branches",
|
||||
|
|
@ -81,7 +72,7 @@ func TestWitnessStatsAdd(t *testing.T) {
|
|||
"bcd": []byte("data6"),
|
||||
},
|
||||
owner: common.Hash{},
|
||||
expectedAccountLeaves: map[int]int64{3: 2}, // "abc" (3) + "bcd" (3)
|
||||
expectedAccountLeaves: map[int64]int64{3: 2}, // "abc" (3) + "bcd" (3)
|
||||
},
|
||||
{
|
||||
name: "siblings are all leaves",
|
||||
|
|
@ -91,7 +82,7 @@ func TestWitnessStatsAdd(t *testing.T) {
|
|||
"ac": []byte("data3"),
|
||||
},
|
||||
owner: common.Hash{},
|
||||
expectedAccountLeaves: map[int]int64{2: 3},
|
||||
expectedAccountLeaves: map[int64]int64{2: 3},
|
||||
},
|
||||
{
|
||||
name: "storage trie leaves",
|
||||
|
|
@ -102,7 +93,7 @@ func TestWitnessStatsAdd(t *testing.T) {
|
|||
"124": []byte("data4"),
|
||||
},
|
||||
owner: common.HexToHash("0x1234"),
|
||||
expectedStorageLeaves: map[int]int64{3: 2}, // "123" (3) + "124" (3)
|
||||
expectedStorageLeaves: map[int64]int64{3: 2}, // "123" (3) + "124" (3)
|
||||
},
|
||||
{
|
||||
name: "complex trie structure",
|
||||
|
|
@ -118,7 +109,7 @@ func TestWitnessStatsAdd(t *testing.T) {
|
|||
"3": []byte("data9"),
|
||||
},
|
||||
owner: common.Hash{},
|
||||
expectedAccountLeaves: map[int]int64{1: 1, 3: 4}, // "123"(3) + "124"(3) + "234"(3) + "235"(3) + "3"(1)
|
||||
expectedAccountLeaves: map[int64]int64{1: 1, 3: 4}, // "123"(3) + "124"(3) + "234"(3) + "235"(3) + "3"(1)
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -127,59 +118,32 @@ func TestWitnessStatsAdd(t *testing.T) {
|
|||
stats := NewWitnessStats()
|
||||
stats.Add(tt.nodes, tt.owner)
|
||||
|
||||
if got, want := stats.accountTrie.LeafDepths(), expectedLeaves(tt.expectedAccountLeaves); got != want {
|
||||
t.Errorf("account trie leaves = %v, want %v", got, want)
|
||||
var expectedAccountTrieLeaves [16]int64
|
||||
for depth, count := range tt.expectedAccountLeaves {
|
||||
expectedAccountTrieLeaves[depth] = count
|
||||
}
|
||||
if got, want := stats.storageTrie.LeafDepths(), expectedLeaves(tt.expectedStorageLeaves); got != want {
|
||||
t.Errorf("storage trie leaves = %v, want %v", got, want)
|
||||
var expectedStorageTrieLeaves [16]int64
|
||||
for depth, count := range tt.expectedStorageLeaves {
|
||||
expectedStorageTrieLeaves[depth] = count
|
||||
}
|
||||
|
||||
// Check account trie depth
|
||||
if stats.accountTrieLeaves != expectedAccountTrieLeaves {
|
||||
t.Errorf("Account trie total depth = %v, want %v", stats.accountTrieLeaves, expectedAccountTrieLeaves)
|
||||
}
|
||||
|
||||
// Check storage trie depth
|
||||
if stats.storageTrieLeaves != expectedStorageTrieLeaves {
|
||||
t.Errorf("Storage trie total depth = %v, want %v", stats.storageTrieLeaves, expectedStorageTrieLeaves)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWitnessStatsStorageTrieAggregation(t *testing.T) {
|
||||
stats := NewWitnessStats()
|
||||
ownerA := common.HexToHash("0xa")
|
||||
ownerB := common.HexToHash("0xb")
|
||||
|
||||
stats.Add(map[string][]byte{
|
||||
"a": []byte("data1"),
|
||||
"ab": []byte("data2"),
|
||||
"abc": []byte("data3"),
|
||||
}, ownerA)
|
||||
stats.Add(map[string][]byte{
|
||||
"xy": []byte("data4"),
|
||||
}, ownerA)
|
||||
stats.Add(map[string][]byte{
|
||||
"1": []byte("data5"),
|
||||
"12": []byte("data6"),
|
||||
"123": []byte("data7"),
|
||||
"124": []byte("data8"),
|
||||
}, ownerB)
|
||||
|
||||
if got, want := stats.storageTrie.LeafDepths(), expectedLeaves(map[int]int64{2: 1, 3: 3}); got != want {
|
||||
t.Errorf("storage leaves = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := stats.accountTrie.LeafDepths(), expectedLeaves(nil); got != want {
|
||||
t.Errorf("account leaves = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWitnessStatsPanicsOnDeepLeaf(t *testing.T) {
|
||||
stats := NewWitnessStats()
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Fatal("expected panic for depth >= 16")
|
||||
}
|
||||
}()
|
||||
stats.Add(map[string][]byte{strings.Repeat("a", 16): []byte("data")}, common.Hash{})
|
||||
}
|
||||
|
||||
func TestWitnessStatsMinMax(t *testing.T) {
|
||||
stats := NewWitnessStats()
|
||||
|
||||
// Add some account trie nodes with varying depths.
|
||||
// Add some account trie nodes with varying depths
|
||||
stats.Add(map[string][]byte{
|
||||
"a": []byte("data1"),
|
||||
"ab": []byte("data2"),
|
||||
|
|
@ -188,21 +152,21 @@ func TestWitnessStatsMinMax(t *testing.T) {
|
|||
"abcde": []byte("data5"),
|
||||
}, common.Hash{})
|
||||
|
||||
// Only "abcde" is a leaf (depth 5).
|
||||
for i, v := range stats.accountTrie.LeafDepths() {
|
||||
// Only "abcde" is a leaf (depth 5)
|
||||
for i, v := range stats.accountTrieLeaves {
|
||||
if v != 0 && i != 5 {
|
||||
t.Errorf("leaf found at invalid depth %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
// Add more leaves with different depths.
|
||||
// Add more leaves with different depths
|
||||
stats.Add(map[string][]byte{
|
||||
"x": []byte("data6"),
|
||||
"yz": []byte("data7"),
|
||||
}, common.Hash{})
|
||||
|
||||
// Now we have leaves at depths 1, 2, and 5.
|
||||
for i, v := range stats.accountTrie.LeafDepths() {
|
||||
// Now we have leaves at depths 1, 2, and 5
|
||||
for i, v := range stats.accountTrieLeaves {
|
||||
if v != 0 && (i != 5 && i != 2 && i != 1) {
|
||||
t.Errorf("leaf found at invalid depth %d", i)
|
||||
}
|
||||
|
|
@ -212,7 +176,7 @@ func TestWitnessStatsMinMax(t *testing.T) {
|
|||
func TestWitnessStatsAverage(t *testing.T) {
|
||||
stats := NewWitnessStats()
|
||||
|
||||
// Add nodes that will create leaves at depths 2, 3, and 4.
|
||||
// Add nodes that will create leaves at depths 2, 3, and 4
|
||||
stats.Add(map[string][]byte{
|
||||
"aa": []byte("data1"),
|
||||
"bb": []byte("data2"),
|
||||
|
|
@ -220,22 +184,22 @@ func TestWitnessStatsAverage(t *testing.T) {
|
|||
"dddd": []byte("data4"),
|
||||
}, common.Hash{})
|
||||
|
||||
// All are leaves: 2 + 2 + 3 + 4 = 11 total, 4 samples.
|
||||
// All are leaves: 2 + 2 + 3 + 4 = 11 total, 4 samples
|
||||
expectedAvg := int64(11) / int64(4)
|
||||
var actualAvg, totalSamples int64
|
||||
for i, c := range stats.accountTrie.LeafDepths() {
|
||||
for i, c := range stats.accountTrieLeaves {
|
||||
actualAvg += c * int64(i)
|
||||
totalSamples += c
|
||||
}
|
||||
actualAvg = actualAvg / totalSamples
|
||||
|
||||
if actualAvg != expectedAvg {
|
||||
t.Errorf("account trie average depth = %d, want %d", actualAvg, expectedAvg)
|
||||
t.Errorf("Account trie average depth = %d, want %d", actualAvg, expectedAvg)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWitnessStatsAdd(b *testing.B) {
|
||||
// Create a realistic trie node structure.
|
||||
// Create a realistic trie node structure
|
||||
nodes := make(map[string][]byte)
|
||||
for i := 0; i < 100; i++ {
|
||||
base := string(rune('a' + i%26))
|
||||
|
|
|
|||
|
|
@ -1476,12 +1476,17 @@ func (p *BlobPool) AvailableBlobs(vhashes []common.Hash) int {
|
|||
// Add inserts a set of blob transactions into the pool if they pass validation (both
|
||||
// consensus validity and pool restrictions).
|
||||
func (p *BlobPool) Add(txs []*types.Transaction, sync bool) []error {
|
||||
errs := make([]error, len(txs))
|
||||
var (
|
||||
errs = make([]error, len(txs))
|
||||
adds = make([]*types.Transaction, 0, len(txs))
|
||||
)
|
||||
for i, tx := range txs {
|
||||
if errs[i] = p.ValidateTxBasics(tx); errs[i] != nil {
|
||||
continue
|
||||
}
|
||||
errs[i] = p.add(tx)
|
||||
if errs[i] = p.add(tx); errs[i] == nil {
|
||||
adds = append(adds, tx.WithoutBlobTxSidecar())
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ import (
|
|||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// CodeChange contains the runtime bytecode deployed at an address and the
|
||||
// transaction index where the deployment took place.
|
||||
type CodeChange struct {
|
||||
TxIndex uint16
|
||||
Code []byte `json:"code,omitempty"`
|
||||
}
|
||||
|
||||
// ConstructionAccountAccess contains post-block account state for mutations as well as
|
||||
// all storage keys that were read during execution. It is used when building block
|
||||
// access list during execution.
|
||||
|
|
@ -48,9 +55,9 @@ type ConstructionAccountAccess struct {
|
|||
// by tx index.
|
||||
NonceChanges map[uint16]uint64 `json:"nonceChanges,omitempty"`
|
||||
|
||||
// CodeChange contains the post-state contract code of an account keyed
|
||||
// by tx index.
|
||||
CodeChange map[uint16][]byte `json:"codeChange,omitempty"`
|
||||
// CodeChange is only set for contract accounts which were deployed in
|
||||
// the block.
|
||||
CodeChange *CodeChange `json:"codeChange,omitempty"`
|
||||
}
|
||||
|
||||
// NewConstructionAccountAccess initializes the account access object.
|
||||
|
|
@ -60,7 +67,6 @@ func NewConstructionAccountAccess() *ConstructionAccountAccess {
|
|||
StorageReads: make(map[common.Hash]struct{}),
|
||||
BalanceChanges: make(map[uint16]*uint256.Int),
|
||||
NonceChanges: make(map[uint16]uint64),
|
||||
CodeChange: make(map[uint16][]byte),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,8 +120,10 @@ func (b *ConstructionBlockAccessList) CodeChange(address common.Address, txIndex
|
|||
if _, ok := b.Accounts[address]; !ok {
|
||||
b.Accounts[address] = NewConstructionAccountAccess()
|
||||
}
|
||||
// TODO(rjl493456442) is it essential to deep-copy the code?
|
||||
b.Accounts[address].CodeChange[txIndex] = bytes.Clone(code)
|
||||
b.Accounts[address].CodeChange = &CodeChange{
|
||||
TxIndex: txIndex,
|
||||
Code: bytes.Clone(code),
|
||||
}
|
||||
}
|
||||
|
||||
// NonceChange records tx post-state nonce of any contract-like accounts whose
|
||||
|
|
@ -162,11 +170,12 @@ func (b *ConstructionBlockAccessList) Copy() *ConstructionBlockAccessList {
|
|||
aaCopy.BalanceChanges = balances
|
||||
aaCopy.NonceChanges = maps.Clone(aa.NonceChanges)
|
||||
|
||||
codes := make(map[uint16][]byte, len(aa.CodeChange))
|
||||
for index, code := range aa.CodeChange {
|
||||
codes[index] = bytes.Clone(code)
|
||||
if aa.CodeChange != nil {
|
||||
aaCopy.CodeChange = &CodeChange{
|
||||
TxIndex: aa.CodeChange.TxIndex,
|
||||
Code: bytes.Clone(aa.CodeChange.Code),
|
||||
}
|
||||
}
|
||||
aaCopy.CodeChange = codes
|
||||
res.Accounts[addr] = &aaCopy
|
||||
}
|
||||
return &res
|
||||
|
|
|
|||
|
|
@ -119,13 +119,6 @@ func (e *encodingSlotWrites) validate() error {
|
|||
return errors.New("storage write tx indices not in order")
|
||||
}
|
||||
|
||||
// encodingCodeChange contains the runtime bytecode deployed at an address
|
||||
// and the transaction index where the deployment took place.
|
||||
type encodingCodeChange struct {
|
||||
TxIndex uint16 `ssz-size:"2"`
|
||||
Code []byte `ssz-max:"300000"` // TODO(rjl493456442) shall we put the limit here? The limit will be increased gradually
|
||||
}
|
||||
|
||||
// AccountAccess is the encoding format of ConstructionAccountAccess.
|
||||
type AccountAccess struct {
|
||||
Address [20]byte `ssz-size:"20"` // 20-byte Ethereum address
|
||||
|
|
@ -133,7 +126,7 @@ type AccountAccess struct {
|
|||
StorageReads [][32]byte `ssz-max:"300000"` // Read-only storage keys
|
||||
BalanceChanges []encodingBalanceChange `ssz-max:"300000"` // Balance changes ([tx_index -> post_balance])
|
||||
NonceChanges []encodingAccountNonce `ssz-max:"300000"` // Nonce changes ([tx_index -> new_nonce])
|
||||
CodeChanges []encodingCodeChange `ssz-max:"300000"` // Code changes ([tx_index -> new_code])
|
||||
Code []CodeChange `ssz-max:"1"` // Code changes ([tx_index -> new_code])
|
||||
}
|
||||
|
||||
// validate converts the account accesses out of encoding format.
|
||||
|
|
@ -173,16 +166,9 @@ func (e *AccountAccess) validate() error {
|
|||
return errors.New("nonce changes not in ascending order by tx index")
|
||||
}
|
||||
|
||||
// Check the code changes are sorted in order
|
||||
if !slices.IsSortedFunc(e.CodeChanges, func(a, b encodingCodeChange) int {
|
||||
return cmp.Compare[uint16](a.TxIndex, b.TxIndex)
|
||||
}) {
|
||||
return errors.New("code changes not in ascending order by tx index")
|
||||
}
|
||||
for _, change := range e.CodeChanges {
|
||||
// TODO(rjl493456442): This check should be fork-aware, since the limit may
|
||||
// differ across forks.
|
||||
if len(change.Code) > params.MaxCodeSize {
|
||||
// Convert code change
|
||||
if len(e.Code) == 1 {
|
||||
if len(e.Code[0].Code) > params.MaxCodeSize {
|
||||
return errors.New("code change contained oversized code")
|
||||
}
|
||||
}
|
||||
|
|
@ -196,8 +182,6 @@ func (e *AccountAccess) Copy() AccountAccess {
|
|||
StorageReads: slices.Clone(e.StorageReads),
|
||||
BalanceChanges: slices.Clone(e.BalanceChanges),
|
||||
NonceChanges: slices.Clone(e.NonceChanges),
|
||||
StorageWrites: make([]encodingSlotWrites, 0, len(e.StorageWrites)),
|
||||
CodeChanges: make([]encodingCodeChange, 0, len(e.CodeChanges)),
|
||||
}
|
||||
for _, storageWrite := range e.StorageWrites {
|
||||
res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{
|
||||
|
|
@ -205,11 +189,13 @@ func (e *AccountAccess) Copy() AccountAccess {
|
|||
Accesses: slices.Clone(storageWrite.Accesses),
|
||||
})
|
||||
}
|
||||
for _, codeChange := range e.CodeChanges {
|
||||
res.CodeChanges = append(res.CodeChanges, encodingCodeChange{
|
||||
TxIndex: codeChange.TxIndex,
|
||||
Code: bytes.Clone(codeChange.Code),
|
||||
})
|
||||
if len(e.Code) == 1 {
|
||||
res.Code = []CodeChange{
|
||||
{
|
||||
e.Code[0].TxIndex,
|
||||
bytes.Clone(e.Code[0].Code),
|
||||
},
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
@ -226,11 +212,11 @@ var _ rlp.Encoder = &ConstructionBlockAccessList{}
|
|||
func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAccess {
|
||||
res := AccountAccess{
|
||||
Address: addr,
|
||||
StorageWrites: make([]encodingSlotWrites, 0, len(a.StorageWrites)),
|
||||
StorageReads: make([][32]byte, 0, len(a.StorageReads)),
|
||||
BalanceChanges: make([]encodingBalanceChange, 0, len(a.BalanceChanges)),
|
||||
NonceChanges: make([]encodingAccountNonce, 0, len(a.NonceChanges)),
|
||||
CodeChanges: make([]encodingCodeChange, 0, len(a.CodeChange)),
|
||||
StorageWrites: make([]encodingSlotWrites, 0),
|
||||
StorageReads: make([][32]byte, 0),
|
||||
BalanceChanges: make([]encodingBalanceChange, 0),
|
||||
NonceChanges: make([]encodingAccountNonce, 0),
|
||||
Code: nil,
|
||||
}
|
||||
|
||||
// Convert write slots
|
||||
|
|
@ -282,13 +268,13 @@ func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAc
|
|||
}
|
||||
|
||||
// Convert code change
|
||||
codeIndices := slices.Collect(maps.Keys(a.CodeChange))
|
||||
slices.SortFunc(codeIndices, cmp.Compare[uint16])
|
||||
for _, idx := range codeIndices {
|
||||
res.CodeChanges = append(res.CodeChanges, encodingCodeChange{
|
||||
TxIndex: idx,
|
||||
Code: a.CodeChange[idx],
|
||||
})
|
||||
if a.CodeChange != nil {
|
||||
res.Code = []CodeChange{
|
||||
{
|
||||
a.CodeChange.TxIndex,
|
||||
bytes.Clone(a.CodeChange.Code),
|
||||
},
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
@ -341,9 +327,9 @@ func (e *BlockAccessList) PrettyPrint() string {
|
|||
printWithIndent(2, fmt.Sprintf("%d: %d", change.TxIdx, change.Nonce))
|
||||
}
|
||||
|
||||
printWithIndent(1, "code changes:")
|
||||
for _, change := range accountDiff.CodeChanges {
|
||||
printWithIndent(2, fmt.Sprintf("%d: %x", change.TxIndex, change.Code))
|
||||
if len(accountDiff.Code) > 0 {
|
||||
printWithIndent(1, "code:")
|
||||
printWithIndent(2, fmt.Sprintf("%d: %x", accountDiff.Code[0].TxIndex, accountDiff.Code[0].Code))
|
||||
}
|
||||
}
|
||||
return res.String()
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ func (obj *BlockAccessList) EncodeRLP(_w io.Writer) error {
|
|||
}
|
||||
w.ListEnd(_tmp15)
|
||||
_tmp18 := w.List()
|
||||
for _, _tmp19 := range _tmp2.CodeChanges {
|
||||
for _, _tmp19 := range _tmp2.Code {
|
||||
_tmp20 := w.List()
|
||||
w.WriteUint64(uint64(_tmp19.TxIndex))
|
||||
w.WriteBytes(_tmp19.Code)
|
||||
|
|
@ -228,13 +228,13 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error {
|
|||
return err
|
||||
}
|
||||
_tmp2.NonceChanges = _tmp17
|
||||
// CodeChanges:
|
||||
var _tmp21 []encodingCodeChange
|
||||
// Code:
|
||||
var _tmp21 []CodeChange
|
||||
if _, err := dec.List(); err != nil {
|
||||
return err
|
||||
}
|
||||
for dec.MoreDataInList() {
|
||||
var _tmp22 encodingCodeChange
|
||||
var _tmp22 CodeChange
|
||||
{
|
||||
if _, err := dec.List(); err != nil {
|
||||
return err
|
||||
|
|
@ -260,7 +260,7 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error {
|
|||
if err := dec.ListEnd(); err != nil {
|
||||
return err
|
||||
}
|
||||
_tmp2.CodeChanges = _tmp21
|
||||
_tmp2.Code = _tmp21
|
||||
if err := dec.ListEnd(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,8 +60,9 @@ func makeTestConstructionBAL() *ConstructionBlockAccessList {
|
|||
1: 2,
|
||||
2: 6,
|
||||
},
|
||||
CodeChange: map[uint16][]byte{
|
||||
0: common.Hex2Bytes("deadbeef"),
|
||||
CodeChange: &CodeChange{
|
||||
TxIndex: 0,
|
||||
Code: common.Hex2Bytes("deadbeef"),
|
||||
},
|
||||
},
|
||||
common.BytesToAddress([]byte{0xff, 0xff, 0xff}): {
|
||||
|
|
@ -84,9 +85,6 @@ func makeTestConstructionBAL() *ConstructionBlockAccessList {
|
|||
NonceChanges: map[uint16]uint64{
|
||||
1: 2,
|
||||
},
|
||||
CodeChange: map[uint16][]byte{
|
||||
0: common.Hex2Bytes("deadbeef"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -181,7 +179,7 @@ func makeTestAccountAccess(sort bool) AccountAccess {
|
|||
StorageReads: storageReads,
|
||||
BalanceChanges: balances,
|
||||
NonceChanges: nonces,
|
||||
CodeChanges: []encodingCodeChange{
|
||||
Code: []CodeChange{
|
||||
{
|
||||
TxIndex: 100,
|
||||
Code: testrand.Bytes(256),
|
||||
|
|
|
|||
|
|
@ -98,9 +98,6 @@ type Header struct {
|
|||
|
||||
// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
|
||||
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
||||
|
||||
// SlotNumber was added by EIP-7843 and is ignored in legacy headers.
|
||||
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`
|
||||
}
|
||||
|
||||
// field type overrides for gencodec
|
||||
|
|
@ -115,7 +112,6 @@ type headerMarshaling struct {
|
|||
Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
|
||||
BlobGasUsed *hexutil.Uint64
|
||||
ExcessBlobGas *hexutil.Uint64
|
||||
SlotNumber *hexutil.Uint64
|
||||
}
|
||||
|
||||
// Hash returns the block hash of the header, which is simply the keccak256 hash of its
|
||||
|
|
@ -320,10 +316,6 @@ func CopyHeader(h *Header) *Header {
|
|||
cpy.RequestsHash = new(common.Hash)
|
||||
*cpy.RequestsHash = *h.RequestsHash
|
||||
}
|
||||
if h.SlotNumber != nil {
|
||||
cpy.SlotNumber = new(uint64)
|
||||
*cpy.SlotNumber = *h.SlotNumber
|
||||
}
|
||||
return &cpy
|
||||
}
|
||||
|
||||
|
|
@ -424,15 +416,6 @@ func (b *Block) BlobGasUsed() *uint64 {
|
|||
return blobGasUsed
|
||||
}
|
||||
|
||||
func (b *Block) SlotNumber() *uint64 {
|
||||
var slotNum *uint64
|
||||
if b.header.SlotNumber != nil {
|
||||
slotNum = new(uint64)
|
||||
*slotNum = *b.header.SlotNumber
|
||||
}
|
||||
return slotNum
|
||||
}
|
||||
|
||||
// Size returns the true RLP encoded storage size of the block, either by encoding
|
||||
// and returning it, or returning a previously cached value.
|
||||
func (b *Block) Size() uint64 {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
|
||||
Hash common.Hash `json:"hash"`
|
||||
}
|
||||
var enc Header
|
||||
|
|
@ -62,7 +61,6 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
||||
enc.ParentBeaconRoot = h.ParentBeaconRoot
|
||||
enc.RequestsHash = h.RequestsHash
|
||||
enc.SlotNumber = (*hexutil.Uint64)(h.SlotNumber)
|
||||
enc.Hash = h.Hash()
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
|
@ -91,7 +89,6 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
|||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
|
||||
}
|
||||
var dec Header
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -172,8 +169,5 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
|||
if dec.RequestsHash != nil {
|
||||
h.RequestsHash = dec.RequestsHash
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
h.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,8 +43,7 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
|||
_tmp4 := obj.ExcessBlobGas != nil
|
||||
_tmp5 := obj.ParentBeaconRoot != nil
|
||||
_tmp6 := obj.RequestsHash != nil
|
||||
_tmp7 := obj.SlotNumber != nil
|
||||
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
|
||||
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||
if obj.BaseFee == nil {
|
||||
w.Write(rlp.EmptyString)
|
||||
} else {
|
||||
|
|
@ -54,48 +53,41 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
|||
w.WriteBigInt(obj.BaseFee)
|
||||
}
|
||||
}
|
||||
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
|
||||
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||
if obj.WithdrawalsHash == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteBytes(obj.WithdrawalsHash[:])
|
||||
}
|
||||
}
|
||||
if _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
|
||||
if _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||
if obj.BlobGasUsed == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteUint64((*obj.BlobGasUsed))
|
||||
}
|
||||
}
|
||||
if _tmp4 || _tmp5 || _tmp6 || _tmp7 {
|
||||
if _tmp4 || _tmp5 || _tmp6 {
|
||||
if obj.ExcessBlobGas == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteUint64((*obj.ExcessBlobGas))
|
||||
}
|
||||
}
|
||||
if _tmp5 || _tmp6 || _tmp7 {
|
||||
if _tmp5 || _tmp6 {
|
||||
if obj.ParentBeaconRoot == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteBytes(obj.ParentBeaconRoot[:])
|
||||
}
|
||||
}
|
||||
if _tmp6 || _tmp7 {
|
||||
if _tmp6 {
|
||||
if obj.RequestsHash == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteBytes(obj.RequestsHash[:])
|
||||
}
|
||||
}
|
||||
if _tmp7 {
|
||||
if obj.SlotNumber == nil {
|
||||
w.Write([]byte{0x80})
|
||||
} else {
|
||||
w.WriteUint64((*obj.SlotNumber))
|
||||
}
|
||||
}
|
||||
w.ListEnd(_tmp0)
|
||||
return w.Flush()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
|
|||
// - the returned bytes,
|
||||
// - the _remaining_ gas,
|
||||
// - any error that occurred
|
||||
func RunPrecompiledContract(stateDB StateDB, p PrecompiledContract, address common.Address, input []byte, suppliedGas uint64, logger *tracing.Hooks) (ret []byte, remainingGas uint64, err error) {
|
||||
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64, logger *tracing.Hooks) (ret []byte, remainingGas uint64, err error) {
|
||||
gasCost := p.RequiredGas(input)
|
||||
if suppliedGas < gasCost {
|
||||
return nil, 0, ErrOutOfGas
|
||||
|
|
@ -271,12 +271,6 @@ func RunPrecompiledContract(stateDB StateDB, p PrecompiledContract, address comm
|
|||
logger.OnGasChange(suppliedGas, suppliedGas-gasCost, tracing.GasChangeCallPrecompiledContract)
|
||||
}
|
||||
suppliedGas -= gasCost
|
||||
|
||||
// Touch the precompile for block-level accessList recording once Amsterdam
|
||||
// fork is activated.
|
||||
if stateDB != nil {
|
||||
stateDB.Exist(address)
|
||||
}
|
||||
output, err := p.Run(input)
|
||||
return output, suppliedGas, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ func FuzzPrecompiledContracts(f *testing.F) {
|
|||
return
|
||||
}
|
||||
inWant := string(input)
|
||||
RunPrecompiledContract(nil, p, a, input, gas, nil)
|
||||
RunPrecompiledContract(p, input, gas, nil)
|
||||
if inHave := string(input); inWant != inHave {
|
||||
t.Errorf("Precompiled %v modified input data", a)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
|
|||
in := common.Hex2Bytes(test.Input)
|
||||
gas := p.RequiredGas(in)
|
||||
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
|
||||
if res, _, err := RunPrecompiledContract(nil, p, common.HexToAddress(addr), in, gas, nil); err != nil {
|
||||
if res, _, err := RunPrecompiledContract(p, in, gas, nil); err != nil {
|
||||
t.Error(err)
|
||||
} else if common.Bytes2Hex(res) != test.Expected {
|
||||
t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
|
||||
|
|
@ -121,7 +121,7 @@ func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
|
|||
gas := test.Gas - 1
|
||||
|
||||
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
|
||||
_, _, err := RunPrecompiledContract(nil, p, common.HexToAddress(addr), in, gas, nil)
|
||||
_, _, err := RunPrecompiledContract(p, in, gas, nil)
|
||||
if err.Error() != "out of gas" {
|
||||
t.Errorf("Expected error [out of gas], got [%v]", err)
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing
|
|||
in := common.Hex2Bytes(test.Input)
|
||||
gas := p.RequiredGas(in)
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
_, _, err := RunPrecompiledContract(nil, p, common.HexToAddress(addr), in, gas, nil)
|
||||
_, _, err := RunPrecompiledContract(p, in, gas, nil)
|
||||
if err.Error() != test.ExpectedError {
|
||||
t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
|
||||
}
|
||||
|
|
@ -169,7 +169,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
|
|||
start := time.Now()
|
||||
for bench.Loop() {
|
||||
copy(data, in)
|
||||
res, _, err = RunPrecompiledContract(nil, p, common.HexToAddress(addr), data, reqGas, nil)
|
||||
res, _, err = RunPrecompiledContract(p, data, reqGas, nil)
|
||||
}
|
||||
elapsed := uint64(time.Since(start))
|
||||
if elapsed < 1 {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ var activators = map[int]func(*JumpTable){
|
|||
7702: enable7702,
|
||||
7939: enable7939,
|
||||
8024: enable8024,
|
||||
7843: enable7843,
|
||||
}
|
||||
|
||||
// EnableEIP enables the given EIP on the config.
|
||||
|
|
@ -580,19 +579,3 @@ func enable7702(jt *JumpTable) {
|
|||
jt[STATICCALL].dynamicGas = gasStaticCallEIP7702
|
||||
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP7702
|
||||
}
|
||||
|
||||
// opSlotNum enables the SLOTNUM opcode
|
||||
func opSlotNum(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
scope.Stack.push(uint256.NewInt(evm.Context.SlotNum))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// enable7843 enables the SLOTNUM opcode as specified in EIP-7843.
|
||||
func enable7843(jt *JumpTable) {
|
||||
jt[SLOTNUM] = &operation{
|
||||
execute: opSlotNum,
|
||||
constantGas: GasQuickStep,
|
||||
minStack: minStack(0, 1),
|
||||
maxStack: maxStack(0, 1),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ type BlockContext struct {
|
|||
BaseFee *big.Int // Provides information for BASEFEE (0 if vm runs with NoBaseFee flag and 0 gas price)
|
||||
BlobBaseFee *big.Int // Provides information for BLOBBASEFEE (0 if vm runs with NoBaseFee flag and 0 blob gas price)
|
||||
Random *common.Hash // Provides information for PREVRANDAO
|
||||
SlotNum uint64 // Provides information for SLOTNUM
|
||||
}
|
||||
|
||||
// TxContext provides the EVM with information about a transaction.
|
||||
|
|
@ -145,8 +144,6 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
|
|||
evm.precompiles = activePrecompiledContracts(evm.chainRules)
|
||||
|
||||
switch {
|
||||
case evm.chainRules.IsAmsterdam:
|
||||
evm.table = &amsterdamInstructionSet
|
||||
case evm.chainRules.IsOsaka:
|
||||
evm.table = &osakaInstructionSet
|
||||
case evm.chainRules.IsVerkle:
|
||||
|
|
@ -248,14 +245,13 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
}
|
||||
syscall := isSystemCall(caller)
|
||||
|
||||
// Fail if we're trying to transfer more than the available balance.
|
||||
if !syscall && !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) {
|
||||
// Fail if we're trying to transfer more than the available balance
|
||||
if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) {
|
||||
return nil, gas, ErrInsufficientBalance
|
||||
}
|
||||
snapshot := evm.StateDB.Snapshot()
|
||||
p, isPrecompile := evm.precompile(addr)
|
||||
|
||||
if !evm.StateDB.Exist(addr) {
|
||||
if !isPrecompile && evm.chainRules.IsEIP4762 && !isSystemCall(caller) {
|
||||
// Add proof of absence to witness
|
||||
|
|
@ -279,18 +275,10 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
}
|
||||
evm.StateDB.CreateAccount(addr)
|
||||
}
|
||||
// Perform the value transfer only in non-syscall mode.
|
||||
// Calling this is required even for zero-value transfers,
|
||||
// to ensure the state clearing mechanism is applied.
|
||||
if !syscall {
|
||||
evm.Context.Transfer(evm.StateDB, caller, addr, value)
|
||||
}
|
||||
evm.Context.Transfer(evm.StateDB, caller, addr, value)
|
||||
|
||||
if isPrecompile {
|
||||
var stateDB StateDB
|
||||
if evm.chainRules.IsAmsterdam {
|
||||
stateDB = evm.StateDB
|
||||
}
|
||||
ret, gas, err = RunPrecompiledContract(stateDB, p, addr, input, gas, evm.Config.Tracer)
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||
} else {
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
code := evm.resolveCode(addr)
|
||||
|
|
@ -314,6 +302,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
|
||||
gas = 0
|
||||
}
|
||||
// TODO: consider clearing up unused snapshots:
|
||||
|
|
@ -353,11 +342,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
|
|||
|
||||
// It is allowed to call precompiles, even via delegatecall
|
||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||
var stateDB StateDB
|
||||
if evm.chainRules.IsAmsterdam {
|
||||
stateDB = evm.StateDB
|
||||
}
|
||||
ret, gas, err = RunPrecompiledContract(stateDB, p, addr, input, gas, evm.Config.Tracer)
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||
} else {
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
|
|
@ -400,11 +385,7 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
|
|||
|
||||
// It is allowed to call precompiles, even via delegatecall
|
||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||
var stateDB StateDB
|
||||
if evm.chainRules.IsAmsterdam {
|
||||
stateDB = evm.StateDB
|
||||
}
|
||||
ret, gas, err = RunPrecompiledContract(stateDB, p, addr, input, gas, evm.Config.Tracer)
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||
} else {
|
||||
// Initialise a new contract and make initialise the delegate values
|
||||
//
|
||||
|
|
@ -456,11 +437,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
|
|||
evm.StateDB.AddBalance(addr, new(uint256.Int), tracing.BalanceChangeTouchAccount)
|
||||
|
||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||
var stateDB StateDB
|
||||
if evm.chainRules.IsAmsterdam {
|
||||
stateDB = evm.StateDB
|
||||
}
|
||||
ret, gas, err = RunPrecompiledContract(stateDB, p, addr, input, gas, evm.Config.Tracer)
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||
} else {
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ var (
|
|||
verkleInstructionSet = newVerkleInstructionSet()
|
||||
pragueInstructionSet = newPragueInstructionSet()
|
||||
osakaInstructionSet = newOsakaInstructionSet()
|
||||
amsterdamInstructionSet = newAmsterdamInstructionSet()
|
||||
)
|
||||
|
||||
// JumpTable contains the EVM opcodes supported at a given fork.
|
||||
|
|
@ -93,12 +92,6 @@ func newVerkleInstructionSet() JumpTable {
|
|||
return validate(instructionSet)
|
||||
}
|
||||
|
||||
func newAmsterdamInstructionSet() JumpTable {
|
||||
instructionSet := newOsakaInstructionSet()
|
||||
enable7843(&instructionSet) // EIP-7843 (SLOTNUM opcode)
|
||||
return validate(instructionSet)
|
||||
}
|
||||
|
||||
func newOsakaInstructionSet() JumpTable {
|
||||
instructionSet := newPragueInstructionSet()
|
||||
enable7939(&instructionSet) // EIP-7939 (CLZ opcode)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ const (
|
|||
BASEFEE OpCode = 0x48
|
||||
BLOBHASH OpCode = 0x49
|
||||
BLOBBASEFEE OpCode = 0x4a
|
||||
SLOTNUM OpCode = 0x4b
|
||||
)
|
||||
|
||||
// 0x50 range - 'storage' and execution.
|
||||
|
|
@ -321,7 +320,6 @@ var opCodeToString = [256]string{
|
|||
BASEFEE: "BASEFEE",
|
||||
BLOBHASH: "BLOBHASH",
|
||||
BLOBBASEFEE: "BLOBBASEFEE",
|
||||
SLOTNUM: "SLOTNUM",
|
||||
|
||||
// 0x50 range - 'storage' and execution.
|
||||
POP: "POP",
|
||||
|
|
@ -504,7 +502,6 @@ var stringToOp = map[string]OpCode{
|
|||
"BASEFEE": BASEFEE,
|
||||
"BLOBHASH": BLOBHASH,
|
||||
"BLOBBASEFEE": BLOBBASEFEE,
|
||||
"SLOTNUM": SLOTNUM,
|
||||
"DELEGATECALL": DELEGATECALL,
|
||||
"STATICCALL": STATICCALL,
|
||||
"CODESIZE": CODESIZE,
|
||||
|
|
|
|||
|
|
@ -47,10 +47,9 @@ import (
|
|||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
// Register adds the engine API and related APIs to the full node.
|
||||
// Register adds the engine API to the full node.
|
||||
func Register(stack *node.Node, backend *eth.Ethereum) error {
|
||||
stack.RegisterAPIs([]rpc.API{
|
||||
newTestingAPI(backend),
|
||||
{
|
||||
Namespace: "engine",
|
||||
Service: NewConsensusAPI(backend),
|
||||
|
|
@ -212,28 +211,6 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
|
|||
return api.forkchoiceUpdated(update, params, engine.PayloadV3, false)
|
||||
}
|
||||
|
||||
// ForkchoiceUpdatedV4 is equivalent to V3 with the addition of slot number
|
||||
// in the payload attributes. It supports only PayloadAttributesV4.
|
||||
func (api *ConsensusAPI) ForkchoiceUpdatedV4(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
|
||||
if params != nil {
|
||||
switch {
|
||||
case params.Withdrawals == nil:
|
||||
return engine.STATUS_INVALID, attributesErr("missing withdrawals")
|
||||
case params.BeaconRoot == nil:
|
||||
return engine.STATUS_INVALID, attributesErr("missing beacon root")
|
||||
case params.SlotNumber == nil:
|
||||
return engine.STATUS_INVALID, attributesErr("missing slot number")
|
||||
case !api.checkFork(params.Timestamp, forks.Amsterdam):
|
||||
return engine.STATUS_INVALID, unsupportedForkErr("fcuV4 must only be called for amsterdam payloads")
|
||||
}
|
||||
}
|
||||
// TODO(matt): the spec requires that fcu is applied when called on a valid
|
||||
// hash, even if params are wrong. To do this we need to split up
|
||||
// forkchoiceUpdate into a function that only updates the head and then a
|
||||
// function that kicks off block construction.
|
||||
return api.forkchoiceUpdated(update, params, engine.PayloadV4, false)
|
||||
}
|
||||
|
||||
func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, payloadWitness bool) (engine.ForkChoiceResponse, error) {
|
||||
api.forkchoiceLock.Lock()
|
||||
defer api.forkchoiceLock.Unlock()
|
||||
|
|
@ -367,7 +344,6 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
|||
Random: payloadAttributes.Random,
|
||||
Withdrawals: payloadAttributes.Withdrawals,
|
||||
BeaconRoot: payloadAttributes.BeaconRoot,
|
||||
SlotNum: payloadAttributes.SlotNumber,
|
||||
Version: payloadVersion,
|
||||
}
|
||||
id := args.Id()
|
||||
|
|
@ -481,18 +457,6 @@ func (api *ConsensusAPI) GetPayloadV5(payloadID engine.PayloadID) (*engine.Execu
|
|||
})
|
||||
}
|
||||
|
||||
// GetPayloadV6 returns a cached payload by id. This endpoint should only
|
||||
// be used after the Amsterdam fork.
|
||||
func (api *ConsensusAPI) GetPayloadV6(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
|
||||
return api.getPayload(
|
||||
payloadID,
|
||||
false,
|
||||
[]engine.PayloadVersion{engine.PayloadV4},
|
||||
[]forks.Fork{
|
||||
forks.Amsterdam,
|
||||
})
|
||||
}
|
||||
|
||||
// getPayload will retrieve the specified payload and verify it conforms to the
|
||||
// endpoint's allowed payload versions and forks.
|
||||
//
|
||||
|
|
@ -735,33 +699,6 @@ func (api *ConsensusAPI) NewPayloadV4(ctx context.Context, params engine.Executa
|
|||
return api.newPayload(ctx, params, versionedHashes, beaconRoot, requests, false)
|
||||
}
|
||||
|
||||
// NewPayloadV5 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
|
||||
func (api *ConsensusAPI) NewPayloadV5(ctx context.Context, params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) {
|
||||
switch {
|
||||
case params.Withdrawals == nil:
|
||||
return invalidStatus, paramsErr("nil withdrawals post-shanghai")
|
||||
case params.ExcessBlobGas == nil:
|
||||
return invalidStatus, paramsErr("nil excessBlobGas post-cancun")
|
||||
case params.BlobGasUsed == nil:
|
||||
return invalidStatus, paramsErr("nil blobGasUsed post-cancun")
|
||||
case versionedHashes == nil:
|
||||
return invalidStatus, paramsErr("nil versionedHashes post-cancun")
|
||||
case beaconRoot == nil:
|
||||
return invalidStatus, paramsErr("nil beaconRoot post-cancun")
|
||||
case executionRequests == nil:
|
||||
return invalidStatus, paramsErr("nil executionRequests post-prague")
|
||||
case params.SlotNumber == nil:
|
||||
return invalidStatus, paramsErr("nil slotnumber post-amsterdam")
|
||||
case !api.checkFork(params.Timestamp, forks.Amsterdam):
|
||||
return invalidStatus, unsupportedForkErr("newPayloadV5 must only be called for amsterdam payloads")
|
||||
}
|
||||
requests := convertRequests(executionRequests)
|
||||
if err := validateRequests(requests); err != nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err)
|
||||
}
|
||||
return api.newPayload(ctx, params, versionedHashes, beaconRoot, requests, false)
|
||||
}
|
||||
|
||||
func (api *ConsensusAPI) newPayload(ctx context.Context, params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte, witness bool) (result engine.PayloadStatusV1, err error) {
|
||||
// The locking here is, strictly, not required. Without these locks, this can happen:
|
||||
//
|
||||
|
|
@ -797,10 +734,6 @@ func (api *ConsensusAPI) newPayload(ctx context.Context, params engine.Executabl
|
|||
if params.ExcessBlobGas != nil {
|
||||
ebg = strconv.Itoa(int(*params.ExcessBlobGas))
|
||||
}
|
||||
slotNum := "nil"
|
||||
if params.SlotNumber != nil {
|
||||
slotNum = strconv.Itoa(int(*params.SlotNumber))
|
||||
}
|
||||
log.Warn("Invalid NewPayload params",
|
||||
"params.Number", params.Number,
|
||||
"params.ParentHash", params.ParentHash,
|
||||
|
|
@ -816,7 +749,6 @@ func (api *ConsensusAPI) newPayload(ctx context.Context, params engine.Executabl
|
|||
"params.BaseFeePerGas", params.BaseFeePerGas,
|
||||
"params.BlobGasUsed", bgu,
|
||||
"params.ExcessBlobGas", ebg,
|
||||
"params.SlotNumber", slotNum,
|
||||
"len(params.Transactions)", len(params.Transactions),
|
||||
"len(params.Withdrawals)", len(params.Withdrawals),
|
||||
"beaconRoot", beaconRoot,
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
// Copyright 2026 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package catalyst
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
// testingAPI implements the testing_ namespace.
|
||||
// It's an engine-API adjacent namespace for testing purposes.
|
||||
type testingAPI struct {
|
||||
eth *eth.Ethereum
|
||||
}
|
||||
|
||||
func newTestingAPI(backend *eth.Ethereum) rpc.API {
|
||||
return rpc.API{
|
||||
Namespace: "testing",
|
||||
Service: &testingAPI{backend},
|
||||
Version: "1.0",
|
||||
Authenticated: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (api *testingAPI) BuildBlockV1(parentHash common.Hash, payloadAttributes engine.PayloadAttributes, transactions *[]hexutil.Bytes, extraData *hexutil.Bytes) (*engine.ExecutionPayloadEnvelope, error) {
|
||||
if api.eth.BlockChain().CurrentBlock().Hash() != parentHash {
|
||||
return nil, errors.New("parentHash is not current head")
|
||||
}
|
||||
// If transactions is empty but not nil, build an empty block
|
||||
// If the transactions is nil, build a block with the current transactions from the txpool
|
||||
// If the transactions is not nil and not empty, build a block with the transactions
|
||||
buildEmpty := transactions != nil && len(*transactions) == 0
|
||||
var txs []*types.Transaction
|
||||
if transactions != nil {
|
||||
dec := make([][]byte, 0, len(*transactions))
|
||||
for _, tx := range *transactions {
|
||||
dec = append(dec, tx)
|
||||
}
|
||||
var err error
|
||||
txs, err = engine.DecodeTransactions(dec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
extra := make([]byte, 0)
|
||||
if extraData != nil {
|
||||
extra = *extraData
|
||||
}
|
||||
args := &miner.BuildPayloadArgs{
|
||||
Parent: parentHash,
|
||||
Timestamp: payloadAttributes.Timestamp,
|
||||
FeeRecipient: payloadAttributes.SuggestedFeeRecipient,
|
||||
Random: payloadAttributes.Random,
|
||||
Withdrawals: payloadAttributes.Withdrawals,
|
||||
BeaconRoot: payloadAttributes.BeaconRoot,
|
||||
}
|
||||
return api.eth.Miner().BuildTestingPayload(args, txs, buildEmpty, extra)
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
// Copyright 2026 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package catalyst
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func TestBuildBlockV1(t *testing.T) {
|
||||
genesis, blocks := generateMergeChain(5, true)
|
||||
n, ethservice := startEthService(t, genesis, blocks)
|
||||
defer n.Close()
|
||||
|
||||
parent := ethservice.BlockChain().CurrentBlock()
|
||||
attrs := engine.PayloadAttributes{
|
||||
Timestamp: parent.Time + 1,
|
||||
Random: crypto.Keccak256Hash([]byte("test")),
|
||||
SuggestedFeeRecipient: parent.Coinbase,
|
||||
Withdrawals: nil,
|
||||
BeaconRoot: nil,
|
||||
}
|
||||
|
||||
currentNonce, _ := ethservice.APIBackend.GetPoolNonce(context.Background(), testAddr)
|
||||
tx, _ := types.SignTx(types.NewTransaction(currentNonce, testAddr, big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
|
||||
|
||||
api := &testingAPI{eth: ethservice}
|
||||
|
||||
t.Run("buildOnCurrentHead", func(t *testing.T) {
|
||||
envelope, err := api.BuildBlockV1(parent.Hash(), attrs, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildBlockV1 failed: %v", err)
|
||||
}
|
||||
if envelope == nil || envelope.ExecutionPayload == nil {
|
||||
t.Fatal("expected non-nil envelope and payload")
|
||||
}
|
||||
payload := envelope.ExecutionPayload
|
||||
if payload.ParentHash != parent.Hash() {
|
||||
t.Errorf("parent hash mismatch: got %x want %x", payload.ParentHash, parent.Hash())
|
||||
}
|
||||
if payload.Number != parent.Number.Uint64()+1 {
|
||||
t.Errorf("block number mismatch: got %d want %d", payload.Number, parent.Number.Uint64()+1)
|
||||
}
|
||||
if payload.Timestamp != attrs.Timestamp {
|
||||
t.Errorf("timestamp mismatch: got %d want %d", payload.Timestamp, attrs.Timestamp)
|
||||
}
|
||||
if payload.FeeRecipient != attrs.SuggestedFeeRecipient {
|
||||
t.Errorf("fee recipient mismatch: got %x want %x", payload.FeeRecipient, attrs.SuggestedFeeRecipient)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("wrongParentHash", func(t *testing.T) {
|
||||
wrongParent := common.Hash{0x01}
|
||||
_, err := api.BuildBlockV1(wrongParent, attrs, nil, nil)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when parentHash is not current head")
|
||||
}
|
||||
if err.Error() != "parentHash is not current head" {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("buildEmptyBlock", func(t *testing.T) {
|
||||
emptyTxs := []hexutil.Bytes{}
|
||||
envelope, err := api.BuildBlockV1(parent.Hash(), attrs, &emptyTxs, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildBlockV1 with empty txs failed: %v", err)
|
||||
}
|
||||
if envelope == nil || envelope.ExecutionPayload == nil {
|
||||
t.Fatal("expected non-nil envelope and payload")
|
||||
}
|
||||
if len(envelope.ExecutionPayload.Transactions) != 0 {
|
||||
t.Errorf("expected empty block, got %d transactions", len(envelope.ExecutionPayload.Transactions))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("buildBlockWithTransactions", func(t *testing.T) {
|
||||
enc, _ := tx.MarshalBinary()
|
||||
txs := []hexutil.Bytes{enc}
|
||||
envelope, err := api.BuildBlockV1(parent.Hash(), attrs, &txs, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildBlockV1 with transaction failed: %v", err)
|
||||
}
|
||||
if len(envelope.ExecutionPayload.Transactions) != 1 {
|
||||
t.Errorf("expected 1 transaction, got %d", len(envelope.ExecutionPayload.Transactions))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("buildBlockWithTransactionsFromTxPool", func(t *testing.T) {
|
||||
ethservice.TxPool().Add([]*types.Transaction{tx}, true)
|
||||
envelope, err := api.BuildBlockV1(parent.Hash(), attrs, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildBlockV1 with transaction failed: %v", err)
|
||||
}
|
||||
if len(envelope.ExecutionPayload.Transactions) != 1 {
|
||||
t.Errorf("expected 1 transaction, got %d", len(envelope.ExecutionPayload.Transactions))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -376,6 +376,5 @@ func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
|
|||
Service: api,
|
||||
Version: "1.0",
|
||||
},
|
||||
newTestingAPI(sim.eth),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package downloader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
|
@ -260,24 +261,23 @@ func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *et
|
|||
// peer in the download tester. The returned function can be used to retrieve
|
||||
// batches of block receipts from the particularly requested peer.
|
||||
func (dlp *downloadTesterPeer) RequestReceipts(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) {
|
||||
blobs := eth.ServiceGetReceiptsQuery(dlp.chain, hashes)
|
||||
receipts := make([]types.Receipts, blobs.Len())
|
||||
blobs := eth.ServiceGetReceiptsQuery68(dlp.chain, hashes)
|
||||
|
||||
// compute hashes
|
||||
hashes = make([]common.Hash, blobs.Len())
|
||||
receipts := make([]types.Receipts, len(blobs))
|
||||
for i, blob := range blobs {
|
||||
rlp.DecodeBytes(blob, &receipts[i])
|
||||
}
|
||||
hasher := trie.NewStackTrie(nil)
|
||||
receiptLists, err := blobs.Items()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
hashes = make([]common.Hash, len(receipts))
|
||||
for i, receipt := range receipts {
|
||||
hashes[i] = types.DeriveSha(receipt, hasher)
|
||||
}
|
||||
for i, rl := range receiptLists {
|
||||
hashes[i] = types.DeriveSha(rl.Derivable(), hasher)
|
||||
req := ð.Request{
|
||||
Peer: dlp.id,
|
||||
}
|
||||
|
||||
// deliver the response right away
|
||||
resp := eth.ReceiptsRLPResponse(types.EncodeBlockReceiptLists(receipts))
|
||||
res := ð.Response{
|
||||
Req: ð.Request{Peer: dlp.id},
|
||||
Req: req,
|
||||
Res: &resp,
|
||||
Meta: hashes,
|
||||
Time: 1,
|
||||
|
|
@ -286,7 +286,7 @@ func (dlp *downloadTesterPeer) RequestReceipts(hashes []common.Hash, sink chan *
|
|||
go func() {
|
||||
sink <- res
|
||||
}()
|
||||
return res.Req, nil
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// ID retrieves the peer's unique identifier.
|
||||
|
|
@ -398,8 +398,8 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCanonicalSynchronisationFull(t *testing.T) { testCanonSync(t, eth.ETH69, FullSync) }
|
||||
func TestCanonicalSynchronisationSnap(t *testing.T) { testCanonSync(t, eth.ETH69, SnapSync) }
|
||||
func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) }
|
||||
func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) }
|
||||
|
||||
func testCanonSync(t *testing.T, protocol uint, mode SyncMode) {
|
||||
success := make(chan struct{})
|
||||
|
|
@ -426,8 +426,8 @@ func testCanonSync(t *testing.T, protocol uint, mode SyncMode) {
|
|||
|
||||
// Tests that if a large batch of blocks are being downloaded, it is throttled
|
||||
// until the cached blocks are retrieved.
|
||||
func TestThrottlingFull(t *testing.T) { testThrottling(t, eth.ETH69, FullSync) }
|
||||
func TestThrottlingSnap(t *testing.T) { testThrottling(t, eth.ETH69, SnapSync) }
|
||||
func TestThrottling68Full(t *testing.T) { testThrottling(t, eth.ETH68, FullSync) }
|
||||
func TestThrottling68Snap(t *testing.T) { testThrottling(t, eth.ETH68, SnapSync) }
|
||||
|
||||
func testThrottling(t *testing.T, protocol uint, mode SyncMode) {
|
||||
tester := newTester(t, mode)
|
||||
|
|
@ -504,8 +504,8 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) {
|
|||
}
|
||||
|
||||
// Tests that a canceled download wipes all previously accumulated state.
|
||||
func TestCancelFull(t *testing.T) { testCancel(t, eth.ETH69, FullSync) }
|
||||
func TestCancelSnap(t *testing.T) { testCancel(t, eth.ETH69, SnapSync) }
|
||||
func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) }
|
||||
func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) }
|
||||
|
||||
func testCancel(t *testing.T, protocol uint, mode SyncMode) {
|
||||
complete := make(chan struct{})
|
||||
|
|
@ -534,10 +534,49 @@ func testCancel(t *testing.T, protocol uint, mode SyncMode) {
|
|||
}
|
||||
}
|
||||
|
||||
// Tests that synchronisations behave well in multi-version protocol environments
|
||||
// and not wreak havoc on other nodes in the network.
|
||||
func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) }
|
||||
func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) }
|
||||
|
||||
func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
|
||||
complete := make(chan struct{})
|
||||
success := func() {
|
||||
close(complete)
|
||||
}
|
||||
tester := newTesterWithNotification(t, mode, success)
|
||||
defer tester.terminate()
|
||||
|
||||
// Create a small enough block chain to download
|
||||
chain := testChainBase.shorten(blockCacheMaxItems - 15)
|
||||
|
||||
// Create peers of every type
|
||||
tester.newPeer("peer 68", eth.ETH68, chain.blocks[1:])
|
||||
|
||||
if err := tester.downloader.BeaconSync(chain.blocks[len(chain.blocks)-1].Header(), nil); err != nil {
|
||||
t.Fatalf("failed to start beacon sync: %v", err)
|
||||
}
|
||||
select {
|
||||
case <-complete:
|
||||
break
|
||||
case <-time.NewTimer(time.Second * 3).C:
|
||||
t.Fatalf("Failed to sync chain in three seconds")
|
||||
}
|
||||
assertOwnChain(t, tester, len(chain.blocks))
|
||||
|
||||
// Check that no peers have been dropped off
|
||||
for _, version := range []int{68} {
|
||||
peer := fmt.Sprintf("peer %d", version)
|
||||
if _, ok := tester.peers[peer]; !ok {
|
||||
t.Errorf("%s dropped", peer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that if a block is empty (e.g. header only), no body request should be
|
||||
// made, and instead the header should be assembled into a whole block in itself.
|
||||
func TestEmptyShortCircuitFull(t *testing.T) { testEmptyShortCircuit(t, eth.ETH69, FullSync) }
|
||||
func TestEmptyShortCircuitSnap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH69, SnapSync) }
|
||||
func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) }
|
||||
func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) }
|
||||
|
||||
func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
|
||||
success := make(chan struct{})
|
||||
|
|
@ -605,8 +644,8 @@ func checkProgress(t *testing.T, d *Downloader, stage string, want ethereum.Sync
|
|||
|
||||
// Tests that peers below a pre-configured checkpoint block are prevented from
|
||||
// being fast-synced from, avoiding potential cheap eclipse attacks.
|
||||
func TestBeaconSyncFull(t *testing.T) { testBeaconSync(t, eth.ETH69, FullSync) }
|
||||
func TestBeaconSyncSnap(t *testing.T) { testBeaconSync(t, eth.ETH69, SnapSync) }
|
||||
func TestBeaconSync68Full(t *testing.T) { testBeaconSync(t, eth.ETH68, FullSync) }
|
||||
func TestBeaconSync68Snap(t *testing.T) { testBeaconSync(t, eth.ETH68, SnapSync) }
|
||||
|
||||
func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) {
|
||||
var cases = []struct {
|
||||
|
|
@ -651,8 +690,8 @@ func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) {
|
|||
|
||||
// Tests that synchronisation progress (origin block number, current block number
|
||||
// and highest block number) is tracked and updated correctly.
|
||||
func TestSyncProgressFull(t *testing.T) { testSyncProgress(t, eth.ETH69, FullSync) }
|
||||
func TestSyncProgressSnap(t *testing.T) { testSyncProgress(t, eth.ETH69, SnapSync) }
|
||||
func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) }
|
||||
func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) }
|
||||
|
||||
func testSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
|
||||
success := make(chan struct{})
|
||||
|
|
|
|||
|
|
@ -845,7 +845,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
|
|||
// Create a peer set to feed headers through
|
||||
peerset := newPeerSet()
|
||||
for _, peer := range tt.peers {
|
||||
peerset.Register(newPeerConnection(peer.id, eth.ETH69, peer, log.New("id", peer.id)))
|
||||
peerset.Register(newPeerConnection(peer.id, eth.ETH68, peer, log.New("id", peer.id)))
|
||||
}
|
||||
// Create a peer dropper to track malicious peers
|
||||
dropped := make(map[string]int)
|
||||
|
|
@ -912,7 +912,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
|
|||
// Apply the post-init events if there's any
|
||||
endpeers := tt.peers
|
||||
if tt.newPeer != nil {
|
||||
if err := peerset.Register(newPeerConnection(tt.newPeer.id, eth.ETH69, tt.newPeer, log.New("id", tt.newPeer.id))); err != nil {
|
||||
if err := peerset.Register(newPeerConnection(tt.newPeer.id, eth.ETH68, tt.newPeer, log.New("id", tt.newPeer.id))); err != nil {
|
||||
t.Errorf("test %d: failed to register new peer: %v", i, err)
|
||||
}
|
||||
time.Sleep(time.Millisecond * 50) // given time for peer registration
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ var (
|
|||
txAnnounceInMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/in", nil)
|
||||
txAnnounceKnownMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/known", nil)
|
||||
txAnnounceUnderpricedMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/underpriced", nil)
|
||||
txAnnounceOnchainMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/onchain", nil)
|
||||
txAnnounceDOSMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/dos", nil)
|
||||
|
||||
txBroadcastInMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/in", nil)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/lru"
|
||||
"github.com/ethereum/go-ethereum/common/mclock"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/txpool"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
|
@ -72,11 +71,6 @@ const (
|
|||
|
||||
// addTxsBatchSize it the max number of transactions to add in a single batch from a peer.
|
||||
addTxsBatchSize = 128
|
||||
|
||||
// txOnChainCacheLimit is number of on-chain transactions to keep in a cache to avoid
|
||||
// re-fetching them soon after they are mined.
|
||||
// Approx 1MB for 30 minutes of transactions at 18 tps
|
||||
txOnChainCacheLimit = 32768
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -158,9 +152,6 @@ type TxFetcher struct {
|
|||
txSeq uint64 // Unique transaction sequence number
|
||||
underpriced *lru.Cache[common.Hash, time.Time] // Transactions discarded as too cheap (don't re-fetch)
|
||||
|
||||
chain *core.BlockChain // Blockchain interface for on-chain checks
|
||||
txOnChainCache *lru.Cache[common.Hash, struct{}] // Cache to avoid fetching once the tx gets on chain
|
||||
|
||||
// Stage 1: Waiting lists for newly discovered transactions that might be
|
||||
// broadcast without needing explicit request/reply round trips.
|
||||
waitlist map[common.Hash]map[string]struct{} // Transactions waiting for an potential broadcast
|
||||
|
|
@ -193,40 +184,36 @@ type TxFetcher struct {
|
|||
|
||||
// NewTxFetcher creates a transaction fetcher to retrieve transaction
|
||||
// based on hash announcements.
|
||||
// Chain can be nil to disable on-chain checks.
|
||||
func NewTxFetcher(chain *core.BlockChain, validateMeta func(common.Hash, byte) error, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string)) *TxFetcher {
|
||||
return NewTxFetcherForTests(chain, validateMeta, addTxs, fetchTxs, dropPeer, mclock.System{}, time.Now, nil)
|
||||
func NewTxFetcher(validateMeta func(common.Hash, byte) error, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string)) *TxFetcher {
|
||||
return NewTxFetcherForTests(validateMeta, addTxs, fetchTxs, dropPeer, mclock.System{}, time.Now, nil)
|
||||
}
|
||||
|
||||
// NewTxFetcherForTests is a testing method to mock out the realtime clock with
|
||||
// a simulated version and the internal randomness with a deterministic one.
|
||||
// Chain can be nil to disable on-chain checks.
|
||||
func NewTxFetcherForTests(
|
||||
chain *core.BlockChain, validateMeta func(common.Hash, byte) error, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string),
|
||||
validateMeta func(common.Hash, byte) error, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string),
|
||||
clock mclock.Clock, realTime func() time.Time, rand *mrand.Rand) *TxFetcher {
|
||||
return &TxFetcher{
|
||||
notify: make(chan *txAnnounce),
|
||||
cleanup: make(chan *txDelivery),
|
||||
drop: make(chan *txDrop),
|
||||
quit: make(chan struct{}),
|
||||
waitlist: make(map[common.Hash]map[string]struct{}),
|
||||
waittime: make(map[common.Hash]mclock.AbsTime),
|
||||
waitslots: make(map[string]map[common.Hash]*txMetadataWithSeq),
|
||||
announces: make(map[string]map[common.Hash]*txMetadataWithSeq),
|
||||
announced: make(map[common.Hash]map[string]struct{}),
|
||||
fetching: make(map[common.Hash]string),
|
||||
requests: make(map[string]*txRequest),
|
||||
alternates: make(map[common.Hash]map[string]struct{}),
|
||||
underpriced: lru.NewCache[common.Hash, time.Time](maxTxUnderpricedSetSize),
|
||||
txOnChainCache: lru.NewCache[common.Hash, struct{}](txOnChainCacheLimit),
|
||||
chain: chain,
|
||||
validateMeta: validateMeta,
|
||||
addTxs: addTxs,
|
||||
fetchTxs: fetchTxs,
|
||||
dropPeer: dropPeer,
|
||||
clock: clock,
|
||||
realTime: realTime,
|
||||
rand: rand,
|
||||
notify: make(chan *txAnnounce),
|
||||
cleanup: make(chan *txDelivery),
|
||||
drop: make(chan *txDrop),
|
||||
quit: make(chan struct{}),
|
||||
waitlist: make(map[common.Hash]map[string]struct{}),
|
||||
waittime: make(map[common.Hash]mclock.AbsTime),
|
||||
waitslots: make(map[string]map[common.Hash]*txMetadataWithSeq),
|
||||
announces: make(map[string]map[common.Hash]*txMetadataWithSeq),
|
||||
announced: make(map[common.Hash]map[string]struct{}),
|
||||
fetching: make(map[common.Hash]string),
|
||||
requests: make(map[string]*txRequest),
|
||||
alternates: make(map[common.Hash]map[string]struct{}),
|
||||
underpriced: lru.NewCache[common.Hash, time.Time](maxTxUnderpricedSetSize),
|
||||
validateMeta: validateMeta,
|
||||
addTxs: addTxs,
|
||||
fetchTxs: fetchTxs,
|
||||
dropPeer: dropPeer,
|
||||
clock: clock,
|
||||
realTime: realTime,
|
||||
rand: rand,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +233,6 @@ func (f *TxFetcher) Notify(peer string, types []byte, sizes []uint32, hashes []c
|
|||
unknownMetas = make([]txMetadata, 0, len(hashes))
|
||||
|
||||
duplicate int64
|
||||
onchain int64
|
||||
underpriced int64
|
||||
)
|
||||
for i, hash := range hashes {
|
||||
|
|
@ -259,12 +245,6 @@ func (f *TxFetcher) Notify(peer string, types []byte, sizes []uint32, hashes []c
|
|||
continue
|
||||
}
|
||||
|
||||
// check on chain as well (no need to check limbo separately, as chain checks limbo too)
|
||||
if _, exist := f.txOnChainCache.Get(hash); exist {
|
||||
onchain++
|
||||
continue
|
||||
}
|
||||
|
||||
if f.isKnownUnderpriced(hash) {
|
||||
underpriced++
|
||||
continue
|
||||
|
|
@ -279,7 +259,6 @@ func (f *TxFetcher) Notify(peer string, types []byte, sizes []uint32, hashes []c
|
|||
}
|
||||
txAnnounceKnownMeter.Mark(duplicate)
|
||||
txAnnounceUnderpricedMeter.Mark(underpriced)
|
||||
txAnnounceOnchainMeter.Mark(onchain)
|
||||
|
||||
// If anything's left to announce, push it into the internal loop
|
||||
if len(unknownHashes) == 0 {
|
||||
|
|
@ -433,18 +412,7 @@ func (f *TxFetcher) loop() {
|
|||
|
||||
waitTrigger = make(chan struct{}, 1)
|
||||
timeoutTrigger = make(chan struct{}, 1)
|
||||
|
||||
oldHead *types.Header
|
||||
)
|
||||
|
||||
// Subscribe to chain events to know when transactions are added to chain
|
||||
var headEventCh chan core.ChainEvent
|
||||
if f.chain != nil {
|
||||
headEventCh = make(chan core.ChainEvent, 10)
|
||||
sub := f.chain.SubscribeChainEvent(headEventCh)
|
||||
defer sub.Unsubscribe()
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case ann := <-f.notify:
|
||||
|
|
@ -869,21 +837,6 @@ func (f *TxFetcher) loop() {
|
|||
f.rescheduleTimeout(timeoutTimer, timeoutTrigger)
|
||||
}
|
||||
|
||||
case ev := <-headEventCh:
|
||||
// New head(s) added
|
||||
newHead := ev.Header
|
||||
if oldHead != nil && newHead.ParentHash != oldHead.Hash() {
|
||||
// Reorg or setHead detected, clear the cache. We could be smarter here and
|
||||
// only remove/add the diff, but this is simpler and not being exact here
|
||||
// only results in a few more fetches.
|
||||
f.txOnChainCache.Purge()
|
||||
}
|
||||
oldHead = newHead
|
||||
// Add all transactions from the new block to the on-chain cache
|
||||
for _, tx := range ev.Transactions {
|
||||
f.txOnChainCache.Add(tx.Hash(), struct{}{})
|
||||
}
|
||||
|
||||
case <-f.quit:
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ type txFetcherTest struct {
|
|||
// and deterministic randomness.
|
||||
func newTestTxFetcher() *TxFetcher {
|
||||
return NewTxFetcher(
|
||||
nil,
|
||||
func(common.Hash, byte) error { return nil },
|
||||
func(txs []*types.Transaction) []error {
|
||||
return make([]error, len(txs))
|
||||
|
|
@ -2192,7 +2191,6 @@ func TestTransactionForgotten(t *testing.T) {
|
|||
}
|
||||
|
||||
fetcher := NewTxFetcherForTests(
|
||||
nil,
|
||||
func(common.Hash, byte) error { return nil },
|
||||
func(txs []*types.Transaction) []error {
|
||||
errs := make([]error, len(txs))
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
|
|||
addTxs := func(txs []*types.Transaction) []error {
|
||||
return h.txpool.Add(txs, false)
|
||||
}
|
||||
|
||||
validateMeta := func(tx common.Hash, kind byte) error {
|
||||
if h.txpool.Has(tx) {
|
||||
return txpool.ErrAlreadyKnown
|
||||
|
|
@ -188,7 +189,8 @@ func newHandler(config *handlerConfig) (*handler, error) {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
h.txFetcher = fetcher.NewTxFetcher(h.chain, validateMeta, addTxs, fetchTx, h.removePeer)
|
||||
|
||||
h.txFetcher = fetcher.NewTxFetcher(validateMeta, addTxs, fetchTx, h.removePeer)
|
||||
return h, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,9 @@ import (
|
|||
// testEthHandler is a mock event handler to listen for inbound network requests
|
||||
// on the `eth` protocol and convert them into a more easily testable form.
|
||||
type testEthHandler struct {
|
||||
txAnnounces event.Feed
|
||||
txBroadcasts event.Feed
|
||||
blockBroadcasts event.Feed
|
||||
txAnnounces event.Feed
|
||||
txBroadcasts event.Feed
|
||||
}
|
||||
|
||||
func (h *testEthHandler) Chain() *core.BlockChain { panic("no backing chain") }
|
||||
|
|
@ -50,6 +51,10 @@ func (h *testEthHandler) PeerInfo(enode.ID) interface{} { panic("not used
|
|||
|
||||
func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
|
||||
switch packet := packet.(type) {
|
||||
case *eth.NewBlockPacket:
|
||||
h.blockBroadcasts.Send(packet.Block)
|
||||
return nil
|
||||
|
||||
case *eth.NewPooledTransactionHashesPacket:
|
||||
h.txAnnounces.Send(packet.Hashes)
|
||||
return nil
|
||||
|
|
@ -77,7 +82,7 @@ func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
|
|||
|
||||
// Tests that peers are correctly accepted (or rejected) based on the advertised
|
||||
// fork IDs in the protocol handshake.
|
||||
func TestForkIDSplit69(t *testing.T) { testForkIDSplit(t, eth.ETH69) }
|
||||
func TestForkIDSplit68(t *testing.T) { testForkIDSplit(t, eth.ETH68) }
|
||||
|
||||
func testForkIDSplit(t *testing.T, protocol uint) {
|
||||
t.Parallel()
|
||||
|
|
@ -229,7 +234,7 @@ func testForkIDSplit(t *testing.T, protocol uint) {
|
|||
}
|
||||
|
||||
// Tests that received transactions are added to the local pool.
|
||||
func TestRecvTransactions69(t *testing.T) { testRecvTransactions(t, eth.ETH69) }
|
||||
func TestRecvTransactions68(t *testing.T) { testRecvTransactions(t, eth.ETH68) }
|
||||
|
||||
func testRecvTransactions(t *testing.T, protocol uint) {
|
||||
t.Parallel()
|
||||
|
|
@ -258,8 +263,7 @@ func testRecvTransactions(t *testing.T, protocol uint) {
|
|||
return eth.Handle((*ethHandler)(handler.handler), peer)
|
||||
})
|
||||
// Run the handshake locally to avoid spinning up a source handler
|
||||
head := handler.chain.CurrentBlock()
|
||||
if err := src.Handshake(1, handler.chain, eth.BlockRangeUpdatePacket{EarliestBlock: 0, LatestBlock: head.Number.Uint64(), LatestBlockHash: head.Hash()}); err != nil {
|
||||
if err := src.Handshake(1, handler.chain, eth.BlockRangeUpdatePacket{}); err != nil {
|
||||
t.Fatalf("failed to run protocol handshake")
|
||||
}
|
||||
// Send the transaction to the sink and verify that it's added to the tx pool
|
||||
|
|
@ -282,7 +286,7 @@ func testRecvTransactions(t *testing.T, protocol uint) {
|
|||
}
|
||||
|
||||
// This test checks that pending transactions are sent.
|
||||
func TestSendTransactions69(t *testing.T) { testSendTransactions(t, eth.ETH69) }
|
||||
func TestSendTransactions68(t *testing.T) { testSendTransactions(t, eth.ETH68) }
|
||||
|
||||
func testSendTransactions(t *testing.T, protocol uint) {
|
||||
t.Parallel()
|
||||
|
|
@ -314,8 +318,7 @@ func testSendTransactions(t *testing.T, protocol uint) {
|
|||
return eth.Handle((*ethHandler)(handler.handler), peer)
|
||||
})
|
||||
// Run the handshake locally to avoid spinning up a source handler
|
||||
head := handler.chain.CurrentBlock()
|
||||
if err := sink.Handshake(1, handler.chain, eth.BlockRangeUpdatePacket{EarliestBlock: 0, LatestBlock: head.Number.Uint64(), LatestBlockHash: head.Hash()}); err != nil {
|
||||
if err := sink.Handshake(1, handler.chain, eth.BlockRangeUpdatePacket{}); err != nil {
|
||||
t.Fatalf("failed to run protocol handshake")
|
||||
}
|
||||
// After the handshake completes, the source handler should stream the sink
|
||||
|
|
@ -335,16 +338,22 @@ func testSendTransactions(t *testing.T, protocol uint) {
|
|||
// Make sure we get all the transactions on the correct channels
|
||||
seen := make(map[common.Hash]struct{})
|
||||
for len(seen) < len(insert) {
|
||||
select {
|
||||
case hashes := <-anns:
|
||||
for _, hash := range hashes {
|
||||
if _, ok := seen[hash]; ok {
|
||||
t.Errorf("duplicate transaction announced: %x", hash)
|
||||
switch protocol {
|
||||
case 68:
|
||||
select {
|
||||
case hashes := <-anns:
|
||||
for _, hash := range hashes {
|
||||
if _, ok := seen[hash]; ok {
|
||||
t.Errorf("duplicate transaction announced: %x", hash)
|
||||
}
|
||||
seen[hash] = struct{}{}
|
||||
}
|
||||
seen[hash] = struct{}{}
|
||||
case <-bcasts:
|
||||
t.Errorf("initial tx broadcast received on post eth/66")
|
||||
}
|
||||
case <-bcasts:
|
||||
t.Errorf("initial tx broadcast received on post eth/66")
|
||||
|
||||
default:
|
||||
panic("unsupported protocol, please extend test")
|
||||
}
|
||||
}
|
||||
for _, tx := range insert {
|
||||
|
|
@ -356,7 +365,7 @@ func testSendTransactions(t *testing.T, protocol uint) {
|
|||
|
||||
// Tests that transactions get propagated to all attached peers, either via direct
|
||||
// broadcasts or via announcements/retrievals.
|
||||
func TestTransactionPropagation69(t *testing.T) { testTransactionPropagation(t, eth.ETH69) }
|
||||
func TestTransactionPropagation68(t *testing.T) { testTransactionPropagation(t, eth.ETH68) }
|
||||
|
||||
func testTransactionPropagation(t *testing.T, protocol uint) {
|
||||
t.Parallel()
|
||||
|
|
|
|||
|
|
@ -166,6 +166,21 @@ type Decoder interface {
|
|||
Time() time.Time
|
||||
}
|
||||
|
||||
var eth68 = map[uint64]msgHandler{
|
||||
NewBlockHashesMsg: handleNewBlockhashes,
|
||||
NewBlockMsg: handleNewBlock,
|
||||
TransactionsMsg: handleTransactions,
|
||||
NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes,
|
||||
GetBlockHeadersMsg: handleGetBlockHeaders,
|
||||
BlockHeadersMsg: handleBlockHeaders,
|
||||
GetBlockBodiesMsg: handleGetBlockBodies,
|
||||
BlockBodiesMsg: handleBlockBodies,
|
||||
GetReceiptsMsg: handleGetReceipts68,
|
||||
ReceiptsMsg: handleReceipts[*ReceiptList68],
|
||||
GetPooledTransactionsMsg: handleGetPooledTransactions,
|
||||
PooledTransactionsMsg: handlePooledTransactions,
|
||||
}
|
||||
|
||||
var eth69 = map[uint64]msgHandler{
|
||||
TransactionsMsg: handleTransactions,
|
||||
NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes,
|
||||
|
|
@ -173,8 +188,8 @@ var eth69 = map[uint64]msgHandler{
|
|||
BlockHeadersMsg: handleBlockHeaders,
|
||||
GetBlockBodiesMsg: handleGetBlockBodies,
|
||||
BlockBodiesMsg: handleBlockBodies,
|
||||
GetReceiptsMsg: handleGetReceipts,
|
||||
ReceiptsMsg: handleReceipts,
|
||||
GetReceiptsMsg: handleGetReceipts69,
|
||||
ReceiptsMsg: handleReceipts[*ReceiptList69],
|
||||
GetPooledTransactionsMsg: handleGetPooledTransactions,
|
||||
PooledTransactionsMsg: handlePooledTransactions,
|
||||
BlockRangeUpdateMsg: handleBlockRangeUpdate,
|
||||
|
|
@ -194,7 +209,9 @@ func handleMessage(backend Backend, peer *Peer) error {
|
|||
defer msg.Discard()
|
||||
|
||||
var handlers map[uint64]msgHandler
|
||||
if peer.version == ETH69 {
|
||||
if peer.version == ETH68 {
|
||||
handlers = eth68
|
||||
} else if peer.version == ETH69 {
|
||||
handlers = eth69
|
||||
} else {
|
||||
return fmt.Errorf("unknown eth protocol version: %v", peer.version)
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ func (b *testBackend) Handle(*Peer, Packet) error {
|
|||
}
|
||||
|
||||
// Tests that block headers can be retrieved from a remote chain based on user queries.
|
||||
func TestGetBlockHeaders69(t *testing.T) { testGetBlockHeaders(t, ETH69) }
|
||||
func TestGetBlockHeaders68(t *testing.T) { testGetBlockHeaders(t, ETH68) }
|
||||
|
||||
func testGetBlockHeaders(t *testing.T, protocol uint) {
|
||||
t.Parallel()
|
||||
|
|
@ -387,7 +387,7 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
|
|||
}
|
||||
|
||||
// Tests that block contents can be retrieved from a remote chain based on their hashes.
|
||||
func TestGetBlockBodies69(t *testing.T) { testGetBlockBodies(t, ETH69) }
|
||||
func TestGetBlockBodies68(t *testing.T) { testGetBlockBodies(t, ETH68) }
|
||||
|
||||
func testGetBlockBodies(t *testing.T, protocol uint) {
|
||||
t.Parallel()
|
||||
|
|
@ -536,7 +536,7 @@ func TestHashBody(t *testing.T) {
|
|||
}
|
||||
|
||||
// Tests that the transaction receipts can be retrieved based on hashes.
|
||||
func TestGetBlockReceipts69(t *testing.T) { testGetBlockReceipts(t, ETH69) }
|
||||
func TestGetBlockReceipts68(t *testing.T) { testGetBlockReceipts(t, ETH68) }
|
||||
|
||||
func testGetBlockReceipts(t *testing.T, protocol uint) {
|
||||
t.Parallel()
|
||||
|
|
@ -586,13 +586,13 @@ func testGetBlockReceipts(t *testing.T, protocol uint) {
|
|||
// Collect the hashes to request, and the response to expect
|
||||
var (
|
||||
hashes []common.Hash
|
||||
receipts rlp.RawList[*ReceiptList]
|
||||
receipts rlp.RawList[*ReceiptList68]
|
||||
)
|
||||
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
|
||||
block := backend.chain.GetBlockByNumber(i)
|
||||
hashes = append(hashes, block.Hash())
|
||||
br := backend.chain.GetReceiptsByHash(block.Hash())
|
||||
receipts.Append(NewReceiptList(br))
|
||||
trs := backend.chain.GetReceiptsByHash(block.Hash())
|
||||
receipts.Append(NewReceiptList68(trs))
|
||||
}
|
||||
|
||||
// Send the hash request and verify the response
|
||||
|
|
@ -600,7 +600,7 @@ func testGetBlockReceipts(t *testing.T, protocol uint) {
|
|||
RequestId: 123,
|
||||
GetReceiptsRequest: hashes,
|
||||
})
|
||||
if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket{
|
||||
if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket[*ReceiptList68]{
|
||||
RequestId: 123,
|
||||
List: receipts,
|
||||
}); err != nil {
|
||||
|
|
@ -656,7 +656,7 @@ func setup() (*testBackend, *testPeer) {
|
|||
}
|
||||
}
|
||||
backend := newTestBackendWithGenerator(maxBodiesServe+15, true, false, gen)
|
||||
peer, _ := newTestPeer("peer", ETH69, backend)
|
||||
peer, _ := newTestPeer("peer", ETH68, backend)
|
||||
// Discard all messages
|
||||
go func() {
|
||||
for {
|
||||
|
|
@ -701,7 +701,7 @@ func testGetPooledTransaction(t *testing.T, blobTx bool) {
|
|||
backend := newTestBackendWithGenerator(0, true, true, nil)
|
||||
defer backend.close()
|
||||
|
||||
peer, _ := newTestPeer("peer", ETH69, backend)
|
||||
peer, _ := newTestPeer("peer", ETH68, backend)
|
||||
defer peer.close()
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package eth
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
|
|
@ -246,27 +247,36 @@ func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesRequ
|
|||
return bodies
|
||||
}
|
||||
|
||||
func handleGetReceipts(backend Backend, msg Decoder, peer *Peer) error {
|
||||
func handleGetReceipts68(backend Backend, msg Decoder, peer *Peer) error {
|
||||
// Decode the block receipts retrieval message
|
||||
var query GetReceiptsPacket
|
||||
if err := msg.Decode(&query); err != nil {
|
||||
return err
|
||||
}
|
||||
response := ServiceGetReceiptsQuery(backend.Chain(), query.GetReceiptsRequest)
|
||||
response := ServiceGetReceiptsQuery68(backend.Chain(), query.GetReceiptsRequest)
|
||||
return peer.ReplyReceiptsRLP(query.RequestId, response)
|
||||
}
|
||||
|
||||
// ServiceGetReceiptsQuery assembles the response to a receipt query.
|
||||
// It does not send the bloom filters for the receipts. It is exposed
|
||||
// to allow external packages to test protocol behavior.
|
||||
func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsRequest) rlp.RawList[*ReceiptList] {
|
||||
func handleGetReceipts69(backend Backend, msg Decoder, peer *Peer) error {
|
||||
// Decode the block receipts retrieval message
|
||||
var query GetReceiptsPacket
|
||||
if err := msg.Decode(&query); err != nil {
|
||||
return err
|
||||
}
|
||||
response := serviceGetReceiptsQuery69(backend.Chain(), query.GetReceiptsRequest)
|
||||
return peer.ReplyReceiptsRLP(query.RequestId, response)
|
||||
}
|
||||
|
||||
// ServiceGetReceiptsQuery68 assembles the response to a receipt query. It is
|
||||
// exposed to allow external packages to test protocol behavior.
|
||||
func ServiceGetReceiptsQuery68(chain *core.BlockChain, query GetReceiptsRequest) []rlp.RawValue {
|
||||
// Gather state data until the fetch or network limits is reached
|
||||
var (
|
||||
bytes int
|
||||
receipts rlp.RawList[*ReceiptList]
|
||||
receipts []rlp.RawValue
|
||||
)
|
||||
for lookups, hash := range query {
|
||||
if bytes >= softResponseLimit || receipts.Len() >= maxReceiptsServe ||
|
||||
if bytes >= softResponseLimit || len(receipts) >= maxReceiptsServe ||
|
||||
lookups >= 2*maxReceiptsServe {
|
||||
break
|
||||
}
|
||||
|
|
@ -282,18 +292,63 @@ func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsRequest) r
|
|||
continue
|
||||
}
|
||||
var err error
|
||||
results, err = blockReceiptsToNetwork(results, body)
|
||||
results, err = blockReceiptsToNetwork68(results, body)
|
||||
if err != nil {
|
||||
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
receipts.AppendRaw(results)
|
||||
receipts = append(receipts, results)
|
||||
bytes += len(results)
|
||||
}
|
||||
return receipts
|
||||
}
|
||||
|
||||
// serviceGetReceiptsQuery69 assembles the response to a receipt query.
|
||||
// It does not send the bloom filters for the receipts
|
||||
func serviceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest) []rlp.RawValue {
|
||||
// Gather state data until the fetch or network limits is reached
|
||||
var (
|
||||
bytes int
|
||||
receipts []rlp.RawValue
|
||||
)
|
||||
for lookups, hash := range query {
|
||||
if bytes >= softResponseLimit || len(receipts) >= maxReceiptsServe ||
|
||||
lookups >= 2*maxReceiptsServe {
|
||||
break
|
||||
}
|
||||
// Retrieve the requested block's receipts
|
||||
results := chain.GetReceiptsRLP(hash)
|
||||
if results == nil {
|
||||
if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
body := chain.GetBodyRLP(hash)
|
||||
if body == nil {
|
||||
continue
|
||||
}
|
||||
var err error
|
||||
results, err = blockReceiptsToNetwork69(results, body)
|
||||
if err != nil {
|
||||
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
receipts = append(receipts, results)
|
||||
bytes += len(results)
|
||||
}
|
||||
return receipts
|
||||
}
|
||||
|
||||
func handleNewBlockhashes(backend Backend, msg Decoder, peer *Peer) error {
|
||||
return errors.New("block announcements disallowed") // We dropped support for non-merge networks
|
||||
}
|
||||
|
||||
func handleNewBlock(backend Backend, msg Decoder, peer *Peer) error {
|
||||
return errors.New("block broadcasts disallowed") // We dropped support for non-merge networks
|
||||
}
|
||||
|
||||
func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error {
|
||||
// A batch of headers arrived to one of our previous requests
|
||||
res := new(BlockHeadersPacket)
|
||||
|
|
@ -435,9 +490,9 @@ func writeTxForHash(tx []byte, buf *bytes.Buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
func handleReceipts(backend Backend, msg Decoder, peer *Peer) error {
|
||||
func handleReceipts[L ReceiptsList](backend Backend, msg Decoder, peer *Peer) error {
|
||||
// A batch of receipts arrived to one of our previous requests
|
||||
res := new(ReceiptsPacket)
|
||||
res := new(ReceiptsPacket[L])
|
||||
if err := msg.Decode(res); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -447,10 +502,16 @@ func handleReceipts(backend Backend, msg Decoder, peer *Peer) error {
|
|||
return fmt.Errorf("Receipts: %w", err)
|
||||
}
|
||||
|
||||
// Assign temporary hashing buffer to each list item, the same buffer is shared
|
||||
// between all receipt list instances.
|
||||
receiptLists, err := res.List.Items()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Receipts: %w", err)
|
||||
}
|
||||
buffers := new(receiptListBuffers)
|
||||
for i := range receiptLists {
|
||||
receiptLists[i].setBuffers(buffers)
|
||||
}
|
||||
|
||||
metadata := func() interface{} {
|
||||
hasher := trie.NewStackTrie(nil)
|
||||
|
|
@ -460,7 +521,6 @@ func handleReceipts(backend Backend, msg Decoder, peer *Peer) error {
|
|||
}
|
||||
return hashes
|
||||
}
|
||||
|
||||
var enc ReceiptsRLPResponse
|
||||
for i := range receiptLists {
|
||||
encReceipts, err := receiptLists[i].EncodeForStorage()
|
||||
|
|
|
|||
|
|
@ -36,6 +36,62 @@ const (
|
|||
// Handshake executes the eth protocol handshake, negotiating version number,
|
||||
// network IDs, difficulties, head and genesis blocks.
|
||||
func (p *Peer) Handshake(networkID uint64, chain forkid.Blockchain, rangeMsg BlockRangeUpdatePacket) error {
|
||||
switch p.version {
|
||||
case ETH69:
|
||||
return p.handshake69(networkID, chain, rangeMsg)
|
||||
case ETH68:
|
||||
return p.handshake68(networkID, chain)
|
||||
default:
|
||||
return errors.New("unsupported protocol version")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Peer) handshake68(networkID uint64, chain forkid.Blockchain) error {
|
||||
var (
|
||||
genesis = chain.Genesis()
|
||||
latest = chain.CurrentHeader()
|
||||
forkID = forkid.NewID(chain.Config(), genesis, latest.Number.Uint64(), latest.Time)
|
||||
forkFilter = forkid.NewFilter(chain)
|
||||
)
|
||||
errc := make(chan error, 2)
|
||||
go func() {
|
||||
pkt := &StatusPacket68{
|
||||
ProtocolVersion: uint32(p.version),
|
||||
NetworkID: networkID,
|
||||
Head: latest.Hash(),
|
||||
Genesis: genesis.Hash(),
|
||||
ForkID: forkID,
|
||||
}
|
||||
errc <- p2p.Send(p.rw, StatusMsg, pkt)
|
||||
}()
|
||||
var status StatusPacket68 // safe to read after two values have been received from errc
|
||||
go func() {
|
||||
errc <- p.readStatus68(networkID, &status, genesis.Hash(), forkFilter)
|
||||
}()
|
||||
|
||||
return waitForHandshake(errc, p)
|
||||
}
|
||||
|
||||
func (p *Peer) readStatus68(networkID uint64, status *StatusPacket68, genesis common.Hash, forkFilter forkid.Filter) error {
|
||||
if err := p.readStatusMsg(status); err != nil {
|
||||
return err
|
||||
}
|
||||
if status.NetworkID != networkID {
|
||||
return fmt.Errorf("%w: %d (!= %d)", errNetworkIDMismatch, status.NetworkID, networkID)
|
||||
}
|
||||
if uint(status.ProtocolVersion) != p.version {
|
||||
return fmt.Errorf("%w: %d (!= %d)", errProtocolVersionMismatch, status.ProtocolVersion, p.version)
|
||||
}
|
||||
if status.Genesis != genesis {
|
||||
return fmt.Errorf("%w: %x (!= %x)", errGenesisMismatch, status.Genesis, genesis)
|
||||
}
|
||||
if err := forkFilter(status.ForkID); err != nil {
|
||||
return fmt.Errorf("%w: %v", errForkIDRejected, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Peer) handshake69(networkID uint64, chain forkid.Blockchain, rangeMsg BlockRangeUpdatePacket) error {
|
||||
var (
|
||||
genesis = chain.Genesis()
|
||||
latest = chain.CurrentHeader()
|
||||
|
|
@ -45,7 +101,7 @@ func (p *Peer) Handshake(networkID uint64, chain forkid.Blockchain, rangeMsg Blo
|
|||
|
||||
errc := make(chan error, 2)
|
||||
go func() {
|
||||
pkt := &StatusPacket{
|
||||
pkt := &StatusPacket69{
|
||||
ProtocolVersion: uint32(p.version),
|
||||
NetworkID: networkID,
|
||||
Genesis: genesis.Hash(),
|
||||
|
|
@ -56,15 +112,15 @@ func (p *Peer) Handshake(networkID uint64, chain forkid.Blockchain, rangeMsg Blo
|
|||
}
|
||||
errc <- p2p.Send(p.rw, StatusMsg, pkt)
|
||||
}()
|
||||
var status StatusPacket // safe to read after two values have been received from errc
|
||||
var status StatusPacket69 // safe to read after two values have been received from errc
|
||||
go func() {
|
||||
errc <- p.readStatus(networkID, &status, genesis.Hash(), forkFilter)
|
||||
errc <- p.readStatus69(networkID, &status, genesis.Hash(), forkFilter)
|
||||
}()
|
||||
|
||||
return waitForHandshake(errc, p)
|
||||
}
|
||||
|
||||
func (p *Peer) readStatus(networkID uint64, status *StatusPacket, genesis common.Hash, forkFilter forkid.Filter) error {
|
||||
func (p *Peer) readStatus69(networkID uint64, status *StatusPacket69, genesis common.Hash, forkFilter forkid.Filter) error {
|
||||
if err := p.readStatusMsg(status); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -135,16 +191,16 @@ func markError(p *Peer, err error) {
|
|||
return
|
||||
}
|
||||
m := meters.get(p.Inbound())
|
||||
switch {
|
||||
case errors.Is(err, errNetworkIDMismatch):
|
||||
switch errors.Unwrap(err) {
|
||||
case errNetworkIDMismatch:
|
||||
m.networkIDMismatch.Mark(1)
|
||||
case errors.Is(err, errProtocolVersionMismatch):
|
||||
case errProtocolVersionMismatch:
|
||||
m.protocolVersionMismatch.Mark(1)
|
||||
case errors.Is(err, errGenesisMismatch):
|
||||
case errGenesisMismatch:
|
||||
m.genesisMismatch.Mark(1)
|
||||
case errors.Is(err, errForkIDRejected):
|
||||
case errForkIDRejected:
|
||||
m.forkidRejected.Mark(1)
|
||||
case errors.Is(err, p2p.DiscReadTimeout):
|
||||
case p2p.DiscReadTimeout:
|
||||
m.timeoutError.Mark(1)
|
||||
default:
|
||||
m.peerError.Mark(1)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package eth
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -27,7 +28,7 @@ import (
|
|||
)
|
||||
|
||||
// Tests that handshake failures are detected and reported correctly.
|
||||
func TestHandshake69(t *testing.T) { testHandshake(t, ETH69) }
|
||||
func TestHandshake68(t *testing.T) { testHandshake(t, ETH68) }
|
||||
|
||||
func testHandshake(t *testing.T, protocol uint) {
|
||||
t.Parallel()
|
||||
|
|
@ -51,25 +52,21 @@ func testHandshake(t *testing.T, protocol uint) {
|
|||
want: errNoStatusMsg,
|
||||
},
|
||||
{
|
||||
code: StatusMsg, data: StatusPacket{10, 1, genesis.Hash(), forkID, 0, head.Number.Uint64(), head.Hash()},
|
||||
code: StatusMsg, data: StatusPacket68{10, 1, new(big.Int), head.Hash(), genesis.Hash(), forkID},
|
||||
want: errProtocolVersionMismatch,
|
||||
},
|
||||
{
|
||||
code: StatusMsg, data: StatusPacket{uint32(protocol), 999, genesis.Hash(), forkID, 0, head.Number.Uint64(), head.Hash()},
|
||||
code: StatusMsg, data: StatusPacket68{uint32(protocol), 999, new(big.Int), head.Hash(), genesis.Hash(), forkID},
|
||||
want: errNetworkIDMismatch,
|
||||
},
|
||||
{
|
||||
code: StatusMsg, data: StatusPacket{uint32(protocol), 1, common.Hash{3}, forkID, 0, head.Number.Uint64(), head.Hash()},
|
||||
code: StatusMsg, data: StatusPacket68{uint32(protocol), 1, new(big.Int), head.Hash(), common.Hash{3}, forkID},
|
||||
want: errGenesisMismatch,
|
||||
},
|
||||
{
|
||||
code: StatusMsg, data: StatusPacket{uint32(protocol), 1, genesis.Hash(), forkid.ID{Hash: [4]byte{0x00, 0x01, 0x02, 0x03}}, 0, head.Number.Uint64(), head.Hash()},
|
||||
code: StatusMsg, data: StatusPacket68{uint32(protocol), 1, new(big.Int), head.Hash(), genesis.Hash(), forkid.ID{Hash: [4]byte{0x00, 0x01, 0x02, 0x03}}},
|
||||
want: errForkIDRejected,
|
||||
},
|
||||
{
|
||||
code: StatusMsg, data: StatusPacket{uint32(protocol), 1, genesis.Hash(), forkID, head.Number.Uint64() + 1, head.Number.Uint64(), head.Hash()},
|
||||
want: errInvalidBlockRange,
|
||||
},
|
||||
}
|
||||
for i, test := range tests {
|
||||
// Create the two peers to shake with each other
|
||||
|
|
|
|||
|
|
@ -215,10 +215,10 @@ func (p *Peer) ReplyBlockBodiesRLP(id uint64, bodies []rlp.RawValue) error {
|
|||
}
|
||||
|
||||
// ReplyReceiptsRLP is the response to GetReceipts.
|
||||
func (p *Peer) ReplyReceiptsRLP(id uint64, receipts rlp.RawList[*ReceiptList]) error {
|
||||
return p2p.Send(p.rw, ReceiptsMsg, &ReceiptsPacket{
|
||||
RequestId: id,
|
||||
List: receipts,
|
||||
func (p *Peer) ReplyReceiptsRLP(id uint64, receipts []rlp.RawValue) error {
|
||||
return p2p.Send(p.rw, ReceiptsMsg, &ReceiptsRLPPacket{
|
||||
RequestId: id,
|
||||
ReceiptsRLPResponse: receipts,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/forkid"
|
||||
|
|
@ -29,6 +30,7 @@ import (
|
|||
|
||||
// Constants to match up protocol versions and messages
|
||||
const (
|
||||
ETH68 = 68
|
||||
ETH69 = 69
|
||||
)
|
||||
|
||||
|
|
@ -38,11 +40,11 @@ const ProtocolName = "eth"
|
|||
|
||||
// ProtocolVersions are the supported versions of the `eth` protocol (first
|
||||
// is primary).
|
||||
var ProtocolVersions = []uint{ETH69}
|
||||
var ProtocolVersions = []uint{ETH69, ETH68}
|
||||
|
||||
// protocolLengths are the number of implemented message corresponding to
|
||||
// different protocol versions.
|
||||
var protocolLengths = map[uint]uint64{ETH69: 18}
|
||||
var protocolLengths = map[uint]uint64{ETH68: 17, ETH69: 18}
|
||||
|
||||
// maxMessageSize is the maximum cap on the size of a protocol message.
|
||||
const maxMessageSize = 10 * 1024 * 1024
|
||||
|
|
@ -86,7 +88,17 @@ type Packet interface {
|
|||
}
|
||||
|
||||
// StatusPacket is the network packet for the status message.
|
||||
type StatusPacket struct {
|
||||
type StatusPacket68 struct {
|
||||
ProtocolVersion uint32
|
||||
NetworkID uint64
|
||||
TD *big.Int
|
||||
Head common.Hash
|
||||
Genesis common.Hash
|
||||
ForkID forkid.ID
|
||||
}
|
||||
|
||||
// StatusPacket69 is the network packet for the status message.
|
||||
type StatusPacket69 struct {
|
||||
ProtocolVersion uint32
|
||||
NetworkID uint64
|
||||
Genesis common.Hash
|
||||
|
|
@ -97,6 +109,26 @@ type StatusPacket struct {
|
|||
LatestBlockHash common.Hash
|
||||
}
|
||||
|
||||
// NewBlockHashesPacket is the network packet for the block announcements.
|
||||
type NewBlockHashesPacket []struct {
|
||||
Hash common.Hash // Hash of one particular block being announced
|
||||
Number uint64 // Number of one particular block being announced
|
||||
}
|
||||
|
||||
// Unpack retrieves the block hashes and numbers from the announcement packet
|
||||
// and returns them in a split flat format that's more consistent with the
|
||||
// internal data structures.
|
||||
func (p *NewBlockHashesPacket) Unpack() ([]common.Hash, []uint64) {
|
||||
var (
|
||||
hashes = make([]common.Hash, len(*p))
|
||||
numbers = make([]uint64, len(*p))
|
||||
)
|
||||
for i, body := range *p {
|
||||
hashes[i], numbers[i] = body.Hash, body.Number
|
||||
}
|
||||
return hashes, numbers
|
||||
}
|
||||
|
||||
// TransactionsPacket is the network packet for broadcasting new transactions.
|
||||
type TransactionsPacket struct {
|
||||
rlp.RawList[*types.Transaction]
|
||||
|
|
@ -171,6 +203,12 @@ type BlockHeadersRLPPacket struct {
|
|||
BlockHeadersRLPResponse
|
||||
}
|
||||
|
||||
// NewBlockPacket is the network packet for the block propagation message.
|
||||
type NewBlockPacket struct {
|
||||
Block *types.Block
|
||||
TD *big.Int
|
||||
}
|
||||
|
||||
// GetBlockBodiesRequest represents a block body query.
|
||||
type GetBlockBodiesRequest []common.Hash
|
||||
|
||||
|
|
@ -220,16 +258,30 @@ type GetReceiptsPacket struct {
|
|||
// ReceiptsResponse is the network packet for block receipts distribution.
|
||||
type ReceiptsResponse []types.Receipts
|
||||
|
||||
// ReceiptsList is a type constraint for block receceipt list types.
|
||||
type ReceiptsList interface {
|
||||
*ReceiptList68 | *ReceiptList69
|
||||
setBuffers(*receiptListBuffers)
|
||||
EncodeForStorage() (rlp.RawValue, error)
|
||||
Derivable() types.DerivableList
|
||||
}
|
||||
|
||||
// ReceiptsPacket is the network packet for block receipts distribution with
|
||||
// request ID wrapping.
|
||||
type ReceiptsPacket struct {
|
||||
type ReceiptsPacket[L ReceiptsList] struct {
|
||||
RequestId uint64
|
||||
List rlp.RawList[*ReceiptList]
|
||||
List rlp.RawList[L]
|
||||
}
|
||||
|
||||
// ReceiptsRLPResponse is used for receipts, when we already have it encoded
|
||||
type ReceiptsRLPResponse []rlp.RawValue
|
||||
|
||||
// ReceiptsRLPPacket is ReceiptsRLPResponse with request ID wrapping.
|
||||
type ReceiptsRLPPacket struct {
|
||||
RequestId uint64
|
||||
ReceiptsRLPResponse
|
||||
}
|
||||
|
||||
// NewPooledTransactionHashesPacket represents a transaction announcement packet on eth/68 and newer.
|
||||
type NewPooledTransactionHashesPacket struct {
|
||||
Types []byte
|
||||
|
|
@ -273,8 +325,14 @@ type BlockRangeUpdatePacket struct {
|
|||
LatestBlockHash common.Hash
|
||||
}
|
||||
|
||||
func (*StatusPacket) Name() string { return "Status" }
|
||||
func (*StatusPacket) Kind() byte { return StatusMsg }
|
||||
func (*StatusPacket68) Name() string { return "Status" }
|
||||
func (*StatusPacket68) Kind() byte { return StatusMsg }
|
||||
|
||||
func (*StatusPacket69) Name() string { return "Status" }
|
||||
func (*StatusPacket69) Kind() byte { return StatusMsg }
|
||||
|
||||
func (*NewBlockHashesPacket) Name() string { return "NewBlockHashes" }
|
||||
func (*NewBlockHashesPacket) Kind() byte { return NewBlockHashesMsg }
|
||||
|
||||
func (*TransactionsPacket) Name() string { return "Transactions" }
|
||||
func (*TransactionsPacket) Kind() byte { return TransactionsMsg }
|
||||
|
|
@ -291,6 +349,9 @@ func (*GetBlockBodiesRequest) Kind() byte { return GetBlockBodiesMsg }
|
|||
func (*BlockBodiesResponse) Name() string { return "BlockBodies" }
|
||||
func (*BlockBodiesResponse) Kind() byte { return BlockBodiesMsg }
|
||||
|
||||
func (*NewBlockPacket) Name() string { return "NewBlock" }
|
||||
func (*NewBlockPacket) Kind() byte { return NewBlockMsg }
|
||||
|
||||
func (*NewPooledTransactionHashesPacket) Name() string { return "NewPooledTransactionHashes" }
|
||||
func (*NewPooledTransactionHashesPacket) Kind() byte { return NewPooledTransactionHashesMsg }
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ func TestEmptyMessages(t *testing.T) {
|
|||
BlockBodiesRLPPacket{1111, BlockBodiesRLPResponse([]rlp.RawValue{})},
|
||||
// Receipts
|
||||
GetReceiptsPacket{1111, GetReceiptsRequest([]common.Hash{})},
|
||||
ReceiptsPacket{1111, encodeRL([]*ReceiptList{})},
|
||||
ReceiptsPacket[*ReceiptList68]{1111, encodeRL([]*ReceiptList68{})},
|
||||
ReceiptsPacket[*ReceiptList69]{1111, encodeRL([]*ReceiptList69{})},
|
||||
// Transactions
|
||||
GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest([]common.Hash{})},
|
||||
PooledTransactionsPacket{1111, encodeRL([]*types.Transaction{})},
|
||||
|
|
@ -121,6 +122,7 @@ func TestMessages(t *testing.T) {
|
|||
txRlps []rlp.RawValue
|
||||
hashes []common.Hash
|
||||
receipts []*types.Receipt
|
||||
receiptsRlp rlp.RawValue
|
||||
|
||||
err error
|
||||
)
|
||||
|
|
@ -189,6 +191,11 @@ func TestMessages(t *testing.T) {
|
|||
}
|
||||
miniDeriveFields(receipts[0], 0)
|
||||
miniDeriveFields(receipts[1], 1)
|
||||
rlpData, err := rlp.EncodeToBytes(receipts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
receiptsRlp = rlpData
|
||||
}
|
||||
|
||||
for i, tc := range []struct {
|
||||
|
|
@ -224,7 +231,16 @@ func TestMessages(t *testing.T) {
|
|||
common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"),
|
||||
},
|
||||
{
|
||||
ReceiptsPacket{1111, encodeRL([]*ReceiptList{NewReceiptList(receipts)})},
|
||||
ReceiptsPacket[*ReceiptList68]{1111, encodeRL([]*ReceiptList68{NewReceiptList68(receipts)})},
|
||||
common.FromHex("f902e6820457f902e0f902ddf901688082014db9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000004000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ffb9016f01f9016b018201bcb9010000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000000000000000040000000000000000000000000004000000000000000000000000000000000000000000000000000000008000400000000000000000000000000000000000000000000000000000000000000000000000000000040f862f860940000000000000000000000000000000000000022f842a00000000000000000000000000000000000000000000000000000000000005668a0000000000000000000000000000000000000000000000000000000000000977386020f0f0f0608"),
|
||||
},
|
||||
{
|
||||
// Identical to the eth/68 encoding above.
|
||||
ReceiptsRLPPacket{1111, ReceiptsRLPResponse([]rlp.RawValue{receiptsRlp})},
|
||||
common.FromHex("f902e6820457f902e0f902ddf901688082014db9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000004000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ffb9016f01f9016b018201bcb9010000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000000000000000040000000000000000000000000004000000000000000000000000000000000000000000000000000000008000400000000000000000000000000000000000000000000000000000000000000000000000000000040f862f860940000000000000000000000000000000000000022f842a00000000000000000000000000000000000000000000000000000000000005668a0000000000000000000000000000000000000000000000000000000000000977386020f0f0f0608"),
|
||||
},
|
||||
{
|
||||
ReceiptsPacket[*ReceiptList69]{1111, encodeRL([]*ReceiptList69{NewReceiptList69(receipts)})},
|
||||
common.FromHex("f8da820457f8d5f8d3f866808082014df85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff86901018201bcf862f860940000000000000000000000000000000000000022f842a00000000000000000000000000000000000000000000000000000000000005668a0000000000000000000000000000000000000000000000000000000000000977386020f0f0f0608"),
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ import (
|
|||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
// This is just a sanity limit for the size of a single receipt.
|
||||
const maxReceiptSize = 16 * 1024 * 1024
|
||||
|
||||
// Receipt is the representation of receipts for networking purposes.
|
||||
type Receipt struct {
|
||||
TxType byte
|
||||
|
|
@ -46,18 +49,154 @@ func newReceipt(tr *types.Receipt) Receipt {
|
|||
return r
|
||||
}
|
||||
|
||||
// decode68 parses a receipt in the eth/68 network encoding.
|
||||
func (r *Receipt) decode68(b []byte) error {
|
||||
k, content, _, err := rlp.Split(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*r = Receipt{}
|
||||
if k == rlp.List {
|
||||
// Legacy receipt.
|
||||
return r.decodeInnerList(b, false, true)
|
||||
}
|
||||
// Typed receipt.
|
||||
if len(content) < 2 || len(content) > maxReceiptSize {
|
||||
return fmt.Errorf("invalid receipt size %d", len(content))
|
||||
}
|
||||
r.TxType = content[0]
|
||||
return r.decodeInnerList(content[1:], false, true)
|
||||
}
|
||||
|
||||
// decode69 parses a receipt in the eth/69 network encoding.
|
||||
func (r *Receipt) decode69(b []byte) error {
|
||||
*r = Receipt{}
|
||||
return r.decodeInnerList(b, true, false)
|
||||
}
|
||||
|
||||
// decodeDatabase parses a receipt in the basic database encoding.
|
||||
func (r *Receipt) decodeDatabase(txType byte, b []byte) error {
|
||||
*r = Receipt{TxType: txType}
|
||||
return r.decodeInnerList(b, false, false)
|
||||
}
|
||||
|
||||
func (r *Receipt) decodeInnerList(input []byte, readTxType, readBloom bool) error {
|
||||
input, _, err := rlp.SplitList(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("inner list: %v", err)
|
||||
}
|
||||
|
||||
// txType
|
||||
if readTxType {
|
||||
var txType uint64
|
||||
txType, input, err = rlp.SplitUint64(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid txType: %w", err)
|
||||
}
|
||||
if txType > 0x7f {
|
||||
return fmt.Errorf("invalid txType: too large")
|
||||
}
|
||||
r.TxType = byte(txType)
|
||||
}
|
||||
|
||||
// status
|
||||
r.PostStateOrStatus, input, err = rlp.SplitString(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid postStateOrStatus: %w", err)
|
||||
}
|
||||
if len(r.PostStateOrStatus) > 1 && len(r.PostStateOrStatus) != 32 {
|
||||
return fmt.Errorf("invalid postStateOrStatus length %d", len(r.PostStateOrStatus))
|
||||
}
|
||||
|
||||
// gas
|
||||
r.GasUsed, input, err = rlp.SplitUint64(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid gasUsed: %w", err)
|
||||
}
|
||||
|
||||
// bloom
|
||||
if readBloom {
|
||||
var bloomBytes []byte
|
||||
bloomBytes, input, err = rlp.SplitString(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid bloom: %v", err)
|
||||
}
|
||||
if len(bloomBytes) != types.BloomByteLength {
|
||||
return fmt.Errorf("invalid bloom length %d", len(bloomBytes))
|
||||
}
|
||||
}
|
||||
|
||||
// logs
|
||||
_, rest, err := rlp.SplitList(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid logs: %w", err)
|
||||
}
|
||||
if len(rest) != 0 {
|
||||
return fmt.Errorf("junk at end of receipt")
|
||||
}
|
||||
r.Logs = input
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodeForStorage produces the the storage encoding, i.e. the result matches
|
||||
// the RLP encoding of types.ReceiptForStorage.
|
||||
func (r *Receipt) encodeForStorage(w *rlp.EncoderBuffer) {
|
||||
list := w.List()
|
||||
w.WriteBytes(r.PostStateOrStatus)
|
||||
w.WriteUint64(r.GasUsed)
|
||||
w.Write(r.Logs)
|
||||
w.ListEnd(list)
|
||||
}
|
||||
|
||||
// encodeForNetwork68 produces the eth/68 network protocol encoding of a receipt.
|
||||
// Note this recomputes the bloom filter of the receipt.
|
||||
func (r *Receipt) encodeForNetwork68(buf *receiptListBuffers, w *rlp.EncoderBuffer) {
|
||||
writeInner := func(w *rlp.EncoderBuffer) {
|
||||
list := w.List()
|
||||
w.WriteBytes(r.PostStateOrStatus)
|
||||
w.WriteUint64(r.GasUsed)
|
||||
bloom := r.bloom(&buf.bloom)
|
||||
w.WriteBytes(bloom[:])
|
||||
w.Write(r.Logs)
|
||||
w.ListEnd(list)
|
||||
}
|
||||
|
||||
if r.TxType == 0 {
|
||||
writeInner(w)
|
||||
} else {
|
||||
buf.tmp.Reset()
|
||||
buf.tmp.WriteByte(r.TxType)
|
||||
buf.enc.Reset(&buf.tmp)
|
||||
writeInner(&buf.enc)
|
||||
buf.enc.Flush()
|
||||
w.WriteBytes(buf.tmp.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
// encodeForNetwork69 produces the eth/69 network protocol encoding of a receipt.
|
||||
func (r *Receipt) encodeForNetwork69(w *rlp.EncoderBuffer) {
|
||||
list := w.List()
|
||||
w.WriteUint64(uint64(r.TxType))
|
||||
w.WriteBytes(r.PostStateOrStatus)
|
||||
w.WriteUint64(r.GasUsed)
|
||||
w.Write(r.Logs)
|
||||
w.ListEnd(list)
|
||||
}
|
||||
|
||||
// encodeForHash encodes a receipt for the block receiptsRoot derivation.
|
||||
func (r *Receipt) encodeForHash(bloomBuf *[6]byte, out *bytes.Buffer) {
|
||||
func (r *Receipt) encodeForHash(buf *receiptListBuffers, out *bytes.Buffer) {
|
||||
// For typed receipts, add the tx type.
|
||||
if r.TxType != 0 {
|
||||
out.WriteByte(r.TxType)
|
||||
}
|
||||
// Encode list = [postStateOrStatus, gasUsed, bloom, logs].
|
||||
w := rlp.NewEncoderBuffer(out)
|
||||
w := &buf.enc
|
||||
w.Reset(out)
|
||||
l := w.List()
|
||||
w.WriteBytes(r.PostStateOrStatus)
|
||||
w.WriteUint64(r.GasUsed)
|
||||
bloom := r.bloom(bloomBuf)
|
||||
bloom := r.bloom(&buf.bloom)
|
||||
w.WriteBytes(bloom[:])
|
||||
w.Write(r.Logs)
|
||||
w.ListEnd(l)
|
||||
|
|
@ -90,98 +229,31 @@ func (r *Receipt) bloom(buffer *[6]byte) types.Bloom {
|
|||
return b
|
||||
}
|
||||
|
||||
// decode assigns the fields of r by decoding the network format.
|
||||
func (r *Receipt) decode(input []byte) error {
|
||||
input, _, err := rlp.SplitList(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("inner list: %v", err)
|
||||
}
|
||||
|
||||
// txType
|
||||
var txType uint64
|
||||
txType, input, err = rlp.SplitUint64(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid txType: %w", err)
|
||||
}
|
||||
if txType > 0x7f {
|
||||
return fmt.Errorf("invalid txType: too large")
|
||||
}
|
||||
r.TxType = byte(txType)
|
||||
|
||||
// status
|
||||
r.PostStateOrStatus, input, err = rlp.SplitString(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid postStateOrStatus: %w", err)
|
||||
}
|
||||
if len(r.PostStateOrStatus) > 1 && len(r.PostStateOrStatus) != 32 {
|
||||
return fmt.Errorf("invalid postStateOrStatus length %d", len(r.PostStateOrStatus))
|
||||
}
|
||||
|
||||
// gas
|
||||
r.GasUsed, input, err = rlp.SplitUint64(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid gasUsed: %w", err)
|
||||
}
|
||||
|
||||
// logs
|
||||
_, rest, err := rlp.SplitList(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid logs: %w", err)
|
||||
}
|
||||
if len(rest) != 0 {
|
||||
return fmt.Errorf("junk at end of receipt")
|
||||
}
|
||||
r.Logs = input
|
||||
return nil
|
||||
type receiptListBuffers struct {
|
||||
enc rlp.EncoderBuffer
|
||||
bloom [6]byte
|
||||
tmp bytes.Buffer
|
||||
}
|
||||
|
||||
// ReceiptList is the block receipt list as downloaded by eth/69.
|
||||
type ReceiptList struct {
|
||||
items rlp.RawList[Receipt]
|
||||
}
|
||||
|
||||
// NewReceiptList creates a receipt list.
|
||||
// This is slow, and exists for testing purposes.
|
||||
func NewReceiptList(trs []*types.Receipt) *ReceiptList {
|
||||
rl := new(ReceiptList)
|
||||
for _, tr := range trs {
|
||||
r := newReceipt(tr)
|
||||
encoded, _ := rlp.EncodeToBytes(&r)
|
||||
rl.items.AppendRaw(encoded)
|
||||
func initBuffers(buf **receiptListBuffers) {
|
||||
if *buf == nil {
|
||||
*buf = new(receiptListBuffers)
|
||||
}
|
||||
return rl
|
||||
}
|
||||
|
||||
// DecodeRLP decodes a list receipts from the network format.
|
||||
func (rl *ReceiptList) DecodeRLP(s *rlp.Stream) error {
|
||||
return rl.items.DecodeRLP(s)
|
||||
}
|
||||
|
||||
// EncodeRLP encodes the list into the network format of eth/69.
|
||||
func (rl *ReceiptList) EncodeRLP(w io.Writer) error {
|
||||
return rl.items.EncodeRLP(w)
|
||||
}
|
||||
|
||||
// EncodeForStorage encodes a list of receipts for the database.
|
||||
// It only strips the first element (TxType) from each receipt's
|
||||
// raw RLP without the actual decoding and re-encoding.
|
||||
func (rl *ReceiptList) EncodeForStorage() (rlp.RawValue, error) {
|
||||
// encodeForStorage encodes a list of receipts for the database.
|
||||
func (buf *receiptListBuffers) encodeForStorage(rs rlp.RawList[Receipt], decode func([]byte, *Receipt) error) (rlp.RawValue, error) {
|
||||
var out bytes.Buffer
|
||||
w := rlp.NewEncoderBuffer(&out)
|
||||
w := &buf.enc
|
||||
w.Reset(&out)
|
||||
outer := w.List()
|
||||
it := rl.items.ContentIterator()
|
||||
it := rs.ContentIterator()
|
||||
for it.Next() {
|
||||
content, _, err := rlp.SplitList(it.Value())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad receipt: %v", err)
|
||||
var receipt Receipt
|
||||
if err := decode(it.Value(), &receipt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _, rest, err := rlp.Split(content)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad receipt: %v", err)
|
||||
}
|
||||
inner := w.List()
|
||||
w.Write(rest)
|
||||
w.ListEnd(inner)
|
||||
receipt.encodeForStorage(w)
|
||||
}
|
||||
if it.Err() != nil {
|
||||
return nil, fmt.Errorf("bad list: %v", it.Err())
|
||||
|
|
@ -191,20 +263,149 @@ func (rl *ReceiptList) EncodeForStorage() (rlp.RawValue, error) {
|
|||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
// Derivable returns a DerivableList, which can be used to decode
|
||||
func (rl *ReceiptList) Derivable() types.DerivableList {
|
||||
var bloomBuf [6]byte
|
||||
// ReceiptList68 is a block receipt list as downloaded by eth/68.
|
||||
// This also implements types.DerivableList for validation purposes.
|
||||
type ReceiptList68 struct {
|
||||
buf *receiptListBuffers
|
||||
items rlp.RawList[Receipt]
|
||||
}
|
||||
|
||||
// NewReceiptList68 creates a receipt list.
|
||||
// This is slow, and exists for testing purposes.
|
||||
func NewReceiptList68(trs []*types.Receipt) *ReceiptList68 {
|
||||
rl := new(ReceiptList68)
|
||||
initBuffers(&rl.buf)
|
||||
enc := rlp.NewEncoderBuffer(nil)
|
||||
for _, tr := range trs {
|
||||
r := newReceipt(tr)
|
||||
r.encodeForNetwork68(rl.buf, &enc)
|
||||
rl.items.AppendRaw(enc.ToBytes())
|
||||
enc.Reset(nil)
|
||||
}
|
||||
return rl
|
||||
}
|
||||
|
||||
func blockReceiptsToNetwork68(blockReceipts, blockBody rlp.RawValue) ([]byte, error) {
|
||||
txTypesIter, err := txTypesInBody(blockBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid block body: %v", err)
|
||||
}
|
||||
nextTxType, stopTxTypes := iter.Pull(txTypesIter)
|
||||
defer stopTxTypes()
|
||||
|
||||
var (
|
||||
out bytes.Buffer
|
||||
buf receiptListBuffers
|
||||
)
|
||||
blockReceiptIter, _ := rlp.NewListIterator(blockReceipts)
|
||||
w := rlp.NewEncoderBuffer(&out)
|
||||
outer := w.List()
|
||||
for i := 0; blockReceiptIter.Next(); i++ {
|
||||
txType, _ := nextTxType()
|
||||
var r Receipt
|
||||
if err := r.decodeDatabase(txType, blockReceiptIter.Value()); err != nil {
|
||||
return nil, fmt.Errorf("invalid database receipt %d: %v", i, err)
|
||||
}
|
||||
r.encodeForNetwork68(&buf, &w)
|
||||
}
|
||||
w.ListEnd(outer)
|
||||
w.Flush()
|
||||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
// setBuffers implements ReceiptsList.
|
||||
func (rl *ReceiptList68) setBuffers(buf *receiptListBuffers) {
|
||||
rl.buf = buf
|
||||
}
|
||||
|
||||
// EncodeForStorage encodes the receipts for storage into the database.
|
||||
func (rl *ReceiptList68) EncodeForStorage() (rlp.RawValue, error) {
|
||||
initBuffers(&rl.buf)
|
||||
return rl.buf.encodeForStorage(rl.items, func(data []byte, r *Receipt) error {
|
||||
return r.decode68(data)
|
||||
})
|
||||
}
|
||||
|
||||
// Derivable turns the receipts into a list that can derive the root hash.
|
||||
func (rl *ReceiptList68) Derivable() types.DerivableList {
|
||||
initBuffers(&rl.buf)
|
||||
return newDerivableRawList(&rl.items, func(data []byte, outbuf *bytes.Buffer) {
|
||||
var r Receipt
|
||||
if r.decode(data) == nil {
|
||||
r.encodeForHash(&bloomBuf, outbuf)
|
||||
if r.decode68(data) == nil {
|
||||
r.encodeForHash(rl.buf, outbuf)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// blockReceiptsToNetwork takes a slice of rlp-encoded receipts, and transactions,
|
||||
// and re-encodes them for the network protocol.
|
||||
func blockReceiptsToNetwork(blockReceipts, blockBody rlp.RawValue) ([]byte, error) {
|
||||
// DecodeRLP decodes a list of receipts from the network format.
|
||||
func (rl *ReceiptList68) DecodeRLP(s *rlp.Stream) error {
|
||||
return rl.items.DecodeRLP(s)
|
||||
}
|
||||
|
||||
// EncodeRLP encodes the list into the network format of eth/68.
|
||||
func (rl *ReceiptList68) EncodeRLP(w io.Writer) error {
|
||||
return rl.items.EncodeRLP(w)
|
||||
}
|
||||
|
||||
// ReceiptList69 is the block receipt list as downloaded by eth/69.
|
||||
// This implements types.DerivableList for validation purposes.
|
||||
type ReceiptList69 struct {
|
||||
buf *receiptListBuffers
|
||||
items rlp.RawList[Receipt]
|
||||
}
|
||||
|
||||
// NewReceiptList69 creates a receipt list.
|
||||
// This is slow, and exists for testing purposes.
|
||||
func NewReceiptList69(trs []*types.Receipt) *ReceiptList69 {
|
||||
rl := new(ReceiptList69)
|
||||
enc := rlp.NewEncoderBuffer(nil)
|
||||
for _, tr := range trs {
|
||||
r := newReceipt(tr)
|
||||
r.encodeForNetwork69(&enc)
|
||||
rl.items.AppendRaw(enc.ToBytes())
|
||||
enc.Reset(nil)
|
||||
}
|
||||
return rl
|
||||
}
|
||||
|
||||
// setBuffers implements ReceiptsList.
|
||||
func (rl *ReceiptList69) setBuffers(buf *receiptListBuffers) {
|
||||
rl.buf = buf
|
||||
}
|
||||
|
||||
// EncodeForStorage encodes the receipts for storage into the database.
|
||||
func (rl *ReceiptList69) EncodeForStorage() (rlp.RawValue, error) {
|
||||
initBuffers(&rl.buf)
|
||||
return rl.buf.encodeForStorage(rl.items, func(data []byte, r *Receipt) error {
|
||||
return r.decode69(data)
|
||||
})
|
||||
}
|
||||
|
||||
// Derivable turns the receipts into a list that can derive the root hash.
|
||||
func (rl *ReceiptList69) Derivable() types.DerivableList {
|
||||
initBuffers(&rl.buf)
|
||||
return newDerivableRawList(&rl.items, func(data []byte, outbuf *bytes.Buffer) {
|
||||
var r Receipt
|
||||
if r.decode69(data) == nil {
|
||||
r.encodeForHash(rl.buf, outbuf)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// DecodeRLP decodes a list receipts from the network format.
|
||||
func (rl *ReceiptList69) DecodeRLP(s *rlp.Stream) error {
|
||||
return rl.items.DecodeRLP(s)
|
||||
}
|
||||
|
||||
// EncodeRLP encodes the list into the network format of eth/69.
|
||||
func (rl *ReceiptList69) EncodeRLP(w io.Writer) error {
|
||||
return rl.items.EncodeRLP(w)
|
||||
}
|
||||
|
||||
// blockReceiptsToNetwork69 takes a slice of rlp-encoded receipts, and transactions,
|
||||
// and applies the type-encoding on the receipts (for non-legacy receipts).
|
||||
// e.g. for non-legacy receipts: receipt-data -> {tx-type || receipt-data}
|
||||
func blockReceiptsToNetwork69(blockReceipts, blockBody rlp.RawValue) ([]byte, error) {
|
||||
txTypesIter, err := txTypesInBody(blockBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid block body: %v", err)
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
func TestReceiptList(t *testing.T) {
|
||||
func TestReceiptList69(t *testing.T) {
|
||||
for i, test := range receiptsTests {
|
||||
// encode receipts from types.ReceiptForStorage object.
|
||||
canonDB, _ := rlp.EncodeToBytes(test.input)
|
||||
|
|
@ -105,13 +105,13 @@ func TestReceiptList(t *testing.T) {
|
|||
canonBody, _ := rlp.EncodeToBytes(blockBody)
|
||||
|
||||
// convert from storage encoding to network encoding
|
||||
network, err := blockReceiptsToNetwork(canonDB, canonBody)
|
||||
network, err := blockReceiptsToNetwork69(canonDB, canonBody)
|
||||
if err != nil {
|
||||
t.Fatalf("test[%d]: blockReceiptsToNetwork error: %v", i, err)
|
||||
t.Fatalf("test[%d]: blockReceiptsToNetwork69 error: %v", i, err)
|
||||
}
|
||||
|
||||
// parse as Receipts response list from network encoding
|
||||
var rl ReceiptList
|
||||
var rl ReceiptList69
|
||||
if err := rlp.DecodeBytes(network, &rl); err != nil {
|
||||
t.Fatalf("test[%d]: can't decode network receipts: %v", i, err)
|
||||
}
|
||||
|
|
@ -127,10 +127,50 @@ func TestReceiptList(t *testing.T) {
|
|||
t.Fatalf("test[%d]: re-encoded network receipt list not equal\nhave: %x\nwant: %x", i, rlNetworkEnc, network)
|
||||
}
|
||||
|
||||
// compute root hash from ReceiptList and compare.
|
||||
// compute root hash from ReceiptList69 and compare.
|
||||
responseHash := types.DeriveSha(rl.Derivable(), trie.NewStackTrie(nil))
|
||||
if responseHash != test.root {
|
||||
t.Fatalf("test[%d]: wrong root hash from ReceiptList\nhave: %v\nwant: %v", i, responseHash, test.root)
|
||||
t.Fatalf("test[%d]: wrong root hash from ReceiptList69\nhave: %v\nwant: %v", i, responseHash, test.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReceiptList68(t *testing.T) {
|
||||
for i, test := range receiptsTests {
|
||||
// encode receipts from types.ReceiptForStorage object.
|
||||
canonDB, _ := rlp.EncodeToBytes(test.input)
|
||||
|
||||
// encode block body from types object.
|
||||
blockBody := types.Body{Transactions: test.txs}
|
||||
canonBody, _ := rlp.EncodeToBytes(blockBody)
|
||||
|
||||
// convert from storage encoding to network encoding
|
||||
network, err := blockReceiptsToNetwork68(canonDB, canonBody)
|
||||
if err != nil {
|
||||
t.Fatalf("test[%d]: blockReceiptsToNetwork68 error: %v", i, err)
|
||||
}
|
||||
|
||||
// parse as Receipts response list from network encoding
|
||||
var rl ReceiptList68
|
||||
if err := rlp.DecodeBytes(network, &rl); err != nil {
|
||||
t.Fatalf("test[%d]: can't decode network receipts: %v", i, err)
|
||||
}
|
||||
rlStorageEnc, err := rl.EncodeForStorage()
|
||||
if err != nil {
|
||||
t.Fatalf("test[%d]: error from EncodeForStorage: %v", i, err)
|
||||
}
|
||||
if !bytes.Equal(rlStorageEnc, canonDB) {
|
||||
t.Fatalf("test[%d]: re-encoded receipts not equal\nhave: %x\nwant: %x", i, rlStorageEnc, canonDB)
|
||||
}
|
||||
rlNetworkEnc, _ := rlp.EncodeToBytes(&rl)
|
||||
if !bytes.Equal(rlNetworkEnc, network) {
|
||||
t.Fatalf("test[%d]: re-encoded network receipt list not equal\nhave: %x\nwant: %x", i, rlNetworkEnc, network)
|
||||
}
|
||||
|
||||
// compute root hash from ReceiptList68 and compare.
|
||||
responseHash := types.DeriveSha(rl.Derivable(), trie.NewStackTrie(nil))
|
||||
if responseHash != test.root {
|
||||
t.Fatalf("test[%d]: wrong root hash from ReceiptList68\nhave: %v\nwant: %v", i, responseHash, test.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1699,13 +1699,9 @@ func (s *Syncer) revertAccountRequest(req *accountRequest) {
|
|||
}
|
||||
close(req.stale)
|
||||
|
||||
// Remove the request from the tracked set and restore the peer to the
|
||||
// idle pool so it can be reassigned work (skip if peer already left).
|
||||
// Remove the request from the tracked set
|
||||
s.lock.Lock()
|
||||
delete(s.accountReqs, req.id)
|
||||
if _, ok := s.peers[req.peer]; ok {
|
||||
s.accountIdlers[req.peer] = struct{}{}
|
||||
}
|
||||
s.lock.Unlock()
|
||||
|
||||
// If there's a timeout timer still running, abort it and mark the account
|
||||
|
|
@ -1744,13 +1740,9 @@ func (s *Syncer) revertBytecodeRequest(req *bytecodeRequest) {
|
|||
}
|
||||
close(req.stale)
|
||||
|
||||
// Remove the request from the tracked set and restore the peer to the
|
||||
// idle pool so it can be reassigned work (skip if peer already left).
|
||||
// Remove the request from the tracked set
|
||||
s.lock.Lock()
|
||||
delete(s.bytecodeReqs, req.id)
|
||||
if _, ok := s.peers[req.peer]; ok {
|
||||
s.bytecodeIdlers[req.peer] = struct{}{}
|
||||
}
|
||||
s.lock.Unlock()
|
||||
|
||||
// If there's a timeout timer still running, abort it and mark the code
|
||||
|
|
@ -1789,13 +1781,9 @@ func (s *Syncer) revertStorageRequest(req *storageRequest) {
|
|||
}
|
||||
close(req.stale)
|
||||
|
||||
// Remove the request from the tracked set and restore the peer to the
|
||||
// idle pool so it can be reassigned work (skip if peer already left).
|
||||
// Remove the request from the tracked set
|
||||
s.lock.Lock()
|
||||
delete(s.storageReqs, req.id)
|
||||
if _, ok := s.peers[req.peer]; ok {
|
||||
s.storageIdlers[req.peer] = struct{}{}
|
||||
}
|
||||
s.lock.Unlock()
|
||||
|
||||
// If there's a timeout timer still running, abort it and mark the storage
|
||||
|
|
@ -1838,13 +1826,9 @@ func (s *Syncer) revertTrienodeHealRequest(req *trienodeHealRequest) {
|
|||
}
|
||||
close(req.stale)
|
||||
|
||||
// Remove the request from the tracked set and restore the peer to the
|
||||
// idle pool so it can be reassigned work (skip if peer already left).
|
||||
// Remove the request from the tracked set
|
||||
s.lock.Lock()
|
||||
delete(s.trienodeHealReqs, req.id)
|
||||
if _, ok := s.peers[req.peer]; ok {
|
||||
s.trienodeHealIdlers[req.peer] = struct{}{}
|
||||
}
|
||||
s.lock.Unlock()
|
||||
|
||||
// If there's a timeout timer still running, abort it and mark the trie node
|
||||
|
|
@ -1883,13 +1867,9 @@ func (s *Syncer) revertBytecodeHealRequest(req *bytecodeHealRequest) {
|
|||
}
|
||||
close(req.stale)
|
||||
|
||||
// Remove the request from the tracked set and restore the peer to the
|
||||
// idle pool so it can be reassigned work (skip if peer already left).
|
||||
// Remove the request from the tracked set
|
||||
s.lock.Lock()
|
||||
delete(s.bytecodeHealReqs, req.id)
|
||||
if _, ok := s.peers[req.peer]; ok {
|
||||
s.bytecodeHealIdlers[req.peer] = struct{}{}
|
||||
}
|
||||
s.lock.Unlock()
|
||||
|
||||
// If there's a timeout timer still running, abort it and mark the code
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import (
|
|||
)
|
||||
|
||||
// Tests that snap sync is disabled after a successful sync cycle.
|
||||
func TestSnapSyncDisabling69(t *testing.T) { testSnapSyncDisabling(t, eth.ETH69, snap.SNAP1) }
|
||||
func TestSnapSyncDisabling68(t *testing.T) { testSnapSyncDisabling(t, eth.ETH68, snap.SNAP1) }
|
||||
|
||||
// Tests that snap sync gets disabled as soon as a real block is successfully
|
||||
// imported into the blockchain.
|
||||
|
|
@ -82,18 +82,15 @@ func testSnapSyncDisabling(t *testing.T, ethVer uint, snapVer uint) {
|
|||
if err := empty.handler.downloader.BeaconSync(full.chain.CurrentBlock(), nil); err != nil {
|
||||
t.Fatal("sync failed:", err)
|
||||
}
|
||||
// Snap sync and mode switching happen asynchronously, poll for completion.
|
||||
timeout := time.NewTimer(15 * time.Second)
|
||||
tick := time.NewTicker(100 * time.Millisecond)
|
||||
defer timeout.Stop()
|
||||
defer tick.Stop()
|
||||
|
||||
for {
|
||||
// Downloader internally has to wait for a timer (3s) to be expired before
|
||||
// exiting. Poll after to determine if sync is disabled.
|
||||
time.Sleep(time.Second * 3)
|
||||
for timeout := time.After(time.Second); ; {
|
||||
select {
|
||||
case <-timeout.C:
|
||||
case <-timeout:
|
||||
t.Fatalf("snap sync not disabled after successful synchronisation")
|
||||
case <-tick.C:
|
||||
if empty.handler.synced.Load() && empty.handler.downloader.ConfigSyncMode() == ethconfig.FullSync {
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
if empty.handler.downloader.ConfigSyncMode() == ethconfig.FullSync {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package logger
|
|||
|
||||
import (
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
|
|
@ -89,10 +88,8 @@ func (al accessList) accessList() types.AccessList {
|
|||
for slot := range slots {
|
||||
tuple.StorageKeys = append(tuple.StorageKeys, slot)
|
||||
}
|
||||
keys := slices.SortedFunc(maps.Keys(slots), common.Hash.Cmp)
|
||||
acl = append(acl, types.AccessTuple{Address: addr, StorageKeys: keys})
|
||||
acl = append(acl, tuple)
|
||||
}
|
||||
slices.SortFunc(acl, func(a, b types.AccessTuple) int { return a.Address.Cmp(b.Address) })
|
||||
return acl
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
tracers.DefaultDirectory.Register("muxTracer", newMuxTracerFromConfig, false)
|
||||
tracers.DefaultDirectory.Register("muxTracer", newMuxTracer, false)
|
||||
}
|
||||
|
||||
// muxTracer is a go implementation of the Tracer interface which
|
||||
|
|
@ -38,8 +38,8 @@ type muxTracer struct {
|
|||
tracers []*tracers.Tracer
|
||||
}
|
||||
|
||||
// newMuxTracerFromConfig returns a new mux tracer.
|
||||
func newMuxTracerFromConfig(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) {
|
||||
// newMuxTracer returns a new mux tracer.
|
||||
func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) {
|
||||
var config map[string]json.RawMessage
|
||||
if err := json.Unmarshal(cfg, &config); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -54,16 +54,7 @@ func newMuxTracerFromConfig(ctx *tracers.Context, cfg json.RawMessage, chainConf
|
|||
objects = append(objects, t)
|
||||
names = append(names, k)
|
||||
}
|
||||
return NewMuxTracer(names, objects)
|
||||
}
|
||||
|
||||
// NewMuxTracer creates a multiplexing tracer that fans out tracing hooks to
|
||||
// multiple child tracers. Each hook invocation is forwarded to all children,
|
||||
// in the order they are provided.
|
||||
//
|
||||
// The names parameter associates a label with each tracer, used as keys in
|
||||
// the aggregated JSON result returned by GetResult.
|
||||
func NewMuxTracer(names []string, objects []*tracers.Tracer) (*tracers.Tracer, error) {
|
||||
t := &muxTracer{names: names, tracers: objects}
|
||||
return &tracers.Tracer{
|
||||
Hooks: &tracing.Hooks{
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
// Copyright 2025 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package native
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||
)
|
||||
|
||||
// opcodeCounter is a simple tracer that counts how many times each opcode is executed.
|
||||
type opcodeCounter struct {
|
||||
counts [256]uint64
|
||||
}
|
||||
|
||||
// NewOpcodeCounter returns a new opcodeCounter tracer.
|
||||
func NewOpcodeCounter() *tracers.Tracer {
|
||||
c := &opcodeCounter{}
|
||||
return &tracers.Tracer{
|
||||
Hooks: &tracing.Hooks{
|
||||
OnOpcode: func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||
c.counts[op]++
|
||||
},
|
||||
},
|
||||
GetResult: c.getResult,
|
||||
Stop: func(err error) {},
|
||||
}
|
||||
}
|
||||
|
||||
// getResult returns the opcode counts keyed by opcode name.
|
||||
func (c *opcodeCounter) getResult() (json.RawMessage, error) {
|
||||
out := make(map[string]uint64)
|
||||
for op, count := range c.counts {
|
||||
if count != 0 {
|
||||
out[vm.OpCode(op).String()] = count
|
||||
}
|
||||
}
|
||||
return json.Marshal(out)
|
||||
}
|
||||
4
go.mod
4
go.mod
|
|
@ -21,7 +21,7 @@ require (
|
|||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
|
||||
github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0
|
||||
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.6
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.5
|
||||
github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab
|
||||
github.com/fatih/color v1.16.0
|
||||
github.com/ferranbt/fastssz v0.1.4
|
||||
|
|
@ -58,7 +58,7 @@ require (
|
|||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
||||
github.com/status-im/keycard-go v0.2.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/supranational/blst v0.3.16
|
||||
github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||
github.com/urfave/cli/v2 v2.27.5
|
||||
go.opentelemetry.io/otel v1.39.0
|
||||
|
|
|
|||
8
go.sum
8
go.sum
|
|
@ -113,8 +113,8 @@ github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA
|
|||
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
|
||||
github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
|
||||
github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.6 h1:xQymkKCT5E2Jiaoqf3v4wsNgjZLY0lRSkZn27fRjSls=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.6/go.mod h1:8HMkUZ5JRv4hpw/XUrYWSQNAUzhHMg2UDb/U+5m+XNw=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
|
||||
github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs=
|
||||
github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk=
|
||||
github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
|
@ -360,8 +360,8 @@ github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
|||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/supranational/blst v0.3.16 h1:bTDadT+3fK497EvLdWRQEjiGnUtzJ7jjIUMF0jqwYhE=
|
||||
github.com/supranational/blst v0.3.16/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||
github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw=
|
||||
github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
|
|
|
|||
|
|
@ -1093,18 +1093,6 @@ func (b *Block) ExcessBlobGas(ctx context.Context) (*hexutil.Uint64, error) {
|
|||
return &ret, nil
|
||||
}
|
||||
|
||||
func (b *Block) SlotNumber(ctx context.Context) (*hexutil.Uint64, error) {
|
||||
header, err := b.resolveHeader(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if header.SlotNumber == nil {
|
||||
return nil, nil
|
||||
}
|
||||
ret := hexutil.Uint64(*header.SlotNumber)
|
||||
return &ret, nil
|
||||
}
|
||||
|
||||
// BlockFilterCriteria encapsulates criteria passed to a `logs` accessor inside
|
||||
// a block.
|
||||
type BlockFilterCriteria struct {
|
||||
|
|
|
|||
|
|
@ -53,10 +53,6 @@ import (
|
|||
// allowed to produce in order to speed up calculations.
|
||||
const estimateGasErrorRatio = 0.015
|
||||
|
||||
// maxGetStorageSlots is the maximum total number of storage slots that can
|
||||
// be requested in a single eth_getStorageValues call.
|
||||
const maxGetStorageSlots = 1024
|
||||
|
||||
var errBlobTxNotSupported = errors.New("signing blob transactions not supported")
|
||||
var errSubClosed = errors.New("chain subscription closed")
|
||||
|
||||
|
|
@ -593,41 +589,6 @@ func (api *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Addre
|
|||
return res[:], state.Error()
|
||||
}
|
||||
|
||||
// GetStorageValues returns multiple storage slot values for multiple accounts
|
||||
// at the given block.
|
||||
func (api *BlockChainAPI) GetStorageValues(ctx context.Context, requests map[common.Address][]common.Hash, blockNrOrHash rpc.BlockNumberOrHash) (map[common.Address][]hexutil.Bytes, error) {
|
||||
// Count total slots requested.
|
||||
var totalSlots int
|
||||
for _, keys := range requests {
|
||||
totalSlots += len(keys)
|
||||
if totalSlots > maxGetStorageSlots {
|
||||
return nil, &clientLimitExceededError{message: fmt.Sprintf("too many slots (max %d)", maxGetStorageSlots)}
|
||||
}
|
||||
}
|
||||
if totalSlots == 0 {
|
||||
return nil, &invalidParamsError{message: "empty request"}
|
||||
}
|
||||
|
||||
state, _, err := api.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||
if state == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[common.Address][]hexutil.Bytes, len(requests))
|
||||
for addr, keys := range requests {
|
||||
vals := make([]hexutil.Bytes, len(keys))
|
||||
for i, key := range keys {
|
||||
v := state.GetState(addr, key)
|
||||
vals[i] = v[:]
|
||||
}
|
||||
if err := state.Error(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[addr] = vals
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetBlockReceipts returns the block receipts for the given block hash or number or tag.
|
||||
func (api *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) {
|
||||
var (
|
||||
|
|
@ -971,9 +932,6 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
|||
if head.RequestsHash != nil {
|
||||
result["requestsHash"] = head.RequestsHash
|
||||
}
|
||||
if head.SlotNumber != nil {
|
||||
result["slotNumber"] = head.SlotNumber
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4065,91 +4065,3 @@ func TestSendRawTransactionSync_Timeout(t *testing.T) {
|
|||
t.Fatalf("expected ErrorData=%s, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStorageValues(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var (
|
||||
addr1 = common.HexToAddress("0x1111")
|
||||
addr2 = common.HexToAddress("0x2222")
|
||||
slot0 = common.Hash{}
|
||||
slot1 = common.BigToHash(big.NewInt(1))
|
||||
slot2 = common.BigToHash(big.NewInt(2))
|
||||
val0 = common.BigToHash(big.NewInt(42))
|
||||
val1 = common.BigToHash(big.NewInt(100))
|
||||
val2 = common.BigToHash(big.NewInt(200))
|
||||
|
||||
genesis = &core.Genesis{
|
||||
Config: params.MergedTestChainConfig,
|
||||
Alloc: types.GenesisAlloc{
|
||||
addr1: {
|
||||
Balance: big.NewInt(params.Ether),
|
||||
Storage: map[common.Hash]common.Hash{
|
||||
slot0: val0,
|
||||
slot1: val1,
|
||||
},
|
||||
},
|
||||
addr2: {
|
||||
Balance: big.NewInt(params.Ether),
|
||||
Storage: map[common.Hash]common.Hash{
|
||||
slot2: val2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
api := NewBlockChainAPI(newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
|
||||
b.SetPoS()
|
||||
}))
|
||||
latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
||||
|
||||
// Happy path: multiple addresses, multiple slots.
|
||||
result, err := api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{
|
||||
addr1: {slot0, slot1},
|
||||
addr2: {slot2},
|
||||
}, latest)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(result) != 2 {
|
||||
t.Fatalf("expected 2 addresses in result, got %d", len(result))
|
||||
}
|
||||
if got := common.BytesToHash(result[addr1][0]); got != val0 {
|
||||
t.Errorf("addr1 slot0: want %x, got %x", val0, got)
|
||||
}
|
||||
if got := common.BytesToHash(result[addr1][1]); got != val1 {
|
||||
t.Errorf("addr1 slot1: want %x, got %x", val1, got)
|
||||
}
|
||||
if got := common.BytesToHash(result[addr2][0]); got != val2 {
|
||||
t.Errorf("addr2 slot2: want %x, got %x", val2, got)
|
||||
}
|
||||
|
||||
// Missing slot returns zero.
|
||||
result, err = api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{
|
||||
addr1: {common.HexToHash("0xff")},
|
||||
}, latest)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got := common.BytesToHash(result[addr1][0]); got != (common.Hash{}) {
|
||||
t.Errorf("missing slot: want zero, got %x", got)
|
||||
}
|
||||
|
||||
// Empty request returns error.
|
||||
_, err = api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{}, latest)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for empty request")
|
||||
}
|
||||
|
||||
// Exceeding slot limit returns error.
|
||||
tooMany := make([]common.Hash, maxGetStorageSlots+1)
|
||||
for i := range tooMany {
|
||||
tooMany[i] = common.BigToHash(big.NewInt(int64(i)))
|
||||
}
|
||||
_, err = api.GetStorageValues(context.Background(), map[common.Address][]common.Hash{
|
||||
addr1: tooMany,
|
||||
}, latest)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for exceeding slot limit")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue