diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index 9f953b82d5..11638a3154 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -7,7 +7,7 @@ on:
- develop
pull_request:
- branches:
+ branches:
- master
- develop
@@ -47,5 +47,3 @@ jobs:
run: |
go mod download
make geth
-
-
diff --git a/.github/workflows/commit-lint.yml b/.github/workflows/commit-lint.yml
index 7df13ebcac..4d16ac7fb2 100644
--- a/.github/workflows/commit-lint.yml
+++ b/.github/workflows/commit-lint.yml
@@ -7,7 +7,7 @@ on:
- develop
pull_request:
- branches:
+ branches:
- master
- develop
diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml
index 234cbfda5b..ff12eb4bec 100644
--- a/.github/workflows/integration-test.yml
+++ b/.github/workflows/integration-test.yml
@@ -7,7 +7,7 @@ on:
- develop
pull_request:
- branches:
+ branches:
- master
- develop
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index daeddb502b..8d55c7780d 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -7,7 +7,7 @@ on:
- develop
pull_request:
- branches:
+ branches:
- master
- develop
@@ -44,7 +44,7 @@ jobs:
${{ runner.os }}-go-
- run: |
- go mod download
+ go mod tidy
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
diff --git a/.github/workflows/nancy.yml b/.github/workflows/nancy.yml
new file mode 100644
index 0000000000..b769191297
--- /dev/null
+++ b/.github/workflows/nancy.yml
@@ -0,0 +1,37 @@
+name: Go Nancy
+
+on:
+ # Scan changed files in PRs (diff-aware scanning):
+ pull_request: {}
+ # Scan on-demand through GitHub Actions interface:
+ workflow_dispatch: {}
+ # Scan mainline branches and report all findings:
+ push:
+ branches: ["master", "develop"]
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ go-version: [1.21.x]
+ os: [ubuntu-latest]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Check out code into the Go module directory
+ uses: actions/checkout@v2
+
+ - name: Set up Go 1.x in order to write go.list file
+ uses: actions/setup-go@v2
+ with:
+ go-version: ${{ matrix.go-version }}
+
+ - name: Go mod tidy
+ run: go mod tidy
+
+ - name: WriteGoList
+ run: go list -json -deps ./... > go.list
+
+ - name: Nancy
+ uses: sonatype-nexus-community/nancy-github-action@main
+ with:
+ nancyCommand: sleuth --loud
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index 9d0f39b378..a7d3304d6a 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -7,7 +7,7 @@ on:
- develop
pull_request:
- branches:
+ branches:
- master
- develop
@@ -51,4 +51,3 @@ jobs:
run: |
go mod download
make test
-
diff --git a/.gitignore b/.gitignore
index 6117fc2329..75d73f5001 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,5 @@ cmd/geth/__debug_bin
cmd/bootnode/bootnode
graphql/__debug_bin
logs/
+
+tests/spec-tests/
diff --git a/.travis.yml b/.travis.yml
index f64d2bb033..a55583a703 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,18 +9,6 @@ jobs:
- azure-osx
include:
- # This builder only tests code linters on latest version of Go
- - stage: lint
- os: linux
- dist: bionic
- go: 1.21.x
- env:
- - lint
- git:
- submodules: false # avoid cloning ethereum/tests
- script:
- - go run build/ci.go lint
-
# These builders create the Docker sub-images for multi-arch push and each
# will attempt to push the multi-arch image if they are the last builder
- stage: build
@@ -66,7 +54,6 @@ jobs:
go: 1.21.x
env:
- azure-linux
- - GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
addons:
@@ -97,15 +84,17 @@ jobs:
- stage: build
if: type = push
os: osx
+ osx_image: xcode14.2
go: 1.21.x
env:
- azure-osx
- - GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go install -dlgo
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
+ - go run build/ci.go install -dlgo -arch arm64
+ - go run build/ci.go archive -arch arm64 -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# These builders run the tests
- stage: build
@@ -113,10 +102,8 @@ jobs:
arch: amd64
dist: bionic
go: 1.21.x
- env:
- - GO111MODULE=on
script:
- - go run build/ci.go test $TEST_PACKAGES
+ - travis_wait 30 go run build/ci.go test $TEST_PACKAGES
- stage: build
if: type = pull_request
@@ -124,19 +111,15 @@ jobs:
arch: arm64
dist: bionic
go: 1.20.x
- env:
- - GO111MODULE=on
script:
- - go run build/ci.go test $TEST_PACKAGES
+ - travis_wait 30 go run build/ci.go test $TEST_PACKAGES
- stage: build
os: linux
dist: bionic
go: 1.20.x
- env:
- - GO111MODULE=on
script:
- - go run build/ci.go test $TEST_PACKAGES
+ - travis_wait 30 go run build/ci.go test $TEST_PACKAGES
# This builder does the Ubuntu PPA nightly uploads
- stage: build
@@ -146,7 +129,6 @@ jobs:
go: 1.21.x
env:
- ubuntu-ppa
- - GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
addons:
@@ -170,7 +152,6 @@ jobs:
go: 1.21.x
env:
- azure-purge
- - GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
script:
@@ -182,8 +163,6 @@ jobs:
os: linux
dist: bionic
go: 1.21.x
- env:
- - GO111MODULE=on
script:
- - go run build/ci.go test -race $TEST_PACKAGES
+ - travis_wait 30 go run build/ci.go test -race $TEST_PACKAGES
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c6a181673f..ffe07a36c8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,101 @@
# Changelog
+## v1.4.0
+#### RPC
+[internal/ethapi: implement eth_getBlockReceipts (#27702)](https://github.com/bnb-chain/bsc/commit/f1801a9feda8f81532c92077d2c9a8b785fd699b)
+[eth, rpc: add configurable option for wsMessageSizeLimit (#27801)](https://github.com/bnb-chain/bsc/commit/705a51e566bc9215975d08f27d23ddab7baa9dd7)
+[api/bind: add CallOpts.BlockHash to allow calling contracts at a specific block hash (#28084)](https://github.com/bnb-chain/bsc/commit/b85c86022e130a76eeb588a5b36e97149b342188)
+[internal/ethapi: eth_call block parameter is optional (#28165)](https://github.com/bnb-chain/bsc/commit/adb9b319c9c61f092755000bf0fc4b3349f5cbbc)
+[internal/ethapi: ethSendTransaction check baseFee (#27834)](https://github.com/bnb-chain/bsc/commit/54a400ee717caf44603fac390314747c5592ee1b)
+#### Command
+[cmd/utils: fix a startup issue on deleted chaindata but dangling ancients(#27989)](https://github.com/bnb-chain/bsc/commit/00fead91c4f58bc7f56f81512280d3120860989c)
+[cmd/geth, internal/flags, go.mod: colorize cli help, support env vars(#28103)](https://github.com/bnb-chain/bsc/commit/d9fbb71d631d1ad0fb1846042e4c50ab893a6fbf)
+[cmd/rlpdump: add -pos flag, displaying byte positions (#28785)](https://github.com/bnb-chain/bsc/commit/1485814f89d8206bb4a1c8e10a4a2893920f683a)
+[cmd/geth: make it possible to autopilot removedb (#28725)](https://github.com/bnb-chain/bsc/commit/1010a79c7cbcdb4741e9f30e8cdc19c679ad7377)
+#### Flag
+[cmd/utils: restore support for txlookuplimit flag (#27917)](https://github.com/bnb-chain/bsc/commit/68855216c903eea9f952a1a7a56e69ea285f284b)
+[cmd/utils, eth: disallow invalid snap sync / snapshot flag combos (#28657)](https://github.com/bnb-chain/bsc/commit/d98d70f670297a4bfa86db1a67a9c024f7186f43)
+#### Client
+[ethclient: use 'input', not 'data' as field for transaction input (#28078)](https://github.com/bnb-chain/bsc/commit/5cf53f51ac556cfff2aee9d405efd336298a3aca)
+[ethclient: fix forwarding 1559 gas fields (#28462)](https://github.com/bnb-chain/bsc/commit/e91cdb49beb4b2a3872b5f2548bf2d6559e4f561)
+[ethclient/simulated: implement new sim backend (#28202)](https://github.com/bnb-chain/bsc/commit/2d08c9900996b5e798f40a3cc6b47f4e51dc487d)
+[ethclient: apply accessList field in toCallArg (#28832)](https://github.com/bnb-chain/bsc/commit/1c488298c807f4daa3cbe260efb88b81902a903d)
+#### Tracer
+[eth/tracers: add position field for callTracer logs (#28389)](https://github.com/bnb-chain/bsc/commit/b1cec853bef98acc750298b1c9b8165f2ac6ce5a)
+[eth/tracers: tx-level state in debug_traceCall (#28460)](https://github.com/bnb-chain/bsc/commit/5fb8ebc9ecb226b84181420b9871c5f61cf4f77d)
+#### Txpool
+[eth/fetcher: allow underpriced transactions in after timeout (#28097)](https://github.com/bnb-chain/bsc/commit/2b7bc2c36b0d0efc83e62ba8e13723b943c4fa6e)
+#### Sync
+[eth/downloader: prevent pivot moves after state commit (#28126)](https://github.com/bnb-chain/bsc/commit/4fa3db49a1e485b8d110c87de6a44f460b45bb9a)
+[core, eth/downloader: fix genesis state missing due to state sync (#28124)](https://github.com/bnb-chain/bsc/commit/c53b0fef2ab8e2a00257b898cad5174e6b73f5fc)
+[core, accounts, eth, trie: handle genesis state missing (#28171)](https://github.com/bnb-chain/bsc/commit/73f5bcb75b562fcb3c109dd9c51f21956bc1f1f4)
+[eth/protocols/snap: fix snap sync failure on empty storage range (#28306)](https://github.com/bnb-chain/bsc/commit/1cb3b6aee4a16ab8e684da63f3cfcd9b961c43af)
+[core, eth, trie: filter out boundary nodes and remove dangling nodes in stacktrie (#28327)](https://github.com/bnb-chain/bsc/commit/ab04aeb855605de51dd1e933f45eb84ad877e715)
+[core, core/rawdb, eth/sync: no tx indexing during snap sync (#28703)](https://github.com/bnb-chain/bsc/commit/78a3c32ef4deb7755e3367e183639b66242654f7)
+#### PBSS Related
+[core/rawdb: skip pathdb state inspection in hashdb mode (#28108)](https://github.com/bnb-chain/bsc/commit/8d38b1fe62950e8675795abf63b7c978415ab7ba)
+[eth: abort on api operations not available in pbss-mode (#28104)](https://github.com/bnb-chain/bsc/commit/b9b99a12e5159c746ef04b7c8febc4db66817b72)
+[trie: remove internal nodes between shortNode and child in path mode (#28163)](https://github.com/bnb-chain/bsc/commit/4773dcbc81aac9d330df29446283361f5a7062c7)
+[trie/triedb/pathdb: improve dirty node flushing trigger (#28426)](https://github.com/bnb-chain/bsc/commit/ea2e66a58e48ef63566d5274c4a875e817a1cd39)
+[core/rawdb: fsync the index file after each freezer write (#28483)](https://github.com/bnb-chain/bsc/commit/326fa00759d959061035becc9514660c24897053)
+[trie: remove inconsistent trie nodes during sync in path mode (#28595)](https://github.com/bnb-chain/bsc/commit/e206d3f8975bd98cc86d14055dca40f996bacc60)
+[core, cmd, trie: fix the condition of pathdb initialization (#28718)](https://github.com/bnb-chain/bsc/commit/cca94792a4112687ce23e7041b95ccc7f4bf6123)
+#### GraphQL
+[graphql: validate block params (#27876](https://github.com/bnb-chain/bsc/commit/5e89ff4d6b0df4bd54d20d90bee5a16abef6b9bc)
+[graphql: always set content-type to application/json (#28417)](https://github.com/bnb-chain/bsc/commit/2d7dba024d76603398907a595da98ad4df81b858)
+#### Cancun
+[core/types: support for optional blob sidecar in BlobTx (#27841)](https://github.com/bnb-chain/bsc/commit/2a6beb6a39d7cb3c5906dd4465d65da6efcc73cd)
+[core, params, beacon/engine: implement EIP 4788 BeaconRoot (#27849)](https://github.com/bnb-chain/bsc/commit/b8d38e76ef07c99d338c7bcd485881850382a58f)
+[miner: add to build block with EIP-4844 blobs (#27875)](https://github.com/bnb-chain/bsc/commit/feb8f416acc3f067ecc8cbdabb8e70679547737a)
+[core: implement BLOBBASEFEE opcode (0x4a) (#28098)](https://github.com/bnb-chain/bsc/commit/c39cbc1a78aa275523c1b0ff9d21b16ba7bfa486)
+[core, eth, miner: start propagating and consuming blob txs (#28243)](https://github.com/bnb-chain/bsc/commit/a8a9c8e4b00c5b9f84242181839234b8e9fd54e3)
+[eth/fetcher: throttle tx fetches to 128KB responses (#28304)](https://github.com/bnb-chain/bsc/commit/a6deb2d994e644300bac43455b1c954976e7382e)
+[crypto/kzg4844: use the new trusted setup file and format (#28383)](https://github.com/bnb-chain/bsc/commit/a6a0ae45b69a95b38b7cb2d085e7833c88b72164)
+[internal/ethapi: handle blobs in API methods (#28786)](https://github.com/bnb-chain/bsc/commit/e5d5e09faae48dac3723634e2b1813e4f2e89535)
+#### P2P
+[cmd/devp2p, eth: drop eth/66 (#28239)](https://github.com/bnb-chain/bsc/commit/bc6d184872889224480cf9df58b0539b210ffa9e)
+[cmd/devp2p: use bootnodes as crawl input (#28139)](https://github.com/bnb-chain/bsc/commit/41a0ad9f03ae8e8389fbe40131f4e6930b5beac5)
+[p2p/discover: add liveness check in collectTableNodes (#28686)](https://github.com/bnb-chain/bsc/commit/5b22a472d6aaaa17daf0543b5914ca1f2f5518a7)
+#### Test
+[build, tests: add execution-spec-tests (#26985)](https://github.com/bnb-chain/bsc/commit/f174ddba7af5c150ecad37430c167194d66d75f1)
+[tests/fuzzers: update fuzzers to be based on go-native fuzzing (#28352)](https://github.com/bnb-chain/bsc/commit/d10a2f6ab727f79a0acff29c8147d54c5e4689ec)
+[tests/fuzzers: move fuzzers into native packages (#28467)](https://github.com/bnb-chain/bsc/commit/2391fbc676d7464bd42e248155558a2bcd6ecf64)
+#### Clear Up
+[eth/downloader: remove header rollback mechanism (#28147)](https://github.com/bnb-chain/bsc/commit/b85c183ea7417e973dbbccd27b3fb7d7097b87dd)
+#### Others
+[core/forkid: correctly compute forkid when timestamp fork is activated in genesis (#27895)](https://github.com/bnb-chain/bsc/commit/32fde3f838d604fdeb7a3ada4f8e02d78301b83d)
+[core/vm/runtime: Add Random field to config (#28001)](https://github.com/bnb-chain/bsc/commit/0ba2d3cfa4e4a0a76cd457b8dc0f49bf1a79b723)
+[core/rawdb: no need to run truncateFile for readonly mode (#28145)](https://github.com/bnb-chain/bsc/commit/545f4c5547178bc8bde6af08b3ccaf68ca27f2c0)
+[core/bloombits: fix deadlock when matcher session hits an error (#28184)](https://github.com/bnb-chain/bsc/commit/c2cfe35f121cb88650b4d90c958bcc4214d0ce7f)
+[core/state, tests: fix memory leak via fastcache (#28387)](https://github.com/bnb-chain/bsc/commit/c1d5a012ea4b824e902db14e47bf147d727c2657)
+[internal/ethapi: compact db missing key starts with 0xff (#28207)](https://github.com/bnb-chain/bsc/commit/46c850a9411d7ff15c1a0342fe29f359e6c390ae)
+[internal/ethapi: fix codehash lookup in eth_getProof (#28357)](https://github.com/bnb-chain/bsc/commit/8b99ad46027a455971ccf9bd1f425b9c58ec5855)
+[eth: set networkID to chainID by default (#28250)](https://github.com/bnb-chain/bsc/commit/4d9f3cd5d751efccd501b08ab6cf38a83b5e2858)
+[eth: fix potential hang in waitSnapExtension (#28744)](https://github.com/bnb-chain/bsc/commit/18e154eaa24d5f7a8b3c48983ad591e6c10963ca)
+[metrics, cmd/geth: informational metrics (prometheus, influxdb, opentsb (#24877)](https://github.com/bnb-chain/bsc/commit/53f3c2ae656cd860a700751b6c5f81ca9c66503d)
+[ethdb/pebble: don't double-close iterator inside pebbleIterator (#28566)](https://github.com/bnb-chain/bsc/commit/6489a0dd1f98e9ce1c64c2eae93c8a88df7ae674)
+[trie/triedb/hashdb: take lock around access to dirties cache (#28542)](https://github.com/bnb-chain/bsc/commit/fa0df76f3cfd186a1f06f2b80aa5dbb89555b009)
+[accounts: properly close managed wallets when closing manager (#28710)](https://github.com/bnb-chain/bsc/commit/d3452a22cc871306c62de52d19295914141863c0)
+[event: fix Resubscribe deadlock when unsubscribing after inner sub ends (#28359)](https://github.com/bnb-chain/bsc/commit/ffc6a0f36edda396a8421cf7a3c0feb88be20d0b)
+[all: replace log15 with slog (#28187)](https://github.com/bnb-chain/bsc/commit/28e73717016cdc9ebdb5fdb3474cfbd3bd2d2524)
+
+## v1.3.10
+FEATURE
+* [\#2047](https://github.com/bnb-chain/bsc/pull/2047) feat: add new fork block and precompile contract for BEP294 and BEP299
+
+## v1.3.9
+FEATURE
+* [\#2186](https://github.com/bnb-chain/bsc/pull/2186) log: support maxBackups in config.toml
+
+BUGFIX
+* [\#2160](https://github.com/bnb-chain/bsc/pull/2160) cmd: fix dump cli cannot work in path mode
+* [\#2183](https://github.com/bnb-chain/bsc/pull/2183) p2p: resolved deadlock on p2p server shutdown
+
+IMPROVEMENT
+* [\#2177](https://github.com/bnb-chain/bsc/pull/0000) build(deps): bump github.com/quic-go/quic-go from 0.39.3 to 0.39.4
+* [\#2185](https://github.com/bnb-chain/bsc/pull/2185) consensus/parlia: set nonce before evm run
+* [\#2190](https://github.com/bnb-chain/bsc/pull/2190) fix(legacypool): deprecate already known error
+* [\#2195](https://github.com/bnb-chain/bsc/pull/2195) eth/fetcher: downgrade state tx log
+
## v1.3.8
FEATURE
* [\#2074](https://github.com/bnb-chain/bsc/pull/2074) faucet: new faucet client
diff --git a/Makefile b/Makefile
index 730bc40706..36d89e60e5 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@
GOBIN = ./build/bin
GO ?= latest
-GORUN = env GO111MODULE=on go run
+GORUN = go run
GIT_COMMIT=$(shell git rev-parse HEAD)
GIT_COMMIT_DATE=$(shell git log -n1 --pretty='format:%cd' --date=format:'%Y%m%d')
@@ -36,7 +36,7 @@ lint: ## Run linters.
$(GORUN) build/ci.go lint
clean:
- env GO111MODULE=on go clean -cache
+ go clean -cache
rm -fr build/_workspace/pkg/ $(GOBIN)/*
# The devtools target installs tools required for 'go generate'.
diff --git a/README.md b/README.md
index b233c37a1c..c95bc0c053 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ The goal of BNB Smart Chain is to bring programmability and interoperability to
BNB Smart Chain starts its development based on go-ethereum fork. So you may see many toolings, binaries and also docs are based on Ethereum ones, such as the name “geth”.
[![API Reference](
-https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667
+https://pkg.go.dev/badge/github.com/ethereum/go-ethereum
)](https://pkg.go.dev/github.com/ethereum/go-ethereum?tab=doc)
[![Discord](https://img.shields.io/badge/discord-join%20chat-blue.svg)](https://discord.gg/z2VpC455eU)
diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go
index 55576070a4..4abf298068 100644
--- a/accounts/abi/abi.go
+++ b/accounts/abi/abi.go
@@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"io"
+ "math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
@@ -246,24 +247,65 @@ func (abi *ABI) HasReceive() bool {
// revertSelector is a special function selector for revert reason unpacking.
var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
+// panicSelector is a special function selector for panic reason unpacking.
+var panicSelector = crypto.Keccak256([]byte("Panic(uint256)"))[:4]
+
+// panicReasons map is for readable panic codes
+// see this linkage for the details
+// https://docs.soliditylang.org/en/v0.8.21/control-structures.html#panic-via-assert-and-error-via-require
+// the reason string list is copied from ether.js
+// https://github.com/ethers-io/ethers.js/blob/fa3a883ff7c88611ce766f58bdd4b8ac90814470/src.ts/abi/interface.ts#L207-L218
+var panicReasons = map[uint64]string{
+ 0x00: "generic panic",
+ 0x01: "assert(false)",
+ 0x11: "arithmetic underflow or overflow",
+ 0x12: "division or modulo by zero",
+ 0x21: "enum overflow",
+ 0x22: "invalid encoded storage byte array accessed",
+ 0x31: "out-of-bounds array access; popping on an empty array",
+ 0x32: "out-of-bounds access of an array or bytesN",
+ 0x41: "out of memory",
+ 0x51: "uninitialized function",
+}
+
// UnpackRevert resolves the abi-encoded revert reason. According to the solidity
// spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert,
-// the provided revert reason is abi-encoded as if it were a call to a function
-// `Error(string)`. So it's a special tool for it.
+// the provided revert reason is abi-encoded as if it were a call to function
+// `Error(string)` or `Panic(uint256)`. So it's a special tool for it.
func UnpackRevert(data []byte) (string, error) {
if len(data) < 4 {
return "", errors.New("invalid data for unpacking")
}
- if !bytes.Equal(data[:4], revertSelector) {
+ switch {
+ case bytes.Equal(data[:4], revertSelector):
+ typ, err := NewType("string", "", nil)
+ if err != nil {
+ return "", err
+ }
+ unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
+ if err != nil {
+ return "", err
+ }
+ return unpacked[0].(string), nil
+ case bytes.Equal(data[:4], panicSelector):
+ typ, err := NewType("uint256", "", nil)
+ if err != nil {
+ return "", err
+ }
+ unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
+ if err != nil {
+ return "", err
+ }
+ pCode := unpacked[0].(*big.Int)
+ // uint64 safety check for future
+ // but the code is not bigger than MAX(uint64) now
+ if pCode.IsUint64() {
+ if reason, ok := panicReasons[pCode.Uint64()]; ok {
+ return reason, nil
+ }
+ }
+ return fmt.Sprintf("unknown panic code: %#x", pCode), nil
+ default:
return "", errors.New("invalid data for unpacking")
}
- typ, err := NewType("string", "", nil)
- if err != nil {
- return "", err
- }
- unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
- if err != nil {
- return "", err
- }
- return unpacked[0].(string), nil
}
diff --git a/accounts/abi/abi_test.go b/accounts/abi/abi_test.go
index 3486ffd1a5..bc76df0dc2 100644
--- a/accounts/abi/abi_test.go
+++ b/accounts/abi/abi_test.go
@@ -120,6 +120,7 @@ var methods = map[string]Method{
}
func TestReader(t *testing.T) {
+ t.Parallel()
abi := ABI{
Methods: methods,
}
@@ -151,6 +152,7 @@ func TestReader(t *testing.T) {
}
func TestInvalidABI(t *testing.T) {
+ t.Parallel()
json := `[{ "type" : "function", "name" : "", "constant" : fals }]`
_, err := JSON(strings.NewReader(json))
if err == nil {
@@ -170,6 +172,7 @@ func TestInvalidABI(t *testing.T) {
// constructor(uint256 a, uint256 b) public{}
// }
func TestConstructor(t *testing.T) {
+ t.Parallel()
json := `[{ "inputs": [{"internalType": "uint256","name": "a","type": "uint256" },{ "internalType": "uint256","name": "b","type": "uint256"}],"stateMutability": "nonpayable","type": "constructor"}]`
method := NewMethod("", "", Constructor, "nonpayable", false, false, []Argument{{"a", Uint256, false}, {"b", Uint256, false}}, nil)
// Test from JSON
@@ -199,6 +202,7 @@ func TestConstructor(t *testing.T) {
}
func TestTestNumbers(t *testing.T) {
+ t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@@ -236,6 +240,7 @@ func TestTestNumbers(t *testing.T) {
}
func TestMethodSignature(t *testing.T) {
+ t.Parallel()
m := NewMethod("foo", "foo", Function, "", false, false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil)
exp := "foo(string,string)"
if m.Sig != exp {
@@ -274,6 +279,7 @@ func TestMethodSignature(t *testing.T) {
}
func TestOverloadedMethodSignature(t *testing.T) {
+ t.Parallel()
json := `[{"constant":true,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
@@ -297,6 +303,7 @@ func TestOverloadedMethodSignature(t *testing.T) {
}
func TestCustomErrors(t *testing.T) {
+ t.Parallel()
json := `[{ "inputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ],"name": "MyError", "type": "error"} ]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
@@ -311,6 +318,7 @@ func TestCustomErrors(t *testing.T) {
}
func TestMultiPack(t *testing.T) {
+ t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@@ -348,6 +356,7 @@ func ExampleJSON() {
}
func TestInputVariableInputLength(t *testing.T) {
+ t.Parallel()
const definition = `[
{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
@@ -476,6 +485,7 @@ func TestInputVariableInputLength(t *testing.T) {
}
func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
+ t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Error(err)
@@ -650,6 +660,7 @@ func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
}
func TestDefaultFunctionParsing(t *testing.T) {
+ t.Parallel()
const definition = `[{ "name" : "balance", "type" : "function" }]`
abi, err := JSON(strings.NewReader(definition))
@@ -663,6 +674,7 @@ func TestDefaultFunctionParsing(t *testing.T) {
}
func TestBareEvents(t *testing.T) {
+ t.Parallel()
const definition = `[
{ "type" : "event", "name" : "balance" },
{ "type" : "event", "name" : "anon", "anonymous" : true},
@@ -739,6 +751,7 @@ func TestBareEvents(t *testing.T) {
//
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
func TestUnpackEvent(t *testing.T) {
+ t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -777,6 +790,7 @@ func TestUnpackEvent(t *testing.T) {
}
func TestUnpackEventIntoMap(t *testing.T) {
+ t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -827,6 +841,7 @@ func TestUnpackEventIntoMap(t *testing.T) {
}
func TestUnpackMethodIntoMap(t *testing.T) {
+ t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -877,6 +892,7 @@ func TestUnpackMethodIntoMap(t *testing.T) {
}
func TestUnpackIntoMapNamingConflict(t *testing.T) {
+ t.Parallel()
// Two methods have the same name
var abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"get","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
abi, err := JSON(strings.NewReader(abiJSON))
@@ -960,6 +976,7 @@ func TestUnpackIntoMapNamingConflict(t *testing.T) {
}
func TestABI_MethodById(t *testing.T) {
+ t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@@ -992,6 +1009,7 @@ func TestABI_MethodById(t *testing.T) {
}
func TestABI_EventById(t *testing.T) {
+ t.Parallel()
tests := []struct {
name string
json string
@@ -1058,6 +1076,7 @@ func TestABI_EventById(t *testing.T) {
}
func TestABI_ErrorByID(t *testing.T) {
+ t.Parallel()
abi, err := JSON(strings.NewReader(`[
{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"MyError1","type":"error"},
{"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"x","type":"tuple"},{"internalType":"address","name":"y","type":"address"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"z","type":"tuple"}],"name":"MyError2","type":"error"},
@@ -1088,6 +1107,7 @@ func TestABI_ErrorByID(t *testing.T) {
// TestDoubleDuplicateMethodNames checks that if transfer0 already exists, there won't be a name
// conflict and that the second transfer method will be renamed transfer1.
func TestDoubleDuplicateMethodNames(t *testing.T) {
+ t.Parallel()
abiJSON := `[{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer0","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"},{"name":"customFallback","type":"string"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -1117,6 +1137,7 @@ func TestDoubleDuplicateMethodNames(t *testing.T) {
// event send();
// }
func TestDoubleDuplicateEventNames(t *testing.T) {
+ t.Parallel()
abiJSON := `[{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "a","type": "uint256"}],"name": "send","type": "event"},{"anonymous": false,"inputs": [],"name": "send0","type": "event"},{ "anonymous": false, "inputs": [],"name": "send","type": "event"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -1144,6 +1165,7 @@ func TestDoubleDuplicateEventNames(t *testing.T) {
// event send(uint256, uint256);
// }
func TestUnnamedEventParam(t *testing.T) {
+ t.Parallel()
abiJSON := `[{ "anonymous": false, "inputs": [{ "indexed": false,"internalType": "uint256", "name": "","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "","type": "uint256"}],"name": "send","type": "event"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
@@ -1173,9 +1195,13 @@ func TestUnpackRevert(t *testing.T) {
{"", "", errors.New("invalid data for unpacking")},
{"08c379a1", "", errors.New("invalid data for unpacking")},
{"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000", "revert reason", nil},
+ {"4e487b710000000000000000000000000000000000000000000000000000000000000000", "generic panic", nil},
+ {"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil},
}
for index, c := range cases {
+ index, c := index, c
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
+ t.Parallel()
got, err := UnpackRevert(common.Hex2Bytes(c.input))
if c.expectErr != nil {
if err == nil {
diff --git a/tests/fuzzers/abi/abifuzzer.go b/accounts/abi/abifuzzer_test.go
similarity index 61%
rename from tests/fuzzers/abi/abifuzzer.go
rename to accounts/abi/abifuzzer_test.go
index 60233d158a..dbf6ab6c54 100644
--- a/tests/fuzzers/abi/abifuzzer.go
+++ b/accounts/abi/abifuzzer_test.go
@@ -20,20 +20,34 @@ import (
"fmt"
"reflect"
"strings"
+ "testing"
- "github.com/ethereum/go-ethereum/accounts/abi"
fuzz "github.com/google/gofuzz"
)
+// TestReplicate can be used to replicate crashers from the fuzzing tests.
+// Just replace testString with the data in .quoted
+func TestReplicate(t *testing.T) {
+ t.Parallel()
+ //t.Skip("Test only useful for reproducing issues")
+ fuzzAbi([]byte("\x20\x20\x20\x20\x20\x20\x20\x20\x80\x00\x00\x00\x20\x20\x20\x20\x00"))
+ //fuzzAbi([]byte("asdfasdfkadsf;lasdf;lasd;lfk"))
+}
+
+// FuzzABI is the main entrypoint for fuzzing
+func FuzzABI(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzAbi(data)
+ })
+}
+
var (
- names = []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"}
- stateMut = []string{"", "pure", "view", "payable"}
- stateMutabilites = []*string{&stateMut[0], &stateMut[1], &stateMut[2], &stateMut[3]}
- pays = []string{"", "true", "false"}
- payables = []*string{&pays[0], &pays[1]}
- vNames = []string{"a", "b", "c", "d", "e", "f", "g"}
- varNames = append(vNames, names...)
- varTypes = []string{"bool", "address", "bytes", "string",
+ names = []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"}
+ stateMut = []string{"pure", "view", "payable"}
+ pays = []string{"true", "false"}
+ vNames = []string{"a", "b", "c", "d", "e", "f", "g"}
+ varNames = append(vNames, names...)
+ varTypes = []string{"bool", "address", "bytes", "string",
"uint8", "int8", "uint8", "int8", "uint16", "int16",
"uint24", "int24", "uint32", "int32", "uint40", "int40", "uint48", "int48", "uint56", "int56",
"uint64", "int64", "uint72", "int72", "uint80", "int80", "uint88", "int88", "uint96", "int96",
@@ -47,7 +61,7 @@ var (
"bytes32", "bytes"}
)
-func unpackPack(abi abi.ABI, method string, input []byte) ([]interface{}, bool) {
+func unpackPack(abi ABI, method string, input []byte) ([]interface{}, bool) {
if out, err := abi.Unpack(method, input); err == nil {
_, err := abi.Pack(method, out...)
if err != nil {
@@ -63,7 +77,7 @@ func unpackPack(abi abi.ABI, method string, input []byte) ([]interface{}, bool)
return nil, false
}
-func packUnpack(abi abi.ABI, method string, input *[]interface{}) bool {
+func packUnpack(abi ABI, method string, input *[]interface{}) bool {
if packed, err := abi.Pack(method, input); err == nil {
outptr := reflect.New(reflect.TypeOf(input))
err := abi.UnpackIntoInterface(outptr.Interface(), method, packed)
@@ -79,12 +93,12 @@ func packUnpack(abi abi.ABI, method string, input *[]interface{}) bool {
return false
}
-type args struct {
+type arg struct {
name string
typ string
}
-func createABI(name string, stateMutability, payable *string, inputs []args) (abi.ABI, error) {
+func createABI(name string, stateMutability, payable *string, inputs []arg) (ABI, error) {
sig := fmt.Sprintf(`[{ "type" : "function", "name" : "%v" `, name)
if stateMutability != nil {
sig += fmt.Sprintf(`, "stateMutability": "%v" `, *stateMutability)
@@ -111,60 +125,55 @@ func createABI(name string, stateMutability, payable *string, inputs []args) (ab
sig += "} ]"
}
sig += `}]`
-
- return abi.JSON(strings.NewReader(sig))
+ //fmt.Printf("sig: %s\n", sig)
+ return JSON(strings.NewReader(sig))
}
-func runFuzzer(input []byte) int {
- good := false
- fuzzer := fuzz.NewFromGoFuzz(input)
-
- name := names[getUInt(fuzzer)%len(names)]
- stateM := stateMutabilites[getUInt(fuzzer)%len(stateMutabilites)]
- payable := payables[getUInt(fuzzer)%len(payables)]
- maxLen := 5
- for k := 1; k < maxLen; k++ {
- var arg []args
- for i := k; i > 0; i-- {
- argName := varNames[i]
- argTyp := varTypes[getUInt(fuzzer)%len(varTypes)]
- if getUInt(fuzzer)%10 == 0 {
- argTyp += "[]"
- } else if getUInt(fuzzer)%10 == 0 {
- arrayArgs := getUInt(fuzzer)%30 + 1
- argTyp += fmt.Sprintf("[%d]", arrayArgs)
- }
- arg = append(arg, args{
- name: argName,
- typ: argTyp,
- })
- }
- abi, err := createABI(name, stateM, payable, arg)
- if err != nil {
- continue
+func fuzzAbi(input []byte) {
+ var (
+ fuzzer = fuzz.NewFromGoFuzz(input)
+ name = oneOf(fuzzer, names)
+ stateM = oneOfOrNil(fuzzer, stateMut)
+ payable = oneOfOrNil(fuzzer, pays)
+ arguments []arg
+ )
+ for i := 0; i < upTo(fuzzer, 10); i++ {
+ argName := oneOf(fuzzer, varNames)
+ argTyp := oneOf(fuzzer, varTypes)
+ switch upTo(fuzzer, 10) {
+ case 0: // 10% chance to make it a slice
+ argTyp += "[]"
+ case 1: // 10% chance to make it an array
+ argTyp += fmt.Sprintf("[%d]", 1+upTo(fuzzer, 30))
+ default:
}
- structs, b := unpackPack(abi, name, input)
- c := packUnpack(abi, name, &structs)
- good = good || b || c
+ arguments = append(arguments, arg{name: argName, typ: argTyp})
}
- if good {
- return 1
+ abi, err := createABI(name, stateM, payable, arguments)
+ if err != nil {
+ //fmt.Printf("err: %v\n", err)
+ panic(err)
}
- return 0
+ structs, _ := unpackPack(abi, name, input)
+ _ = packUnpack(abi, name, &structs)
}
-func Fuzz(input []byte) int {
- return runFuzzer(input)
-}
-
-func getUInt(fuzzer *fuzz.Fuzzer) int {
+func upTo(fuzzer *fuzz.Fuzzer, max int) int {
var i int
fuzzer.Fuzz(&i)
if i < 0 {
- i = -i
- if i < 0 {
- return 0
- }
+ return (-1 - i) % max
+ }
+ return i % max
+}
+
+func oneOf(fuzzer *fuzz.Fuzzer, options []string) string {
+ return options[upTo(fuzzer, len(options))]
+}
+
+func oneOfOrNil(fuzzer *fuzz.Fuzzer, options []string) *string {
+ if i := upTo(fuzzer, len(options)+1); i < len(options) {
+ return &options[i]
}
- return i
+ return nil
}
diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go
index 2e48d539e0..fa5461895a 100644
--- a/accounts/abi/argument.go
+++ b/accounts/abi/argument.go
@@ -80,7 +80,7 @@ func (arguments Arguments) isTuple() bool {
func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) {
if len(data) == 0 {
if len(arguments.NonIndexed()) != 0 {
- return nil, errors.New("abi: attempting to unmarshall an empty string while arguments are expected")
+ return nil, errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
}
return make([]interface{}, 0), nil
}
@@ -95,7 +95,7 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
}
if len(data) == 0 {
if len(arguments.NonIndexed()) != 0 {
- return errors.New("abi: attempting to unmarshall an empty string while arguments are expected")
+ return errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
}
return nil // Nothing to unmarshal, return
}
diff --git a/accounts/abi/bind/auth.go b/accounts/abi/bind/auth.go
index 494dc88a57..0740c69510 100644
--- a/accounts/abi/bind/auth.go
+++ b/accounts/abi/bind/auth.go
@@ -56,7 +56,7 @@ func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
}
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
-// an decrypted key from a keystore.
+// a decrypted key from a keystore.
//
// Deprecated: Use NewKeyStoreTransactorWithChainID instead.
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
@@ -117,7 +117,7 @@ func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.I
}
// NewKeyStoreTransactorWithChainID is a utility method to easily create a transaction signer from
-// an decrypted key from a keystore.
+// a decrypted key from a keystore.
func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) (*TransactOpts, error) {
if chainID == nil {
return nil, ErrNoChainID
diff --git a/accounts/abi/bind/backend.go b/accounts/abi/bind/backend.go
index bc691538b8..153ba46415 100644
--- a/accounts/abi/bind/backend.go
+++ b/accounts/abi/bind/backend.go
@@ -37,6 +37,10 @@ var (
// on a backend that doesn't implement PendingContractCaller.
ErrNoPendingState = errors.New("backend does not support pending state")
+ // ErrNoBlockHashState is raised when attempting to perform a block hash action
+ // on a backend that doesn't implement BlockHashContractCaller.
+ ErrNoBlockHashState = errors.New("backend does not support block hash state")
+
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
// an empty contract behind.
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
@@ -65,11 +69,27 @@ type PendingContractCaller interface {
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
}
+// BlockHashContractCaller defines methods to perform contract calls on a specific block hash.
+// Call will try to discover this interface when access to a block by hash is requested.
+// If the backend does not support the block hash state, Call returns ErrNoBlockHashState.
+type BlockHashContractCaller interface {
+ // CodeAtHash returns the code of the given account in the state at the specified block hash.
+ CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error)
+
+ // CallContractAtHash executes an Ethereum contract call against the state at the specified block hash.
+ CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error)
+}
+
// ContractTransactor defines the methods needed to allow operating with a contract
// on a write only basis. Besides the transacting method, the remainder are helpers
// used when the user does not provide some needed values, but rather leaves it up
// to the transactor to decide.
type ContractTransactor interface {
+ ethereum.GasEstimator
+ ethereum.GasPricer
+ ethereum.GasPricer1559
+ ethereum.TransactionSender
+
// HeaderByNumber returns a block header from the current canonical chain. If
// number is nil, the latest known header is returned.
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
@@ -80,48 +100,22 @@ type ContractTransactor interface {
// PendingNonceAt retrieves the current pending nonce associated with an account.
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
- // SuggestGasPrice retrieves the currently suggested gas price to allow a timely
- // execution of a transaction.
- SuggestGasPrice(ctx context.Context) (*big.Int, error)
-
- // SuggestGasTipCap retrieves the currently suggested 1559 priority fee to allow
- // a timely execution of a transaction.
- SuggestGasTipCap(ctx context.Context) (*big.Int, error)
-
- // EstimateGas tries to estimate the gas needed to execute a specific
- // transaction based on the current pending state of the backend blockchain.
- // There is no guarantee that this is the true gas limit requirement as other
- // transactions may be added or removed by miners, but it should provide a basis
- // for setting a reasonable default.
- EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)
-
- // SendTransaction injects the transaction into the pending pool for execution.
- SendTransaction(ctx context.Context, tx *types.Transaction) error
-
// SendTransactionConditional injects the conditional transaction into the pending pool for execution after verification.
SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts ethapi.TransactionOpts) error
}
-// ContractFilterer defines the methods needed to access log events using one-off
-// queries or continuous event subscriptions.
-type ContractFilterer interface {
- // FilterLogs executes a log filter operation, blocking during execution and
- // returning all the results in one batch.
- //
- // TODO(karalabe): Deprecate when the subscription one can return past data too.
- FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error)
-
- // SubscribeFilterLogs creates a background log filtering operation, returning
- // a subscription immediately, which can be used to stream the found events.
- SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
-}
-
// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
type DeployBackend interface {
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
}
+// ContractFilterer defines the methods needed to access log events using one-off
+// queries or continuous event subscriptions.
+type ContractFilterer interface {
+ ethereum.LogFilterer
+}
+
// ContractBackend defines the methods needed to work with contracts on a read-write basis.
type ContractBackend interface {
ContractCaller
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index ec0164d96e..756a9d3552 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -18,942 +18,35 @@ package backends
import (
"context"
- "errors"
- "fmt"
- "math/big"
- "sync"
- "time"
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/common/math"
- "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/bloombits"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/eth/filters"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/internal/ethapi"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/rpc"
+ "github.com/ethereum/go-ethereum/ethclient/simulated"
)
-// This nil assignment ensures at compile time that SimulatedBackend implements bind.ContractBackend.
-var _ bind.ContractBackend = (*SimulatedBackend)(nil)
-
-var (
- errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
- errBlockDoesNotExist = errors.New("block does not exist in blockchain")
- errTransactionDoesNotExist = errors.New("transaction does not exist")
-)
-
-// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
-// the background. Its main purpose is to allow for easy testing of contract bindings.
-// Simulated backend implements the following interfaces:
-// ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor,
-// DeployBackend, GasEstimator, GasPricer, LogFilterer, PendingContractCaller, TransactionReader, and TransactionSender
+// SimulatedBackend is a simulated blockchain.
+// Deprecated: use package github.com/ethereum/go-ethereum/ethclient/simulated instead.
type SimulatedBackend struct {
- database ethdb.Database // In memory database to store our testing data
- blockchain *core.BlockChain // Ethereum blockchain to handle the consensus
-
- mu sync.Mutex
- pendingBlock *types.Block // Currently pending block that will be imported on request
- pendingState *state.StateDB // Currently pending state that will be the active on request
- pendingReceipts types.Receipts // Currently receipts for the pending block
-
- events *filters.EventSystem // for filtering log events live
- filterSystem *filters.FilterSystem // for filtering database logs
-
- config *params.ChainConfig
+ *simulated.Backend
+ simulated.Client
}
-// NewSimulatedBackendWithDatabase creates a new binding backend based on the given database
-// and uses a simulated blockchain for testing purposes.
-// A simulated backend always uses chainID 1337.
-func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
- genesis := core.Genesis{
- Config: params.AllEthashProtocolChanges,
- GasLimit: gasLimit,
- Alloc: alloc,
- }
- blockchain, _ := core.NewBlockChain(database, nil, &genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
-
- backend := &SimulatedBackend{
- database: database,
- blockchain: blockchain,
- config: genesis.Config,
- }
-
- filterBackend := &filterBackend{database, blockchain, backend}
- backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
- backend.events = filters.NewEventSystem(backend.filterSystem)
-
- header := backend.blockchain.CurrentBlock()
- block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
-
- backend.rollback(block)
- return backend
+// Fork sets the head to a new block, which is based on the provided parentHash.
+func (b *SimulatedBackend) Fork(ctx context.Context, parentHash common.Hash) error {
+ return b.Backend.Fork(parentHash)
}
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes.
-// A simulated backend always uses chainID 1337.
-func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
- return NewSimulatedBackendWithDatabase(rawdb.NewMemoryDatabase(), alloc, gasLimit)
-}
-
-// Close terminates the underlying blockchain's update loop.
-func (b *SimulatedBackend) Close() error {
- b.blockchain.Stop()
- return nil
-}
-
-// Commit imports all the pending transactions as a single block and starts a
-// fresh new state.
-func (b *SimulatedBackend) Commit() common.Hash {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil {
- panic(err) // This cannot happen unless the simulator is wrong, fail in that case
- }
- blockHash := b.pendingBlock.Hash()
-
- // Using the last inserted block here makes it possible to build on a side
- // chain after a fork.
- b.rollback(b.pendingBlock)
-
- return blockHash
-}
-
-// Rollback aborts all pending transactions, reverting to the last committed state.
-func (b *SimulatedBackend) Rollback() {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- header := b.blockchain.CurrentBlock()
- block := b.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
-
- b.rollback(block)
-}
-
-func (b *SimulatedBackend) rollback(parent *types.Block) {
- blocks, _ := core.GenerateChain(b.config, parent, ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
-
- b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), b.blockchain.StateCache(), nil)
-}
-
-// Fork creates a side-chain that can be used to simulate reorgs.
//
-// This function should be called with the ancestor block where the new side
-// chain should be started. Transactions (old and new) can then be applied on
-// top and Commit-ed.
-//
-// Note, the side-chain will only become canonical (and trigger the events) when
-// it becomes longer. Until then CallContract will still operate on the current
-// canonical chain.
-//
-// There is a % chance that the side chain becomes canonical at the same length
-// to simulate live network behavior.
-func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if len(b.pendingBlock.Transactions()) != 0 {
- return errors.New("pending block dirty")
- }
- block, err := b.blockByHash(ctx, parent)
- if err != nil {
- return err
- }
- b.rollback(block)
- return nil
-}
-
-// stateByBlockNumber retrieves a state by a given blocknumber.
-func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) {
- if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 {
- return b.blockchain.State()
- }
- block, err := b.blockByNumber(ctx, blockNumber)
- if err != nil {
- return nil, err
- }
- return b.blockchain.StateAt(block.Root())
-}
-
-// CodeAt returns the code associated with a certain account in the blockchain.
-func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
- if err != nil {
- return nil, err
- }
-
- return stateDB.GetCode(contract), nil
-}
-
-// BalanceAt returns the wei balance of a certain account in the blockchain.
-func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
- if err != nil {
- return nil, err
- }
-
- return stateDB.GetBalance(contract), nil
-}
-
-// NonceAt returns the nonce of a certain account in the blockchain.
-func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (uint64, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
- if err != nil {
- return 0, err
- }
-
- return stateDB.GetNonce(contract), nil
-}
-
-// StorageAt returns the value of key in the storage of an account in the blockchain.
-func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
- if err != nil {
- return nil, err
- }
-
- val := stateDB.GetState(contract, key)
- return val[:], nil
-}
-
-// TransactionReceipt returns the receipt of a transaction.
-func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash, b.config)
- if receipt == nil {
- return nil, ethereum.NotFound
- }
- return receipt, nil
-}
-
-// TransactionByHash checks the pool of pending transactions in addition to the
-// blockchain. The isPending return value indicates whether the transaction has been
-// mined yet. Note that the transaction may not be part of the canonical chain even if
-// it's not pending.
-func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- tx := b.pendingBlock.Transaction(txHash)
- if tx != nil {
- return tx, true, nil
- }
- tx, _, _, _ = rawdb.ReadTransaction(b.database, txHash)
- if tx != nil {
- return tx, false, nil
- }
- return nil, false, ethereum.NotFound
-}
-
-// BlockByHash retrieves a block based on the block hash.
-func (b *SimulatedBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- return b.blockByHash(ctx, hash)
-}
-
-// blockByHash retrieves a block based on the block hash without Locking.
-func (b *SimulatedBackend) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
- if hash == b.pendingBlock.Hash() {
- return b.pendingBlock, nil
- }
-
- block := b.blockchain.GetBlockByHash(hash)
- if block != nil {
- return block, nil
- }
-
- return nil, errBlockDoesNotExist
-}
-
-// BlockByNumber retrieves a block from the database by number, caching it
-// (associated with its hash) if found.
-func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- return b.blockByNumber(ctx, number)
-}
-
-// blockByNumber retrieves a block from the database by number, caching it
-// (associated with its hash) if found without Lock.
-func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
- if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 {
- return b.blockByHash(ctx, b.blockchain.CurrentBlock().Hash())
- }
-
- block := b.blockchain.GetBlockByNumber(uint64(number.Int64()))
- if block == nil {
- return nil, errBlockDoesNotExist
- }
-
- return block, nil
-}
-
-// HeaderByHash returns a block header from the current canonical chain.
-func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if hash == b.pendingBlock.Hash() {
- return b.pendingBlock.Header(), nil
- }
-
- header := b.blockchain.GetHeaderByHash(hash)
- if header == nil {
- return nil, errBlockDoesNotExist
- }
-
- return header, nil
-}
-
-// HeaderByNumber returns a block header from the current canonical chain. If number is
-// nil, the latest known header is returned.
-func (b *SimulatedBackend) HeaderByNumber(ctx context.Context, block *big.Int) (*types.Header, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if block == nil || block.Cmp(b.pendingBlock.Number()) == 0 {
- return b.blockchain.CurrentHeader(), nil
- }
-
- return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil
-}
-
-// TransactionCount returns the number of transactions in a given block.
-func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if blockHash == b.pendingBlock.Hash() {
- return uint(b.pendingBlock.Transactions().Len()), nil
- }
-
- block := b.blockchain.GetBlockByHash(blockHash)
- if block == nil {
- return uint(0), errBlockDoesNotExist
- }
-
- return uint(block.Transactions().Len()), nil
-}
-
-// TransactionInBlock returns the transaction for a specific block at a specific index.
-func (b *SimulatedBackend) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if blockHash == b.pendingBlock.Hash() {
- transactions := b.pendingBlock.Transactions()
- if uint(len(transactions)) < index+1 {
- return nil, errTransactionDoesNotExist
- }
-
- return transactions[index], nil
- }
-
- block := b.blockchain.GetBlockByHash(blockHash)
- if block == nil {
- return nil, errBlockDoesNotExist
- }
-
- transactions := block.Transactions()
- if uint(len(transactions)) < index+1 {
- return nil, errTransactionDoesNotExist
- }
-
- return transactions[index], nil
-}
-
-// PendingCodeAt returns the code associated with an account in the pending state.
-func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- return b.pendingState.GetCode(contract), nil
-}
-
-func newRevertError(result *core.ExecutionResult) *revertError {
- reason, errUnpack := abi.UnpackRevert(result.Revert())
- err := errors.New("execution reverted")
- if errUnpack == nil {
- err = fmt.Errorf("execution reverted: %v", reason)
- }
- return &revertError{
- error: err,
- reason: hexutil.Encode(result.Revert()),
- }
-}
-
-// revertError is an API error that encompasses an EVM revert with JSON error
-// code and a binary data blob.
-type revertError struct {
- error
- reason string // revert reason hex encoded
-}
-
-// ErrorCode returns the JSON error code for a revert.
-// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
-func (e *revertError) ErrorCode() int {
- return 3
-}
-
-// ErrorData returns the hex encoded revert reason.
-func (e *revertError) ErrorData() interface{} {
- return e.reason
-}
-
-// CallContract executes a contract call.
-func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
- return nil, errBlockNumberUnsupported
- }
- stateDB, err := b.blockchain.State()
- if err != nil {
- return nil, err
- }
- res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), stateDB)
- if err != nil {
- return nil, err
- }
- // If the result contains a revert reason, try to unpack and return it.
- if len(res.Revert()) > 0 {
- return nil, newRevertError(res)
- }
- return res.Return(), res.Err
-}
-
-// PendingCallContract executes a contract call on the pending state.
-func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
- defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
-
- res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState)
- if err != nil {
- return nil, err
- }
- // If the result contains a revert reason, try to unpack and return it.
- if len(res.Revert()) > 0 {
- return nil, newRevertError(res)
- }
- return res.Return(), res.Err
-}
-
-// PendingNonceAt implements PendingStateReader.PendingNonceAt, retrieving
-// the nonce currently pending for the account.
-func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- return b.pendingState.GetOrNewStateObject(account).Nonce(), nil
-}
-
-// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
-// chain doesn't have miners, we just return a gas price of 1 for any call.
-func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if b.pendingBlock.Header().BaseFee != nil {
- return b.pendingBlock.Header().BaseFee, nil
- }
- return big.NewInt(1), nil
-}
-
-// SuggestGasTipCap implements ContractTransactor.SuggestGasTipCap. Since the simulated
-// chain doesn't have miners, we just return a gas tip of 1 for any call.
-func (b *SimulatedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
- return big.NewInt(1), nil
-}
-
-// EstimateGas executes the requested code against the currently pending block/state and
-// returns the used amount of gas.
-func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- // Determine the lowest and highest possible gas limits to binary search in between
- var (
- lo uint64 = params.TxGas - 1
- hi uint64
- cap uint64
- )
- if call.Gas >= params.TxGas {
- hi = call.Gas
- } else {
- hi = b.pendingBlock.GasLimit()
- }
- // Normalize the max fee per gas the call is willing to spend.
- var feeCap *big.Int
- if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
- return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
- } else if call.GasPrice != nil {
- feeCap = call.GasPrice
- } else if call.GasFeeCap != nil {
- feeCap = call.GasFeeCap
- } else {
- feeCap = common.Big0
- }
- // Recap the highest gas allowance with account's balance.
- if feeCap.BitLen() != 0 {
- balance := b.pendingState.GetBalance(call.From) // from can't be nil
- available := new(big.Int).Set(balance)
- if call.Value != nil {
- if call.Value.Cmp(available) >= 0 {
- return 0, core.ErrInsufficientFundsForTransfer
- }
- available.Sub(available, call.Value)
- }
- allowance := new(big.Int).Div(available, feeCap)
- if allowance.IsUint64() && hi > allowance.Uint64() {
- transfer := call.Value
- if transfer == nil {
- transfer = new(big.Int)
- }
- log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
- "sent", transfer, "feecap", feeCap, "fundable", allowance)
- hi = allowance.Uint64()
- }
- }
- cap = hi
-
- // Create a helper to check if a gas allowance results in an executable transaction
- executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
- call.Gas = gas
-
- snapshot := b.pendingState.Snapshot()
- res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState)
- b.pendingState.RevertToSnapshot(snapshot)
-
- if err != nil {
- if errors.Is(err, core.ErrIntrinsicGas) {
- return true, nil, nil // Special case, raise gas limit
- }
- return true, nil, err // Bail out
- }
- return res.Failed(), res, nil
- }
- // Execute the binary search and hone in on an executable gas limit
- for lo+1 < hi {
- mid := (hi + lo) / 2
- failed, _, err := executable(mid)
-
- // If the error is not nil(consensus error), it means the provided message
- // call or transaction will never be accepted no matter how much gas it is
- // assigned. Return the error directly, don't struggle any more
- if err != nil {
- return 0, err
- }
- if failed {
- lo = mid
- } else {
- hi = mid
- }
- }
- // Reject the transaction as invalid if it still fails at the highest allowance
- if hi == cap {
- failed, result, err := executable(hi)
- if err != nil {
- return 0, err
- }
- if failed {
- if result != nil && result.Err != vm.ErrOutOfGas {
- if len(result.Revert()) > 0 {
- return 0, newRevertError(result)
- }
- return 0, result.Err
- }
- // Otherwise, the specified gas cap is too low
- return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap)
- }
- }
- return hi, nil
-}
-
-// callContract implements common code between normal and pending contract calls.
-// state is modified during execution, make sure to copy it if necessary.
-func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, header *types.Header, stateDB *state.StateDB) (*core.ExecutionResult, error) {
- // Gas prices post 1559 need to be initialized
- if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
- return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
- }
- head := b.blockchain.CurrentHeader()
- if !b.blockchain.Config().IsLondon(head.Number) {
- // If there's no basefee, then it must be a non-1559 execution
- if call.GasPrice == nil {
- call.GasPrice = new(big.Int)
- }
- call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
- } else {
- // A basefee is provided, necessitating 1559-type execution
- if call.GasPrice != nil {
- // User specified the legacy gas field, convert to 1559 gas typing
- call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
- } else {
- // User specified 1559 gas fields (or none), use those
- if call.GasFeeCap == nil {
- call.GasFeeCap = new(big.Int)
- }
- if call.GasTipCap == nil {
- call.GasTipCap = new(big.Int)
- }
- // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
- call.GasPrice = new(big.Int)
- if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
- call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap)
- }
- }
- }
- // Ensure message is initialized properly.
- if call.Gas == 0 {
- call.Gas = 50000000
- }
- if call.Value == nil {
- call.Value = new(big.Int)
- }
-
- // Set infinite balance to the fake caller account.
- from := stateDB.GetOrNewStateObject(call.From)
- from.SetBalance(math.MaxBig256)
-
- // Execute the call.
- msg := &core.Message{
- From: call.From,
- To: call.To,
- Value: call.Value,
- GasLimit: call.Gas,
- GasPrice: call.GasPrice,
- GasFeeCap: call.GasFeeCap,
- GasTipCap: call.GasTipCap,
- Data: call.Data,
- AccessList: call.AccessList,
- SkipAccountChecks: true,
- }
-
- // Create a new environment which holds all relevant information
- // about the transaction and calling mechanisms.
- txContext := core.NewEVMTxContext(msg)
- evmContext := core.NewEVMBlockContext(header, b.blockchain, nil)
- vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})
- gasPool := new(core.GasPool).AddGas(math.MaxUint64)
-
- return core.ApplyMessage(vmEnv, msg, gasPool)
-}
-
-// SendTransaction updates the pending block to include the given transaction.
-func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- // Get the last block
- block, err := b.blockByHash(ctx, b.pendingBlock.ParentHash())
- if err != nil {
- return errors.New("could not fetch parent")
- }
- // Check transaction validity
- signer := types.MakeSigner(b.blockchain.Config(), block.Number(), block.Time())
- sender, err := types.Sender(signer, tx)
- if err != nil {
- return fmt.Errorf("invalid transaction: %v", err)
- }
- nonce := b.pendingState.GetNonce(sender)
- if tx.Nonce() != nonce {
- return fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce)
- }
- // Include tx in chain
- blocks, receipts := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
- for _, tx := range b.pendingBlock.Transactions() {
- block.AddTxWithChain(b.blockchain, tx)
- }
- block.AddTxWithChain(b.blockchain, tx)
- })
- stateDB, _ := b.blockchain.State()
-
- b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
- b.pendingReceipts = receipts[0]
- return nil
-}
-
-// SendTransaction updates the pending block to include the given transaction.
-func (b *SimulatedBackend) SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts ethapi.TransactionOpts) error {
- state, err := b.blockchain.State()
- if err != nil {
- return err
- }
- if err := opts.Check(b.pendingBlock.NumberU64(), b.pendingBlock.Time(), state); err != nil {
- return err
- }
- return b.SendTransaction(ctx, tx)
-}
-
-// FilterLogs executes a log filter operation, blocking during execution and
-// returning all the results in one batch.
+// A simulated backend always uses chainID 1337.
//
-// TODO(karalabe): Deprecate when the subscription one can return past data too.
-func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) {
- var filter *filters.Filter
- if query.BlockHash != nil {
- // Block filter requested, construct a single-shot filter
- filter = b.filterSystem.NewBlockFilter(*query.BlockHash, query.Addresses, query.Topics)
- } else {
- // Initialize unset filter boundaries to run from genesis to chain head
- from := int64(0)
- if query.FromBlock != nil {
- from = query.FromBlock.Int64()
- }
- to := int64(-1)
- if query.ToBlock != nil {
- to = query.ToBlock.Int64()
- }
- // Construct the range filter
- filter = b.filterSystem.NewRangeFilter(from, to, query.Addresses, query.Topics, false)
- }
- // Run the filter and return all the logs
- logs, err := filter.Logs(ctx)
- if err != nil {
- return nil, err
- }
- res := make([]types.Log, len(logs))
- for i, nLog := range logs {
- res[i] = *nLog
- }
- return res, nil
-}
-
-// SubscribeFilterLogs creates a background log filtering operation, returning a
-// subscription immediately, which can be used to stream the found events.
-func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
- // Subscribe to contract events
- sink := make(chan []*types.Log)
-
- sub, err := b.events.SubscribeLogs(query, sink)
- if err != nil {
- return nil, err
- }
- // Since we're getting logs in batches, we need to flatten them into a plain stream
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case logs := <-sink:
- for _, nlog := range logs {
- select {
- case ch <- *nlog:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
-
-// SubscribeNewHead returns an event subscription for a new header.
-func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
- // subscribe to a new head
- sink := make(chan *types.Header)
- sub := b.events.SubscribeNewHeads(sink)
-
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case head := <-sink:
- select {
- case ch <- head:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
-
-// AdjustTime adds a time shift to the simulated clock.
-// It can only be called on empty blocks.
-func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
- b.mu.Lock()
- defer b.mu.Unlock()
-
- if len(b.pendingBlock.Transactions()) != 0 {
- return errors.New("Could not adjust time on non-empty block")
- }
- // Get the last block
- block := b.blockchain.GetBlockByHash(b.pendingBlock.ParentHash())
- if block == nil {
- return errors.New("could not find parent")
- }
-
- blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
- block.OffsetTime(int64(adjustment.Seconds()))
- })
- stateDB, _ := b.blockchain.State()
-
- b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
-
- return nil
-}
-
-// Blockchain returns the underlying blockchain.
-func (b *SimulatedBackend) Blockchain() *core.BlockChain {
- return b.blockchain
-}
-
-// filterBackend implements filters.Backend to support filtering for logs without
-// taking bloom-bits acceleration structures into account.
-type filterBackend struct {
- db ethdb.Database
- bc *core.BlockChain
- backend *SimulatedBackend
-}
-
-func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db }
-
-func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") }
-
-func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
- switch number {
- case rpc.PendingBlockNumber:
- if block := fb.backend.pendingBlock; block != nil {
- return block.Header(), nil
- }
- return nil, nil
- case rpc.LatestBlockNumber:
- return fb.bc.CurrentHeader(), nil
- case rpc.FinalizedBlockNumber:
- return fb.bc.CurrentFinalBlock(), nil
- case rpc.SafeBlockNumber:
- return fb.bc.CurrentSafeBlock(), nil
- default:
- return fb.bc.GetHeaderByNumber(uint64(number.Int64())), nil
- }
-}
-
-func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
- return fb.bc.GetHeaderByHash(hash), nil
-}
-
-func (fb *filterBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
- if body := fb.bc.GetBody(hash); body != nil {
- return body, nil
- }
- return nil, errors.New("block body not found")
-}
-
-func (fb *filterBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
- return fb.backend.pendingBlock, fb.backend.pendingReceipts
-}
-
-func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
- number := rawdb.ReadHeaderNumber(fb.db, hash)
- if number == nil {
- return nil, nil
- }
- header := rawdb.ReadHeader(fb.db, hash, *number)
- if header == nil {
- return nil, nil
+// Deprecated: please use simulated.Backend from package
+// github.com/ethereum/go-ethereum/ethclient/simulated instead.
+func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
+ b := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(gasLimit))
+ return &SimulatedBackend{
+ Backend: b,
+ Client: b.Client(),
}
- return rawdb.ReadReceipts(fb.db, hash, *number, header.Time, fb.bc.Config()), nil
-}
-
-func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
- logs := rawdb.ReadLogs(fb.db, hash, number, fb.bc.Config())
- return logs, nil
-}
-
-func (fb *filterBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
- return nullSubscription()
-}
-
-func (fb *filterBackend) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription {
- return nullSubscription()
-}
-
-func (fb *filterBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
- return fb.bc.SubscribeChainEvent(ch)
-}
-
-func (fb *filterBackend) SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription {
- return fb.bc.SubscribeFinalizedHeaderEvent(ch)
-}
-
-func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
- return fb.bc.SubscribeRemovedLogsEvent(ch)
-}
-
-func (fb *filterBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
- return fb.bc.SubscribeLogsEvent(ch)
-}
-
-func (fb *filterBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
- return nullSubscription()
-}
-
-func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 }
-
-func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) {
- panic("not supported")
-}
-
-func (fb *filterBackend) ChainConfig() *params.ChainConfig {
- panic("not supported")
-}
-
-func (fb *filterBackend) CurrentHeader() *types.Header {
- panic("not supported")
-}
-
-func nullSubscription() event.Subscription {
- return event.NewSubscription(func(quit <-chan struct{}) error {
- <-quit
- return nil
- })
}
diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go
deleted file mode 100644
index 11900a6cf5..0000000000
--- a/accounts/abi/bind/backends/simulated_test.go
+++ /dev/null
@@ -1,1400 +0,0 @@
-// Copyright 2019 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package backends
-
-import (
- "bytes"
- "context"
- "errors"
- "math/big"
- "math/rand"
- "reflect"
- "strings"
- "testing"
- "time"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/params"
-)
-
-func TestSimulatedBackend(t *testing.T) {
- var gasLimit uint64 = 8000029
- key, _ := crypto.GenerateKey() // nolint: gosec
- auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
- genAlloc := make(core.GenesisAlloc)
- genAlloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(9223372036854775807)}
-
- sim := NewSimulatedBackend(genAlloc, gasLimit)
- defer sim.Close()
-
- // should return an error if the tx is not found
- txHash := common.HexToHash("2")
- _, isPending, err := sim.TransactionByHash(context.Background(), txHash)
-
- if isPending {
- t.Fatal("transaction should not be pending")
- }
- if err != ethereum.NotFound {
- t.Fatalf("err should be `ethereum.NotFound` but received %v", err)
- }
-
- // generate a transaction and confirm you can retrieve it
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- code := `6060604052600a8060106000396000f360606040526008565b00`
- var gas uint64 = 3000000
- tx := types.NewContractCreation(0, big.NewInt(0), gas, gasPrice, common.FromHex(code))
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, key)
-
- err = sim.SendTransaction(context.Background(), tx)
- if err != nil {
- t.Fatal("error sending transaction")
- }
-
- txHash = tx.Hash()
- _, isPending, err = sim.TransactionByHash(context.Background(), txHash)
- if err != nil {
- t.Fatalf("error getting transaction with hash: %v", txHash.String())
- }
- if !isPending {
- t.Fatal("transaction should have pending status")
- }
-
- sim.Commit()
- _, isPending, err = sim.TransactionByHash(context.Background(), txHash)
- if err != nil {
- t.Fatalf("error getting transaction with hash: %v", txHash.String())
- }
- if isPending {
- t.Fatal("transaction should not have pending status")
- }
-}
-
-var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
-
-// the following is based on this contract:
-//
-// contract T {
-// event received(address sender, uint amount, bytes memo);
-// event receivedAddr(address sender);
-//
-// function receive(bytes calldata memo) external payable returns (string memory res) {
-// emit received(msg.sender, msg.value, memo);
-// emit receivedAddr(msg.sender);
-// return "hello world";
-// }
-// }
-const abiJSON = `[ { "constant": false, "inputs": [ { "name": "memo", "type": "bytes" } ], "name": "receive", "outputs": [ { "name": "res", "type": "string" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" }, { "indexed": false, "name": "amount", "type": "uint256" }, { "indexed": false, "name": "memo", "type": "bytes" } ], "name": "received", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" } ], "name": "receivedAddr", "type": "event" } ]`
-const abiBin = `0x608060405234801561001057600080fd5b506102a0806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029`
-const deployedCode = `60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029`
-
-// expected return value contains "hello world"
-var expectedReturn = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-
-func simTestBackend(testAddr common.Address) *SimulatedBackend {
- return NewSimulatedBackend(
- core.GenesisAlloc{
- testAddr: {Balance: big.NewInt(10000000000000000)},
- }, 10000000,
- )
-}
-
-func TestNewSimulatedBackend(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- expectedBal := big.NewInt(10000000000000000)
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- if sim.config != params.AllEthashProtocolChanges {
- t.Errorf("expected sim config to equal params.AllEthashProtocolChanges, got %v", sim.config)
- }
-
- if sim.blockchain.Config() != params.AllEthashProtocolChanges {
- t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config)
- }
-
- stateDB, _ := sim.blockchain.State()
- bal := stateDB.GetBalance(testAddr)
- if bal.Cmp(expectedBal) != 0 {
- t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
- }
-}
-
-func TestAdjustTime(t *testing.T) {
- sim := NewSimulatedBackend(
- core.GenesisAlloc{}, 10000000,
- )
- defer sim.Close()
-
- prevTime := sim.pendingBlock.Time()
- if err := sim.AdjustTime(time.Second); err != nil {
- t.Error(err)
- }
- newTime := sim.pendingBlock.Time()
-
- if newTime-prevTime != uint64(time.Second.Seconds()) {
- t.Errorf("adjusted time not equal to a second. prev: %v, new: %v", prevTime, newTime)
- }
-}
-
-func TestNewAdjustTimeFail(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.blockchain.Stop()
-
- // Create tx and send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
- sim.SendTransaction(context.Background(), signedTx)
- // AdjustTime should fail on non-empty block
- if err := sim.AdjustTime(time.Second); err == nil {
- t.Error("Expected adjust time to error on non-empty block")
- }
- sim.Commit()
-
- prevTime := sim.pendingBlock.Time()
- if err := sim.AdjustTime(time.Minute); err != nil {
- t.Error(err)
- }
- newTime := sim.pendingBlock.Time()
- if newTime-prevTime != uint64(time.Minute.Seconds()) {
- t.Errorf("adjusted time not equal to a minute. prev: %v, new: %v", prevTime, newTime)
- }
- // Put a transaction after adjusting time
- tx2 := types.NewTransaction(1, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx2, err := types.SignTx(tx2, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
- sim.SendTransaction(context.Background(), signedTx2)
- sim.Commit()
- newTime = sim.pendingBlock.Time()
- if newTime-prevTime >= uint64(time.Minute.Seconds()) {
- t.Errorf("time adjusted, but shouldn't be: prev: %v, new: %v", prevTime, newTime)
- }
-}
-
-func TestBalanceAt(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- expectedBal := big.NewInt(10000000000000000)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- bal, err := sim.BalanceAt(bgCtx, testAddr, nil)
- if err != nil {
- t.Error(err)
- }
-
- if bal.Cmp(expectedBal) != 0 {
- t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
- }
-}
-
-func TestBlockByHash(t *testing.T) {
- sim := NewSimulatedBackend(
- core.GenesisAlloc{}, 10000000,
- )
- defer sim.Close()
- bgCtx := context.Background()
-
- block, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
- blockByHash, err := sim.BlockByHash(bgCtx, block.Hash())
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
-
- if block.Hash() != blockByHash.Hash() {
- t.Errorf("did not get expected block")
- }
-}
-
-func TestBlockByNumber(t *testing.T) {
- sim := NewSimulatedBackend(
- core.GenesisAlloc{}, 10000000,
- )
- defer sim.Close()
- bgCtx := context.Background()
-
- block, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
- if block.NumberU64() != 0 {
- t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64())
- }
-
- // create one block
- sim.Commit()
-
- block, err = sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
- if block.NumberU64() != 1 {
- t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64())
- }
-
- blockByNumber, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get block by number: %v", err)
- }
- if blockByNumber.Hash() != block.Hash() {
- t.Errorf("did not get the same block with height of 1 as before")
- }
-}
-
-func TestNonceAt(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- nonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(0))
- if err != nil {
- t.Errorf("could not get nonce for test addr: %v", err)
- }
-
- if nonce != uint64(0) {
- t.Errorf("received incorrect nonce. expected 0, got %v", nonce)
- }
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
- sim.Commit()
-
- newNonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get nonce for test addr: %v", err)
- }
-
- if newNonce != nonce+uint64(1) {
- t.Errorf("received incorrect nonce. expected 1, got %v", nonce)
- }
- // create some more blocks
- sim.Commit()
- // Check that we can get data for an older block/state
- newNonce, err = sim.NonceAt(bgCtx, testAddr, big.NewInt(1))
- if err != nil {
- t.Fatalf("could not get nonce for test addr: %v", err)
- }
- if newNonce != nonce+uint64(1) {
- t.Fatalf("received incorrect nonce. expected 1, got %v", nonce)
- }
-}
-
-func TestSendTransaction(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
- sim.Commit()
-
- block, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get block at height 1: %v", err)
- }
-
- if signedTx.Hash() != block.Transactions()[0].Hash() {
- t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash())
- }
-}
-
-func TestTransactionByHash(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := NewSimulatedBackend(
- core.GenesisAlloc{
- testAddr: {Balance: big.NewInt(10000000000000000)},
- }, 10000000,
- )
- defer sim.Close()
- bgCtx := context.Background()
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- // ensure tx is committed pending
- receivedTx, pending, err := sim.TransactionByHash(bgCtx, signedTx.Hash())
- if err != nil {
- t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err)
- }
- if !pending {
- t.Errorf("expected transaction to be in pending state")
- }
- if receivedTx.Hash() != signedTx.Hash() {
- t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash())
- }
-
- sim.Commit()
-
- // ensure tx is not and committed pending
- receivedTx, pending, err = sim.TransactionByHash(bgCtx, signedTx.Hash())
- if err != nil {
- t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err)
- }
- if pending {
- t.Errorf("expected transaction to not be in pending state")
- }
- if receivedTx.Hash() != signedTx.Hash() {
- t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash())
- }
-}
-
-func TestEstimateGas(t *testing.T) {
- /*
- pragma solidity ^0.6.4;
- contract GasEstimation {
- function PureRevert() public { revert(); }
- function Revert() public { revert("revert reason");}
- function OOG() public { for (uint i = 0; ; i++) {}}
- function Assert() public { assert(false);}
- function Valid() public {}
- }
- */
- const contractAbi = "[{\"inputs\":[],\"name\":\"Assert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OOG\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PureRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Revert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Valid\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
- const contractBin = "0x60806040523480156100115760006000fd5b50610017565b61016e806100266000396000f3fe60806040523480156100115760006000fd5b506004361061005c5760003560e01c806350f6fe3414610062578063aa8b1d301461006c578063b9b046f914610076578063d8b9839114610080578063e09fface1461008a5761005c565b60006000fd5b61006a610094565b005b6100746100ad565b005b61007e6100b5565b005b6100886100c2565b005b610092610135565b005b6000600090505b5b808060010191505061009b565b505b565b60006000fd5b565b600015156100bf57fe5b5b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f72657665727420726561736f6e0000000000000000000000000000000000000081526020015060200191505060405180910390fd5b565b5b56fea2646970667358221220345bbcbb1a5ecf22b53a78eaebf95f8ee0eceff6d10d4b9643495084d2ec934a64736f6c63430006040033"
-
- key, _ := crypto.GenerateKey()
- addr := crypto.PubkeyToAddress(key.PublicKey)
- opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
-
- sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether)}}, 10000000)
- defer sim.Close()
-
- parsed, _ := abi.JSON(strings.NewReader(contractAbi))
- contractAddr, _, _, _ := bind.DeployContract(opts, parsed, common.FromHex(contractBin), sim)
- sim.Commit()
-
- var cases = []struct {
- name string
- message ethereum.CallMsg
- expect uint64
- expectError error
- expectData interface{}
- }{
- {"plain transfer(valid)", ethereum.CallMsg{
- From: addr,
- To: &addr,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: big.NewInt(1),
- Data: nil,
- }, params.TxGas, nil, nil},
-
- {"plain transfer(invalid)", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: big.NewInt(1),
- Data: nil,
- }, 0, errors.New("execution reverted"), nil},
-
- {"Revert", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("d8b98391"),
- }, 0, errors.New("execution reverted: revert reason"), "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000"},
-
- {"PureRevert", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("aa8b1d30"),
- }, 0, errors.New("execution reverted"), nil},
-
- {"OOG", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 100000,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("50f6fe34"),
- }, 0, errors.New("gas required exceeds allowance (100000)"), nil},
-
- {"Assert", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 100000,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("b9b046f9"),
- }, 0, errors.New("invalid opcode: INVALID"), nil},
-
- {"Valid", ethereum.CallMsg{
- From: addr,
- To: &contractAddr,
- Gas: 100000,
- GasPrice: big.NewInt(0),
- Value: nil,
- Data: common.Hex2Bytes("e09fface"),
- }, 21275, nil, nil},
- }
- for _, c := range cases {
- got, err := sim.EstimateGas(context.Background(), c.message)
- if c.expectError != nil {
- if err == nil {
- t.Fatalf("Expect error, got nil")
- }
- if c.expectError.Error() != err.Error() {
- t.Fatalf("Expect error, want %v, got %v", c.expectError, err)
- }
- if c.expectData != nil {
- if err, ok := err.(*revertError); !ok {
- t.Fatalf("Expect revert error, got %T", err)
- } else if !reflect.DeepEqual(err.ErrorData(), c.expectData) {
- t.Fatalf("Error data mismatch, want %v, got %v", c.expectData, err.ErrorData())
- }
- }
- continue
- }
- if got != c.expect {
- t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got)
- }
- }
-}
-
-func TestEstimateGasWithPrice(t *testing.T) {
- key, _ := crypto.GenerateKey()
- addr := crypto.PubkeyToAddress(key.PublicKey)
-
- sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether*2 + 2e17)}}, 10000000)
- defer sim.Close()
-
- recipient := common.HexToAddress("deadbeef")
- var cases = []struct {
- name string
- message ethereum.CallMsg
- expect uint64
- expectError error
- }{
- {"EstimateWithoutPrice", ethereum.CallMsg{
- From: addr,
- To: &recipient,
- Gas: 0,
- GasPrice: big.NewInt(0),
- Value: big.NewInt(100000000000),
- Data: nil,
- }, 21000, nil},
-
- {"EstimateWithPrice", ethereum.CallMsg{
- From: addr,
- To: &recipient,
- Gas: 0,
- GasPrice: big.NewInt(100000000000),
- Value: big.NewInt(100000000000),
- Data: nil,
- }, 21000, nil},
-
- {"EstimateWithVeryHighPrice", ethereum.CallMsg{
- From: addr,
- To: &recipient,
- Gas: 0,
- GasPrice: big.NewInt(1e14), // gascost = 2.1ether
- Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether
- Data: nil,
- }, 21000, nil},
-
- {"EstimateWithSuperhighPrice", ethereum.CallMsg{
- From: addr,
- To: &recipient,
- Gas: 0,
- GasPrice: big.NewInt(2e14), // gascost = 4.2ether
- Value: big.NewInt(100000000000),
- Data: nil,
- }, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14)
-
- {"EstimateEIP1559WithHighFees", ethereum.CallMsg{
- From: addr,
- To: &addr,
- Gas: 0,
- GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether
- GasTipCap: big.NewInt(1),
- Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether
- Data: nil,
- }, params.TxGas, nil},
-
- {"EstimateEIP1559WithSuperHighFees", ethereum.CallMsg{
- From: addr,
- To: &addr,
- Gas: 0,
- GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether
- GasTipCap: big.NewInt(1),
- Value: big.NewInt(1e17 + 1), // the remaining balance for fee is 2.1ether
- Data: nil,
- }, params.TxGas, errors.New("gas required exceeds allowance (20999)")}, // 20999=(2.2ether-0.1ether-1wei)/(1e14)
- }
- for i, c := range cases {
- got, err := sim.EstimateGas(context.Background(), c.message)
- if c.expectError != nil {
- if err == nil {
- t.Fatalf("test %d: expect error, got nil", i)
- }
- if c.expectError.Error() != err.Error() {
- t.Fatalf("test %d: expect error, want %v, got %v", i, c.expectError, err)
- }
- continue
- }
- if c.expectError == nil && err != nil {
- t.Fatalf("test %d: didn't expect error, got %v", i, err)
- }
- if got != c.expect {
- t.Fatalf("test %d: gas estimation mismatch, want %d, got %d", i, c.expect, got)
- }
- }
-}
-
-func TestHeaderByHash(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- header, err := sim.HeaderByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
- headerByHash, err := sim.HeaderByHash(bgCtx, header.Hash())
- if err != nil {
- t.Errorf("could not get recent block: %v", err)
- }
-
- if header.Hash() != headerByHash.Hash() {
- t.Errorf("did not get expected block")
- }
-}
-
-func TestHeaderByNumber(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- latestBlockHeader, err := sim.HeaderByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get header for tip of chain: %v", err)
- }
- if latestBlockHeader == nil {
- t.Errorf("received a nil block header")
- } else if latestBlockHeader.Number.Uint64() != uint64(0) {
- t.Errorf("expected block header number 0, instead got %v", latestBlockHeader.Number.Uint64())
- }
-
- sim.Commit()
-
- latestBlockHeader, err = sim.HeaderByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get header for blockheight of 1: %v", err)
- }
-
- blockHeader, err := sim.HeaderByNumber(bgCtx, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get header for blockheight of 1: %v", err)
- }
-
- if blockHeader.Hash() != latestBlockHeader.Hash() {
- t.Errorf("block header and latest block header are not the same")
- }
- if blockHeader.Number.Int64() != int64(1) {
- t.Errorf("did not get blockheader for block 1. instead got block %v", blockHeader.Number.Int64())
- }
-
- block, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
- if err != nil {
- t.Errorf("could not get block for blockheight of 1: %v", err)
- }
-
- if block.Hash() != blockHeader.Hash() {
- t.Errorf("block hash and block header hash do not match. expected %v, got %v", block.Hash(), blockHeader.Hash())
- }
-}
-
-func TestTransactionCount(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
- currentBlock, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil || currentBlock == nil {
- t.Error("could not get current block")
- }
-
- count, err := sim.TransactionCount(bgCtx, currentBlock.Hash())
- if err != nil {
- t.Error("could not get current block's transaction count")
- }
-
- if count != 0 {
- t.Errorf("expected transaction count of %v does not match actual count of %v", 0, count)
- }
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- sim.Commit()
-
- lastBlock, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get header for tip of chain: %v", err)
- }
-
- count, err = sim.TransactionCount(bgCtx, lastBlock.Hash())
- if err != nil {
- t.Error("could not get current block's transaction count")
- }
-
- if count != 1 {
- t.Errorf("expected transaction count of %v does not match actual count of %v", 1, count)
- }
-}
-
-func TestTransactionInBlock(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- transaction, err := sim.TransactionInBlock(bgCtx, sim.pendingBlock.Hash(), uint(0))
- if err == nil && err != errTransactionDoesNotExist {
- t.Errorf("expected a transaction does not exist error to be received but received %v", err)
- }
- if transaction != nil {
- t.Errorf("expected transaction to be nil but received %v", transaction)
- }
-
- // expect pending nonce to be 0 since account has not been used
- pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr)
- if err != nil {
- t.Errorf("did not get the pending nonce: %v", err)
- }
-
- if pendingNonce != uint64(0) {
- t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
- }
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- sim.Commit()
-
- lastBlock, err := sim.BlockByNumber(bgCtx, nil)
- if err != nil {
- t.Errorf("could not get header for tip of chain: %v", err)
- }
-
- transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(1))
- if err == nil && err != errTransactionDoesNotExist {
- t.Errorf("expected a transaction does not exist error to be received but received %v", err)
- }
- if transaction != nil {
- t.Errorf("expected transaction to be nil but received %v", transaction)
- }
-
- transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(0))
- if err != nil {
- t.Errorf("could not get transaction in the lastest block with hash %v: %v", lastBlock.Hash().String(), err)
- }
-
- if signedTx.Hash().String() != transaction.Hash().String() {
- t.Errorf("received transaction that did not match the sent transaction. expected hash %v, got hash %v", signedTx.Hash().String(), transaction.Hash().String())
- }
-}
-
-func TestPendingNonceAt(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- // expect pending nonce to be 0 since account has not been used
- pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr)
- if err != nil {
- t.Errorf("did not get the pending nonce: %v", err)
- }
-
- if pendingNonce != uint64(0) {
- t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
- }
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
-
- // expect pending nonce to be 1 since account has submitted one transaction
- pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr)
- if err != nil {
- t.Errorf("did not get the pending nonce: %v", err)
- }
-
- if pendingNonce != uint64(1) {
- t.Errorf("expected pending nonce of 1 got %v", pendingNonce)
- }
-
- // make a new transaction with a nonce of 1
- tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err = types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not send tx: %v", err)
- }
-
- // expect pending nonce to be 2 since account now has two transactions
- pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr)
- if err != nil {
- t.Errorf("did not get the pending nonce: %v", err)
- }
-
- if pendingNonce != uint64(2) {
- t.Errorf("expected pending nonce of 2 got %v", pendingNonce)
- }
-}
-
-func TestTransactionReceipt(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
-
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- // create a signed transaction to send
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err != nil {
- t.Errorf("could not sign tx: %v", err)
- }
-
- // send tx to simulated backend
- err = sim.SendTransaction(bgCtx, signedTx)
- if err != nil {
- t.Errorf("could not add tx to pending block: %v", err)
- }
- sim.Commit()
-
- receipt, err := sim.TransactionReceipt(bgCtx, signedTx.Hash())
- if err != nil {
- t.Errorf("could not get transaction receipt: %v", err)
- }
-
- if receipt.ContractAddress != testAddr && receipt.TxHash != signedTx.Hash() {
- t.Errorf("received receipt is not correct: %v", receipt)
- }
-}
-
-func TestSuggestGasPrice(t *testing.T) {
- sim := NewSimulatedBackend(
- core.GenesisAlloc{},
- 10000000,
- )
- defer sim.Close()
- bgCtx := context.Background()
- gasPrice, err := sim.SuggestGasPrice(bgCtx)
- if err != nil {
- t.Errorf("could not get gas price: %v", err)
- }
- if gasPrice.Uint64() != sim.pendingBlock.Header().BaseFee.Uint64() {
- t.Errorf("gas price was not expected value of %v. actual: %v", sim.pendingBlock.Header().BaseFee.Uint64(), gasPrice.Uint64())
- }
-}
-
-func TestPendingCodeAt(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
- code, err := sim.CodeAt(bgCtx, testAddr, nil)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- if len(code) != 0 {
- t.Errorf("got code for account that does not have contract code")
- }
-
- parsed, err := abi.JSON(strings.NewReader(abiJSON))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
- contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
- }
-
- code, err = sim.PendingCodeAt(bgCtx, contractAddr)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- if len(code) == 0 {
- t.Errorf("did not get code for account that has contract code")
- }
- // ensure code received equals code deployed
- if !bytes.Equal(code, common.FromHex(deployedCode)) {
- t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
- }
-}
-
-func TestCodeAt(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
- code, err := sim.CodeAt(bgCtx, testAddr, nil)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- if len(code) != 0 {
- t.Errorf("got code for account that does not have contract code")
- }
-
- parsed, err := abi.JSON(strings.NewReader(abiJSON))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
- contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
- }
-
- sim.Commit()
- code, err = sim.CodeAt(bgCtx, contractAddr, nil)
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- if len(code) == 0 {
- t.Errorf("did not get code for account that has contract code")
- }
- // ensure code received equals code deployed
- if !bytes.Equal(code, common.FromHex(deployedCode)) {
- t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
- }
-}
-
-// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
-//
-// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
-func TestPendingAndCallContract(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- parsed, err := abi.JSON(strings.NewReader(abiJSON))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- contractAuth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
- addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(abiBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v", err)
- }
-
- input, err := parsed.Pack("receive", []byte("X"))
- if err != nil {
- t.Errorf("could not pack receive function on contract: %v", err)
- }
-
- // make sure you can call the contract in pending state
- res, err := sim.PendingCallContract(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- })
- if err != nil {
- t.Errorf("could not call receive method on contract: %v", err)
- }
- if len(res) == 0 {
- t.Errorf("result of contract call was empty: %v", res)
- }
-
- // while comparing against the byte array is more exact, also compare against the human readable string for readability
- if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
- t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
- }
-
- sim.Commit()
-
- // make sure you can call the contract
- res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- }, nil)
- if err != nil {
- t.Errorf("could not call receive method on contract: %v", err)
- }
- if len(res) == 0 {
- t.Errorf("result of contract call was empty: %v", res)
- }
-
- if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
- t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
- }
-}
-
-// This test is based on the following contract:
-/*
-contract Reverter {
- function revertString() public pure{
- require(false, "some error");
- }
- function revertNoString() public pure {
- require(false, "");
- }
- function revertASM() public pure {
- assembly {
- revert(0x0, 0x0)
- }
- }
- function noRevert() public pure {
- assembly {
- // Assembles something that looks like require(false, "some error") but is not reverted
- mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
- mstore(0x4, 0x0000000000000000000000000000000000000000000000000000000000000020)
- mstore(0x24, 0x000000000000000000000000000000000000000000000000000000000000000a)
- mstore(0x44, 0x736f6d65206572726f7200000000000000000000000000000000000000000000)
- return(0x0, 0x64)
- }
- }
-}*/
-func TestCallContractRevert(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- bgCtx := context.Background()
-
- reverterABI := `[{"inputs": [],"name": "noRevert","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertASM","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertNoString","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertString","outputs": [],"stateMutability": "pure","type": "function"}]`
- reverterBin := "608060405234801561001057600080fd5b506101d3806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634b409e01146100515780639b340e361461005b5780639bd6103714610065578063b7246fc11461006f575b600080fd5b610059610079565b005b6100636100ca565b005b61006d6100cf565b005b610077610145565b005b60006100c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526000815260200160200191505060405180910390fd5b565b600080fd5b6000610143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f736f6d65206572726f720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b7f08c379a0000000000000000000000000000000000000000000000000000000006000526020600452600a6024527f736f6d65206572726f720000000000000000000000000000000000000000000060445260646000f3fea2646970667358221220cdd8af0609ec4996b7360c7c780bad5c735740c64b1fffc3445aa12d37f07cb164736f6c63430006070033"
-
- parsed, err := abi.JSON(strings.NewReader(reverterABI))
- if err != nil {
- t.Errorf("could not get code at test addr: %v", err)
- }
- contractAuth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
- addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(reverterBin), sim)
- if err != nil {
- t.Errorf("could not deploy contract: %v", err)
- }
-
- inputs := make(map[string]interface{}, 3)
- inputs["revertASM"] = nil
- inputs["revertNoString"] = ""
- inputs["revertString"] = "some error"
-
- call := make([]func([]byte) ([]byte, error), 2)
- call[0] = func(input []byte) ([]byte, error) {
- return sim.PendingCallContract(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- })
- }
- call[1] = func(input []byte) ([]byte, error) {
- return sim.CallContract(bgCtx, ethereum.CallMsg{
- From: testAddr,
- To: &addr,
- Data: input,
- }, nil)
- }
-
- // Run pending calls then commit
- for _, cl := range call {
- for key, val := range inputs {
- input, err := parsed.Pack(key)
- if err != nil {
- t.Errorf("could not pack %v function on contract: %v", key, err)
- }
-
- res, err := cl(input)
- if err == nil {
- t.Errorf("call to %v was not reverted", key)
- }
- if res != nil {
- t.Errorf("result from %v was not nil: %v", key, res)
- }
- if val != nil {
- rerr, ok := err.(*revertError)
- if !ok {
- t.Errorf("expect revert error")
- }
- if rerr.Error() != "execution reverted: "+val.(string) {
- t.Errorf("error was malformed: got %v want %v", rerr.Error(), val)
- }
- } else {
- // revert(0x0,0x0)
- if err.Error() != "execution reverted" {
- t.Errorf("error was malformed: got %v want %v", err, "execution reverted")
- }
- }
- }
- input, err := parsed.Pack("noRevert")
- if err != nil {
- t.Errorf("could not pack noRevert function on contract: %v", err)
- }
- res, err := cl(input)
- if err != nil {
- t.Error("call to noRevert was reverted")
- }
- if res == nil {
- t.Errorf("result from noRevert was nil")
- }
- sim.Commit()
- }
-}
-
-// TestFork check that the chain length after a reorg is correct.
-// Steps:
-// 1. Save the current block which will serve as parent for the fork.
-// 2. Mine n blocks with n ∈ [0, 20].
-// 3. Assert that the chain length is n.
-// 4. Fork by using the parent block as ancestor.
-// 5. Mine n+1 blocks which should trigger a reorg.
-// 6. Assert that the chain length is n+1.
-// Since Commit() was called 2n+1 times in total,
-// having a chain length of just n+1 means that a reorg occurred.
-func TestFork(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- // 1.
- parent := sim.blockchain.CurrentBlock()
- // 2.
- n := int(rand.Int31n(21))
- for i := 0; i < n; i++ {
- sim.Commit()
- }
- // 3.
- if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n) {
- t.Error("wrong chain length")
- }
- // 4.
- sim.Fork(context.Background(), parent.Hash())
- // 5.
- for i := 0; i < n+1; i++ {
- sim.Commit()
- }
- // 6.
- if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n+1) {
- t.Error("wrong chain length")
- }
-}
-
-/*
-Example contract to test event emission:
-
- pragma solidity >=0.7.0 <0.9.0;
- contract Callable {
- event Called();
- function Call() public { emit Called(); }
- }
-*/
-const callableAbi = "[{\"anonymous\":false,\"inputs\":[],\"name\":\"Called\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"Call\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
-
-const callableBin = "6080604052348015600f57600080fd5b5060998061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806334e2292114602d575b600080fd5b60336035565b005b7f81fab7a4a0aa961db47eefc81f143a5220e8c8495260dd65b1356f1d19d3c7b860405160405180910390a156fea2646970667358221220029436d24f3ac598ceca41d4d712e13ced6d70727f4cdc580667de66d2f51d8b64736f6c63430008010033"
-
-// TestForkLogsReborn check that the simulated reorgs
-// correctly remove and reborn logs.
-// Steps:
-// 1. Deploy the Callable contract.
-// 2. Set up an event subscription.
-// 3. Save the current block which will serve as parent for the fork.
-// 4. Send a transaction.
-// 5. Check that the event was included.
-// 6. Fork by using the parent block as ancestor.
-// 7. Mine two blocks to trigger a reorg.
-// 8. Check that the event was removed.
-// 9. Re-send the transaction and mine a block.
-// 10. Check that the event was reborn.
-func TestForkLogsReborn(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- // 1.
- parsed, _ := abi.JSON(strings.NewReader(callableAbi))
- auth, _ := bind.NewKeyedTransactorWithChainID(testKey, big.NewInt(1337))
- _, _, contract, err := bind.DeployContract(auth, parsed, common.FromHex(callableBin), sim)
- if err != nil {
- t.Errorf("deploying contract: %v", err)
- }
- sim.Commit()
- // 2.
- logs, sub, err := contract.WatchLogs(nil, "Called")
- if err != nil {
- t.Errorf("watching logs: %v", err)
- }
- defer sub.Unsubscribe()
- // 3.
- parent := sim.blockchain.CurrentBlock()
- // 4.
- tx, err := contract.Transact(auth, "Call")
- if err != nil {
- t.Errorf("transacting: %v", err)
- }
- sim.Commit()
- // 5.
- log := <-logs
- if log.TxHash != tx.Hash() {
- t.Error("wrong event tx hash")
- }
- if log.Removed {
- t.Error("Event should be included")
- }
- // 6.
- if err := sim.Fork(context.Background(), parent.Hash()); err != nil {
- t.Errorf("forking: %v", err)
- }
- // 7.
- sim.Commit()
- sim.Commit()
- // 8.
- log = <-logs
- if log.TxHash != tx.Hash() {
- t.Error("wrong event tx hash")
- }
- if !log.Removed {
- t.Error("Event should be removed")
- }
- // 9.
- if err := sim.SendTransaction(context.Background(), tx); err != nil {
- t.Errorf("sending transaction: %v", err)
- }
- sim.Commit()
- // 10.
- log = <-logs
- if log.TxHash != tx.Hash() {
- t.Error("wrong event tx hash")
- }
- if log.Removed {
- t.Error("Event should be included")
- }
-}
-
-// TestForkResendTx checks that re-sending a TX after a fork
-// is possible and does not cause a "nonce mismatch" panic.
-// Steps:
-// 1. Save the current block which will serve as parent for the fork.
-// 2. Send a transaction.
-// 3. Check that the TX is included in block 1.
-// 4. Fork by using the parent block as ancestor.
-// 5. Mine a block, Re-send the transaction and mine another one.
-// 6. Check that the TX is now included in block 2.
-func TestForkResendTx(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
- // 1.
- parent := sim.blockchain.CurrentBlock()
- // 2.
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
- sim.SendTransaction(context.Background(), tx)
- sim.Commit()
- // 3.
- receipt, _ := sim.TransactionReceipt(context.Background(), tx.Hash())
- if h := receipt.BlockNumber.Uint64(); h != 1 {
- t.Errorf("TX included in wrong block: %d", h)
- }
- // 4.
- if err := sim.Fork(context.Background(), parent.Hash()); err != nil {
- t.Errorf("forking: %v", err)
- }
- // 5.
- sim.Commit()
- if err := sim.SendTransaction(context.Background(), tx); err != nil {
- t.Errorf("sending transaction: %v", err)
- }
- sim.Commit()
- // 6.
- receipt, _ = sim.TransactionReceipt(context.Background(), tx.Hash())
- if h := receipt.BlockNumber.Uint64(); h != 2 {
- t.Errorf("TX included in wrong block: %d", h)
- }
-}
-
-func TestCommitReturnValue(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- startBlockHeight := sim.blockchain.CurrentBlock().Number.Uint64()
-
- // Test if Commit returns the correct block hash
- h1 := sim.Commit()
- if h1 != sim.blockchain.CurrentBlock().Hash() {
- t.Error("Commit did not return the hash of the last block.")
- }
-
- // Create a block in the original chain (containing a transaction to force different block hashes)
- head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
- _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
- tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
- sim.SendTransaction(context.Background(), tx)
- h2 := sim.Commit()
-
- // Create another block in the original chain
- sim.Commit()
-
- // Fork at the first bock
- if err := sim.Fork(context.Background(), h1); err != nil {
- t.Errorf("forking: %v", err)
- }
-
- // Test if Commit returns the correct block hash after the reorg
- h2fork := sim.Commit()
- if h2 == h2fork {
- t.Error("The block in the fork and the original block are the same block!")
- }
- if sim.blockchain.GetHeader(h2fork, startBlockHeight+2) == nil {
- t.Error("Could not retrieve the just created block (side-chain)")
- }
-}
-
-// TestAdjustTimeAfterFork ensures that after a fork, AdjustTime uses the pending fork
-// block's parent rather than the canonical head's parent.
-func TestAdjustTimeAfterFork(t *testing.T) {
- testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
- sim := simTestBackend(testAddr)
- defer sim.Close()
-
- sim.Commit() // h1
- h1 := sim.blockchain.CurrentHeader().Hash()
- sim.Commit() // h2
- sim.Fork(context.Background(), h1)
- sim.AdjustTime(1 * time.Second)
- sim.Commit()
-
- head := sim.blockchain.CurrentHeader()
- if head.Number == common.Big2 && head.ParentHash != h1 {
- t.Errorf("failed to build block on fork")
- }
-}
diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go
index b03f431f77..96d284cdcc 100644
--- a/accounts/abi/bind/base.go
+++ b/accounts/abi/bind/base.go
@@ -48,6 +48,7 @@ type CallOpts struct {
Pending bool // Whether to operate on the pending state or the last known one
From common.Address // Optional the sender address, otherwise the first account is used
BlockNumber *big.Int // Optional the block number on which the call should be performed
+ BlockHash common.Hash // Optional the block hash on which the call should be performed
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}
@@ -189,6 +190,23 @@ func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method stri
return ErrNoCode
}
}
+ } else if opts.BlockHash != (common.Hash{}) {
+ bh, ok := c.caller.(BlockHashContractCaller)
+ if !ok {
+ return ErrNoBlockHashState
+ }
+ output, err = bh.CallContractAtHash(ctx, msg, opts.BlockHash)
+ if err != nil {
+ return err
+ }
+ if len(output) == 0 {
+ // Make sure we have a contract to operate on, and bail out otherwise.
+ if code, err = bh.CodeAtHash(ctx, c.address, opts.BlockHash); err != nil {
+ return err
+ } else if len(code) == 0 {
+ return ErrNoCode
+ }
+ }
} else {
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
if err != nil {
@@ -220,7 +238,7 @@ func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...in
if err != nil {
return nil, err
}
- // todo(rjl493456442) check the method is payable or not,
+ // todo(rjl493456442) check whether the method is payable or not,
// reject invalid transaction at the first place
return c.transact(opts, &c.address, input)
}
@@ -228,7 +246,7 @@ func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...in
// RawTransact initiates a transaction with the given raw calldata as the input.
// It's usually used to initiate transactions for invoking **Fallback** function.
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
- // todo(rjl493456442) check the method is payable or not,
+ // todo(rjl493456442) check whether the method is payable or not,
// reject invalid transaction at the first place
return c.transact(opts, &c.address, calldata)
}
diff --git a/accounts/abi/bind/base_test.go b/accounts/abi/bind/base_test.go
index 5dfa18e2e7..99621767ff 100644
--- a/accounts/abi/bind/base_test.go
+++ b/accounts/abi/bind/base_test.go
@@ -119,7 +119,28 @@ func (mc *mockPendingCaller) PendingCallContract(ctx context.Context, call ether
return mc.pendingCallContractBytes, mc.pendingCallContractErr
}
+type mockBlockHashCaller struct {
+ *mockCaller
+ codeAtHashBytes []byte
+ codeAtHashErr error
+ codeAtHashCalled bool
+ callContractAtHashCalled bool
+ callContractAtHashBytes []byte
+ callContractAtHashErr error
+}
+
+func (mc *mockBlockHashCaller) CodeAtHash(ctx context.Context, contract common.Address, hash common.Hash) ([]byte, error) {
+ mc.codeAtHashCalled = true
+ return mc.codeAtHashBytes, mc.codeAtHashErr
+}
+
+func (mc *mockBlockHashCaller) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, hash common.Hash) ([]byte, error) {
+ mc.callContractAtHashCalled = true
+ return mc.callContractAtHashBytes, mc.callContractAtHashErr
+}
+
func TestPassingBlockNumber(t *testing.T) {
+ t.Parallel()
mc := &mockPendingCaller{
mockCaller: &mockCaller{
codeAtBytes: []byte{1, 2, 3},
@@ -171,6 +192,7 @@ func TestPassingBlockNumber(t *testing.T) {
const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158"
func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) {
+ t.Parallel()
hash := crypto.Keccak256Hash([]byte("testName"))
topics := []common.Hash{
crypto.Keccak256Hash([]byte("received(string,address,uint256,bytes)")),
@@ -192,6 +214,7 @@ func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) {
}
func TestUnpackAnonymousLogIntoMap(t *testing.T) {
+ t.Parallel()
mockLog := newMockLog(nil, common.HexToHash("0x0"))
abiString := `[{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"received","type":"event"}]`
@@ -209,6 +232,7 @@ func TestUnpackAnonymousLogIntoMap(t *testing.T) {
}
func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) {
+ t.Parallel()
sliceBytes, err := rlp.EncodeToBytes([]string{"name1", "name2", "name3", "name4"})
if err != nil {
t.Fatal(err)
@@ -234,6 +258,7 @@ func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) {
}
func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) {
+ t.Parallel()
arrBytes, err := rlp.EncodeToBytes([2]common.Address{common.HexToAddress("0x0"), common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")})
if err != nil {
t.Fatal(err)
@@ -259,6 +284,7 @@ func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) {
}
func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) {
+ t.Parallel()
mockAddress := common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")
addrBytes := mockAddress.Bytes()
hash := crypto.Keccak256Hash([]byte("mockFunction(address,uint)"))
@@ -285,6 +311,7 @@ func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) {
}
func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) {
+ t.Parallel()
bytes := []byte{1, 2, 3, 4, 5}
hash := crypto.Keccak256Hash(bytes)
topics := []common.Hash{
@@ -307,6 +334,7 @@ func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) {
}
func TestTransactGasFee(t *testing.T) {
+ t.Parallel()
assert := assert.New(t)
// GasTipCap and GasFeeCap
@@ -382,6 +410,7 @@ func newMockLog(topics []common.Hash, txHash common.Hash) types.Log {
}
func TestCall(t *testing.T) {
+ t.Parallel()
var method, methodWithArg = "something", "somethingArrrrg"
tests := []struct {
name, method string
@@ -405,6 +434,15 @@ func TestCall(t *testing.T) {
Pending: true,
},
method: method,
+ }, {
+ name: "ok hash",
+ mc: &mockBlockHashCaller{
+ codeAtHashBytes: []byte{0},
+ },
+ opts: &bind.CallOpts{
+ BlockHash: common.Hash{0xaa},
+ },
+ method: method,
}, {
name: "pack error, no method",
mc: new(mockCaller),
@@ -418,6 +456,14 @@ func TestCall(t *testing.T) {
},
method: method,
wantErrExact: bind.ErrNoPendingState,
+ }, {
+ name: "interface error, blockHash but not a BlockHashContractCaller",
+ mc: new(mockCaller),
+ opts: &bind.CallOpts{
+ BlockHash: common.Hash{0xaa},
+ },
+ method: method,
+ wantErrExact: bind.ErrNoBlockHashState,
}, {
name: "pending call canceled",
mc: &mockPendingCaller{
@@ -465,6 +511,34 @@ func TestCall(t *testing.T) {
mc: new(mockCaller),
method: method,
wantErrExact: bind.ErrNoCode,
+ }, {
+ name: "call contract at hash error",
+ mc: &mockBlockHashCaller{
+ callContractAtHashErr: context.DeadlineExceeded,
+ },
+ opts: &bind.CallOpts{
+ BlockHash: common.Hash{0xaa},
+ },
+ method: method,
+ wantErrExact: context.DeadlineExceeded,
+ }, {
+ name: "code at error",
+ mc: &mockBlockHashCaller{
+ codeAtHashErr: errors.New(""),
+ },
+ opts: &bind.CallOpts{
+ BlockHash: common.Hash{0xaa},
+ },
+ method: method,
+ wantErr: true,
+ }, {
+ name: "no code at hash",
+ mc: new(mockBlockHashCaller),
+ opts: &bind.CallOpts{
+ BlockHash: common.Hash{0xaa},
+ },
+ method: method,
+ wantErrExact: bind.ErrNoCode,
}, {
name: "unpack error missing arg",
mc: &mockCaller{
@@ -512,6 +586,7 @@ func TestCall(t *testing.T) {
// TestCrashers contains some strings which previously caused the abi codec to crash.
func TestCrashers(t *testing.T) {
+ t.Parallel()
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"_1"}]}]}]`))
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"&"}]}]}]`))
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"----"}]}]}]`))
diff --git a/accounts/abi/bind/bind.go b/accounts/abi/bind/bind.go
index 8a54a0e6ef..e902345f09 100644
--- a/accounts/abi/bind/bind.go
+++ b/accounts/abi/bind/bind.go
@@ -79,7 +79,7 @@ func isKeyWord(arg string) bool {
// Bind generates a Go wrapper around a contract ABI. This wrapper isn't meant
// to be used as is in client code, but rather as an intermediate struct which
-// enforces compile time type safety and naming convention opposed to having to
+// enforces compile time type safety and naming convention as opposed to having to
// manually maintain hard coded strings that break on runtime.
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string, aliases map[string]string) (string, error) {
var (
@@ -363,7 +363,7 @@ func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
// parameters that are not value types i.e. arrays and structs are not
// stored directly but instead a keccak256-hash of an encoding is stored.
//
- // We only convert stringS and bytes to hash, still need to deal with
+ // We only convert strings and bytes to hash, still need to deal with
// array(both fixed-size and dynamic-size) and struct.
if bound == "string" || bound == "[]byte" {
bound = "common.Hash"
diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go
index 50dda67f5e..11bfd0378d 100644
--- a/accounts/abi/bind/bind_test.go
+++ b/accounts/abi/bind/bind_test.go
@@ -305,6 +305,7 @@ var bindTests = []struct {
if err != nil {
t.Fatalf("Failed to deploy interactor contract: %v", err)
}
+ sim.Commit()
if _, err := interactor.Transact(auth, "Transact string"); err != nil {
t.Fatalf("Failed to transact with interactor contract: %v", err)
}
@@ -512,6 +513,7 @@ var bindTests = []struct {
if err != nil {
t.Fatalf("Failed to deploy defaulter contract: %v", err)
}
+ sim.Commit()
if _, err := (&DefaulterRaw{defaulter}).Transfer(auth); err != nil {
t.Fatalf("Failed to invoke default method: %v", err)
}
@@ -1677,7 +1679,7 @@ var bindTests = []struct {
}
sim.Commit()
- // This test the existence of the free retreiver call for view and pure functions
+ // This test the existence of the free retriever call for view and pure functions
if num, err := pav.PureFunc(nil); err != nil {
t.Fatalf("Failed to call anonymous field retriever: %v", err)
} else if num.Cmp(big.NewInt(42)) != 0 {
@@ -1874,6 +1876,7 @@ var bindTests = []struct {
[]string{"0x6080604052348015600f57600080fd5b5060998061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063726c638214602d575b600080fd5b60336035565b005b60405163024876cd60e61b815260016004820152600260248201526003604482015260640160405180910390fdfea264697066735822122093f786a1bc60216540cd999fbb4a6109e0fef20abcff6e9107fb2817ca968f3c64736f6c63430008070033"},
[]string{`[{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError1","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError2","type":"error"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"uint256","name":"c","type":"uint256"}],"name":"MyError3","type":"error"},{"inputs":[],"name":"Error","outputs":[],"stateMutability":"pure","type":"function"}]`},
`
+ "context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -1895,7 +1898,7 @@ var bindTests = []struct {
t.Fatal(err)
}
sim.Commit()
- _, err = bind.WaitDeployed(nil, sim, tx)
+ _, err = bind.WaitDeployed(context.Background(), sim, tx)
if err != nil {
t.Error(err)
}
@@ -1926,6 +1929,7 @@ var bindTests = []struct {
bytecode: []string{`0x608060405234801561001057600080fd5b506040516101c43803806101c48339818101604052810190610032919061014a565b50610177565b6000604051905090565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100958261004c565b810181811067ffffffffffffffff821117156100b4576100b361005d565b5b80604052505050565b60006100c7610038565b90506100d3828261008c565b919050565b6000819050919050565b6100eb816100d8565b81146100f657600080fd5b50565b600081519050610108816100e2565b92915050565b60006020828403121561012457610123610047565b5b61012e60206100bd565b9050600061013e848285016100f9565b60008301525092915050565b6000602082840312156101605761015f610042565b5b600061016e8482850161010e565b91505092915050565b603f806101856000396000f3fe6080604052600080fdfea2646970667358221220cdffa667affecefac5561f65f4a4ba914204a8d4eb859d8cd426fb306e5c12a364736f6c634300080a0033`},
abi: []string{`[{"inputs":[{"components":[{"internalType":"uint256","name":"field","type":"uint256"}],"internalType":"struct ConstructorWithStructParam.StructType","name":"st","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"}]`},
imports: `
+ "context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -1948,7 +1952,7 @@ var bindTests = []struct {
}
sim.Commit()
- if _, err = bind.WaitDeployed(nil, sim, tx); err != nil {
+ if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
t.Logf("Deployment tx: %+v", tx)
t.Errorf("bind.WaitDeployed(nil, %T, ) got err %v; want nil err", sim, err)
}
@@ -1974,6 +1978,7 @@ var bindTests = []struct {
bytecode: []string{"0x608060405234801561001057600080fd5b5061042b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063c2bb515f1461003b578063cce7b04814610059575b600080fd5b610043610075565b60405161005091906101af565b60405180910390f35b610073600480360381019061006e91906103ac565b6100b5565b005b61007d6100b8565b604051806040016040528060405180602001604052806000815250815260200160405180602001604052806000815250815250905090565b50565b604051806040016040528060608152602001606081525090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561010c5780820151818401526020810190506100f1565b8381111561011b576000848401525b50505050565b6000601f19601f8301169050919050565b600061013d826100d2565b61014781856100dd565b93506101578185602086016100ee565b61016081610121565b840191505092915050565b600060408301600083015184820360008601526101888282610132565b915050602083015184820360208601526101a28282610132565b9150508091505092915050565b600060208201905081810360008301526101c9818461016b565b905092915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61022282610121565b810181811067ffffffffffffffff82111715610241576102406101ea565b5b80604052505050565b60006102546101d1565b90506102608282610219565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff82111561028f5761028e6101ea565b5b61029882610121565b9050602081019050919050565b82818337600083830152505050565b60006102c76102c284610274565b61024a565b9050828152602081018484840111156102e3576102e261026f565b5b6102ee8482856102a5565b509392505050565b600082601f83011261030b5761030a61026a565b5b813561031b8482602086016102b4565b91505092915050565b60006040828403121561033a576103396101e5565b5b610344604061024a565b9050600082013567ffffffffffffffff81111561036457610363610265565b5b610370848285016102f6565b600083015250602082013567ffffffffffffffff81111561039457610393610265565b5b6103a0848285016102f6565b60208301525092915050565b6000602082840312156103c2576103c16101db565b5b600082013567ffffffffffffffff8111156103e0576103df6101e0565b5b6103ec84828501610324565b9150509291505056fea264697066735822122033bca1606af9b6aeba1673f98c52003cec19338539fb44b86690ce82c51483b564736f6c634300080e0033"},
abi: []string{`[ { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "int256", "name": "msg", "type": "int256" }, { "indexed": false, "internalType": "int256", "name": "_msg", "type": "int256" } ], "name": "log", "type": "event" }, { "inputs": [ { "components": [ { "internalType": "bytes", "name": "data", "type": "bytes" }, { "internalType": "bytes", "name": "_data", "type": "bytes" } ], "internalType": "struct oracle.request", "name": "req", "type": "tuple" } ], "name": "addRequest", "outputs": [], "stateMutability": "pure", "type": "function" }, { "inputs": [], "name": "getRequest", "outputs": [ { "components": [ { "internalType": "bytes", "name": "data", "type": "bytes" }, { "internalType": "bytes", "name": "_data", "type": "bytes" } ], "internalType": "struct oracle.request", "name": "", "type": "tuple" } ], "stateMutability": "pure", "type": "function" } ]`},
imports: `
+ "context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -1996,7 +2001,7 @@ var bindTests = []struct {
}
sim.Commit()
- if _, err = bind.WaitDeployed(nil, sim, tx); err != nil {
+ if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
t.Logf("Deployment tx: %+v", tx)
t.Errorf("bind.WaitDeployed(nil, %T, ) got err %v; want nil err", sim, err)
}
@@ -2014,6 +2019,7 @@ var bindTests = []struct {
bytecode: []string{"0x608060405234801561001057600080fd5b5060dc8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063527a119f14602d575b600080fd5b60436004803603810190603f9190605b565b6045565b005b50565b6000813590506055816092565b92915050565b600060208284031215606e57606d608d565b5b6000607a848285016048565b91505092915050565b6000819050919050565b600080fd5b6099816083565b811460a357600080fd5b5056fea2646970667358221220d4f4525e2615516394055d369fb17df41c359e5e962734f27fd683ea81fd9db164736f6c63430008070033"},
abi: []string{`[{"inputs":[{"internalType":"uint256","name":"range","type":"uint256"}],"name":"functionWithKeywordParameter","outputs":[],"stateMutability":"pure","type":"function"}]`},
imports: `
+ "context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -2034,7 +2040,7 @@ var bindTests = []struct {
}
sim.Commit()
- if _, err = bind.WaitDeployed(nil, sim, tx); err != nil {
+ if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
t.Errorf("error deploying the contract: %v", err)
}
`,
@@ -2067,6 +2073,7 @@ var bindTests = []struct {
// Tests that packages generated by the binder can be successfully compiled and
// the requested tester run against it.
func TestGolangBindings(t *testing.T) {
+ t.Parallel()
// Skip the test if no Go command can be found
gocmd := runtime.GOROOT() + "/bin/go"
if !common.FileExist(gocmd) {
@@ -2127,7 +2134,7 @@ func TestGolangBindings(t *testing.T) {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
}
- replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/tendermint@v0.0.0", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/tendermint@v0.31.15") // Repo root
+ replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/tendermint@v0.0.0", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/tendermint@v0.31.16") // Repo root
replacer.Dir = pkg
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace tendermint dependency to bnb-chain source: %v\n%s", err, out)
diff --git a/accounts/abi/bind/util_test.go b/accounts/abi/bind/util_test.go
index 75fbc91ceb..9fd919a295 100644
--- a/accounts/abi/bind/util_test.go
+++ b/accounts/abi/bind/util_test.go
@@ -24,11 +24,12 @@ import (
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethclient/simulated"
+ "github.com/ethereum/go-ethereum/params"
)
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@@ -53,21 +54,21 @@ var waitDeployedTests = map[string]struct {
}
func TestWaitDeployed(t *testing.T) {
+ t.Parallel()
for name, test := range waitDeployedTests {
- backend := backends.NewSimulatedBackend(
+ backend := simulated.NewBackend(
core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
},
- 10000000,
)
defer backend.Close()
// Create the transaction
- head, _ := backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
+ head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, gasPrice, common.FromHex(test.code))
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
+ tx, _ = types.SignTx(tx, types.LatestSignerForChainID(big.NewInt(1337)), testKey)
// Wait for it to get mined in the background.
var (
@@ -77,12 +78,12 @@ func TestWaitDeployed(t *testing.T) {
ctx = context.Background()
)
go func() {
- address, err = bind.WaitDeployed(ctx, backend, tx)
+ address, err = bind.WaitDeployed(ctx, backend.Client(), tx)
close(mined)
}()
// Send and mine the transaction.
- backend.SendTransaction(ctx, tx)
+ backend.Client().SendTransaction(ctx, tx)
backend.Commit()
select {
@@ -100,41 +101,40 @@ func TestWaitDeployed(t *testing.T) {
}
func TestWaitDeployedCornerCases(t *testing.T) {
- backend := backends.NewSimulatedBackend(
+ backend := simulated.NewBackend(
core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
},
- 10000000,
)
defer backend.Close()
- head, _ := backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
+ head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
// Create a transaction to an account.
code := "6060604052600a8060106000396000f360606040526008565b00"
tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, gasPrice, common.FromHex(code))
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
+ tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- backend.SendTransaction(ctx, tx)
+ backend.Client().SendTransaction(ctx, tx)
backend.Commit()
- notContentCreation := errors.New("tx is not contract creation")
- if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != notContentCreation.Error() {
- t.Errorf("error missmatch: want %q, got %q, ", notContentCreation, err)
+ notContractCreation := errors.New("tx is not contract creation")
+ if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != notContractCreation.Error() {
+ t.Errorf("error mismatch: want %q, got %q, ", notContractCreation, err)
}
// Create a transaction that is not mined.
tx = types.NewContractCreation(1, big.NewInt(0), 3000000, gasPrice, common.FromHex(code))
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
+ tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey)
go func() {
contextCanceled := errors.New("context canceled")
- if _, err := bind.WaitDeployed(ctx, backend, tx); err.Error() != contextCanceled.Error() {
- t.Errorf("error missmatch: want %q, got %q, ", contextCanceled, err)
+ if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != contextCanceled.Error() {
+ t.Errorf("error mismatch: want %q, got %q, ", contextCanceled, err)
}
}()
- backend.SendTransaction(ctx, tx)
+ backend.Client().SendTransaction(ctx, tx)
cancel()
}
diff --git a/accounts/abi/error.go b/accounts/abi/error.go
index 218a22f1e4..8e50112ec5 100644
--- a/accounts/abi/error.go
+++ b/accounts/abi/error.go
@@ -18,7 +18,6 @@ package abi
import (
"bytes"
- "errors"
"fmt"
"strings"
@@ -84,10 +83,10 @@ func (e Error) String() string {
func (e *Error) Unpack(data []byte) (interface{}, error) {
if len(data) < 4 {
- return "", errors.New("invalid data for unpacking")
+ return "", fmt.Errorf("insufficient data for unpacking: have %d, want at least 4", len(data))
}
if !bytes.Equal(data[:4], e.ID[:4]) {
- return "", errors.New("invalid data for unpacking")
+ return "", fmt.Errorf("invalid identifier, have %#x want %#x", data[:4], e.ID[:4])
}
return e.Inputs.Unpack(data[4:])
}
diff --git a/accounts/abi/event_test.go b/accounts/abi/event_test.go
index 8f73419496..fffe28ea63 100644
--- a/accounts/abi/event_test.go
+++ b/accounts/abi/event_test.go
@@ -81,6 +81,7 @@ var pledgeData1 = "00000000000000000000000000ce0d46d924cc8437c806721496599fc3ffa
var mixedCaseData1 = "00000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000020489e8000000000000000000000000000000000000000000000000000000000000000f4241"
func TestEventId(t *testing.T) {
+ t.Parallel()
var table = []struct {
definition string
expectations map[string]common.Hash
@@ -112,6 +113,7 @@ func TestEventId(t *testing.T) {
}
func TestEventString(t *testing.T) {
+ t.Parallel()
var table = []struct {
definition string
expectations map[string]string
@@ -146,6 +148,7 @@ func TestEventString(t *testing.T) {
// TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array.
func TestEventMultiValueWithArrayUnpack(t *testing.T) {
+ t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
abi, err := JSON(strings.NewReader(definition))
require.NoError(t, err)
@@ -161,6 +164,7 @@ func TestEventMultiValueWithArrayUnpack(t *testing.T) {
}
func TestEventTupleUnpack(t *testing.T) {
+ t.Parallel()
type EventTransfer struct {
Value *big.Int
}
@@ -351,6 +355,7 @@ func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, ass
// TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder.
func TestEventUnpackIndexed(t *testing.T) {
+ t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
type testStruct struct {
Value1 uint8 // indexed
@@ -368,6 +373,7 @@ func TestEventUnpackIndexed(t *testing.T) {
// TestEventIndexedWithArrayUnpack verifies that decoder will not overflow when static array is indexed input.
func TestEventIndexedWithArrayUnpack(t *testing.T) {
+ t.Parallel()
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]`
type testStruct struct {
Value1 [2]uint8 // indexed
diff --git a/accounts/abi/method.go b/accounts/abi/method.go
index f69e3ee9b5..c5a1a71f47 100644
--- a/accounts/abi/method.go
+++ b/accounts/abi/method.go
@@ -117,24 +117,23 @@ func NewMethod(name string, rawName string, funType FunctionType, mutability str
sig = fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ","))
id = crypto.Keccak256([]byte(sig))[:4]
}
- // Extract meaningful state mutability of solidity method.
- // If it's default value, never print it.
- state := mutability
- if state == "nonpayable" {
- state = ""
- }
- if state != "" {
- state = state + " "
- }
identity := fmt.Sprintf("function %v", rawName)
- if funType == Fallback {
+ switch funType {
+ case Fallback:
identity = "fallback"
- } else if funType == Receive {
+ case Receive:
identity = "receive"
- } else if funType == Constructor {
+ case Constructor:
identity = "constructor"
}
- str := fmt.Sprintf("%v(%v) %sreturns(%v)", identity, strings.Join(inputNames, ", "), state, strings.Join(outputNames, ", "))
+ var str string
+ // Extract meaningful state mutability of solidity method.
+ // If it's empty string or default value "nonpayable", never print it.
+ if mutability == "" || mutability == "nonpayable" {
+ str = fmt.Sprintf("%v(%v) returns(%v)", identity, strings.Join(inputNames, ", "), strings.Join(outputNames, ", "))
+ } else {
+ str = fmt.Sprintf("%v(%v) %s returns(%v)", identity, strings.Join(inputNames, ", "), mutability, strings.Join(outputNames, ", "))
+ }
return Method{
Name: name,
diff --git a/accounts/abi/method_test.go b/accounts/abi/method_test.go
index 395a528965..6322173920 100644
--- a/accounts/abi/method_test.go
+++ b/accounts/abi/method_test.go
@@ -35,6 +35,7 @@ const methoddata = `
]`
func TestMethodString(t *testing.T) {
+ t.Parallel()
var table = []struct {
method string
expectation string
@@ -84,11 +85,12 @@ func TestMethodString(t *testing.T) {
for _, test := range table {
var got string
- if test.method == "fallback" {
+ switch test.method {
+ case "fallback":
got = abi.Fallback.String()
- } else if test.method == "receive" {
+ case "receive":
got = abi.Receive.String()
- } else {
+ default:
got = abi.Methods[test.method].String()
}
if got != test.expectation {
@@ -98,6 +100,7 @@ func TestMethodString(t *testing.T) {
}
func TestMethodSig(t *testing.T) {
+ t.Parallel()
var cases = []struct {
method string
expect string
diff --git a/accounts/abi/pack.go b/accounts/abi/pack.go
index 0cd91cb4fa..beef1fa37f 100644
--- a/accounts/abi/pack.go
+++ b/accounts/abi/pack.go
@@ -57,7 +57,7 @@ func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
reflectValue = mustArrayToByteSlice(reflectValue)
}
if reflectValue.Type() != reflect.TypeOf([]byte{}) {
- return []byte{}, errors.New("Bytes type is neither slice nor array")
+ return []byte{}, errors.New("bytes type is neither slice nor array")
}
return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()), nil
case FixedBytesTy, FunctionTy:
@@ -66,7 +66,7 @@ func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
}
return common.RightPadBytes(reflectValue.Bytes(), 32), nil
default:
- return []byte{}, fmt.Errorf("Could not pack element, unknown type: %v", t.T)
+ return []byte{}, fmt.Errorf("could not pack element, unknown type: %v", t.T)
}
}
diff --git a/accounts/abi/pack_test.go b/accounts/abi/pack_test.go
index 5c7cb1cc1a..00bdae469e 100644
--- a/accounts/abi/pack_test.go
+++ b/accounts/abi/pack_test.go
@@ -32,8 +32,11 @@ import (
// TestPack tests the general pack/unpack tests in packing_test.go
func TestPack(t *testing.T) {
+ t.Parallel()
for i, test := range packUnpackTests {
+ i, test := i, test
t.Run(strconv.Itoa(i), func(t *testing.T) {
+ t.Parallel()
encb, err := hex.DecodeString(test.packed)
if err != nil {
t.Fatalf("invalid hex %s: %v", test.packed, err)
@@ -57,6 +60,7 @@ func TestPack(t *testing.T) {
}
func TestMethodPack(t *testing.T) {
+ t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
@@ -177,6 +181,7 @@ func TestMethodPack(t *testing.T) {
}
func TestPackNumber(t *testing.T) {
+ t.Parallel()
tests := []struct {
value reflect.Value
packed []byte
diff --git a/accounts/abi/reflect.go b/accounts/abi/reflect.go
index 48d2ef41ec..1863e5bb7d 100644
--- a/accounts/abi/reflect.go
+++ b/accounts/abi/reflect.go
@@ -134,7 +134,7 @@ func setSlice(dst, src reflect.Value) error {
dst.Set(slice)
return nil
}
- return errors.New("Cannot set slice, destination not settable")
+ return errors.New("cannot set slice, destination not settable")
}
func setArray(dst, src reflect.Value) error {
@@ -155,7 +155,7 @@ func setArray(dst, src reflect.Value) error {
dst.Set(array)
return nil
}
- return errors.New("Cannot set array, destination not settable")
+ return errors.New("cannot set array, destination not settable")
}
func setStruct(dst, src reflect.Value) error {
@@ -163,7 +163,7 @@ func setStruct(dst, src reflect.Value) error {
srcField := src.Field(i)
dstField := dst.Field(i)
if !dstField.IsValid() || !srcField.IsValid() {
- return fmt.Errorf("Could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField)
+ return fmt.Errorf("could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField)
}
if err := set(dstField, srcField); err != nil {
return err
diff --git a/accounts/abi/reflect_test.go b/accounts/abi/reflect_test.go
index 76ef1ad2aa..6c7ae57087 100644
--- a/accounts/abi/reflect_test.go
+++ b/accounts/abi/reflect_test.go
@@ -170,8 +170,11 @@ var reflectTests = []reflectTest{
}
func TestReflectNameToStruct(t *testing.T) {
+ t.Parallel()
for _, test := range reflectTests {
+ test := test
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc))
if len(test.err) > 0 {
if err == nil || err.Error() != test.err {
@@ -192,6 +195,7 @@ func TestReflectNameToStruct(t *testing.T) {
}
func TestConvertType(t *testing.T) {
+ t.Parallel()
// Test Basic Struct
type T struct {
X *big.Int
diff --git a/accounts/abi/selector_parser_test.go b/accounts/abi/selector_parser_test.go
index f6f134492b..6cb0ae0e70 100644
--- a/accounts/abi/selector_parser_test.go
+++ b/accounts/abi/selector_parser_test.go
@@ -24,6 +24,7 @@ import (
)
func TestParseSelector(t *testing.T) {
+ t.Parallel()
mkType := func(types ...interface{}) []ArgumentMarshaling {
var result []ArgumentMarshaling
for i, typeOrComponents := range types {
diff --git a/accounts/abi/topics.go b/accounts/abi/topics.go
index 360df7d5e8..7ce9b7273c 100644
--- a/accounts/abi/topics.go
+++ b/accounts/abi/topics.go
@@ -24,6 +24,7 @@ import (
"reflect"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
)
@@ -41,8 +42,7 @@ func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) {
case common.Address:
copy(topic[common.HashLength-common.AddressLength:], rule[:])
case *big.Int:
- blob := rule.Bytes()
- copy(topic[common.HashLength-len(blob):], blob)
+ copy(topic[:], math.U256Bytes(rule))
case bool:
if rule {
topic[common.HashLength-1] = 1
@@ -75,7 +75,7 @@ func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) {
copy(topic[:], hash[:])
default:
- // todo(rjl493456442) according solidity documentation, indexed event
+ // todo(rjl493456442) according to solidity documentation, indexed event
// parameters that are not value types i.e. arrays and structs are not
// stored directly but instead a keccak256-hash of an encoding is stored.
//
diff --git a/accounts/abi/topics_test.go b/accounts/abi/topics_test.go
index 30cf21d0b8..9e1efd3821 100644
--- a/accounts/abi/topics_test.go
+++ b/accounts/abi/topics_test.go
@@ -17,6 +17,7 @@
package abi
import (
+ "math"
"math/big"
"reflect"
"testing"
@@ -26,6 +27,7 @@ import (
)
func TestMakeTopics(t *testing.T) {
+ t.Parallel()
type args struct {
query [][]interface{}
}
@@ -54,9 +56,27 @@ func TestMakeTopics(t *testing.T) {
false,
},
{
- "support *big.Int types in topics",
- args{[][]interface{}{{big.NewInt(1).Lsh(big.NewInt(2), 254)}}},
- [][]common.Hash{{common.Hash{128}}},
+ "support positive *big.Int types in topics",
+ args{[][]interface{}{
+ {big.NewInt(1)},
+ {big.NewInt(1).Lsh(big.NewInt(2), 254)},
+ }},
+ [][]common.Hash{
+ {common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001")},
+ {common.Hash{128}},
+ },
+ false,
+ },
+ {
+ "support negative *big.Int types in topics",
+ args{[][]interface{}{
+ {big.NewInt(-1)},
+ {big.NewInt(math.MinInt64)},
+ }},
+ [][]common.Hash{
+ {common.MaxHash},
+ {common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000")},
+ },
false,
},
{
@@ -117,7 +137,9 @@ func TestMakeTopics(t *testing.T) {
},
}
for _, tt := range tests {
+ tt := tt
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
got, err := MakeTopics(tt.args.query...)
if (err != nil) != tt.wantErr {
t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr)
@@ -347,10 +369,13 @@ func setupTopicsTests() []topicTest {
}
func TestParseTopics(t *testing.T) {
+ t.Parallel()
tests := setupTopicsTests()
for _, tt := range tests {
+ tt := tt
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
createObj := tt.args.createObj()
if err := ParseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr)
@@ -364,10 +389,13 @@ func TestParseTopics(t *testing.T) {
}
func TestParseTopicsIntoMap(t *testing.T) {
+ t.Parallel()
tests := setupTopicsTests()
for _, tt := range tests {
+ tt := tt
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
outMap := make(map[string]interface{})
if err := ParseTopicsIntoMap(outMap, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr {
t.Errorf("parseTopicsIntoMap() error = %v, wantErr %v", err, tt.wantErr)
diff --git a/accounts/abi/type_test.go b/accounts/abi/type_test.go
index a72531ba27..ae69872ad8 100644
--- a/accounts/abi/type_test.go
+++ b/accounts/abi/type_test.go
@@ -31,6 +31,7 @@ type typeWithoutStringer Type
// Tests that all allowed types get recognized by the type parser.
func TestTypeRegexp(t *testing.T) {
+ t.Parallel()
tests := []struct {
blob string
components []ArgumentMarshaling
@@ -117,6 +118,7 @@ func TestTypeRegexp(t *testing.T) {
}
func TestTypeCheck(t *testing.T) {
+ t.Parallel()
for i, test := range []struct {
typ string
components []ArgumentMarshaling
@@ -308,6 +310,7 @@ func TestTypeCheck(t *testing.T) {
}
func TestInternalType(t *testing.T) {
+ t.Parallel()
components := []ArgumentMarshaling{{Name: "a", Type: "int64"}}
internalType := "struct a.b[]"
kind := Type{
@@ -332,6 +335,7 @@ func TestInternalType(t *testing.T) {
}
func TestGetTypeSize(t *testing.T) {
+ t.Parallel()
var testCases = []struct {
typ string
components []ArgumentMarshaling
@@ -368,6 +372,7 @@ func TestGetTypeSize(t *testing.T) {
}
func TestNewFixedBytesOver32(t *testing.T) {
+ t.Parallel()
_, err := NewType("bytes4096", "", nil)
if err == nil {
t.Errorf("fixed bytes with size over 32 is not spec'd")
diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go
index 68451483cd..905b5ce629 100644
--- a/accounts/abi/unpack.go
+++ b/accounts/abi/unpack.go
@@ -160,13 +160,14 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
// this value will become our slice or our array, depending on the type
var refSlice reflect.Value
- if t.T == SliceTy {
+ switch t.T {
+ case SliceTy:
// declare our slice
refSlice = reflect.MakeSlice(t.GetType(), size, size)
- } else if t.T == ArrayTy {
+ case ArrayTy:
// declare our array
refSlice = reflect.New(t.GetType()).Elem()
- } else {
+ default:
return nil, errors.New("abi: invalid type in array/slice unpacking stage")
}
diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go
index 6dd2db0d58..29891ec0a4 100644
--- a/accounts/abi/unpack_test.go
+++ b/accounts/abi/unpack_test.go
@@ -33,6 +33,7 @@ import (
// TestUnpack tests the general pack/unpack tests in packing_test.go
func TestUnpack(t *testing.T) {
+ t.Parallel()
for i, test := range packUnpackTests {
t.Run(strconv.Itoa(i)+" "+test.def, func(t *testing.T) {
//Unpack
@@ -206,13 +207,13 @@ var unpackTests = []unpackTest{
def: `[{"type":"bool"}]`,
enc: "",
want: false,
- err: "abi: attempting to unmarshall an empty string while arguments are expected",
+ err: "abi: attempting to unmarshal an empty string while arguments are expected",
},
{
def: `[{"type":"bytes32","indexed":true},{"type":"uint256","indexed":false}]`,
enc: "",
want: false,
- err: "abi: attempting to unmarshall an empty string while arguments are expected",
+ err: "abi: attempting to unmarshal an empty string while arguments are expected",
},
{
def: `[{"type":"bool","indexed":true},{"type":"uint64","indexed":true}]`,
@@ -224,6 +225,7 @@ var unpackTests = []unpackTest{
// TestLocalUnpackTests runs test specially designed only for unpacking.
// All test cases that can be used to test packing and unpacking should move to packing_test.go
func TestLocalUnpackTests(t *testing.T) {
+ t.Parallel()
for i, test := range unpackTests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
//Unpack
@@ -251,6 +253,7 @@ func TestLocalUnpackTests(t *testing.T) {
}
func TestUnpackIntoInterfaceSetDynamicArrayOutput(t *testing.T) {
+ t.Parallel()
abi, err := JSON(strings.NewReader(`[{"constant":true,"inputs":[],"name":"testDynamicFixedBytes15","outputs":[{"name":"","type":"bytes15[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"testDynamicFixedBytes32","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"}]`))
if err != nil {
t.Fatal(err)
@@ -321,6 +324,7 @@ func methodMultiReturn(require *require.Assertions) (ABI, []byte, methodMultiOut
}
func TestMethodMultiReturn(t *testing.T) {
+ t.Parallel()
type reversed struct {
String string
Int *big.Int
@@ -400,6 +404,7 @@ func TestMethodMultiReturn(t *testing.T) {
}
func TestMultiReturnWithArray(t *testing.T) {
+ t.Parallel()
const definition = `[{"name" : "multi", "type": "function", "outputs": [{"type": "uint64[3]"}, {"type": "uint64"}]}]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
@@ -423,6 +428,7 @@ func TestMultiReturnWithArray(t *testing.T) {
}
func TestMultiReturnWithStringArray(t *testing.T) {
+ t.Parallel()
const definition = `[{"name" : "multi", "type": "function", "outputs": [{"name": "","type": "uint256[3]"},{"name": "","type": "address"},{"name": "","type": "string[2]"},{"name": "","type": "bool"}]}]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
@@ -453,6 +459,7 @@ func TestMultiReturnWithStringArray(t *testing.T) {
}
func TestMultiReturnWithStringSlice(t *testing.T) {
+ t.Parallel()
const definition = `[{"name" : "multi", "type": "function", "outputs": [{"name": "","type": "string[]"},{"name": "","type": "uint256[]"}]}]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
@@ -485,6 +492,7 @@ func TestMultiReturnWithStringSlice(t *testing.T) {
}
func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
+ t.Parallel()
// Similar to TestMultiReturnWithArray, but with a special case in mind:
// values of nested static arrays count towards the size as well, and any element following
// after such nested array argument should be read with the correct offset,
@@ -525,6 +533,7 @@ func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
}
func TestUnmarshal(t *testing.T) {
+ t.Parallel()
const definition = `[
{ "name" : "int", "type": "function", "outputs": [ { "type": "uint256" } ] },
{ "name" : "bool", "type": "function", "outputs": [ { "type": "bool" } ] },
@@ -774,6 +783,7 @@ func TestUnmarshal(t *testing.T) {
}
func TestUnpackTuple(t *testing.T) {
+ t.Parallel()
const simpleTuple = `[{"name":"tuple","type":"function","outputs":[{"type":"tuple","name":"ret","components":[{"type":"int256","name":"a"},{"type":"int256","name":"b"}]}]}]`
abi, err := JSON(strings.NewReader(simpleTuple))
if err != nil {
@@ -876,6 +886,7 @@ func TestUnpackTuple(t *testing.T) {
}
func TestOOMMaliciousInput(t *testing.T) {
+ t.Parallel()
oomTests := []unpackTest{
{
def: `[{"type": "uint8[]"}]`,
@@ -946,6 +957,7 @@ func TestOOMMaliciousInput(t *testing.T) {
}
func TestPackAndUnpackIncompatibleNumber(t *testing.T) {
+ t.Parallel()
var encodeABI Arguments
uint256Ty, err := NewType("uint256", "", nil)
if err != nil {
diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go
index e8274f9f04..2c4138aa78 100644
--- a/accounts/accounts_test.go
+++ b/accounts/accounts_test.go
@@ -24,6 +24,7 @@ import (
)
func TestTextHash(t *testing.T) {
+ t.Parallel()
hash := TextHash([]byte("Hello Joe"))
want := hexutil.MustDecode("0xa080337ae51c4e064c189e113edd0ba391df9206e2f49db658bb32cf2911730b")
if !bytes.Equal(hash, want) {
diff --git a/accounts/hd_test.go b/accounts/hd_test.go
index 0743bbe666..118ec5187b 100644
--- a/accounts/hd_test.go
+++ b/accounts/hd_test.go
@@ -25,6 +25,7 @@ import (
// Tests that HD derivation paths can be correctly parsed into our internal binary
// representation.
func TestHDPathParsing(t *testing.T) {
+ t.Parallel()
tests := []struct {
input string
output DerivationPath
@@ -89,6 +90,7 @@ func testDerive(t *testing.T, next func() DerivationPath, expected []string) {
}
func TestHdPathIteration(t *testing.T) {
+ t.Parallel()
testDerive(t, DefaultIterator(DefaultBaseDerivationPath),
[]string{
"m/44'/60'/0'/0/0", "m/44'/60'/0'/0/1",
diff --git a/accounts/keystore/account_cache_test.go b/accounts/keystore/account_cache_test.go
index 3847e9daf6..48a238048f 100644
--- a/accounts/keystore/account_cache_test.go
+++ b/accounts/keystore/account_cache_test.go
@@ -68,7 +68,7 @@ func waitWatcherStart(ks *KeyStore) bool {
func waitForAccounts(wantAccounts []accounts.Account, ks *KeyStore) error {
var list []accounts.Account
- for t0 := time.Now(); time.Since(t0) < 5*time.Second; time.Sleep(200 * time.Millisecond) {
+ for t0 := time.Now(); time.Since(t0) < 5*time.Second; time.Sleep(100 * time.Millisecond) {
list = ks.Accounts()
if reflect.DeepEqual(list, wantAccounts) {
// ks should have also received change notifications
@@ -152,6 +152,7 @@ func TestWatchNoDir(t *testing.T) {
}
func TestCacheInitialReload(t *testing.T) {
+ t.Parallel()
cache, _ := newAccountCache(cachetestDir)
accounts := cache.accounts()
if !reflect.DeepEqual(accounts, cachetestAccounts) {
@@ -160,6 +161,7 @@ func TestCacheInitialReload(t *testing.T) {
}
func TestCacheAddDeleteOrder(t *testing.T) {
+ t.Parallel()
cache, _ := newAccountCache("testdata/no-such-dir")
cache.watcher.running = true // prevent unexpected reloads
@@ -244,6 +246,7 @@ func TestCacheAddDeleteOrder(t *testing.T) {
}
func TestCacheFind(t *testing.T) {
+ t.Parallel()
dir := filepath.Join("testdata", "dir")
cache, _ := newAccountCache(dir)
cache.watcher.running = true // prevent unexpected reloads
@@ -350,7 +353,7 @@ func TestUpdatedKeyfileContents(t *testing.T) {
return
}
// needed so that modTime of `file` is different to its current value after forceCopyFile
- time.Sleep(time.Second)
+ os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second))
// Now replace file contents
if err := forceCopyFile(file, cachetestAccounts[1].URL.Path); err != nil {
@@ -366,7 +369,7 @@ func TestUpdatedKeyfileContents(t *testing.T) {
}
// needed so that modTime of `file` is different to its current value after forceCopyFile
- time.Sleep(time.Second)
+ os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second))
// Now replace file contents again
if err := forceCopyFile(file, cachetestAccounts[2].URL.Path); err != nil {
@@ -382,7 +385,7 @@ func TestUpdatedKeyfileContents(t *testing.T) {
}
// needed so that modTime of `file` is different to its current value after os.WriteFile
- time.Sleep(time.Second)
+ os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second))
// Now replace file contents with crap
if err := os.WriteFile(file, []byte("foo"), 0600); err != nil {
diff --git a/tests/fuzzers/keystore/keystore-fuzzer.go b/accounts/keystore/keystore_fuzzing_test.go
similarity index 66%
rename from tests/fuzzers/keystore/keystore-fuzzer.go
rename to accounts/keystore/keystore_fuzzing_test.go
index e3bcae92e1..d38ccaf11b 100644
--- a/tests/fuzzers/keystore/keystore-fuzzer.go
+++ b/accounts/keystore/keystore_fuzzing_test.go
@@ -1,4 +1,4 @@
-// Copyright 2019 The go-ethereum Authors
+// Copyright 2017 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
@@ -17,21 +17,18 @@
package keystore
import (
- "os"
-
- "github.com/ethereum/go-ethereum/accounts/keystore"
+ "testing"
)
-func Fuzz(input []byte) int {
- ks := keystore.NewKeyStore("/tmp/ks", keystore.LightScryptN, keystore.LightScryptP)
-
- a, err := ks.NewAccount(string(input))
- if err != nil {
- panic(err)
- }
- if err := ks.Unlock(a, string(input)); err != nil {
- panic(err)
- }
- os.Remove(a.URL.Path)
- return 1
+func FuzzPassword(f *testing.F) {
+ f.Fuzz(func(t *testing.T, password string) {
+ ks := NewKeyStore(t.TempDir(), LightScryptN, LightScryptP)
+ a, err := ks.NewAccount(password)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := ks.Unlock(a, password); err != nil {
+ t.Fatal(err)
+ }
+ })
}
diff --git a/accounts/keystore/keystore_test.go b/accounts/keystore/keystore_test.go
index deb7cae9f9..c9a23eddd6 100644
--- a/accounts/keystore/keystore_test.go
+++ b/accounts/keystore/keystore_test.go
@@ -36,6 +36,7 @@ import (
var testSigData = make([]byte, 32)
func TestKeyStore(t *testing.T) {
+ t.Parallel()
dir, ks := tmpKeyStore(t, true)
a, err := ks.NewAccount("foo")
@@ -70,6 +71,7 @@ func TestKeyStore(t *testing.T) {
}
func TestSign(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStore(t, true)
pass := "" // not used but required by API
@@ -86,6 +88,7 @@ func TestSign(t *testing.T) {
}
func TestSignWithPassphrase(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStore(t, true)
pass := "passwd"
@@ -280,6 +283,7 @@ type walletEvent struct {
// Tests that wallet notifications and correctly fired when accounts are added
// or deleted from the keystore.
func TestWalletNotifications(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStore(t, false)
// Subscribe to the wallet feed and collect events.
@@ -341,6 +345,7 @@ func TestWalletNotifications(t *testing.T) {
// TestImportExport tests the import functionality of a keystore.
func TestImportECDSA(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStore(t, true)
key, err := crypto.GenerateKey()
if err != nil {
@@ -359,6 +364,7 @@ func TestImportECDSA(t *testing.T) {
// TestImportECDSA tests the import and export functionality of a keystore.
func TestImportExport(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStore(t, true)
acc, err := ks.NewAccount("old")
if err != nil {
@@ -387,6 +393,7 @@ func TestImportExport(t *testing.T) {
// TestImportRace tests the keystore on races.
// This test should fail under -race if importing races.
func TestImportRace(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStore(t, true)
acc, err := ks.NewAccount("old")
if err != nil {
diff --git a/accounts/keystore/passphrase.go b/accounts/keystore/passphrase.go
index 8d6ed2b14e..e7a7f8d0cb 100644
--- a/accounts/keystore/passphrase.go
+++ b/accounts/keystore/passphrase.go
@@ -136,7 +136,7 @@ func (ks keyStorePassphrase) JoinPath(filename string) string {
return filepath.Join(ks.keysDirPath, filename)
}
-// Encryptdata encrypts the data given as 'data' with the password 'auth'.
+// EncryptDataV3 encrypts the data given as 'data' with the password 'auth'.
func EncryptDataV3(data, auth []byte, scryptN, scryptP int) (CryptoJSON, error) {
salt := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
diff --git a/accounts/keystore/passphrase_test.go b/accounts/keystore/passphrase_test.go
index 1356b31780..20ec0f5519 100644
--- a/accounts/keystore/passphrase_test.go
+++ b/accounts/keystore/passphrase_test.go
@@ -30,6 +30,7 @@ const (
// Tests that a json key file can be decrypted and encrypted in multiple rounds.
func TestKeyEncryptDecrypt(t *testing.T) {
+ t.Parallel()
keyjson, err := os.ReadFile("testdata/very-light-scrypt.json")
if err != nil {
t.Fatal(err)
@@ -54,7 +55,7 @@ func TestKeyEncryptDecrypt(t *testing.T) {
// Recrypt with a new password and start over
password += "new data appended" // nolint: gosec
if keyjson, err = EncryptKey(key, password, veryLightScryptN, veryLightScryptP); err != nil {
- t.Errorf("test %d: failed to recrypt key %v", i, err)
+ t.Errorf("test %d: failed to re-encrypt key %v", i, err)
}
}
}
diff --git a/accounts/keystore/plain_test.go b/accounts/keystore/plain_test.go
index 93165d5cd3..737eb7fd61 100644
--- a/accounts/keystore/plain_test.go
+++ b/accounts/keystore/plain_test.go
@@ -40,6 +40,7 @@ func tmpKeyStoreIface(t *testing.T, encrypted bool) (dir string, ks keyStore) {
}
func TestKeyStorePlain(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStoreIface(t, false)
pass := "" // not used but required by API
@@ -60,6 +61,7 @@ func TestKeyStorePlain(t *testing.T) {
}
func TestKeyStorePassphrase(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStoreIface(t, true)
pass := "foo"
@@ -80,6 +82,7 @@ func TestKeyStorePassphrase(t *testing.T) {
}
func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
+ t.Parallel()
_, ks := tmpKeyStoreIface(t, true)
pass := "foo"
@@ -93,6 +96,7 @@ func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
}
func TestImportPreSaleKey(t *testing.T) {
+ t.Parallel()
dir, ks := tmpKeyStoreIface(t, true)
// file content of a presale key file generated with:
diff --git a/accounts/keystore/watch.go b/accounts/keystore/watch.go
index 3f64b89c58..1bef321cd1 100644
--- a/accounts/keystore/watch.go
+++ b/accounts/keystore/watch.go
@@ -20,6 +20,7 @@
package keystore
import (
+ "os"
"time"
"github.com/ethereum/go-ethereum/log"
@@ -77,7 +78,9 @@ func (w *watcher) loop() {
}
defer watcher.Close()
if err := watcher.Add(w.ac.keydir); err != nil {
- logger.Warn("Failed to watch keystore folder", "err", err)
+ if !os.IsNotExist(err) {
+ logger.Warn("Failed to watch keystore folder", "err", err)
+ }
return
}
@@ -122,7 +125,7 @@ func (w *watcher) loop() {
if !ok {
return
}
- log.Info("Filsystem watcher error", "err", err)
+ log.Info("Filesystem watcher error", "err", err)
case <-debounce.C:
w.ac.scanAccounts()
rescanTriggered = false
diff --git a/accounts/manager.go b/accounts/manager.go
index a0b5c329cd..cbe4f7c79d 100644
--- a/accounts/manager.go
+++ b/accounts/manager.go
@@ -98,6 +98,9 @@ func NewManager(config *Config, backends ...Backend) *Manager {
// Close terminates the account manager's internal notification processes.
func (am *Manager) Close() error {
+ for _, w := range am.wallets {
+ w.Close()
+ }
errc := make(chan error)
am.quit <- errc
return <-errc
diff --git a/accounts/scwallet/README.md b/accounts/scwallet/README.md
index 4313d9c6b2..28079c4743 100644
--- a/accounts/scwallet/README.md
+++ b/accounts/scwallet/README.md
@@ -8,7 +8,7 @@
## Preparing the smartcard
- **WARNING: FOILLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS**
+ **WARNING: FOLLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS**
You can use status' [keycard-cli](https://github.com/status-im/keycard-cli) and you should get _at least_ version 2.1.1 of their [smartcard application](https://github.com/status-im/status-keycard/releases/download/2.2.1/keycard_v2.2.1.cap)
diff --git a/accounts/scwallet/wallet.go b/accounts/scwallet/wallet.go
index 067bda83f1..f0ca9085b6 100644
--- a/accounts/scwallet/wallet.go
+++ b/accounts/scwallet/wallet.go
@@ -776,16 +776,16 @@ func (w *Wallet) findAccountPath(account accounts.Account) (accounts.DerivationP
return nil, fmt.Errorf("scheme %s does not match wallet scheme %s", account.URL.Scheme, w.Hub.scheme)
}
- parts := strings.SplitN(account.URL.Path, "/", 2)
- if len(parts) != 2 {
+ url, path, found := strings.Cut(account.URL.Path, "/")
+ if !found {
return nil, fmt.Errorf("invalid URL format: %s", account.URL)
}
- if parts[0] != fmt.Sprintf("%x", w.PublicKey[1:3]) {
+ if url != fmt.Sprintf("%x", w.PublicKey[1:3]) {
return nil, fmt.Errorf("URL %s is not for this wallet", account.URL)
}
- return accounts.ParseDerivationPath(parts[1])
+ return accounts.ParseDerivationPath(path)
}
// Session represents a secured communication session with the wallet.
diff --git a/accounts/url_test.go b/accounts/url_test.go
index 239aa06d22..f481a1016d 100644
--- a/accounts/url_test.go
+++ b/accounts/url_test.go
@@ -21,6 +21,7 @@ import (
)
func TestURLParsing(t *testing.T) {
+ t.Parallel()
url, err := parseURL("https://ethereum.org")
if err != nil {
t.Errorf("unexpected error: %v", err)
@@ -40,6 +41,7 @@ func TestURLParsing(t *testing.T) {
}
func TestURLString(t *testing.T) {
+ t.Parallel()
url := URL{Scheme: "https", Path: "ethereum.org"}
if url.String() != "https://ethereum.org" {
t.Errorf("expected: %v, got: %v", "https://ethereum.org", url.String())
@@ -52,10 +54,11 @@ func TestURLString(t *testing.T) {
}
func TestURLMarshalJSON(t *testing.T) {
+ t.Parallel()
url := URL{Scheme: "https", Path: "ethereum.org"}
json, err := url.MarshalJSON()
if err != nil {
- t.Errorf("unexpcted error: %v", err)
+ t.Errorf("unexpected error: %v", err)
}
if string(json) != "\"https://ethereum.org\"" {
t.Errorf("expected: %v, got: %v", "\"https://ethereum.org\"", string(json))
@@ -63,10 +66,11 @@ func TestURLMarshalJSON(t *testing.T) {
}
func TestURLUnmarshalJSON(t *testing.T) {
+ t.Parallel()
url := &URL{}
err := url.UnmarshalJSON([]byte("\"https://ethereum.org\""))
if err != nil {
- t.Errorf("unexpcted error: %v", err)
+ t.Errorf("unexpected error: %v", err)
}
if url.Scheme != "https" {
t.Errorf("expected: %v, got: %v", "https", url.Scheme)
@@ -77,6 +81,7 @@ func TestURLUnmarshalJSON(t *testing.T) {
}
func TestURLComparison(t *testing.T) {
+ t.Parallel()
tests := []struct {
urlA URL
urlB URL
diff --git a/accounts/usbwallet/ledger.go b/accounts/usbwallet/ledger.go
index 723df0f2b3..d0cb93e74e 100644
--- a/accounts/usbwallet/ledger.go
+++ b/accounts/usbwallet/ledger.go
@@ -279,7 +279,7 @@ func (w *ledgerDriver) ledgerDerive(derivationPath []uint32) (common.Address, er
}
hexstr := reply[1 : 1+int(reply[0])]
- // Decode the hex sting into an Ethereum address and return
+ // Decode the hex string into an Ethereum address and return
var address common.Address
if _, err = hex.Decode(address[:], hexstr); err != nil {
return common.Address{}, err
diff --git a/accounts/usbwallet/wallet.go b/accounts/usbwallet/wallet.go
index 05add081ab..69083dc893 100644
--- a/accounts/usbwallet/wallet.go
+++ b/accounts/usbwallet/wallet.go
@@ -483,6 +483,10 @@ func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Accoun
w.stateLock.Lock()
defer w.stateLock.Unlock()
+ if w.device == nil {
+ return accounts.Account{}, accounts.ErrWalletClosed
+ }
+
if _, ok := w.paths[address]; !ok {
w.accounts = append(w.accounts, account)
w.paths[address] = make(accounts.DerivationPath, len(path))
diff --git a/appveyor.yml b/appveyor.yml
index 114aec644b..4a8c4b737a 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -54,4 +54,4 @@ for:
- go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
- go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
test_script:
- - go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC%
+ - go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short
diff --git a/beacon/engine/errors.go b/beacon/engine/errors.go
index 769001b9e3..62773a0ea9 100644
--- a/beacon/engine/errors.go
+++ b/beacon/engine/errors.go
@@ -80,6 +80,7 @@ var (
InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
+ UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"}
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}
diff --git a/beacon/engine/gen_blockparams.go b/beacon/engine/gen_blockparams.go
index 0dd2b52597..b1f01b50ff 100644
--- a/beacon/engine/gen_blockparams.go
+++ b/beacon/engine/gen_blockparams.go
@@ -20,12 +20,14 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
Random common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
+ BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
var enc PayloadAttributes
enc.Timestamp = hexutil.Uint64(p.Timestamp)
enc.Random = p.Random
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
enc.Withdrawals = p.Withdrawals
+ enc.BeaconRoot = p.BeaconRoot
return json.Marshal(&enc)
}
@@ -36,6 +38,7 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
Random *common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
+ BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
var dec PayloadAttributes
if err := json.Unmarshal(input, &dec); err != nil {
@@ -56,5 +59,8 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
if dec.Withdrawals != nil {
p.Withdrawals = dec.Withdrawals
}
+ if dec.BeaconRoot != nil {
+ p.BeaconRoot = dec.BeaconRoot
+ }
return nil
}
diff --git a/beacon/engine/gen_epe.go b/beacon/engine/gen_epe.go
index 664a50fc5b..e69f9a5951 100644
--- a/beacon/engine/gen_epe.go
+++ b/beacon/engine/gen_epe.go
@@ -18,11 +18,13 @@ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
+ Override bool `json:"shouldOverrideBuilder"`
}
var enc ExecutionPayloadEnvelope
enc.ExecutionPayload = e.ExecutionPayload
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
enc.BlobsBundle = e.BlobsBundle
+ enc.Override = e.Override
return json.Marshal(&enc)
}
@@ -32,6 +34,7 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
+ Override *bool `json:"shouldOverrideBuilder"`
}
var dec ExecutionPayloadEnvelope
if err := json.Unmarshal(input, &dec); err != nil {
@@ -48,5 +51,8 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
if dec.BlobsBundle != nil {
e.BlobsBundle = dec.BlobsBundle
}
+ if dec.Override != nil {
+ e.Override = *dec.Override
+ }
return nil
}
diff --git a/beacon/engine/types.go b/beacon/engine/types.go
index f1801edd1a..f72319ad50 100644
--- a/beacon/engine/types.go
+++ b/beacon/engine/types.go
@@ -23,10 +23,19 @@ import (
"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/kzg4844"
"github.com/ethereum/go-ethereum/trie"
)
+// PayloadVersion denotes the version of PayloadAttributes used to request the
+// building of the payload to commence.
+type PayloadVersion byte
+
+var (
+ PayloadV1 PayloadVersion = 0x1
+ PayloadV2 PayloadVersion = 0x2
+ PayloadV3 PayloadVersion = 0x3
+)
+
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
// PayloadAttributes describes the environment context in which a block should
@@ -36,6 +45,7 @@ type PayloadAttributes struct {
Random common.Hash `json:"prevRandao" gencodec:"required"`
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
+ BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
// JSON type overrides for PayloadAttributes.
@@ -86,6 +96,7 @@ type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
+ Override bool `json:"shouldOverrideBuilder"`
}
type BlobsBundleV1 struct {
@@ -114,6 +125,21 @@ type TransitionConfigurationV1 struct {
// PayloadID is an identifier of the payload build process
type PayloadID [8]byte
+// Version returns the payload version associated with the identifier.
+func (b PayloadID) Version() PayloadVersion {
+ return PayloadVersion(b[0])
+}
+
+// Is returns whether the identifier matches any of provided payload versions.
+func (b PayloadID) Is(versions ...PayloadVersion) bool {
+ for _, v := range versions {
+ if v == b.Version() {
+ return true
+ }
+ }
+ return false
+}
+
func (b PayloadID) String() string {
return hexutil.Encode(b[:])
}
@@ -172,7 +198,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
// and that the blockhash of the constructed block matches the parameters. Nil
// Withdrawals value will propagate through the returned block. Empty
// Withdrawals value must be passed via non-nil, length 0 value in params.
-func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash) (*types.Block, error) {
+func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
txs, err := decodeTransactions(params.Transactions)
if err != nil {
return nil, err
@@ -208,24 +234,25 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
withdrawalsRoot = &h
}
header := &types.Header{
- ParentHash: params.ParentHash,
- UncleHash: types.EmptyUncleHash,
- Coinbase: params.FeeRecipient,
- Root: params.StateRoot,
- TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
- ReceiptHash: params.ReceiptsRoot,
- Bloom: types.BytesToBloom(params.LogsBloom),
- Difficulty: common.Big0,
- Number: new(big.Int).SetUint64(params.Number),
- GasLimit: params.GasLimit,
- GasUsed: params.GasUsed,
- Time: params.Timestamp,
- BaseFee: params.BaseFeePerGas,
- Extra: params.ExtraData,
- MixDigest: params.Random,
- WithdrawalsHash: withdrawalsRoot,
- ExcessBlobGas: params.ExcessBlobGas,
- BlobGasUsed: params.BlobGasUsed,
+ ParentHash: params.ParentHash,
+ UncleHash: types.EmptyUncleHash,
+ Coinbase: params.FeeRecipient,
+ Root: params.StateRoot,
+ TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
+ ReceiptHash: params.ReceiptsRoot,
+ Bloom: types.BytesToBloom(params.LogsBloom),
+ Difficulty: common.Big0,
+ Number: new(big.Int).SetUint64(params.Number),
+ GasLimit: params.GasLimit,
+ GasUsed: params.GasUsed,
+ Time: params.Timestamp,
+ BaseFee: params.BaseFeePerGas,
+ Extra: params.ExtraData,
+ MixDigest: params.Random,
+ WithdrawalsHash: withdrawalsRoot,
+ ExcessBlobGas: params.ExcessBlobGas,
+ BlobGasUsed: params.BlobGasUsed,
+ ParentBeaconRoot: beaconRoot,
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
if block.Hash() != params.BlockHash {
@@ -236,7 +263,7 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
// BlockToExecutableData constructs the ExecutableData structure by filling the
// fields from the given block. It assumes the given block is post-merge block.
-func BlockToExecutableData(block *types.Block, fees *big.Int, blobs []kzg4844.Blob, commitments []kzg4844.Commitment, proofs []kzg4844.Proof) *ExecutionPayloadEnvelope {
+func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope {
data := &ExecutableData{
BlockHash: block.Hash(),
ParentHash: block.ParentHash(),
@@ -256,17 +283,19 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, blobs []kzg4844.Bl
BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(),
}
- blobsBundle := BlobsBundleV1{
+ bundle := BlobsBundleV1{
Commitments: make([]hexutil.Bytes, 0),
Blobs: make([]hexutil.Bytes, 0),
Proofs: make([]hexutil.Bytes, 0),
}
- for i := range blobs {
- blobsBundle.Blobs = append(blobsBundle.Blobs, hexutil.Bytes(blobs[i][:]))
- blobsBundle.Commitments = append(blobsBundle.Commitments, hexutil.Bytes(commitments[i][:]))
- blobsBundle.Proofs = append(blobsBundle.Proofs, hexutil.Bytes(proofs[i][:]))
+ for _, sidecar := range sidecars {
+ for j := range sidecar.Blobs {
+ bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:]))
+ bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[j][:]))
+ bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
+ }
}
- return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &blobsBundle}
+ return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
}
// ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
diff --git a/beacon/types/update.go b/beacon/types/light_sync.go
similarity index 88%
rename from beacon/types/update.go
rename to beacon/types/light_sync.go
index 06c1b61792..3284081e4d 100644
--- a/beacon/types/update.go
+++ b/beacon/types/light_sync.go
@@ -25,6 +25,24 @@ import (
"github.com/ethereum/go-ethereum/common"
)
+// BootstrapData contains a sync committee where light sync can be started,
+// together with a proof through a beacon header and corresponding state.
+// Note: BootstrapData is fetched from a server based on a known checkpoint hash.
+type BootstrapData struct {
+ Header Header
+ CommitteeRoot common.Hash
+ Committee *SerializedSyncCommittee `rlp:"-"`
+ CommitteeBranch merkle.Values
+}
+
+// Validate verifies the proof included in BootstrapData.
+func (c *BootstrapData) Validate() error {
+ if c.CommitteeRoot != c.Committee.Root() {
+ return errors.New("wrong committee root")
+ }
+ return merkle.VerifyProof(c.Header.StateRoot, params.StateIndexSyncCommittee, c.CommitteeBranch, merkle.Value(c.CommitteeRoot))
+}
+
// LightClientUpdate is a proof of the next sync committee root based on a header
// signed by the sync committee of the given period. Optionally, the update can
// prove quasi-finality by the signed header referring to a previous, finalized
diff --git a/build/checksums.txt b/build/checksums.txt
index cba0263f88..96815ff791 100644
--- a/build/checksums.txt
+++ b/build/checksums.txt
@@ -1,21 +1,26 @@
# This file contains sha256 checksums of optional build dependencies.
-# version:golang 1.21.5
+# version:spec-tests 1.0.6
+# https://github.com/ethereum/execution-spec-tests/releases
+# https://github.com/ethereum/execution-spec-tests/releases/download/v1.0.6/
+485af7b66cf41eb3a8c1bd46632913b8eb95995df867cf665617bbc9b4beedd1 fixtures_develop.tar.gz
+
+# version:golang 1.21.6
# https://go.dev/dl/
-285cbbdf4b6e6e62ed58f370f3f6d8c30825d6e56c5853c66d3c23bcdb09db19 go1.21.5.src.tar.gz
-a2e1d5743e896e5fe1e7d96479c0a769254aed18cf216cf8f4c3a2300a9b3923 go1.21.5.darwin-amd64.tar.gz
-d0f8ac0c4fb3efc223a833010901d02954e3923cfe2c9a2ff0e4254a777cc9cc go1.21.5.darwin-arm64.tar.gz
-2c05bbe0dc62456b90b7ddd354a54f373b7c377a98f8b22f52ab694b4f6cca58 go1.21.5.freebsd-386.tar.gz
-30b6c64e9a77129605bc12f836422bf09eec577a8c899ee46130aeff81567003 go1.21.5.freebsd-amd64.tar.gz
-8f4dba9cf5c61757bbd7e9ebdb93b6a30a1b03f4a636a1ba0cc2f27b907ab8e1 go1.21.5.linux-386.tar.gz
-e2bc0b3e4b64111ec117295c088bde5f00eeed1567999ff77bc859d7df70078e go1.21.5.linux-amd64.tar.gz
-841cced7ecda9b2014f139f5bab5ae31785f35399f236b8b3e75dff2a2978d96 go1.21.5.linux-arm64.tar.gz
-837f4bf4e22fcdf920ffeaa4abf3d02d1314e03725431065f4d44c46a01b42fe go1.21.5.linux-armv6l.tar.gz
-907b8c6ec4be9b184952e5d3493be66b1746442394a8bc78556c56834cd7c38b go1.21.5.linux-ppc64le.tar.gz
-9c4a81b72ebe44368813cd03684e1080a818bf915d84163abae2ed325a1b2dc0 go1.21.5.linux-s390x.tar.gz
-6da2418889dfb37763d0eb149c4a8d728c029e12f0cd54fbca0a31ae547e2d34 go1.21.5.windows-386.zip
-bbe603cde7c9dee658f45164b4d06de1eff6e6e6b800100824e7c00d56a9a92f go1.21.5.windows-amd64.zip
-9b7acca50e674294e43202df4fbc26d5af4d8bc3170a3342a1514f09a2dab5e9 go1.21.5.windows-arm64.zip
+124926a62e45f78daabbaedb9c011d97633186a33c238ffc1e25320c02046248 go1.21.6.src.tar.gz
+31d6ecca09010ab351e51343a5af81d678902061fee871f912bdd5ef4d778850 go1.21.6.darwin-amd64.tar.gz
+0ff541fb37c38e5e5c5bcecc8f4f43c5ffd5e3a6c33a5d3e4003ded66fcfb331 go1.21.6.darwin-arm64.tar.gz
+a1d1a149b34bf0f53965a237682c6da1140acabb131bf0e597240e4a140b0e5e go1.21.6.freebsd-386.tar.gz
+de59e1217e4398b1522eed8dddabab2fa1b97aecbdca3af08e34832b4f0e3f81 go1.21.6.freebsd-amd64.tar.gz
+05d09041b5a1193c14e4b2db3f7fcc649b236c567f5eb93305c537851b72dd95 go1.21.6.linux-386.tar.gz
+3f934f40ac360b9c01f616a9aa1796d227d8b0328bf64cb045c7b8c4ee9caea4 go1.21.6.linux-amd64.tar.gz
+e2e8aa88e1b5170a0d495d7d9c766af2b2b6c6925a8f8956d834ad6b4cacbd9a go1.21.6.linux-arm64.tar.gz
+6a8eda6cc6a799ff25e74ce0c13fdc1a76c0983a0bb07c789a2a3454bf6ec9b2 go1.21.6.linux-armv6l.tar.gz
+e872b1e9a3f2f08fd4554615a32ca9123a4ba877ab6d19d36abc3424f86bc07f go1.21.6.linux-ppc64le.tar.gz
+92894d0f732d3379bc414ffdd617eaadad47e1d72610e10d69a1156db03fc052 go1.21.6.linux-s390x.tar.gz
+65b38857135cf45c80e1d267e0ce4f80fe149326c68835217da4f2da9b7943fe go1.21.6.windows-386.zip
+27ac9dd6e66fb3fd0acfa6792ff053c86e7d2c055b022f4b5d53bfddec9e3301 go1.21.6.windows-amd64.zip
+b93aff8f3c882c764c66a39b7a1483b0460e051e9992bf3435479129e5051bcd go1.21.6.windows-arm64.zip
# version:golangci 1.55.2
# https://github.com/golangci/golangci-lint/releases/
@@ -57,4 +62,4 @@ a5e68ae73d38748b5269fad36ac7575e3c162a5dc63ef58abdea03cc5da4522a golangci-lint-
#
# version:ppa-builder 1.19.6
# https://go.dev/dl/
-d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz
\ No newline at end of file
+d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz
diff --git a/build/ci.go b/build/ci.go
index b1dd476b17..9c2680384e 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -120,15 +120,16 @@ var (
// Distros for which packages are created.
// Note: vivid is unsupported because there is no golang-1.6 package for it.
// Note: the following Ubuntu releases have been officially deprecated on Launchpad:
- // wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish
+ // wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish,
+ // kinetic
debDistroGoBoots = map[string]string{
- "trusty": "golang-1.11", // EOL: 04/2024
- "xenial": "golang-go", // EOL: 04/2026
- "bionic": "golang-go", // EOL: 04/2028
- "focal": "golang-go", // EOL: 04/2030
- "jammy": "golang-go", // EOL: 04/2032
- "kinetic": "golang-go", // EOL: 07/2023
- "lunar": "golang-go", // EOL: 01/2024
+ "trusty": "golang-1.11", // 14.04, EOL: 04/2024
+ "xenial": "golang-go", // 16.04, EOL: 04/2026
+ "bionic": "golang-go", // 18.04, EOL: 04/2028
+ "focal": "golang-go", // 20.04, EOL: 04/2030
+ "jammy": "golang-go", // 22.04, EOL: 04/2032
+ "lunar": "golang-go", // 23.04, EOL: 01/2024
+ "mantic": "golang-go", // 23.10, EOL: 07/2024
}
debGoBootPaths = map[string]string{
@@ -136,18 +137,8 @@ var (
"golang-go": "/usr/lib/go",
}
- // This is the version of Go that will be downloaded by
- //
- // go run ci.go install -dlgo
- dlgoVersion = "1.21.5"
-
- // This is the version of Go that will be used to bootstrap the PPA builder.
- //
- // This version is fine to be old and full of security holes, we just use it
- // to build the latest Go. Don't change it. If it ever becomes insufficient,
- // we need to switch over to a recursive builder to jumpt across supported
- // versions.
- gobootVersion = "1.19.6"
+ // This is where the tests should be unpacked.
+ executionSpecTestsDir = "tests/spec-tests"
)
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
@@ -185,6 +176,8 @@ func main() {
doWindowsInstaller(os.Args[2:])
case "purge":
doPurge(os.Args[2:])
+ case "sanitycheck":
+ doSanityCheck()
default:
log.Fatal("unknown command ", os.Args[1])
}
@@ -207,9 +200,8 @@ func doInstall(cmdline []string) {
tc := build.GoToolchain{GOARCH: *arch, CC: *cc}
if *dlgo {
csdb := build.MustLoadChecksums("build/checksums.txt")
- tc.Root = build.DownloadGo(csdb, dlgoVersion)
+ tc.Root = build.DownloadGo(csdb)
}
-
// Disable CLI markdown doc generation in release builds.
buildTags := []string{"urfave_cli_no_docs"}
@@ -300,14 +292,19 @@ func doTest(cmdline []string) {
verbose = flag.Bool("v", false, "Whether to log verbosely")
timeout = flag.String("timeout", "10m", `Timeout of runing tests`)
race = flag.Bool("race", false, "Execute the race detector")
+ short = flag.Bool("short", false, "Pass the 'short'-flag to go test")
+ cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads")
)
flag.CommandLine.Parse(cmdline)
+ // Get test fixtures.
+ csdb := build.MustLoadChecksums("build/checksums.txt")
+ downloadSpecTestFixtures(csdb, *cachedir)
+
// Configure the toolchain.
tc := build.GoToolchain{GOARCH: *arch, CC: *cc}
if *dlgo {
- csdb := build.MustLoadChecksums("build/checksums.txt")
- tc.Root = build.DownloadGo(csdb, dlgoVersion)
+ tc.Root = build.DownloadGo(csdb)
}
gotest := tc.Go("test")
@@ -317,6 +314,9 @@ func doTest(cmdline []string) {
// Enable CKZG backend in CI.
gotest.Args = append(gotest.Args, "-tags=ckzg")
+ // Enable integration-tests
+ gotest.Args = append(gotest.Args, "-tags=integrationtests")
+
// Test a single package at a time. CI builders are slow
// and some tests run into timeouts under load.
gotest.Args = append(gotest.Args, "-p", "1")
@@ -332,6 +332,9 @@ func doTest(cmdline []string) {
if *race {
gotest.Args = append(gotest.Args, "-race")
}
+ if *short {
+ gotest.Args = append(gotest.Args, "-short")
+ }
packages := []string{"./..."}
if len(flag.CommandLine.Args()) > 0 {
@@ -341,6 +344,25 @@ func doTest(cmdline []string) {
build.MustRun(gotest)
}
+// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures.
+func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string {
+ executionSpecTestsVersion, err := build.Version(csdb, "spec-tests")
+ if err != nil {
+ log.Fatal(err)
+ }
+ ext := ".tar.gz"
+ base := "fixtures_develop" // TODO(MariusVanDerWijden) rename once the version becomes part of the filename
+ url := fmt.Sprintf("https://github.com/ethereum/execution-spec-tests/releases/download/v%s/%s%s", executionSpecTestsVersion, base, ext)
+ archivePath := filepath.Join(cachedir, base+ext)
+ if err := csdb.DownloadFile(url, archivePath); err != nil {
+ log.Fatal(err)
+ }
+ if err := build.ExtractArchive(archivePath, executionSpecTestsDir); err != nil {
+ log.Fatal(err)
+ }
+ return filepath.Join(cachedir, base)
+}
+
// doLint runs golangci-lint on requested packages.
func doLint(cmdline []string) {
var (
@@ -354,15 +376,17 @@ func doLint(cmdline []string) {
linter := downloadLinter(*cachedir)
lflags := []string{"run", "--config", ".golangci.yml"}
- build.MustRunCommand(linter, append(lflags, packages...)...)
+ build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
fmt.Println("You have achieved perfection.")
}
// downloadLinter downloads and unpacks golangci-lint.
func downloadLinter(cachedir string) string {
- const version = "1.52.2"
-
csdb := build.MustLoadChecksums("build/checksums.txt")
+ version, err := build.Version(csdb, "golangci")
+ if err != nil {
+ log.Fatal(err)
+ }
arch := runtime.GOARCH
ext := ".tar.gz"
@@ -744,6 +768,10 @@ func doDebianSource(cmdline []string) {
// to bootstrap the builder Go.
func downloadGoBootstrapSources(cachedir string) string {
csdb := build.MustLoadChecksums("build/checksums.txt")
+ gobootVersion, err := build.Version(csdb, "ppa-builder")
+ if err != nil {
+ log.Fatal(err)
+ }
file := fmt.Sprintf("go%s.src.tar.gz", gobootVersion)
url := "https://dl.google.com/go/" + file
dst := filepath.Join(cachedir, file)
@@ -756,6 +784,10 @@ func downloadGoBootstrapSources(cachedir string) string {
// downloadGoSources downloads the Go source tarball.
func downloadGoSources(cachedir string) string {
csdb := build.MustLoadChecksums("build/checksums.txt")
+ dlgoVersion, err := build.Version(csdb, "golang")
+ if err != nil {
+ log.Fatal(err)
+ }
file := fmt.Sprintf("go%s.src.tar.gz", dlgoVersion)
url := "https://dl.google.com/go/" + file
dst := filepath.Join(cachedir, file)
@@ -1082,3 +1114,7 @@ func doPurge(cmdline []string) {
log.Fatal(err)
}
}
+
+func doSanityCheck() {
+ build.DownloadAndVerifyChecksums(build.MustLoadChecksums("build/checksums.txt"))
+}
diff --git a/build/nsis.geth.nsi b/build/nsis.geth.nsi
index 1034f30235..03710dd95d 100644
--- a/build/nsis.geth.nsi
+++ b/build/nsis.geth.nsi
@@ -20,7 +20,7 @@
# - NSIS Large Strings build, http://nsis.sourceforge.net/Special_Builds
# - SFP, http://nsis.sourceforge.net/NSIS_Simple_Firewall_Plugin (put dll in NSIS\Plugins\x86-ansi)
#
-# After intalling NSIS extra the NSIS Large Strings build zip and replace the makensis.exe and the
+# After installing NSIS extra the NSIS Large Strings build zip and replace the makensis.exe and the
# files found in Stub.
#
# based on: http://nsis.sourceforge.net/A_simple_installer_with_start_menu_shortcut_and_uninstaller
diff --git a/build/update-license.go b/build/update-license.go
index 52a54bf66a..70e2de06c7 100644
--- a/build/update-license.go
+++ b/build/update-license.go
@@ -65,10 +65,8 @@ var (
"vendor/", "tests/testdata/", "build/",
// don't relicense vendored sources
- "cmd/internal/browser",
"common/bitutil/bitutil",
"common/prque/",
- "consensus/ethash/xor.go",
"crypto/blake2b/",
"crypto/bn256/",
"crypto/bls12381/",
@@ -78,6 +76,7 @@ var (
"log/",
"metrics/",
"signer/rules/deps",
+ "internal/reexec",
// skip special licenses
"crypto/secp256k1", // Relicensed to BSD-3 via https://github.com/ethereum/go-ethereum/pull/17225
diff --git a/cmd/abigen/main.go b/cmd/abigen/main.go
index 221f45c078..0149dec527 100644
--- a/cmd/abigen/main.go
+++ b/cmd/abigen/main.go
@@ -232,7 +232,7 @@ func abigen(c *cli.Context) error {
}
func main() {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)
diff --git a/cmd/abigen/namefilter_test.go b/cmd/abigen/namefilter_test.go
index 42ba55be5e..ccee712018 100644
--- a/cmd/abigen/namefilter_test.go
+++ b/cmd/abigen/namefilter_test.go
@@ -8,6 +8,7 @@ import (
)
func TestNameFilter(t *testing.T) {
+ t.Parallel()
_, err := newNameFilter("Foo")
require.Error(t, err)
_, err = newNameFilter("too/many:colons:Foo")
diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go
index 438c318107..3fea735067 100644
--- a/cmd/bootnode/main.go
+++ b/cmd/bootnode/main.go
@@ -54,10 +54,11 @@ func main() {
)
flag.Parse()
- glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
- glogger.Verbosity(log.Lvl(*verbosity))
+ glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
+ slogVerbosity := log.FromLegacyLevel(*verbosity)
+ glogger.Verbosity(slogVerbosity)
glogger.Vmodule(*vmodule)
- log.Root().SetHandler(glogger)
+ log.SetDefault(log.NewLogger(glogger))
natm, err := nat.Parse(*natdesc)
if err != nil {
diff --git a/cmd/clef/README.md b/cmd/clef/README.md
index 85c9c70606..3a43db8c95 100644
--- a/cmd/clef/README.md
+++ b/cmd/clef/README.md
@@ -2,7 +2,7 @@
Clef can be used to sign transactions and data and is meant as a(n eventual) replacement for Geth's account management. This allows DApps to not depend on Geth's account management. When a DApp wants to sign data (or a transaction), it can send the content to Clef, which will then provide the user with context and asks for permission to sign the content. If the users grants the signing request, Clef will send the signature back to the DApp.
-This setup allows a DApp to connect to a remote Ethereum node and send transactions that are locally signed. This can help in situations when a DApp is connected to an untrusted remote Ethereum node, because a local one is not available, not synchronised with the chain, or is a node that has no built-in (or limited) account management.
+This setup allows a DApp to connect to a remote Ethereum node and send transactions that are locally signed. This can help in situations when a DApp is connected to an untrusted remote Ethereum node, because a local one is not available, not synchronized with the chain, or is a node that has no built-in (or limited) account management.
Clef can run as a daemon on the same machine, off a usb-stick like [USB armory](https://inversepath.com/usbarmory), or even a separate VM in a [QubesOS](https://www.qubes-os.org/) type setup.
diff --git a/cmd/clef/consolecmd_test.go b/cmd/clef/consolecmd_test.go
index 283d7e8def..c8b37f5b92 100644
--- a/cmd/clef/consolecmd_test.go
+++ b/cmd/clef/consolecmd_test.go
@@ -26,12 +26,13 @@ import (
// TestImportRaw tests clef --importraw
func TestImportRaw(t *testing.T) {
+ t.Parallel()
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Cleanup(func() { os.Remove(keyPath) })
- t.Parallel()
t.Run("happy-path", func(t *testing.T) {
+ t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword")
@@ -43,6 +44,7 @@ func TestImportRaw(t *testing.T) {
})
// tests clef --importraw with mismatched passwords.
t.Run("pw-mismatch", func(t *testing.T) {
+ t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword1").input("myverylongpassword2").WaitExit()
@@ -52,6 +54,7 @@ func TestImportRaw(t *testing.T) {
})
// tests clef --importraw with a too short password.
t.Run("short-pw", func(t *testing.T) {
+ t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("shorty").input("shorty").WaitExit()
@@ -64,12 +67,13 @@ func TestImportRaw(t *testing.T) {
// TestListAccounts tests clef --list-accounts
func TestListAccounts(t *testing.T) {
+ t.Parallel()
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Cleanup(func() { os.Remove(keyPath) })
- t.Parallel()
t.Run("no-accounts", func(t *testing.T) {
+ t.Parallel()
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "list-accounts")
if out := string(clef.Output()); !strings.Contains(out, "The keystore is empty.") {
t.Logf("Output\n%v", out)
@@ -77,6 +81,7 @@ func TestListAccounts(t *testing.T) {
}
})
t.Run("one-account", func(t *testing.T) {
+ t.Parallel()
// First, we need to import
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword").WaitExit()
@@ -91,12 +96,13 @@ func TestListAccounts(t *testing.T) {
// TestListWallets tests clef --list-wallets
func TestListWallets(t *testing.T) {
+ t.Parallel()
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Cleanup(func() { os.Remove(keyPath) })
- t.Parallel()
t.Run("no-accounts", func(t *testing.T) {
+ t.Parallel()
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "list-wallets")
if out := string(clef.Output()); !strings.Contains(out, "There are no wallets.") {
t.Logf("Output\n%v", out)
@@ -104,6 +110,7 @@ func TestListWallets(t *testing.T) {
}
})
t.Run("one-account", func(t *testing.T) {
+ t.Parallel()
// First, we need to import
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword").WaitExit()
diff --git a/cmd/clef/main.go b/cmd/clef/main.go
index 06a8cd7ab7..f9b00e4a12 100644
--- a/cmd/clef/main.go
+++ b/cmd/clef/main.go
@@ -492,7 +492,8 @@ func initialize(c *cli.Context) error {
if usecolor {
output = colorable.NewColorable(logOutput)
}
- log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int(logLevelFlag.Name)), log.StreamHandler(output, log.TerminalFormat(usecolor))))
+ verbosity := log.FromLegacyLevel(c.Int(logLevelFlag.Name))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(output, verbosity, usecolor)))
return nil
}
@@ -581,6 +582,7 @@ func accountImport(c *cli.Context) error {
return err
}
if first != second {
+ //lint:ignore ST1005 This is a message for the user
return errors.New("Passwords do not match")
}
acc, err := internalApi.ImportRawKey(hex.EncodeToString(crypto.FromECDSA(pKey)), first)
@@ -702,6 +704,7 @@ func signer(c *cli.Context) error {
log.Info("Starting signer", "chainid", chainId, "keystore", ksLoc,
"light-kdf", lightKdf, "advanced", advanced)
am := core.StartClefAccountManager(ksLoc, nousb, lightKdf, scpath)
+ defer am.Close()
apiImpl := core.NewSignerAPI(am, chainId, nousb, ui, db, advanced, pwStorage)
// Establish the bidirectional communication, by creating a new UI backend and registering
diff --git a/cmd/clef/pythonsigner.py b/cmd/clef/pythonsigner.py
index b9ea1e406a..5d0eb18dcc 100644
--- a/cmd/clef/pythonsigner.py
+++ b/cmd/clef/pythonsigner.py
@@ -91,7 +91,7 @@ def approveTx(self, req):
{"jsonrpc":"2.0","id":20,"method":"ui_approveTx","params":[{"transaction":{"from":"0xDEADbEeF000000000000000000000000DeaDbeEf","to":"0xDEADbEeF000000000000000000000000DeaDbeEf","gas":"0x3e8","gasPrice":"0x5","maxFeePerGas":null,"maxPriorityFeePerGas":null,"value":"0x6","nonce":"0x1","data":"0x"},"call_info":null,"meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}}]}
:param transaction: transaction info
- :param call_info: info abou the call, e.g. if ABI info could not be
+ :param call_info: info about the call, e.g. if ABI info could not be
:param meta: metadata about the request, e.g. where the call comes from
:return:
""" # noqa: E501
diff --git a/cmd/clef/run_test.go b/cmd/clef/run_test.go
index fc3145b1e0..5fa6e02e14 100644
--- a/cmd/clef/run_test.go
+++ b/cmd/clef/run_test.go
@@ -21,8 +21,8 @@ import (
"os"
"testing"
- "github.com/docker/docker/pkg/reexec"
"github.com/ethereum/go-ethereum/internal/cmdtest"
+ "github.com/ethereum/go-ethereum/internal/reexec"
)
const registeredName = "clef-test"
diff --git a/cmd/devp2p/README.md b/cmd/devp2p/README.md
index 5ca7b497a2..284dfe0a45 100644
--- a/cmd/devp2p/README.md
+++ b/cmd/devp2p/README.md
@@ -108,31 +108,32 @@ Start the test by running `devp2p discv5 test -listen1 127.0.0.1 -listen2 127.0.
The Eth Protocol test suite is a conformance test suite for the [eth protocol][eth].
-To run the eth protocol test suite against your implementation, the node needs to be initialized as such:
-
-1. initialize the geth node with the `genesis.json` file contained in the `testdata` directory
-2. import the `halfchain.rlp` file in the `testdata` directory
-3. run geth with the following flags:
-```
-geth --datadir --nodiscover --nat=none --networkid 19763 --verbosity 5
-```
-
-Then, run the following command, replacing `` with the enode of the geth node:
- ```
- devp2p rlpx eth-test cmd/devp2p/internal/ethtest/testdata/chain.rlp cmd/devp2p/internal/ethtest/testdata/genesis.json
-```
+To run the eth protocol test suite against your implementation, the node needs to be initialized
+with our test chain. The chain files are located in `./cmd/devp2p/internal/ethtest/testdata`.
+
+1. initialize the geth node with the `genesis.json` file
+2. import blocks from `chain.rlp`
+3. run the client using the resulting database. For geth, use a command like the one below:
+
+ geth \
+ --datadir \
+ --nodiscover \
+ --nat=none \
+ --networkid 3503995874084926 \
+ --verbosity 5 \
+ --authrpc.jwtsecret 0x7365637265747365637265747365637265747365637265747365637265747365
+
+Note that the tests also require access to the engine API.
+The test suite can now be executed using the devp2p tool.
+
+ devp2p rlpx eth-test \
+ --chain internal/ethtest/testdata \
+ --node enode://.... \
+ --engineapi http://127.0.0.1:8551 \
+ --jwtsecret 0x7365637265747365637265747365637265747365637265747365637265747365
Repeat the above process (re-initialising the node) in order to run the Eth Protocol test suite again.
-#### Eth66 Test Suite
-
-The Eth66 test suite is also a conformance test suite for the eth 66 protocol version specifically.
-To run the eth66 protocol test suite, initialize a geth node as described above and run the following command,
-replacing `` with the enode of the geth node:
-
- ```
- devp2p rlpx eth66-test cmd/devp2p/internal/ethtest/testdata/chain.rlp cmd/devp2p/internal/ethtest/testdata/genesis.json
-```
[eth]: https://github.com/ethereum/devp2p/blob/master/caps/eth.md
[dns-tutorial]: https://geth.ethereum.org/docs/developers/geth-developer/dns-discovery-setup
diff --git a/cmd/devp2p/crawl.go b/cmd/devp2p/crawl.go
index 8c0defff6d..4288a5feb8 100644
--- a/cmd/devp2p/crawl.go
+++ b/cmd/devp2p/crawl.go
@@ -17,6 +17,7 @@
package main
import (
+ "errors"
"sync"
"sync/atomic"
"time"
@@ -51,7 +52,14 @@ type resolver interface {
RequestENR(*enode.Node) (*enode.Node, error)
}
-func newCrawler(input nodeSet, disc resolver, iters ...enode.Iterator) *crawler {
+func newCrawler(input nodeSet, bootnodes []*enode.Node, disc resolver, iters ...enode.Iterator) (*crawler, error) {
+ if len(input) == 0 {
+ input.add(bootnodes...)
+ }
+ if len(input) == 0 {
+ return nil, errors.New("no input nodes to start crawling")
+ }
+
c := &crawler{
input: input,
output: make(nodeSet, len(input)),
@@ -67,7 +75,7 @@ func newCrawler(input nodeSet, disc resolver, iters ...enode.Iterator) *crawler
for id, n := range input {
c.output[id] = n
}
- return c
+ return c, nil
}
func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
diff --git a/cmd/devp2p/discv4cmd.go b/cmd/devp2p/discv4cmd.go
index 0117c7eb82..45bcdcd367 100644
--- a/cmd/devp2p/discv4cmd.go
+++ b/cmd/devp2p/discv4cmd.go
@@ -143,7 +143,7 @@ var discoveryNodeFlags = []cli.Flag{
func discv4Ping(ctx *cli.Context) error {
n := getNodeArg(ctx)
- disc := startV4(ctx)
+ disc, _ := startV4(ctx)
defer disc.Close()
start := time.Now()
@@ -156,7 +156,7 @@ func discv4Ping(ctx *cli.Context) error {
func discv4RequestRecord(ctx *cli.Context) error {
n := getNodeArg(ctx)
- disc := startV4(ctx)
+ disc, _ := startV4(ctx)
defer disc.Close()
respN, err := disc.RequestENR(n)
@@ -169,7 +169,7 @@ func discv4RequestRecord(ctx *cli.Context) error {
func discv4Resolve(ctx *cli.Context) error {
n := getNodeArg(ctx)
- disc := startV4(ctx)
+ disc, _ := startV4(ctx)
defer disc.Close()
fmt.Println(disc.Resolve(n).String())
@@ -196,10 +196,13 @@ func discv4ResolveJSON(ctx *cli.Context) error {
nodeargs = append(nodeargs, n)
}
- // Run the crawler.
- disc := startV4(ctx)
+ disc, config := startV4(ctx)
defer disc.Close()
- c := newCrawler(inputSet, disc, enode.IterNodes(nodeargs))
+
+ c, err := newCrawler(inputSet, config.Bootnodes, disc, enode.IterNodes(nodeargs))
+ if err != nil {
+ return err
+ }
c.revalidateInterval = 0
output := c.run(0, 1)
writeNodesJSON(nodesFile, output)
@@ -211,14 +214,18 @@ func discv4Crawl(ctx *cli.Context) error {
return errors.New("need nodes file as argument")
}
nodesFile := ctx.Args().First()
- var inputSet nodeSet
+ inputSet := make(nodeSet)
if common.FileExist(nodesFile) {
inputSet = loadNodesJSON(nodesFile)
}
- disc := startV4(ctx)
+ disc, config := startV4(ctx)
defer disc.Close()
- c := newCrawler(inputSet, disc, disc.RandomNodes())
+
+ c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes())
+ if err != nil {
+ return err
+ }
c.revalidateInterval = 10 * time.Minute
output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name))
writeNodesJSON(nodesFile, output)
@@ -229,7 +236,7 @@ func discv4Crawl(ctx *cli.Context) error {
func discv4Test(ctx *cli.Context) error {
// Configure test package globals.
if !ctx.IsSet(remoteEnodeFlag.Name) {
- return fmt.Errorf("Missing -%v", remoteEnodeFlag.Name)
+ return fmt.Errorf("missing -%v", remoteEnodeFlag.Name)
}
v4test.Remote = ctx.String(remoteEnodeFlag.Name)
v4test.Listen1 = ctx.String(testListen1Flag.Name)
@@ -238,14 +245,14 @@ func discv4Test(ctx *cli.Context) error {
}
// startV4 starts an ephemeral discovery V4 node.
-func startV4(ctx *cli.Context) *discover.UDPv4 {
+func startV4(ctx *cli.Context) (*discover.UDPv4, discover.Config) {
ln, config := makeDiscoveryConfig(ctx)
socket := listen(ctx, ln)
disc, err := discover.ListenV4(socket, ln, config)
if err != nil {
exit(err)
}
- return disc
+ return disc, config
}
func makeDiscoveryConfig(ctx *cli.Context) (*enode.LocalNode, discover.Config) {
diff --git a/cmd/devp2p/discv5cmd.go b/cmd/devp2p/discv5cmd.go
index c5e226f0d1..0dac945269 100644
--- a/cmd/devp2p/discv5cmd.go
+++ b/cmd/devp2p/discv5cmd.go
@@ -81,7 +81,7 @@ var (
func discv5Ping(ctx *cli.Context) error {
n := getNodeArg(ctx)
- disc := startV5(ctx)
+ disc, _ := startV5(ctx)
defer disc.Close()
fmt.Println(disc.Ping(n))
@@ -90,7 +90,7 @@ func discv5Ping(ctx *cli.Context) error {
func discv5Resolve(ctx *cli.Context) error {
n := getNodeArg(ctx)
- disc := startV5(ctx)
+ disc, _ := startV5(ctx)
defer disc.Close()
fmt.Println(disc.Resolve(n))
@@ -102,14 +102,18 @@ func discv5Crawl(ctx *cli.Context) error {
return errors.New("need nodes file as argument")
}
nodesFile := ctx.Args().First()
- var inputSet nodeSet
+ inputSet := make(nodeSet)
if common.FileExist(nodesFile) {
inputSet = loadNodesJSON(nodesFile)
}
- disc := startV5(ctx)
+ disc, config := startV5(ctx)
defer disc.Close()
- c := newCrawler(inputSet, disc, disc.RandomNodes())
+
+ c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes())
+ if err != nil {
+ return err
+ }
c.revalidateInterval = 10 * time.Minute
output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name))
writeNodesJSON(nodesFile, output)
@@ -127,7 +131,7 @@ func discv5Test(ctx *cli.Context) error {
}
func discv5Listen(ctx *cli.Context) error {
- disc := startV5(ctx)
+ disc, _ := startV5(ctx)
defer disc.Close()
fmt.Println(disc.Self())
@@ -135,12 +139,12 @@ func discv5Listen(ctx *cli.Context) error {
}
// startV5 starts an ephemeral discovery v5 node.
-func startV5(ctx *cli.Context) *discover.UDPv5 {
+func startV5(ctx *cli.Context) (*discover.UDPv5, discover.Config) {
ln, config := makeDiscoveryConfig(ctx)
socket := listen(ctx, ln)
disc, err := discover.ListenV5(socket, ln, config)
if err != nil {
exit(err)
}
- return disc
+ return disc, config
}
diff --git a/cmd/devp2p/dns_cloudflare.go b/cmd/devp2p/dns_cloudflare.go
index 903d754dd7..a3cc69cf19 100644
--- a/cmd/devp2p/dns_cloudflare.go
+++ b/cmd/devp2p/dns_cloudflare.go
@@ -114,7 +114,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
records = lrecords
log.Info(fmt.Sprintf("Retrieving existing TXT records on %s", name))
- entries, err := c.DNSRecords(context.Background(), c.zoneID, cloudflare.DNSRecord{Type: "TXT"})
+ entries, _, err := c.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), cloudflare.ListDNSRecordsParams{Type: "TXT"})
if err != nil {
return err
}
@@ -141,14 +141,25 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
if path != name {
ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare
}
- record := cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl}
- _, err = c.CreateDNSRecord(context.Background(), c.zoneID, record)
+ record := cloudflare.CreateDNSRecordParams{Type: "TXT", Name: path, Content: val, TTL: ttl}
+ _, err = c.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record)
} else if old.Content != val {
// Entry already exists, only change its content.
log.Info(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val))
updated++
- old.Content = val
- err = c.UpdateDNSRecord(context.Background(), c.zoneID, old.ID, old)
+
+ record := cloudflare.UpdateDNSRecordParams{
+ Type: old.Type,
+ Name: old.Name,
+ Content: val,
+ Data: old.Data,
+ ID: old.ID,
+ Priority: old.Priority,
+ TTL: old.TTL,
+ Proxied: old.Proxied,
+ Tags: old.Tags,
+ }
+ _, err = c.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record)
} else {
skipped++
log.Debug(fmt.Sprintf("Skipping %s = %q", path, val))
@@ -168,7 +179,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
// Stale entry, nuke it.
log.Debug(fmt.Sprintf("Deleting %s = %q", path, entry.Content))
deleted++
- if err := c.DeleteDNSRecord(context.Background(), c.zoneID, entry.ID); err != nil {
+ if err := c.DeleteDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), entry.ID); err != nil {
return fmt.Errorf("failed to delete %s: %v", path, err)
}
}
diff --git a/cmd/devp2p/dns_route53_test.go b/cmd/devp2p/dns_route53_test.go
index e6eb516e6b..af39c70a36 100644
--- a/cmd/devp2p/dns_route53_test.go
+++ b/cmd/devp2p/dns_route53_test.go
@@ -26,6 +26,7 @@ import (
// This test checks that computeChanges/splitChanges create DNS changes in
// leaf-added -> root-changed -> leaf-deleted order.
func TestRoute53ChangeSort(t *testing.T) {
+ t.Parallel()
testTree0 := map[string]recordSet{
"2kfjogvxdqtxxugbh7gs7naaai.n": {ttl: 3333, values: []string{
`"enr:-HW4QO1ml1DdXLeZLsUxewnthhUy8eROqkDyoMTyavfks9JlYQIlMFEUoM78PovJDPQrAkrb3LRJ-""vtrymDguKCOIAWAgmlkgnY0iXNlY3AyNTZrMaEDffaGfJzgGhUif1JqFruZlYmA31HzathLSWxfbq_QoQ4"`,
@@ -164,6 +165,7 @@ func TestRoute53ChangeSort(t *testing.T) {
// This test checks that computeChanges compares the quoted value of the records correctly.
func TestRoute53NoChange(t *testing.T) {
+ t.Parallel()
// Existing record set.
testTree0 := map[string]recordSet{
"n": {ttl: rootTTL, values: []string{
diff --git a/cmd/devp2p/internal/ethtest/chain.go b/cmd/devp2p/internal/ethtest/chain.go
index 5e3d9fe98d..e8b3725b17 100644
--- a/cmd/devp2p/internal/ethtest/chain.go
+++ b/cmd/devp2p/internal/ethtest/chain.go
@@ -17,27 +17,118 @@
package ethtest
import (
+ "bytes"
"compress/gzip"
+ "crypto/ecdsa"
"encoding/json"
"errors"
"fmt"
"io"
"math/big"
"os"
+ "path"
+ "sort"
"strings"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
+ "golang.org/x/exp/slices"
)
+// Chain is a lightweight blockchain-like store which can read a hivechain
+// created chain.
type Chain struct {
- genesis core.Genesis
- blocks []*types.Block
- chainConfig *params.ChainConfig
+ genesis core.Genesis
+ blocks []*types.Block
+ state map[common.Address]state.DumpAccount // state of head block
+ senders map[common.Address]*senderInfo
+ config *params.ChainConfig
+}
+
+// NewChain takes the given chain.rlp file, and decodes and returns
+// the blocks from the file.
+func NewChain(dir string) (*Chain, error) {
+ gen, err := loadGenesis(path.Join(dir, "genesis.json"))
+ if err != nil {
+ return nil, err
+ }
+ gblock := gen.ToBlock()
+
+ blocks, err := blocksFromFile(path.Join(dir, "chain.rlp"), gblock)
+ if err != nil {
+ return nil, err
+ }
+ state, err := readState(path.Join(dir, "headstate.json"))
+ if err != nil {
+ return nil, err
+ }
+ accounts, err := readAccounts(path.Join(dir, "accounts.json"))
+ if err != nil {
+ return nil, err
+ }
+ return &Chain{
+ genesis: gen,
+ blocks: blocks,
+ state: state,
+ senders: accounts,
+ config: gen.Config,
+ }, nil
+}
+
+// senderInfo is an account record as output in the "accounts.json" file from
+// hivechain.
+type senderInfo struct {
+ Key *ecdsa.PrivateKey `json:"key"`
+ Nonce uint64 `json:"nonce"`
+}
+
+// Head returns the chain head.
+func (c *Chain) Head() *types.Block {
+ return c.blocks[c.Len()-1]
+}
+
+// AccountsInHashOrder returns all accounts of the head state, ordered by hash of address.
+func (c *Chain) AccountsInHashOrder() []state.DumpAccount {
+ list := make([]state.DumpAccount, len(c.state))
+ i := 0
+ for addr, acc := range c.state {
+ addr := addr
+ list[i] = acc
+ list[i].Address = &addr
+ if len(acc.AddressHash) != 32 {
+ panic(fmt.Errorf("missing/invalid SecureKey in dump account %v", addr))
+ }
+ i++
+ }
+ slices.SortFunc(list, func(x, y state.DumpAccount) int {
+ return bytes.Compare(x.AddressHash, y.AddressHash)
+ })
+ return list
+}
+
+// CodeHashes returns all bytecode hashes contained in the head state.
+func (c *Chain) CodeHashes() []common.Hash {
+ var hashes []common.Hash
+ seen := make(map[common.Hash]struct{})
+ seen[types.EmptyCodeHash] = struct{}{}
+ for _, acc := range c.state {
+ h := common.BytesToHash(acc.CodeHash)
+ if _, ok := seen[h]; ok {
+ continue
+ }
+ hashes = append(hashes, h)
+ seen[h] = struct{}{}
+ }
+ slices.SortFunc(hashes, (common.Hash).Cmp)
+ return hashes
}
// Len returns the length of the chain.
@@ -45,6 +136,11 @@ func (c *Chain) Len() int {
return len(c.blocks)
}
+// ForkID gets the fork id of the chain.
+func (c *Chain) ForkID() forkid.ID {
+ return forkid.NewID(c.config, c.blocks[0], uint64(c.Len()), c.blocks[c.Len()-1].Time())
+}
+
// TD calculates the total difficulty of the chain at the
// chain head.
func (c *Chain) TD() *big.Int {
@@ -55,19 +151,12 @@ func (c *Chain) TD() *big.Int {
return sum
}
-// TotalDifficultyAt calculates the total difficulty of the chain
-// at the given block height.
-func (c *Chain) TotalDifficultyAt(height int) *big.Int {
- sum := new(big.Int)
- if height >= c.Len() {
- return sum
- }
- for _, block := range c.blocks[:height+1] {
- sum.Add(sum, block.Difficulty())
- }
- return sum
+// GetBlock returns the block at the specified number.
+func (c *Chain) GetBlock(number int) *types.Block {
+ return c.blocks[number]
}
+// RootAt returns the state root for the block at the given height.
func (c *Chain) RootAt(height int) common.Hash {
if height < c.Len() {
return c.blocks[height].Root()
@@ -75,37 +164,56 @@ func (c *Chain) RootAt(height int) common.Hash {
return common.Hash{}
}
-// ForkID gets the fork id of the chain.
-func (c *Chain) ForkID() forkid.ID {
- return forkid.NewID(c.chainConfig, c.blocks[0].Hash(), uint64(c.Len()), c.blocks[0].Time())
+// GetSender returns the address associated with account at the index in the
+// pre-funded accounts list.
+func (c *Chain) GetSender(idx int) (common.Address, uint64) {
+ var accounts Addresses
+ for addr := range c.senders {
+ accounts = append(accounts, addr)
+ }
+ sort.Sort(accounts)
+ addr := accounts[idx]
+ return addr, c.senders[addr].Nonce
}
-// Shorten returns a copy chain of a desired height from the imported
-func (c *Chain) Shorten(height int) *Chain {
- blocks := make([]*types.Block, height)
- copy(blocks, c.blocks[:height])
+// IncNonce increases the specified signing account's pending nonce.
+func (c *Chain) IncNonce(addr common.Address, amt uint64) {
+ if _, ok := c.senders[addr]; !ok {
+ panic("nonce increment for non-signer")
+ }
+ c.senders[addr].Nonce += amt
+}
- config := *c.chainConfig
- return &Chain{
- blocks: blocks,
- chainConfig: &config,
+// Balance returns the balance of an account at the head of the chain.
+func (c *Chain) Balance(addr common.Address) *big.Int {
+ bal := new(big.Int)
+ if acc, ok := c.state[addr]; ok {
+ bal, _ = bal.SetString(acc.Balance, 10)
}
+ return bal
}
-// Head returns the chain head.
-func (c *Chain) Head() *types.Block {
- return c.blocks[c.Len()-1]
+// SignTx signs a transaction for the specified from account, so long as that
+// account was in the hivechain accounts dump.
+func (c *Chain) SignTx(from common.Address, tx *types.Transaction) (*types.Transaction, error) {
+ signer := types.LatestSigner(c.config)
+ acc, ok := c.senders[from]
+ if !ok {
+ return nil, fmt.Errorf("account not available for signing: %s", from)
+ }
+ return types.SignTx(tx, signer, acc.Key)
}
-func (c *Chain) GetHeaders(req *GetBlockHeaders) ([]*types.Header, error) {
+// GetHeaders returns the headers base on an ethGetPacketHeadersPacket.
+func (c *Chain) GetHeaders(req *eth.GetBlockHeadersPacket) ([]*types.Header, error) {
if req.Amount < 1 {
return nil, errors.New("no block headers requested")
}
-
- headers := make([]*types.Header, req.Amount)
- var blockNumber uint64
-
- // range over blocks to check if our chain has the requested header
+ var (
+ headers = make([]*types.Header, req.Amount)
+ blockNumber uint64
+ )
+ // Range over blocks to check if our chain has the requested header.
for _, block := range c.blocks {
if block.Hash() == req.Origin.Hash || block.Number().Uint64() == req.Origin.Number {
headers[0] = block.Header()
@@ -115,40 +223,30 @@ func (c *Chain) GetHeaders(req *GetBlockHeaders) ([]*types.Header, error) {
if headers[0] == nil {
return nil, fmt.Errorf("no headers found for given origin number %v, hash %v", req.Origin.Number, req.Origin.Hash)
}
-
if req.Reverse {
for i := 1; i < int(req.Amount); i++ {
blockNumber -= (1 - req.Skip)
headers[i] = c.blocks[blockNumber].Header()
}
-
return headers, nil
}
-
for i := 1; i < int(req.Amount); i++ {
blockNumber += (1 + req.Skip)
headers[i] = c.blocks[blockNumber].Header()
}
-
return headers, nil
}
-// loadChain takes the given chain.rlp file, and decodes and returns
-// the blocks from the file.
-func loadChain(chainfile string, genesis string) (*Chain, error) {
- gen, err := loadGenesis(genesis)
- if err != nil {
- return nil, err
- }
- gblock := gen.ToBlock()
+// Shorten returns a copy chain of a desired height from the imported
+func (c *Chain) Shorten(height int) *Chain {
+ blocks := make([]*types.Block, height)
+ copy(blocks, c.blocks[:height])
- blocks, err := blocksFromFile(chainfile, gblock)
- if err != nil {
- return nil, err
+ config := *c.config
+ return &Chain{
+ blocks: blocks,
+ config: &config,
}
-
- c := &Chain{genesis: gen, blocks: blocks, chainConfig: gen.Config}
- return c, nil
}
func loadGenesis(genesisFile string) (core.Genesis, error) {
@@ -163,6 +261,22 @@ func loadGenesis(genesisFile string) (core.Genesis, error) {
return gen, nil
}
+type Addresses []common.Address
+
+func (a Addresses) Len() int {
+ return len(a)
+}
+
+func (a Addresses) Less(i, j int) bool {
+ return bytes.Compare(a[i][:], a[j][:]) < 0
+}
+
+func (a Addresses) Swap(i, j int) {
+ tmp := a[i]
+ a[i] = a[j]
+ a[j] = tmp
+}
+
func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, error) {
// Load chain.rlp.
fh, err := os.Open(chainfile)
@@ -193,3 +307,47 @@ func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, erro
}
return blocks, nil
}
+
+func readState(file string) (map[common.Address]state.DumpAccount, error) {
+ f, err := os.ReadFile(file)
+ if err != nil {
+ return nil, fmt.Errorf("unable to read state: %v", err)
+ }
+ var dump state.Dump
+ if err := json.Unmarshal(f, &dump); err != nil {
+ return nil, fmt.Errorf("unable to unmarshal state: %v", err)
+ }
+
+ state := make(map[common.Address]state.DumpAccount)
+ for key, acct := range dump.Accounts {
+ var addr common.Address
+ if err := addr.UnmarshalText([]byte(key)); err != nil {
+ return nil, fmt.Errorf("invalid address %q", key)
+ }
+ state[addr] = acct
+ }
+ return state, nil
+}
+
+func readAccounts(file string) (map[common.Address]*senderInfo, error) {
+ f, err := os.ReadFile(file)
+ if err != nil {
+ return nil, fmt.Errorf("unable to read state: %v", err)
+ }
+ type account struct {
+ Key hexutil.Bytes `json:"key"`
+ }
+ keys := make(map[common.Address]account)
+ if err := json.Unmarshal(f, &keys); err != nil {
+ return nil, fmt.Errorf("unable to unmarshal accounts: %v", err)
+ }
+ accounts := make(map[common.Address]*senderInfo)
+ for addr, acc := range keys {
+ pk, err := crypto.HexToECDSA(common.Bytes2Hex(acc.Key))
+ if err != nil {
+ return nil, fmt.Errorf("unable to read private key for %s: %v", err, addr)
+ }
+ accounts[addr] = &senderInfo{Key: pk, Nonce: 0}
+ }
+ return accounts, nil
+}
diff --git a/cmd/devp2p/internal/ethtest/chain_test.go b/cmd/devp2p/internal/ethtest/chain_test.go
index 67221923a6..62bd6d26ea 100644
--- a/cmd/devp2p/internal/ethtest/chain_test.go
+++ b/cmd/devp2p/internal/ethtest/chain_test.go
@@ -30,6 +30,7 @@ import (
// TestEthProtocolNegotiation tests whether the test suite
// can negotiate the highest eth protocol in a status message exchange
func TestEthProtocolNegotiation(t *testing.T) {
+ t.Parallel()
var tests = []struct {
conn *Conn
caps []p2p.Cap
@@ -122,30 +123,27 @@ func TestEthProtocolNegotiation(t *testing.T) {
}
}
-// TestChain_GetHeaders tests whether the test suite can correctly
+// TestChainGetHeaders tests whether the test suite can correctly
// respond to a GetBlockHeaders request from a node.
-func TestChain_GetHeaders(t *testing.T) {
- chainFile, err := filepath.Abs("./testdata/chain.rlp")
- if err != nil {
- t.Fatal(err)
- }
- genesisFile, err := filepath.Abs("./testdata/genesis.json")
+func TestChainGetHeaders(t *testing.T) {
+ t.Parallel()
+
+ dir, err := filepath.Abs("./testdata")
if err != nil {
t.Fatal(err)
}
-
- chain, err := loadChain(chainFile, genesisFile)
+ chain, err := NewChain(dir)
if err != nil {
t.Fatal(err)
}
var tests = []struct {
- req GetBlockHeaders
+ req eth.GetBlockHeadersPacket
expected []*types.Header
}{
{
- req: GetBlockHeaders{
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ req: eth.GetBlockHeadersPacket{
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Number: uint64(2)},
Amount: uint64(5),
Skip: 1,
@@ -161,8 +159,8 @@ func TestChain_GetHeaders(t *testing.T) {
},
},
{
- req: GetBlockHeaders{
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ req: eth.GetBlockHeadersPacket{
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Number: uint64(chain.Len() - 1)},
Amount: uint64(3),
Skip: 0,
@@ -176,8 +174,8 @@ func TestChain_GetHeaders(t *testing.T) {
},
},
{
- req: GetBlockHeaders{
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ req: eth.GetBlockHeadersPacket{
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Hash: chain.Head().Hash()},
Amount: uint64(1),
Skip: 0,
diff --git a/cmd/devp2p/internal/ethtest/conn.go b/cmd/devp2p/internal/ethtest/conn.go
new file mode 100644
index 0000000000..e13f47082a
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/conn.go
@@ -0,0 +1,370 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package ethtest
+
+import (
+ "crypto/ecdsa"
+ "errors"
+ "fmt"
+ "net"
+ "reflect"
+ "time"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/protocols/eth"
+ "github.com/ethereum/go-ethereum/eth/protocols/snap"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/rlpx"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+var (
+ pretty = spew.ConfigState{
+ Indent: " ",
+ DisableCapacities: true,
+ DisablePointerAddresses: true,
+ SortKeys: true,
+ }
+ timeout = 2 * time.Second
+)
+
+// dial attempts to dial the given node and perform a handshake, returning the
+// created Conn if successful.
+func (s *Suite) dial() (*Conn, error) {
+ key, _ := crypto.GenerateKey()
+ return s.dialAs(key)
+}
+
+// dialAs attempts to dial a given node and perform a handshake using the given
+// private key.
+func (s *Suite) dialAs(key *ecdsa.PrivateKey) (*Conn, error) {
+ fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", s.Dest.IP(), s.Dest.TCP()))
+ if err != nil {
+ return nil, err
+ }
+ conn := Conn{Conn: rlpx.NewConn(fd, s.Dest.Pubkey())}
+ conn.ourKey = key
+ _, err = conn.Handshake(conn.ourKey)
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+ conn.caps = []p2p.Cap{
+ {Name: "eth", Version: 67},
+ {Name: "eth", Version: 68},
+ }
+ conn.ourHighestProtoVersion = 68
+ return &conn, nil
+}
+
+// dialSnap creates a connection with snap/1 capability.
+func (s *Suite) dialSnap() (*Conn, error) {
+ conn, err := s.dial()
+ if err != nil {
+ return nil, fmt.Errorf("dial failed: %v", err)
+ }
+ conn.caps = append(conn.caps, p2p.Cap{Name: "snap", Version: 1})
+ conn.ourHighestSnapProtoVersion = 1
+ return conn, nil
+}
+
+// Conn represents an individual connection with a peer
+type Conn struct {
+ *rlpx.Conn
+ ourKey *ecdsa.PrivateKey
+ negotiatedProtoVersion uint
+ negotiatedSnapProtoVersion uint
+ ourHighestProtoVersion uint
+ ourHighestSnapProtoVersion uint
+ caps []p2p.Cap
+}
+
+// Read reads a packet from the connection.
+func (c *Conn) Read() (uint64, []byte, error) {
+ c.SetReadDeadline(time.Now().Add(timeout))
+ code, data, _, err := c.Conn.Read()
+ if err != nil {
+ return 0, nil, err
+ }
+ return code, data, nil
+}
+
+// ReadMsg attempts to read a devp2p message with a specific code.
+func (c *Conn) ReadMsg(proto Proto, code uint64, msg any) error {
+ c.SetReadDeadline(time.Now().Add(timeout))
+ for {
+ got, data, err := c.Read()
+ if err != nil {
+ return err
+ }
+ if protoOffset(proto)+code == got {
+ return rlp.DecodeBytes(data, msg)
+ }
+ }
+}
+
+// Write writes a eth packet to the connection.
+func (c *Conn) Write(proto Proto, code uint64, msg any) error {
+ c.SetWriteDeadline(time.Now().Add(timeout))
+ payload, err := rlp.EncodeToBytes(msg)
+ if err != nil {
+ return err
+ }
+ _, err = c.Conn.Write(protoOffset(proto)+code, payload)
+ return err
+}
+
+// ReadEth reads an Eth sub-protocol wire message.
+func (c *Conn) ReadEth() (any, error) {
+ c.SetReadDeadline(time.Now().Add(timeout))
+ for {
+ code, data, _, err := c.Conn.Read()
+ if err != nil {
+ return nil, err
+ }
+ if code == pingMsg {
+ c.Write(baseProto, pongMsg, []byte{})
+ continue
+ }
+ if getProto(code) != ethProto {
+ // Read until eth message.
+ continue
+ }
+ code -= baseProtoLen
+
+ var msg any
+ switch int(code) {
+ case eth.StatusMsg:
+ msg = new(eth.StatusPacket)
+ case eth.GetBlockHeadersMsg:
+ msg = new(eth.GetBlockHeadersPacket)
+ case eth.BlockHeadersMsg:
+ msg = new(eth.BlockHeadersPacket)
+ case eth.GetBlockBodiesMsg:
+ 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:
+ msg = new(eth.NewPooledTransactionHashesPacket68)
+ case eth.GetPooledTransactionsMsg:
+ msg = new(eth.GetPooledTransactionsPacket)
+ case eth.PooledTransactionsMsg:
+ msg = new(eth.PooledTransactionsPacket)
+ default:
+ panic(fmt.Sprintf("unhandled eth msg code %d", code))
+ }
+ if err := rlp.DecodeBytes(data, msg); err != nil {
+ return nil, fmt.Errorf("unable to decode eth msg: %v", err)
+ }
+ return msg, nil
+ }
+}
+
+// ReadSnap reads a snap/1 response with the given id from the connection.
+func (c *Conn) ReadSnap() (any, error) {
+ c.SetReadDeadline(time.Now().Add(timeout))
+ for {
+ code, data, _, err := c.Conn.Read()
+ if err != nil {
+ return nil, err
+ }
+ if getProto(code) != snapProto {
+ // Read until snap message.
+ continue
+ }
+ code -= baseProtoLen + ethProtoLen
+
+ var msg any
+ switch int(code) {
+ case snap.GetAccountRangeMsg:
+ msg = new(snap.GetAccountRangePacket)
+ case snap.AccountRangeMsg:
+ msg = new(snap.AccountRangePacket)
+ case snap.GetStorageRangesMsg:
+ msg = new(snap.GetStorageRangesPacket)
+ case snap.StorageRangesMsg:
+ msg = new(snap.StorageRangesPacket)
+ case snap.GetByteCodesMsg:
+ msg = new(snap.GetByteCodesPacket)
+ case snap.ByteCodesMsg:
+ msg = new(snap.ByteCodesPacket)
+ case snap.GetTrieNodesMsg:
+ msg = new(snap.GetTrieNodesPacket)
+ case snap.TrieNodesMsg:
+ msg = new(snap.TrieNodesPacket)
+ default:
+ panic(fmt.Errorf("unhandled snap code: %d", code))
+ }
+ if err := rlp.DecodeBytes(data, msg); err != nil {
+ return nil, fmt.Errorf("could not rlp decode message: %v", err)
+ }
+ return msg, nil
+ }
+}
+
+// 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 {
+ if err := c.handshake(); err != nil {
+ return fmt.Errorf("handshake failed: %v", err)
+ }
+ if err := c.statusExchange(chain, status); err != nil {
+ return fmt.Errorf("status exchange failed: %v", err)
+ }
+ return nil
+}
+
+// handshake performs a protocol handshake with the node.
+func (c *Conn) handshake() error {
+ // Write hello to client.
+ pub0 := crypto.FromECDSAPub(&c.ourKey.PublicKey)[1:]
+ ourHandshake := &protoHandshake{
+ Version: 5,
+ Caps: c.caps,
+ ID: pub0,
+ }
+ if err := c.Write(baseProto, handshakeMsg, ourHandshake); err != nil {
+ return fmt.Errorf("write to connection failed: %v", err)
+ }
+ // Read hello from client.
+ code, data, err := c.Read()
+ if err != nil {
+ return fmt.Errorf("erroring reading handshake: %v", err)
+ }
+ switch code {
+ case handshakeMsg:
+ msg := new(protoHandshake)
+ if err := rlp.DecodeBytes(data, &msg); err != nil {
+ return fmt.Errorf("error decoding handshake msg: %v", err)
+ }
+ // Set snappy if version is at least 5.
+ if msg.Version >= 5 {
+ c.SetSnappy(true)
+ }
+ c.negotiateEthProtocol(msg.Caps)
+ if c.negotiatedProtoVersion == 0 {
+ return fmt.Errorf("could not negotiate eth protocol (remote caps: %v, local eth version: %v)", msg.Caps, c.ourHighestProtoVersion)
+ }
+ // If we require snap, verify that it was negotiated.
+ if c.ourHighestSnapProtoVersion != c.negotiatedSnapProtoVersion {
+ return fmt.Errorf("could not negotiate snap protocol (remote caps: %v, local snap version: %v)", msg.Caps, c.ourHighestSnapProtoVersion)
+ }
+ return nil
+ default:
+ return fmt.Errorf("bad handshake: got msg code %d", code)
+ }
+}
+
+// negotiateEthProtocol sets the Conn's eth protocol version to highest
+// advertised capability from peer.
+func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) {
+ var highestEthVersion uint
+ var highestSnapVersion uint
+ for _, capability := range caps {
+ switch capability.Name {
+ case "eth":
+ if capability.Version > highestEthVersion && capability.Version <= c.ourHighestProtoVersion {
+ highestEthVersion = capability.Version
+ }
+ case "snap":
+ if capability.Version > highestSnapVersion && capability.Version <= c.ourHighestSnapProtoVersion {
+ highestSnapVersion = capability.Version
+ }
+ }
+ }
+ c.negotiatedProtoVersion = highestEthVersion
+ c.negotiatedSnapProtoVersion = highestSnapVersion
+}
+
+// statusExchange performs a `Status` message exchange with the given node.
+func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket) error {
+loop:
+ for {
+ code, data, err := c.Read()
+ if err != nil {
+ return fmt.Errorf("failed to read from connection: %w", err)
+ }
+ switch code {
+ case eth.StatusMsg + protoOffset(ethProto):
+ msg := new(eth.StatusPacket)
+ if err := rlp.DecodeBytes(data, &msg); err != nil {
+ return fmt.Errorf("error decoding status packet: %w", err)
+ }
+ if have, want := msg.Head, chain.blocks[chain.Len()-1].Hash(); have != want {
+ return fmt.Errorf("wrong head block in status, want: %#x (block %d) have %#x",
+ want, chain.blocks[chain.Len()-1].NumberU64(), have)
+ }
+ if have, want := msg.TD.Cmp(chain.TD()), 0; have != want {
+ return fmt.Errorf("wrong TD in status: have %v want %v", have, want)
+ }
+ if have, want := msg.ForkID, chain.ForkID(); !reflect.DeepEqual(have, want) {
+ return fmt.Errorf("wrong fork ID in status: have %v, want %v", have, want)
+ }
+ if have, want := msg.ProtocolVersion, c.ourHighestProtoVersion; have != uint32(want) {
+ return fmt.Errorf("wrong protocol version: have %v, want %v", have, want)
+ }
+ // make sure eth protocol version is set for negotiation
+ if c.negotiatedProtoVersion == 0 {
+ return errors.New("eth protocol version must be set in Conn")
+ }
+ if status == nil {
+ // default status message
+ status = ð.StatusPacket{
+ ProtocolVersion: uint32(c.negotiatedProtoVersion),
+ NetworkID: chain.config.ChainID.Uint64(),
+ TD: chain.TD(),
+ Head: chain.blocks[chain.Len()-1].Hash(),
+ Genesis: chain.blocks[0].Hash(),
+ ForkID: chain.ForkID(),
+ }
+ }
+ if err := c.Write(ethProto, eth.StatusMsg, status); err != nil {
+ return fmt.Errorf("write to connection failed: %v", err)
+ }
+ case eth.UpgradeStatusMsg + protoOffset(ethProto):
+ msg := new(eth.UpgradeStatusPacket)
+ if err := rlp.DecodeBytes(data, &msg); err != nil {
+ return fmt.Errorf("error decoding status packet: %w", err)
+ }
+ if err := c.Write(ethProto, eth.UpgradeStatusMsg, msg); err != nil {
+ return fmt.Errorf("write to connection failed: %v", err)
+ }
+ break loop
+ case discMsg:
+ var msg []p2p.DiscReason
+ if rlp.DecodeBytes(data, &msg); len(msg) == 0 {
+ return errors.New("invalid disconnect message")
+ }
+ return fmt.Errorf("disconnect received: %v", pretty.Sdump(msg))
+ case pingMsg:
+ // TODO (renaynay): in the future, this should be an error
+ // (PINGs should not be a response upon fresh connection)
+ c.Write(baseProto, pongMsg, nil)
+ default:
+ return fmt.Errorf("bad status message: code %d", code)
+ }
+ }
+
+ return nil
+}
diff --git a/cmd/devp2p/internal/ethtest/engine.go b/cmd/devp2p/internal/ethtest/engine.go
new file mode 100644
index 0000000000..ea4fc76e6f
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/engine.go
@@ -0,0 +1,69 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package ethtest
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "path"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/golang-jwt/jwt/v4"
+)
+
+// EngineClient is a wrapper around engine-related data.
+type EngineClient struct {
+ url string
+ jwt [32]byte
+ headfcu []byte
+}
+
+// NewEngineClient creates a new engine client.
+func NewEngineClient(dir, url, jwt string) (*EngineClient, error) {
+ headfcu, err := os.ReadFile(path.Join(dir, "headfcu.json"))
+ if err != nil {
+ return nil, fmt.Errorf("failed to read headfcu: %w", err)
+ }
+ return &EngineClient{url, common.HexToHash(jwt), headfcu}, nil
+}
+
+// token returns the jwt claim token for authorization.
+func (ec *EngineClient) token() string {
+ claims := jwt.RegisteredClaims{IssuedAt: jwt.NewNumericDate(time.Now())}
+ token, _ := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(ec.jwt[:])
+ return token
+}
+
+// sendForkchoiceUpdated sends an fcu for the head of the generated chain.
+func (ec *EngineClient) sendForkchoiceUpdated() error {
+ var (
+ req, _ = http.NewRequest(http.MethodPost, ec.url, io.NopCloser(bytes.NewReader(ec.headfcu)))
+ header = make(http.Header)
+ )
+ // Set header
+ header.Set("accept", "application/json")
+ header.Set("content-type", "application/json")
+ header.Set("Authorization", fmt.Sprintf("Bearer %v", ec.token()))
+ req.Header = header
+
+ _, err := new(http.Client).Do(req)
+ return err
+}
diff --git a/cmd/devp2p/internal/ethtest/helpers.go b/cmd/devp2p/internal/ethtest/helpers.go
deleted file mode 100644
index bab9696ffc..0000000000
--- a/cmd/devp2p/internal/ethtest/helpers.go
+++ /dev/null
@@ -1,675 +0,0 @@
-// Copyright 2021 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see .
-
-package ethtest
-
-import (
- "errors"
- "fmt"
- "net"
- "reflect"
- "strings"
- "time"
-
- "github.com/davecgh/go-spew/spew"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth/protocols/eth"
- "github.com/ethereum/go-ethereum/internal/utesting"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/p2p/rlpx"
-)
-
-var (
- pretty = spew.ConfigState{
- Indent: " ",
- DisableCapacities: true,
- DisablePointerAddresses: true,
- SortKeys: true,
- }
- timeout = 20 * time.Second
-)
-
-// dial attempts to dial the given node and perform a handshake,
-// returning the created Conn if successful.
-func (s *Suite) dial() (*Conn, error) {
- // dial
- fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", s.Dest.IP(), s.Dest.TCP()))
- if err != nil {
- return nil, err
- }
- conn := Conn{Conn: rlpx.NewConn(fd, s.Dest.Pubkey())}
- // do encHandshake
- conn.ourKey, _ = crypto.GenerateKey()
- _, err = conn.Handshake(conn.ourKey)
- if err != nil {
- conn.Close()
- return nil, err
- }
- // set default p2p capabilities
- conn.caps = []p2p.Cap{
- {Name: "eth", Version: 66},
- {Name: "eth", Version: 67},
- {Name: "eth", Version: 68},
- }
- conn.ourHighestProtoVersion = 68
- return &conn, nil
-}
-
-// dialSnap creates a connection with snap/1 capability.
-func (s *Suite) dialSnap() (*Conn, error) {
- conn, err := s.dial()
- if err != nil {
- return nil, fmt.Errorf("dial failed: %v", err)
- }
- conn.caps = append(conn.caps, p2p.Cap{Name: "snap", Version: 1})
- conn.ourHighestSnapProtoVersion = 1
- return conn, nil
-}
-
-// 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 *Status) error {
- if err := c.handshake(); err != nil {
- return fmt.Errorf("handshake failed: %v", err)
- }
- if _, err := c.statusExchange(chain, status); err != nil {
- return fmt.Errorf("status exchange failed: %v", err)
- }
- return nil
-}
-
-// handshake performs a protocol handshake with the node.
-func (c *Conn) handshake() error {
- defer c.SetDeadline(time.Time{})
- c.SetDeadline(time.Now().Add(10 * time.Second))
- // write hello to client
- pub0 := crypto.FromECDSAPub(&c.ourKey.PublicKey)[1:]
- ourHandshake := &Hello{
- Version: 5,
- Caps: c.caps,
- ID: pub0,
- }
- if err := c.Write(ourHandshake); err != nil {
- return fmt.Errorf("write to connection failed: %v", err)
- }
- // read hello from client
- switch msg := c.Read().(type) {
- case *Hello:
- // set snappy if version is at least 5
- if msg.Version >= 5 {
- c.SetSnappy(true)
- }
- c.negotiateEthProtocol(msg.Caps)
- if c.negotiatedProtoVersion == 0 {
- return fmt.Errorf("could not negotiate eth protocol (remote caps: %v, local eth version: %v)", msg.Caps, c.ourHighestProtoVersion)
- }
- // If we require snap, verify that it was negotiated
- if c.ourHighestSnapProtoVersion != c.negotiatedSnapProtoVersion {
- return fmt.Errorf("could not negotiate snap protocol (remote caps: %v, local snap version: %v)", msg.Caps, c.ourHighestSnapProtoVersion)
- }
- return nil
- default:
- return fmt.Errorf("bad handshake: %#v", msg)
- }
-}
-
-// negotiateEthProtocol sets the Conn's eth protocol version to highest
-// advertised capability from peer.
-func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) {
- var highestEthVersion uint
- var highestSnapVersion uint
- for _, capability := range caps {
- switch capability.Name {
- case "eth":
- if capability.Version > highestEthVersion && capability.Version <= c.ourHighestProtoVersion {
- highestEthVersion = capability.Version
- }
- case "snap":
- if capability.Version > highestSnapVersion && capability.Version <= c.ourHighestSnapProtoVersion {
- highestSnapVersion = capability.Version
- }
- }
- }
- c.negotiatedProtoVersion = highestEthVersion
- c.negotiatedSnapProtoVersion = highestSnapVersion
-}
-
-// statusExchange performs a `Status` message exchange with the given node.
-func (c *Conn) statusExchange(chain *Chain, status *Status) (Message, error) {
- defer c.SetDeadline(time.Time{})
- c.SetDeadline(time.Now().Add(20 * time.Second))
-
- // read status message from client
- var message Message
-loop:
- for {
- switch msg := c.Read().(type) {
- case *Status:
- if have, want := msg.Head, chain.blocks[chain.Len()-1].Hash(); have != want {
- return nil, fmt.Errorf("wrong head block in status, want: %#x (block %d) have %#x",
- want, chain.blocks[chain.Len()-1].NumberU64(), have)
- }
- if have, want := msg.TD.Cmp(chain.TD()), 0; have != want {
- return nil, fmt.Errorf("wrong TD in status: have %v want %v", have, want)
- }
- if have, want := msg.ForkID, chain.ForkID(); !reflect.DeepEqual(have, want) {
- return nil, fmt.Errorf("wrong fork ID in status: have %v, want %v", have, want)
- }
- if have, want := msg.ProtocolVersion, c.ourHighestProtoVersion; have != uint32(want) {
- return nil, fmt.Errorf("wrong protocol version: have %v, want %v", have, want)
- }
- message = msg
- break loop
- case *Disconnect:
- return nil, fmt.Errorf("disconnect received: %v", msg.Reason)
- case *Ping:
- c.Write(&Pong{}) // TODO (renaynay): in the future, this should be an error
- // (PINGs should not be a response upon fresh connection)
- default:
- return nil, fmt.Errorf("bad status message: %s", pretty.Sdump(msg))
- }
- }
- // make sure eth protocol version is set for negotiation
- if c.negotiatedProtoVersion == 0 {
- return nil, errors.New("eth protocol version must be set in Conn")
- }
- if status == nil {
- // default status message
- status = &Status{
- ProtocolVersion: uint32(c.negotiatedProtoVersion),
- NetworkID: chain.chainConfig.ChainID.Uint64(),
- TD: chain.TD(),
- Head: chain.blocks[chain.Len()-1].Hash(),
- Genesis: chain.blocks[0].Hash(),
- ForkID: chain.ForkID(),
- }
- }
- if err := c.Write(status); err != nil {
- return nil, fmt.Errorf("write to connection failed: %v", err)
- }
-
- // exchange UpgradeStatus
- if c.negotiatedProtoVersion >= eth.ETH67 {
- extensionRaw, _ := (ð.UpgradeStatusExtension{}).Encode()
- upgradeStatus := UpgradeStatus{
- Extension: extensionRaw,
- }
- if err := c.Write(upgradeStatus); err != nil {
- return nil, fmt.Errorf("write to connection failed: %v", err)
- }
- switch msg := c.Read().(type) {
- case *UpgradeStatus:
- log.Debug("receive UpgradeStatus")
- case *Disconnect:
- return nil, fmt.Errorf("disconnect received: %v", msg.Reason)
- case *Ping:
- c.Write(&Pong{}) // TODO (renaynay): in the future, this should be an error
- // (PINGs should not be a response upon fresh connection)
- default:
- return nil, fmt.Errorf("bad status message: %s", pretty.Sdump(msg))
- }
- }
-
- return message, nil
-}
-
-// createSendAndRecvConns creates two connections, one for sending messages to the
-// node, and one for receiving messages from the node.
-func (s *Suite) createSendAndRecvConns() (*Conn, *Conn, error) {
- sendConn, err := s.dial()
- if err != nil {
- return nil, nil, fmt.Errorf("dial failed: %v", err)
- }
- recvConn, err := s.dial()
- if err != nil {
- sendConn.Close()
- return nil, nil, fmt.Errorf("dial failed: %v", err)
- }
- return sendConn, recvConn, nil
-}
-
-// readAndServe serves GetBlockHeaders requests while waiting
-// on another message from the node.
-func (c *Conn) readAndServe(chain *Chain, timeout time.Duration) Message {
- start := time.Now()
- for time.Since(start) < timeout {
- c.SetReadDeadline(time.Now().Add(10 * time.Second))
-
- msg := c.Read()
- switch msg := msg.(type) {
- case *Ping:
- c.Write(&Pong{})
- case *GetBlockHeaders:
- headers, err := chain.GetHeaders(msg)
- if err != nil {
- return errorf("could not get headers for inbound header request: %v", err)
- }
- resp := &BlockHeaders{
- RequestId: msg.ReqID(),
- BlockHeadersPacket: eth.BlockHeadersPacket(headers),
- }
- if err := c.Write(resp); err != nil {
- return errorf("could not write to connection: %v", err)
- }
- default:
- return msg
- }
- }
- return errorf("no message received within %v", timeout)
-}
-
-// headersRequest executes the given `GetBlockHeaders` request.
-func (c *Conn) headersRequest(request *GetBlockHeaders, chain *Chain, reqID uint64) ([]*types.Header, error) {
- defer c.SetReadDeadline(time.Time{})
- c.SetReadDeadline(time.Now().Add(20 * time.Second))
-
- // write request
- request.RequestId = reqID
- if err := c.Write(request); err != nil {
- return nil, fmt.Errorf("could not write to connection: %v", err)
- }
-
- // wait for response
- msg := c.waitForResponse(chain, timeout, request.RequestId)
- resp, ok := msg.(*BlockHeaders)
- if !ok {
- return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg))
- }
- headers := []*types.Header(resp.BlockHeadersPacket)
- return headers, nil
-}
-
-func (c *Conn) snapRequest(msg Message, id uint64, chain *Chain) (Message, error) {
- defer c.SetReadDeadline(time.Time{})
- c.SetReadDeadline(time.Now().Add(5 * time.Second))
- if err := c.Write(msg); err != nil {
- return nil, fmt.Errorf("could not write to connection: %v", err)
- }
- return c.ReadSnap(id)
-}
-
-// headersMatch returns whether the received headers match the given request
-func headersMatch(expected []*types.Header, headers []*types.Header) bool {
- return reflect.DeepEqual(expected, headers)
-}
-
-// waitForResponse reads from the connection until a response with the expected
-// request ID is received.
-func (c *Conn) waitForResponse(chain *Chain, timeout time.Duration, requestID uint64) Message {
- for {
- msg := c.readAndServe(chain, timeout)
- if msg.ReqID() == requestID {
- return msg
- }
- }
-}
-
-// sendNextBlock broadcasts the next block in the chain and waits
-// for the node to propagate the block and import it into its chain.
-func (s *Suite) sendNextBlock() error {
- // set up sending and receiving connections
- sendConn, recvConn, err := s.createSendAndRecvConns()
- if err != nil {
- return err
- }
- defer sendConn.Close()
- defer recvConn.Close()
- if err = sendConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
- if err = recvConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
- // create new block announcement
- nextBlock := s.fullChain.blocks[s.chain.Len()]
- blockAnnouncement := &NewBlock{
- Block: nextBlock,
- TD: s.fullChain.TotalDifficultyAt(s.chain.Len()),
- }
- // send announcement and wait for node to request the header
- if err = s.testAnnounce(sendConn, recvConn, blockAnnouncement); err != nil {
- return fmt.Errorf("failed to announce block: %v", err)
- }
- // wait for client to update its chain
- if err = s.waitForBlockImport(recvConn, nextBlock); err != nil {
- return fmt.Errorf("failed to receive confirmation of block import: %v", err)
- }
- // update test suite chain
- s.chain.blocks = append(s.chain.blocks, nextBlock)
- return nil
-}
-
-// testAnnounce writes a block announcement to the node and waits for the node
-// to propagate it.
-func (s *Suite) testAnnounce(sendConn, receiveConn *Conn, blockAnnouncement *NewBlock) error {
- if err := sendConn.Write(blockAnnouncement); err != nil {
- return fmt.Errorf("could not write to connection: %v", err)
- }
- return s.waitAnnounce(receiveConn, blockAnnouncement)
-}
-
-// waitAnnounce waits for a NewBlock or NewBlockHashes announcement from the node.
-func (s *Suite) waitAnnounce(conn *Conn, blockAnnouncement *NewBlock) error {
- for {
- switch msg := conn.readAndServe(s.chain, timeout).(type) {
- case *NewBlock:
- if !reflect.DeepEqual(blockAnnouncement.Block.Header(), msg.Block.Header()) {
- return fmt.Errorf("wrong header in block announcement: \nexpected %v "+
- "\ngot %v", blockAnnouncement.Block.Header(), msg.Block.Header())
- }
- if !reflect.DeepEqual(blockAnnouncement.TD, msg.TD) {
- return fmt.Errorf("wrong TD in announcement: expected %v, got %v", blockAnnouncement.TD, msg.TD)
- }
- return nil
- case *NewBlockHashes:
- hashes := *msg
- if blockAnnouncement.Block.Hash() != hashes[0].Hash {
- return fmt.Errorf("wrong block hash in announcement: expected %v, got %v", blockAnnouncement.Block.Hash(), hashes[0].Hash)
- }
- return nil
-
- // ignore tx announcements from previous tests
- case *NewPooledTransactionHashes66:
- continue
- case *NewPooledTransactionHashes:
- continue
- case *Transactions:
- continue
-
- default:
- return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
- }
- }
-}
-
-func (s *Suite) waitForBlockImport(conn *Conn, block *types.Block) error {
- defer conn.SetReadDeadline(time.Time{})
- conn.SetReadDeadline(time.Now().Add(20 * time.Second))
- // create request
- req := &GetBlockHeaders{
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
- Origin: eth.HashOrNumber{Hash: block.Hash()},
- Amount: 1,
- },
- }
-
- // loop until BlockHeaders response contains desired block, confirming the
- // node imported the block
- for {
- requestID := uint64(54)
- headers, err := conn.headersRequest(req, s.chain, requestID)
- if err != nil {
- return fmt.Errorf("GetBlockHeader request failed: %v", err)
- }
- // if headers response is empty, node hasn't imported block yet, try again
- if len(headers) == 0 {
- time.Sleep(100 * time.Millisecond)
- continue
- }
- if !reflect.DeepEqual(block.Header(), headers[0]) {
- return fmt.Errorf("wrong header returned: wanted %v, got %v", block.Header(), headers[0])
- }
- return nil
- }
-}
-
-func (s *Suite) oldAnnounce() error {
- sendConn, receiveConn, err := s.createSendAndRecvConns()
- if err != nil {
- return err
- }
- defer sendConn.Close()
- defer receiveConn.Close()
- if err := sendConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
- if err := receiveConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
- // create old block announcement
- oldBlockAnnounce := &NewBlock{
- Block: s.chain.blocks[len(s.chain.blocks)/2],
- TD: s.chain.blocks[len(s.chain.blocks)/2].Difficulty(),
- }
- if err := sendConn.Write(oldBlockAnnounce); err != nil {
- return fmt.Errorf("could not write to connection: %v", err)
- }
- // wait to see if the announcement is propagated
- switch msg := receiveConn.readAndServe(s.chain, time.Second*8).(type) {
- case *NewBlock:
- block := *msg
- if block.Block.Hash() == oldBlockAnnounce.Block.Hash() {
- return fmt.Errorf("unexpected: block propagated: %s", pretty.Sdump(msg))
- }
- case *NewBlockHashes:
- hashes := *msg
- for _, hash := range hashes {
- if hash.Hash == oldBlockAnnounce.Block.Hash() {
- return fmt.Errorf("unexpected: block announced: %s", pretty.Sdump(msg))
- }
- }
- case *Error:
- errMsg := *msg
- // check to make sure error is timeout (propagation didn't come through == test successful)
- if !strings.Contains(errMsg.String(), "timeout") {
- return fmt.Errorf("unexpected error: %v", pretty.Sdump(msg))
- }
- default:
- return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
- }
- return nil
-}
-
-func (s *Suite) maliciousHandshakes(t *utesting.T) error {
- conn, err := s.dial()
- if err != nil {
- return fmt.Errorf("dial failed: %v", err)
- }
- defer conn.Close()
-
- // write hello to client
- pub0 := crypto.FromECDSAPub(&conn.ourKey.PublicKey)[1:]
- handshakes := []*Hello{
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: largeString(2), Version: 64},
- },
- ID: pub0,
- },
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: "eth", Version: 64},
- {Name: "eth", Version: 65},
- },
- ID: append(pub0, byte(0)),
- },
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: "eth", Version: 64},
- {Name: "eth", Version: 65},
- },
- ID: append(pub0, pub0...),
- },
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: "eth", Version: 64},
- {Name: "eth", Version: 65},
- },
- ID: largeBuffer(2),
- },
- {
- Version: 5,
- Caps: []p2p.Cap{
- {Name: largeString(2), Version: 64},
- },
- ID: largeBuffer(2),
- },
- }
- for i, handshake := range handshakes {
- t.Logf("Testing malicious handshake %v\n", i)
- if err := conn.Write(handshake); err != nil {
- return fmt.Errorf("could not write to connection: %v", err)
- }
- // check that the peer disconnected
- for i := 0; i < 2; i++ {
- switch msg := conn.readAndServe(s.chain, 20*time.Second).(type) {
- case *Disconnect:
- case *Error:
- case *Hello:
- // Discard one hello as Hello's are sent concurrently
- continue
- default:
- return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
- }
- }
- // dial for the next round
- conn, err = s.dial()
- if err != nil {
- return fmt.Errorf("dial failed: %v", err)
- }
- }
- return nil
-}
-
-func (s *Suite) maliciousStatus(conn *Conn) error {
- if err := conn.handshake(); err != nil {
- return fmt.Errorf("handshake failed: %v", err)
- }
- status := &Status{
- ProtocolVersion: uint32(conn.negotiatedProtoVersion),
- NetworkID: s.chain.chainConfig.ChainID.Uint64(),
- TD: largeNumber(2),
- Head: s.chain.blocks[s.chain.Len()-1].Hash(),
- Genesis: s.chain.blocks[0].Hash(),
- ForkID: s.chain.ForkID(),
- }
-
- // get status
- msg, err := conn.statusExchange(s.chain, status)
- if err != nil {
- return fmt.Errorf("status exchange failed: %v", err)
- }
- switch msg := msg.(type) {
- case *Status:
- default:
- return fmt.Errorf("expected status, got: %#v ", msg)
- }
-
- // wait for disconnect
- switch msg := conn.readAndServe(s.chain, timeout).(type) {
- case *Disconnect:
- return nil
- case *Error:
- return nil
- default:
- return fmt.Errorf("expected disconnect, got: %s", pretty.Sdump(msg))
- }
-}
-
-func (s *Suite) hashAnnounce() error {
- // create connections
- sendConn, recvConn, err := s.createSendAndRecvConns()
- if err != nil {
- return fmt.Errorf("failed to create connections: %v", err)
- }
- defer sendConn.Close()
- defer recvConn.Close()
- if err := sendConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
- if err := recvConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- // create NewBlockHashes announcement
- type anno struct {
- Hash common.Hash // Hash of one particular block being announced
- Number uint64 // Number of one particular block being announced
- }
- nextBlock := s.fullChain.blocks[s.chain.Len()]
- announcement := anno{Hash: nextBlock.Hash(), Number: nextBlock.Number().Uint64()}
- newBlockHash := &NewBlockHashes{announcement}
- if err := sendConn.Write(newBlockHash); err != nil {
- return fmt.Errorf("failed to write to connection: %v", err)
- }
-
- // Announcement sent, now wait for a header request
- msg := sendConn.Read()
- blockHeaderReq, ok := msg.(*GetBlockHeaders)
- if !ok {
- return fmt.Errorf("unexpected %s", pretty.Sdump(msg))
- }
- if blockHeaderReq.Amount != 1 {
- return fmt.Errorf("unexpected number of block headers requested: %v", blockHeaderReq.Amount)
- }
- if blockHeaderReq.Origin.Hash != announcement.Hash {
- return fmt.Errorf("unexpected block header requested. Announced:\n %v\n Remote request:\n%v",
- pretty.Sdump(announcement),
- pretty.Sdump(blockHeaderReq))
- }
- err = sendConn.Write(&BlockHeaders{
- RequestId: blockHeaderReq.ReqID(),
- BlockHeadersPacket: eth.BlockHeadersPacket{nextBlock.Header()},
- })
- if err != nil {
- return fmt.Errorf("failed to write to connection: %v", err)
- }
-
- // wait for block announcement
- msg = recvConn.readAndServe(s.chain, timeout)
- switch msg := msg.(type) {
- case *NewBlockHashes:
- hashes := *msg
- if len(hashes) != 1 {
- return fmt.Errorf("unexpected new block hash announcement: wanted 1 announcement, got %d", len(hashes))
- }
- if nextBlock.Hash() != hashes[0].Hash {
- return fmt.Errorf("unexpected block hash announcement, wanted %v, got %v", nextBlock.Hash(),
- hashes[0].Hash)
- }
-
- case *NewBlock:
- // node should only propagate NewBlock without having requested the body if the body is empty
- nextBlockBody := nextBlock.Body()
- if len(nextBlockBody.Transactions) != 0 || len(nextBlockBody.Uncles) != 0 {
- return fmt.Errorf("unexpected non-empty new block propagated: %s", pretty.Sdump(msg))
- }
- if msg.Block.Hash() != nextBlock.Hash() {
- return fmt.Errorf("mismatched hash of propagated new block: wanted %v, got %v",
- nextBlock.Hash(), msg.Block.Hash())
- }
- // check to make sure header matches header that was sent to the node
- if !reflect.DeepEqual(nextBlock.Header(), msg.Block.Header()) {
- return fmt.Errorf("incorrect header received: wanted %v, got %v", nextBlock.Header(), msg.Block.Header())
- }
- default:
- return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
- }
- // confirm node imported block
- if err := s.waitForBlockImport(recvConn, nextBlock); err != nil {
- return fmt.Errorf("error waiting for node to import new block: %v", err)
- }
- // update the chain
- s.chain.blocks = append(s.chain.blocks, nextBlock)
- return nil
-}
diff --git a/cmd/devp2p/internal/ethtest/large.go b/cmd/devp2p/internal/ethtest/large.go
deleted file mode 100644
index 40626c2068..0000000000
--- a/cmd/devp2p/internal/ethtest/large.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see .
-
-package ethtest
-
-import (
- "crypto/rand"
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
-)
-
-// largeNumber returns a very large big.Int.
-func largeNumber(megabytes int) *big.Int {
- buf := make([]byte, megabytes*1024*1024)
- rand.Read(buf)
- bigint := new(big.Int)
- bigint.SetBytes(buf)
- return bigint
-}
-
-// largeBuffer returns a very large buffer.
-func largeBuffer(megabytes int) []byte {
- buf := make([]byte, megabytes*1024*1024)
- rand.Read(buf)
- return buf
-}
-
-// largeString returns a very large string.
-func largeString(megabytes int) string {
- buf := make([]byte, megabytes*1024*1024)
- rand.Read(buf)
- return hexutil.Encode(buf)
-}
-
-func largeBlock() *types.Block {
- return types.NewBlockWithHeader(largeHeader())
-}
-
-// Returns a random hash
-func randHash() common.Hash {
- var h common.Hash
- rand.Read(h[:])
- return h
-}
-
-func largeHeader() *types.Header {
- return &types.Header{
- MixDigest: randHash(),
- ReceiptHash: randHash(),
- TxHash: randHash(),
- Nonce: types.BlockNonce{},
- Extra: []byte{},
- Bloom: types.Bloom{},
- GasUsed: 0,
- Coinbase: common.Address{},
- GasLimit: 0,
- UncleHash: types.EmptyUncleHash,
- Time: 1337,
- ParentHash: randHash(),
- Root: randHash(),
- Number: largeNumber(2),
- Difficulty: largeNumber(2),
- }
-}
diff --git a/cmd/devp2p/internal/ethtest/mkchain.sh b/cmd/devp2p/internal/ethtest/mkchain.sh
new file mode 100644
index 0000000000..b9253e8ca7
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/mkchain.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+hivechain generate \
+ --fork-interval 6 \
+ --tx-interval 1 \
+ --length 500 \
+ --outdir testdata \
+ --lastfork cancun \
+ --outputs accounts,genesis,chain,headstate,txinfo,headblock,headfcu,newpayload,forkenv
diff --git a/cmd/devp2p/internal/ethtest/protocol.go b/cmd/devp2p/internal/ethtest/protocol.go
new file mode 100644
index 0000000000..f5f5f7e489
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/protocol.go
@@ -0,0 +1,87 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+package ethtest
+
+import (
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Unexported devp2p message codes from p2p/peer.go.
+const (
+ handshakeMsg = 0x00
+ discMsg = 0x01
+ pingMsg = 0x02
+ pongMsg = 0x03
+)
+
+// Unexported devp2p protocol lengths from p2p package.
+const (
+ baseProtoLen = 16
+ ethProtoLen = 17
+ snapProtoLen = 8
+)
+
+// Unexported handshake structure from p2p/peer.go.
+type protoHandshake struct {
+ Version uint64
+ Name string
+ Caps []p2p.Cap
+ ListenPort uint64
+ ID []byte
+ Rest []rlp.RawValue `rlp:"tail"`
+}
+
+type Hello = protoHandshake
+
+// Proto is an enum representing devp2p protocol types.
+type Proto int
+
+const (
+ baseProto Proto = iota
+ ethProto
+ snapProto
+)
+
+// getProto returns the protocol a certain message code is associated with
+// (assuming the negotiated capabilities are exactly {eth,snap})
+func getProto(code uint64) Proto {
+ switch {
+ case code < baseProtoLen:
+ return baseProto
+ case code < baseProtoLen+ethProtoLen:
+ return ethProto
+ case code < baseProtoLen+ethProtoLen+snapProtoLen:
+ return snapProto
+ default:
+ panic("unhandled msg code beyond last protocol")
+ }
+}
+
+// protoOffset will return the offset at which the specified protocol's messages
+// begin.
+func protoOffset(proto Proto) uint64 {
+ switch proto {
+ case baseProto:
+ return 0
+ case ethProto:
+ return baseProtoLen
+ case snapProto:
+ return baseProtoLen + ethProtoLen
+ default:
+ panic("unhandled protocol")
+ }
+}
diff --git a/cmd/devp2p/internal/ethtest/snap.go b/cmd/devp2p/internal/ethtest/snap.go
index 8378cbcb62..64e0633585 100644
--- a/cmd/devp2p/internal/ethtest/snap.go
+++ b/cmd/devp2p/internal/ethtest/snap.go
@@ -20,9 +20,12 @@ import (
"bytes"
"errors"
"fmt"
+ "math/big"
"math/rand"
+ "reflect"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
@@ -32,6 +35,13 @@ import (
"golang.org/x/crypto/sha3"
)
+func (c *Conn) snapRequest(code uint64, msg any) (any, error) {
+ if err := c.Write(snapProto, code, msg); err != nil {
+ return nil, fmt.Errorf("could not write to connection: %v", err)
+ }
+ return c.ReadSnap()
+}
+
func (s *Suite) TestSnapStatus(t *utesting.T) {
conn, err := s.dialSnap()
if err != nil {
@@ -44,74 +54,269 @@ func (s *Suite) TestSnapStatus(t *utesting.T) {
}
type accRangeTest struct {
- nBytes uint64
- root common.Hash
- origin common.Hash
- limit common.Hash
+ nBytes uint64
+ root common.Hash
+ startingHash common.Hash
+ limitHash common.Hash
expAccounts int
expFirst common.Hash
expLast common.Hash
+
+ desc string
}
// TestSnapGetAccountRange various forms of GetAccountRange requests.
func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
var (
- root = s.chain.RootAt(999)
- ffHash = common.MaxHash
- zero = common.Hash{}
- firstKeyMinus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf29")
- firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
- firstKeyPlus1 = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2b")
- secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
- storageRoot = common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790")
+ ffHash = common.MaxHash
+ zero = common.Hash{}
+
+ // test values derived from chain/ account dump
+ root = s.chain.Head().Root()
+ headstate = s.chain.AccountsInHashOrder()
+ firstKey = common.BytesToHash(headstate[0].AddressHash)
+ secondKey = common.BytesToHash(headstate[1].AddressHash)
+ storageRoot = findNonEmptyStorageRoot(headstate)
)
- for i, tc := range []accRangeTest{
+
+ tests := []accRangeTest{
// Tests decreasing the number of bytes
- {4000, root, zero, ffHash, 76, firstKey, common.HexToHash("0xd2669dcf3858e7f1eecb8b5fedbf22fbea3e9433848a75035f79d68422c2dcda")},
- {3000, root, zero, ffHash, 57, firstKey, common.HexToHash("0x9b63fa753ece5cb90657d02ecb15df4dc1508d8c1d187af1bf7f1a05e747d3c7")},
- {2000, root, zero, ffHash, 38, firstKey, common.HexToHash("0x5e6140ecae4354a9e8f47559a8c6209c1e0e69cb077b067b528556c11698b91f")},
- {1, root, zero, ffHash, 1, firstKey, firstKey},
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 86,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"),
+ desc: "In this test, we request the entire state range, but limit the response to 4000 bytes.",
+ },
+ {
+ nBytes: 3000,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 65,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x2e6fe1362b3e388184fd7bf08e99e74170b26361624ffd1c5f646da7067b58b6"),
+ desc: "In this test, we request the entire state range, but limit the response to 3000 bytes.",
+ },
+ {
+ nBytes: 2000,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 44,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x1c3f74249a4892081ba0634a819aec9ed25f34c7653f5719b9098487e65ab595"),
+ desc: "In this test, we request the entire state range, but limit the response to 2000 bytes.",
+ },
+ {
+ nBytes: 1,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `In this test, we request the entire state range, but limit the response to 1 byte.
+The server should return the first account of the state.`,
+ },
+ {
+ nBytes: 0,
+ root: root,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `Here we request with a responseBytes limit of zero.
+The server should return one account.`,
+ },
// Tests variations of the range
- //
- // [00b to firstkey]: should return [firstkey, secondkey], where secondkey is out of bounds
- {4000, root, common.HexToHash("0x00bf000000000000000000000000000000000000000000000000000000000000"), common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2b"), 2, firstKey, secondKey},
- // [00b0 to 0bf0]: where both are before firstkey. Should return firstKey (even though it's out of bounds)
- {4000, root, common.HexToHash("0x00b0000000000000000000000000000000000000000000000000000000000000"), common.HexToHash("0x00bf100000000000000000000000000000000000000000000000000000000000"), 1, firstKey, firstKey},
- {4000, root, zero, zero, 1, firstKey, firstKey},
- {4000, root, firstKey, ffHash, 76, firstKey, common.HexToHash("0xd2669dcf3858e7f1eecb8b5fedbf22fbea3e9433848a75035f79d68422c2dcda")},
- {4000, root, firstKeyPlus1, ffHash, 76, secondKey, common.HexToHash("0xd28f55d3b994f16389f36944ad685b48e0fc3f8fbe86c3ca92ebecadf16a783f")},
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: hashAdd(firstKey, -500),
+ limitHash: hashAdd(firstKey, 1),
+ expAccounts: 2,
+ expFirst: firstKey,
+ expLast: secondKey,
+ desc: `In this test, we request a range where startingHash is before the first available
+account key, and limitHash is after. The server should return the first and second
+account of the state (because the second account is the 'next available').`,
+ },
+
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: hashAdd(firstKey, -500),
+ limitHash: hashAdd(firstKey, -450),
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `Here we request range where both bounds are before the first available account key.
+This should return the first account (even though it's out of bounds).`,
+ },
+
+ // More range tests:
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: zero,
+ limitHash: zero,
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `In this test, both startingHash and limitHash are zero.
+The server should return the first available account.`,
+ },
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: firstKey,
+ limitHash: ffHash,
+ expAccounts: 86,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"),
+ desc: `In this test, startingHash is exactly the first available account key.
+The server should return the first available account of the state as the first item.`,
+ },
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: hashAdd(firstKey, 1),
+ limitHash: ffHash,
+ expAccounts: 86,
+ expFirst: secondKey,
+ expLast: common.HexToHash("0x4615e5f5df5b25349a00ad313c6cd0436b6c08ee5826e33a018661997f85ebaa"),
+ desc: `In this test, startingHash is after the first available key.
+The server should return the second account of the state as the first item.`,
+ },
// Test different root hashes
- //
- // A stateroot that does not exist
- {4000, common.Hash{0x13, 37}, zero, ffHash, 0, zero, zero},
+
+ {
+ nBytes: 4000,
+ root: common.Hash{0x13, 0x37},
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 0,
+ expFirst: zero,
+ expLast: zero,
+ desc: `This test requests a non-existent state root.`,
+ },
+
// The genesis stateroot (we expect it to not be served)
- {4000, s.chain.RootAt(0), zero, ffHash, 0, zero, zero},
- // A 127 block old stateroot, expected to be served
- {4000, s.chain.RootAt(999 - 127), zero, ffHash, 77, firstKey, common.HexToHash("0xe4c6fdef5dd4e789a2612390806ee840b8ec0fe52548f8b4efe41abb20c37aac")},
- // A root which is not actually an account root, but a storage root
- {4000, storageRoot, zero, ffHash, 0, zero, zero},
+ {
+ nBytes: 4000,
+ root: s.chain.RootAt(0),
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 0,
+ expFirst: zero,
+ expLast: zero,
+ desc: `This test requests data at the state root of the genesis block. We expect the
+server to return no data because genesis is older than 127 blocks.`,
+ },
+
+ {
+ nBytes: 4000,
+ root: s.chain.RootAt(int(s.chain.Head().Number().Uint64()) - 127),
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 84,
+ expFirst: firstKey,
+ expLast: common.HexToHash("0x580aa878e2f92d113a12c0a3ce3c21972b03dbe80786858d49a72097e2c491a3"),
+ desc: `This test requests data at a state root that is 127 blocks old.
+We expect the server to have this state available.`,
+ },
+
+ {
+ nBytes: 4000,
+ root: storageRoot,
+ startingHash: zero,
+ limitHash: ffHash,
+ expAccounts: 0,
+ expFirst: zero,
+ expLast: zero,
+ desc: `This test requests data at a state root that is actually the storage root of
+an existing account. The server is supposed to ignore this request.`,
+ },
// And some non-sensical requests
- //
- // range from [0xFF to 0x00], wrong order. Expect not to be serviced
- {4000, root, ffHash, zero, 0, zero, zero},
- // range from [firstkey, firstkey-1], wrong order. Expect to get first key.
- {4000, root, firstKey, firstKeyMinus1, 1, firstKey, firstKey},
+
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: ffHash,
+ limitHash: zero,
+ expAccounts: 0,
+ expFirst: zero,
+ expLast: zero,
+ desc: `In this test, the startingHash is after limitHash (wrong order). The server
+should ignore this invalid request.`,
+ },
+
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: firstKey,
+ limitHash: hashAdd(firstKey, -1),
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `In this test, the startingHash is the first available key, and limitHash is
+a key before startingHash (wrong order). The server should return the first available key.`,
+ },
+
// range from [firstkey, 0], wrong order. Expect to get first key.
- {4000, root, firstKey, zero, 1, firstKey, firstKey},
- // Max bytes: 0. Expect to deliver one account.
- {0, root, zero, ffHash, 1, firstKey, firstKey},
- } {
+ {
+ nBytes: 4000,
+ root: root,
+ startingHash: firstKey,
+ limitHash: zero,
+ expAccounts: 1,
+ expFirst: firstKey,
+ expLast: firstKey,
+ desc: `In this test, the startingHash is the first available key and limitHash is zero.
+(wrong order). The server should return the first available key.`,
+ },
+ }
+
+ for i, tc := range tests {
tc := tc
+ if i > 0 {
+ t.Log("\n")
+ }
+ t.Logf("-- Test %d", i)
+ t.Log(tc.desc)
+ t.Log(" request:")
+ t.Logf(" root: %x", tc.root)
+ t.Logf(" range: %#x - %#x", tc.startingHash, tc.limitHash)
+ t.Logf(" responseBytes: %d", tc.nBytes)
if err := s.snapGetAccountRange(t, &tc); err != nil {
- t.Errorf("test %d \n root: %x\n range: %#x - %#x\n bytes: %d\nfailed: %v", i, tc.root, tc.origin, tc.limit, tc.nBytes, err)
+ t.Errorf("test %d failed: %v", i, err)
}
}
}
+func hashAdd(h common.Hash, n int64) common.Hash {
+ hb := h.Big()
+ return common.BigToHash(hb.Add(hb, big.NewInt(n)))
+}
+
+func findNonEmptyStorageRoot(accounts []state.DumpAccount) common.Hash {
+ for i := range accounts {
+ if len(accounts[i].Storage) != 0 {
+ return common.BytesToHash(accounts[i].Root)
+ }
+ }
+ panic("can't find account with non-empty storage")
+}
+
type stRangesTest struct {
root common.Hash
accounts []common.Hash
@@ -119,87 +324,125 @@ type stRangesTest struct {
limit []byte
nBytes uint64
- expSlots int
+ expSlots [][]*snap.StorageData
+
+ desc string
}
// TestSnapGetStorageRanges various forms of GetStorageRanges requests.
func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) {
var (
+ acct = common.HexToAddress("0x8bebc8ba651aee624937e7d897853ac30c95a067")
+ acctHash = common.BytesToHash(s.chain.state[acct].AddressHash)
ffHash = common.MaxHash
zero = common.Hash{}
- firstKey = common.HexToHash("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
- secondKey = common.HexToHash("0x09e47cd5056a689e708f22fe1f932709a320518e444f5f7d8d46a3da523d6606")
+ blockroot = s.chain.Head().Root()
)
- for i, tc := range []stRangesTest{
+
+ // These are the storage slots of the test account, encoded as snap response data.
+ acctSlots := []*snap.StorageData{
{
- root: s.chain.RootAt(999),
- accounts: []common.Hash{secondKey, firstKey},
- origin: zero[:],
- limit: ffHash[:],
- nBytes: 500,
- expSlots: 0,
+ Hash: common.HexToHash("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"),
+ Body: []byte{0x02},
+ },
+ {
+ Hash: common.HexToHash("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"),
+ Body: []byte{0x01},
+ },
+ {
+ Hash: common.HexToHash("0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b"),
+ Body: []byte{0x03},
},
+ }
+ tests := []stRangesTest{
/*
Some tests against this account:
- {
- "balance": "0",
- "nonce": 1,
- "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790",
- "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
- "storage": {
- "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02",
- "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01",
- "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03"
- },
- "key": "0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844"
+
+ "0x8bebc8ba651aee624937e7d897853ac30c95a067": {
+ "balance": "1",
+ "nonce": 1,
+ "root": "0xe318dff15b33aa7f2f12d5567d58628e3e3f2e8859e46b56981a4083b391da17",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ // Note: keys below are hashed!!!
+ "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02",
+ "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01",
+ "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03"
+ },
+ "key": "0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"
}
*/
+
{ // [:] -> [slot1, slot2, slot3]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+ desc: `This request has a range of 00..ff.
+The server should return all storage slots of the test account.`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: zero[:],
limit: ffHash[:],
nBytes: 500,
- expSlots: 3,
+ expSlots: [][]*snap.StorageData{acctSlots},
},
+
{ // [slot1:] -> [slot1, slot2, slot3]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+ desc: `This test requests slots starting at the first available key.
+The server should return all storage slots of the test account.`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"),
limit: ffHash[:],
- nBytes: 500,
- expSlots: 3,
+ nBytes: 1000,
+ expSlots: [][]*snap.StorageData{acctSlots},
},
- { // [slot1+ :] -> [slot2, slot3]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+
+ { // [slot1+:] -> [slot2, slot3]
+ desc: `This test requests slots starting at a key one past the first available key.
+The server should return the remaining two slots of the test account.`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf"),
limit: ffHash[:],
nBytes: 500,
- expSlots: 2,
+ expSlots: [][]*snap.StorageData{acctSlots[1:]},
},
+
{ // [slot1:slot2] -> [slot1, slot2]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+ desc: `This test requests a range which is exactly the first and second available key.`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"),
limit: common.FromHex("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"),
nBytes: 500,
- expSlots: 2,
+ expSlots: [][]*snap.StorageData{acctSlots[:2]},
},
+
{ // [slot1+:slot2+] -> [slot2, slot3]
- root: s.chain.RootAt(999),
- accounts: []common.Hash{common.HexToHash("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844")},
+ desc: `This test requests a range where limitHash is after the second, but before the third slot
+of the test account. The server should return slots [2,3] (i.e. the 'next available' needs to be returned).`,
+ root: blockroot,
+ accounts: []common.Hash{acctHash},
origin: common.FromHex("0x4fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
limit: common.FromHex("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7"),
nBytes: 500,
- expSlots: 2,
+ expSlots: [][]*snap.StorageData{acctSlots[1:]},
},
- } {
+ }
+
+ for i, tc := range tests {
tc := tc
+ if i > 0 {
+ t.Log("\n")
+ }
+ t.Logf("-- Test %d", i)
+ t.Log(tc.desc)
+ t.Log(" request:")
+ t.Logf(" root: %x", tc.root)
+ t.Logf(" accounts: %x", tc.accounts)
+ t.Logf(" range: %#x - %#x", tc.origin, tc.limit)
+ t.Logf(" responseBytes: %d", tc.nBytes)
if err := s.snapGetStorageRanges(t, &tc); err != nil {
- t.Errorf("test %d \n root: %x\n range: %#x - %#x\n bytes: %d\n #accounts: %d\nfailed: %v",
- i, tc.root, tc.origin, tc.limit, tc.nBytes, len(tc.accounts), err)
+ t.Errorf(" failed: %v", err)
}
}
}
@@ -209,87 +452,92 @@ type byteCodesTest struct {
hashes []common.Hash
expHashes int
+
+ desc string
}
// TestSnapGetByteCodes various forms of GetByteCodes requests.
func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
- // The halfchain import should yield these bytecodes
- var hcBytecodes []common.Hash
- for _, s := range []string{
- "0x200c90460d8b0063210d5f5b9918e053c8f2c024485e0f1b48be8b1fc71b1317",
- "0x20ba67ed4ac6aff626e0d1d4db623e2fada9593daeefc4a6eb4b70e6cff986f3",
- "0x24b5b4902cb3d897c1cee9f16be8e897d8fa277c04c6dc8214f18295fca5de44",
- "0x320b9d0a2be39b8a1c858f9f8cb96b1df0983071681de07ded3a7c0d05db5fd6",
- "0x48cb0d5275936a24632babc7408339f9f7b051274809de565b8b0db76e97e03c",
- "0x67c7a6f5cdaa43b4baa0e15b2be63346d1b9ce9f2c3d7e5804e0cacd44ee3b04",
- "0x6d8418059bdc8c3fabf445e6bfc662af3b6a4ae45999b953996e42c7ead2ab49",
- "0x7043422e5795d03f17ee0463a37235258e609fdd542247754895d72695e3e142",
- "0x727f9e6f0c4bac1ff8d72c2972122d9c8d37ccb37e04edde2339e8da193546f1",
- "0x86ccd5e23c78568a8334e0cebaf3e9f48c998307b0bfb1c378cee83b4bfb29cb",
- "0x8fc89b00d6deafd4c4279531e743365626dbfa28845ec697919d305c2674302d",
- "0x92cfc353bcb9746bb6f9996b6b9df779c88af2e9e0eeac44879ca19887c9b732",
- "0x941b4872104f0995a4898fcf0f615ea6bf46bfbdfcf63ea8f2fd45b3f3286b77",
- "0xa02fe8f41159bb39d2b704c633c3d6389cf4bfcb61a2539a9155f60786cf815f",
- "0xa4b94e0afdffcb0af599677709dac067d3145489ea7aede57672bee43e3b7373",
- "0xaf4e64edd3234c1205b725e42963becd1085f013590bd7ed93f8d711c5eb65fb",
- "0xb69a18fa855b742031420081999086f6fb56c3930ae8840944e8b8ae9931c51e",
- "0xc246c217bc73ce6666c93a93a94faa5250564f50a3fdc27ea74c231c07fe2ca6",
- "0xcd6e4ab2c3034df2a8a1dfaaeb1c4baecd162a93d22de35e854ee2945cbe0c35",
- "0xe24b692d09d6fc2f3d1a6028c400a27c37d7cbb11511907c013946d6ce263d3b",
- "0xe440c5f0e8603fd1ed25976eee261ccee8038cf79d6a4c0eb31b2bf883be737f",
- "0xe6eacbc509203d21ac814b350e72934fde686b7f673c19be8cf956b0c70078ce",
- "0xe8530de4371467b5be7ea0e69e675ab36832c426d6c1ce9513817c0f0ae1486b",
- "0xe85d487abbbc83bf3423cf9731360cf4f5a37220e18e5add54e72ee20861196a",
- "0xf195ea389a5eea28db0be93660014275b158963dec44af1dfa7d4743019a9a49",
- } {
- hcBytecodes = append(hcBytecodes, common.HexToHash(s))
- }
-
- for i, tc := range []byteCodesTest{
+ var (
+ allHashes = s.chain.CodeHashes()
+ headRoot = s.chain.Head().Root()
+ genesisRoot = s.chain.RootAt(0)
+ )
+
+ tests := []byteCodesTest{
// A few stateroots
{
- nBytes: 10000, hashes: []common.Hash{s.chain.RootAt(0), s.chain.RootAt(999)},
+ desc: `Here we request state roots as code hashes. The server should deliver an empty response with no items.`,
+ nBytes: 10000,
+ hashes: []common.Hash{genesisRoot, headRoot},
expHashes: 0,
},
{
- nBytes: 10000, hashes: []common.Hash{s.chain.RootAt(0), s.chain.RootAt(0)},
+ desc: `Here we request the genesis state root (which is not an existing code hash) two times. The server should deliver an empty response with no items.`,
+ nBytes: 10000,
+ hashes: []common.Hash{genesisRoot, genesisRoot},
expHashes: 0,
},
// Empties
{
- nBytes: 10000, hashes: []common.Hash{types.EmptyRootHash},
+ desc: `Here we request the empty state root (which is not an existing code hash). The server should deliver an empty response with no items.`,
+ nBytes: 10000,
+ hashes: []common.Hash{types.EmptyRootHash},
expHashes: 0,
},
{
- nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash},
+ desc: `Here we request the empty code hash. The server should deliver an empty response item.`,
+ nBytes: 10000,
+ hashes: []common.Hash{types.EmptyCodeHash},
expHashes: 1,
},
{
- nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash},
+ desc: `In this test, we request the empty code hash three times. The server should deliver the empty item three times.`,
+ nBytes: 10000,
+ hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash},
expHashes: 3,
},
// The existing bytecodes
{
- nBytes: 10000, hashes: hcBytecodes,
- expHashes: len(hcBytecodes),
+ desc: `Here we request all available contract codes. The server should deliver them all in one response.`,
+ nBytes: 100000,
+ hashes: allHashes,
+ expHashes: len(allHashes),
},
// The existing, with limited byte arg
{
- nBytes: 1, hashes: hcBytecodes,
+ desc: `In this test, the request has a bytes limit of one. The server should deliver one item.`,
+ nBytes: 1,
+ hashes: allHashes,
expHashes: 1,
},
{
- nBytes: 0, hashes: hcBytecodes,
+ desc: `In this test, the request has a bytes limit of zero. The server should deliver one item.`,
+ nBytes: 0,
+ hashes: allHashes,
expHashes: 1,
},
+ // Request the same hash multiple times.
{
- nBytes: 1000, hashes: []common.Hash{hcBytecodes[0], hcBytecodes[0], hcBytecodes[0], hcBytecodes[0]},
+ desc: `This test requests the same code hash multiple times. The server should deliver it multiple times.`,
+ nBytes: 1000,
+ hashes: []common.Hash{allHashes[0], allHashes[0], allHashes[0], allHashes[0]},
expHashes: 4,
},
- } {
+ }
+
+ for i, tc := range tests {
tc := tc
+ if i > 0 {
+ t.Log("\n")
+ }
+ t.Logf("-- Test %d", i)
+ t.Log(tc.desc)
+ t.Log(" request:")
+ t.Logf(" hashes: %x", tc.hashes)
+ t.Logf(" responseBytes: %d", tc.nBytes)
if err := s.snapGetByteCodes(t, &tc); err != nil {
- t.Errorf("test %d \n bytes: %d\n #hashes: %d\nfailed: %v", i, tc.nBytes, len(tc.hashes), err)
+ t.Errorf("failed: %v", err)
}
}
}
@@ -299,8 +547,10 @@ type trieNodesTest struct {
paths []snap.TrieNodePathSet
nBytes uint64
- expHashes []common.Hash
- expReject bool
+ expHashes []common.Hash // expected response
+ expReject bool // if true, request should be rejected
+
+ desc string
}
func decodeNibbles(nibbles []byte, bytes []byte) {
@@ -344,29 +594,32 @@ func hexToCompact(hex []byte) []byte {
// TestSnapTrieNodes various forms of GetTrieNodes requests.
func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
- key := common.FromHex("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
- // helper function to iterate the key, and generate the compact-encoded
- // trie paths along the way.
- pathTo := func(length int) snap.TrieNodePathSet {
- hex := keybytesToHex(key)[:length]
- hex[len(hex)-1] = 0 // remove term flag
- hKey := hexToCompact(hex)
- return snap.TrieNodePathSet{hKey}
- }
- var accPaths []snap.TrieNodePathSet
+ var (
+ // This is the known address of the snap storage testing contract.
+ storageAcct = common.HexToAddress("0x8bebc8ba651aee624937e7d897853ac30c95a067")
+ storageAcctHash = common.BytesToHash(s.chain.state[storageAcct].AddressHash)
+ // This is the known address of an existing account.
+ key = common.FromHex("0xa87387b50b481431c6ccdb9ae99a54d4dcdd4a3eff75d7b17b4818f7bbfc21e9")
+ empty = types.EmptyCodeHash
+ accPaths []snap.TrieNodePathSet
+ )
for i := 1; i <= 65; i++ {
- accPaths = append(accPaths, pathTo(i))
+ accPaths = append(accPaths, makeSnapPath(key, i))
}
- empty := types.EmptyCodeHash
- for i, tc := range []trieNodesTest{
+
+ tests := []trieNodesTest{
{
- root: s.chain.RootAt(999),
+ desc: `In this test, we send an empty request to the node.`,
+ root: s.chain.Head().Root(),
paths: nil,
nBytes: 500,
expHashes: nil,
},
+
{
- root: s.chain.RootAt(999),
+ desc: `In this test, we send a request containing an empty path-set.
+The server should reject the request.`,
+ root: s.chain.Head().Root(),
paths: []snap.TrieNodePathSet{
{}, // zero-length pathset should 'abort' and kick us off
{[]byte{0}},
@@ -375,18 +628,21 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
expHashes: []common.Hash{},
expReject: true,
},
+
{
- root: s.chain.RootAt(999),
+ desc: `Here we request the root node of the trie. The server should respond with the root node.`,
+ root: s.chain.RootAt(int(s.chain.Head().NumberU64() - 1)),
paths: []snap.TrieNodePathSet{
{[]byte{0}},
{[]byte{1}, []byte{0}},
},
- nBytes: 5000,
- //0x6b3724a41b8c38b46d4d02fba2bb2074c47a507eb16a9a4b978f91d32e406faf
- expHashes: []common.Hash{s.chain.RootAt(999)},
+ nBytes: 5000,
+ expHashes: []common.Hash{s.chain.RootAt(int(s.chain.Head().NumberU64() - 1))},
},
+
{ // nonsensically long path
- root: s.chain.RootAt(999),
+ desc: `In this test, we request a very long trie node path. The server should respond with an empty node (keccak256("")).`,
+ root: s.chain.Head().Root(),
paths: []snap.TrieNodePathSet{
{[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8}},
@@ -394,25 +650,19 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
nBytes: 5000,
expHashes: []common.Hash{common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")},
},
- {
- root: s.chain.RootAt(0),
- paths: []snap.TrieNodePathSet{
- {[]byte{0}},
- {[]byte{1}, []byte{0}},
- },
- nBytes: 5000,
- expHashes: []common.Hash{
- common.HexToHash("0x1ee1bb2fbac4d46eab331f3e8551e18a0805d084ed54647883aa552809ca968d"),
- },
- },
+
{
// The leaf is only a couple of levels down, so the continued trie traversal causes lookup failures.
- root: s.chain.RootAt(999),
+ desc: `Here we request some known accounts from the state.`,
+ root: s.chain.Head().Root(),
paths: accPaths,
nBytes: 5000,
expHashes: []common.Hash{
- common.HexToHash("0xbcefee69b37cca1f5bf3a48aebe08b35f2ea1864fa958bb0723d909a0e0d28d8"),
- common.HexToHash("0x4fb1e4e2391e4b4da471d59641319b8fa25d76c973d4bec594d7b00a69ae5135"),
+ // It's a bit unfortunate these are hard-coded, but the result depends on
+ // a lot of aspects of the state trie and can't be guessed in a simple
+ // way. So you'll have to update this when the test chain is changed.
+ common.HexToHash("0x3e963a69401a70224cbfb8c0cc2249b019041a538675d71ccf80c9328d114e2e"),
+ common.HexToHash("0xd0670d09cdfbf3c6320eb3e92c47c57baa6c226551a2d488c05581091e6b1689"),
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
@@ -420,55 +670,84 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
empty, empty, empty},
},
+
{
- // Basically the same as above, with different ordering
- root: s.chain.RootAt(999),
+ desc: `In this test, we request some known accounts in state. The requested paths are NOT in key order.`,
+ root: s.chain.Head().Root(),
paths: []snap.TrieNodePathSet{
accPaths[10], accPaths[1], accPaths[0],
},
nBytes: 5000,
+ // As with the previous test, this result depends on the whole tree and will have to
+ // be updated when the test chain is changed.
expHashes: []common.Hash{
empty,
- common.HexToHash("0x4fb1e4e2391e4b4da471d59641319b8fa25d76c973d4bec594d7b00a69ae5135"),
- common.HexToHash("0xbcefee69b37cca1f5bf3a48aebe08b35f2ea1864fa958bb0723d909a0e0d28d8"),
+ common.HexToHash("0xd0670d09cdfbf3c6320eb3e92c47c57baa6c226551a2d488c05581091e6b1689"),
+ common.HexToHash("0x3e963a69401a70224cbfb8c0cc2249b019041a538675d71ccf80c9328d114e2e"),
},
},
+
+ // Storage tests.
+ // These use the known storage test account.
+
{
- /*
- A test against this account, requesting trie nodes for the storage trie
+ desc: `This test requests the storage root node of a known account.`,
+ root: s.chain.Head().Root(),
+ paths: []snap.TrieNodePathSet{
{
- "balance": "0",
- "nonce": 1,
- "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790",
- "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
- "storage": {
- "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02",
- "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01",
- "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03"
- },
- "key": "0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844"
- }
- */
- root: s.chain.RootAt(999),
+ storageAcctHash[:],
+ []byte{0},
+ },
+ },
+ nBytes: 5000,
+ expHashes: []common.Hash{
+ common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790"),
+ },
+ },
+
+ {
+ desc: `This test requests multiple storage nodes of a known account.`,
+ root: s.chain.Head().Root(),
paths: []snap.TrieNodePathSet{
{
- common.FromHex("0xf493f79c43bd747129a226ad42529885a4b108aba6046b2d12071695a6627844"),
+ storageAcctHash[:],
[]byte{0},
+ []byte{0x1b},
},
},
nBytes: 5000,
expHashes: []common.Hash{
common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790"),
+ common.HexToHash("0xf4984a11f61a2921456141df88de6e1a710d28681b91af794c5a721e47839cd7"),
},
},
- }[7:] {
+ }
+
+ for i, tc := range tests {
tc := tc
+ if i > 0 {
+ t.Log("\n")
+ }
+ t.Logf("-- Test %d", i)
+ t.Log(tc.desc)
+ t.Log(" request:")
+ t.Logf(" root: %x", tc.root)
+ t.Logf(" paths: %x", tc.paths)
+ t.Logf(" responseBytes: %d", tc.nBytes)
+
if err := s.snapGetTrieNodes(t, &tc); err != nil {
- t.Errorf("test %d \n #hashes %x\n root: %#x\n bytes: %d\nfailed: %v", i, len(tc.expHashes), tc.root, tc.nBytes, err)
+ t.Errorf(" failed: %v", err)
}
}
}
+func makeSnapPath(key []byte, length int) snap.TrieNodePathSet {
+ hex := keybytesToHex(key)[:length]
+ hex[len(hex)-1] = 0 // remove term flag
+ hKey := hexToCompact(hex)
+ return snap.TrieNodePathSet{hKey}
+}
+
func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
conn, err := s.dialSnap()
if err != nil {
@@ -479,22 +758,20 @@ func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
t.Fatalf("peering failed: %v", err)
}
// write request
- req := &GetAccountRange{
+ req := &snap.GetAccountRangePacket{
ID: uint64(rand.Int63()),
Root: tc.root,
- Origin: tc.origin,
- Limit: tc.limit,
+ Origin: tc.startingHash,
+ Limit: tc.limitHash,
Bytes: tc.nBytes,
}
- resp, err := conn.snapRequest(req, req.ID, s.chain)
+ msg, err := conn.snapRequest(snap.GetAccountRangeMsg, req)
if err != nil {
return fmt.Errorf("account range request failed: %v", err)
}
- var res *snap.AccountRangePacket
- if r, ok := resp.(*AccountRange); !ok {
- return fmt.Errorf("account range response wrong: %T %v", resp, resp)
- } else {
- res = (*snap.AccountRangePacket)(r)
+ res, ok := msg.(*snap.AccountRangePacket)
+ if !ok {
+ return fmt.Errorf("account range response wrong: %T %v", msg, msg)
}
if exp, got := tc.expAccounts, len(res.Accounts); exp != got {
return fmt.Errorf("expected %d accounts, got %d", exp, got)
@@ -536,11 +813,7 @@ func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
}
proofdb := nodes.Set()
- var end []byte
- if len(keys) > 0 {
- end = keys[len(keys)-1]
- }
- _, err = trie.VerifyRangeProof(tc.root, tc.origin[:], end, keys, accounts, proofdb)
+ _, err = trie.VerifyRangeProof(tc.root, tc.startingHash[:], keys, accounts, proofdb)
return err
}
@@ -553,8 +826,9 @@ func (s *Suite) snapGetStorageRanges(t *utesting.T, tc *stRangesTest) error {
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
+
// write request
- req := &GetStorageRanges{
+ req := &snap.GetStorageRangesPacket{
ID: uint64(rand.Int63()),
Root: tc.root,
Accounts: tc.accounts,
@@ -562,28 +836,38 @@ func (s *Suite) snapGetStorageRanges(t *utesting.T, tc *stRangesTest) error {
Limit: tc.limit,
Bytes: tc.nBytes,
}
- resp, err := conn.snapRequest(req, req.ID, s.chain)
+ msg, err := conn.snapRequest(snap.GetStorageRangesMsg, req)
if err != nil {
return fmt.Errorf("account range request failed: %v", err)
}
- var res *snap.StorageRangesPacket
- if r, ok := resp.(*StorageRanges); !ok {
- return fmt.Errorf("account range response wrong: %T %v", resp, resp)
- } else {
- res = (*snap.StorageRangesPacket)(r)
+ res, ok := msg.(*snap.StorageRangesPacket)
+ if !ok {
+ return fmt.Errorf("account range response wrong: %T %v", msg, msg)
}
- gotSlots := 0
+
// Ensure the ranges are monotonically increasing
for i, slots := range res.Slots {
- gotSlots += len(slots)
for j := 1; j < len(slots); j++ {
if bytes.Compare(slots[j-1].Hash[:], slots[j].Hash[:]) >= 0 {
return fmt.Errorf("storage slots not monotonically increasing for account #%d: #%d [%x] vs #%d [%x]", i, j-1, slots[j-1].Hash[:], j, slots[j].Hash[:])
}
}
}
- if exp, got := tc.expSlots, gotSlots; exp != got {
- return fmt.Errorf("expected %d slots, got %d", exp, got)
+
+ // Compute expected slot hashes.
+ var expHashes [][]common.Hash
+ for _, acct := range tc.expSlots {
+ var list []common.Hash
+ for _, s := range acct {
+ list = append(list, s.Hash)
+ }
+ expHashes = append(expHashes, list)
+ }
+
+ // Check response.
+ if !reflect.DeepEqual(res.Slots, tc.expSlots) {
+ t.Log(" expected slot hashes:", expHashes)
+ return fmt.Errorf("wrong storage slots in response: %#v", res.Slots)
}
return nil
}
@@ -598,24 +882,22 @@ func (s *Suite) snapGetByteCodes(t *utesting.T, tc *byteCodesTest) error {
t.Fatalf("peering failed: %v", err)
}
// write request
- req := &GetByteCodes{
+ req := &snap.GetByteCodesPacket{
ID: uint64(rand.Int63()),
Hashes: tc.hashes,
Bytes: tc.nBytes,
}
- resp, err := conn.snapRequest(req, req.ID, s.chain)
+ msg, err := conn.snapRequest(snap.GetByteCodesMsg, req)
if err != nil {
return fmt.Errorf("getBytecodes request failed: %v", err)
}
- var res *snap.ByteCodesPacket
- if r, ok := resp.(*ByteCodes); !ok {
- return fmt.Errorf("bytecodes response wrong: %T %v", resp, resp)
- } else {
- res = (*snap.ByteCodesPacket)(r)
+ res, ok := msg.(*snap.ByteCodesPacket)
+ if !ok {
+ return fmt.Errorf("bytecodes response wrong: %T %v", msg, msg)
}
if exp, got := tc.expHashes, len(res.Codes); exp != got {
for i, c := range res.Codes {
- fmt.Printf("%d. %#x\n", i, c)
+ t.Logf("%d. %#x\n", i, c)
}
return fmt.Errorf("expected %d bytecodes, got %d", exp, got)
}
@@ -658,25 +940,24 @@ func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error {
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // write request
- req := &GetTrieNodes{
+
+ // write0 request
+ req := &snap.GetTrieNodesPacket{
ID: uint64(rand.Int63()),
Root: tc.root,
Paths: tc.paths,
Bytes: tc.nBytes,
}
- resp, err := conn.snapRequest(req, req.ID, s.chain)
+ msg, err := conn.snapRequest(snap.GetTrieNodesMsg, req)
if err != nil {
if tc.expReject {
return nil
}
return fmt.Errorf("trienodes request failed: %v", err)
}
- var res *snap.TrieNodesPacket
- if r, ok := resp.(*TrieNodes); !ok {
- return fmt.Errorf("trienodes response wrong: %T %v", resp, resp)
- } else {
- res = (*snap.TrieNodesPacket)(r)
+ res, ok := msg.(*snap.TrieNodesPacket)
+ if !ok {
+ return fmt.Errorf("trienodes response wrong: %T %v", msg, msg)
}
// Check the correctness
@@ -687,14 +968,14 @@ func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error {
hash := make([]byte, 32)
trienodes := res.Nodes
if got, want := len(trienodes), len(tc.expHashes); got != want {
- return fmt.Errorf("wrong trienode count, got %d, want %d\n", got, want)
+ return fmt.Errorf("wrong trienode count, got %d, want %d", got, want)
}
for i, trienode := range trienodes {
hasher.Reset()
hasher.Write(trienode)
hasher.Read(hash)
if got, want := hash, tc.expHashes[i]; !bytes.Equal(got, want[:]) {
- fmt.Printf("hash %d wrong, got %#x, want %#x\n", i, got, want)
+ t.Logf(" hash %d wrong, got %#x, want %#x\n", i, got, want)
err = fmt.Errorf("hash %d wrong, got %#x, want %#x", i, got, want)
}
}
diff --git a/cmd/devp2p/internal/ethtest/snapTypes.go b/cmd/devp2p/internal/ethtest/snapTypes.go
deleted file mode 100644
index 6bcaa9291a..0000000000
--- a/cmd/devp2p/internal/ethtest/snapTypes.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see .
-
-package ethtest
-
-import "github.com/ethereum/go-ethereum/eth/protocols/snap"
-
-// GetAccountRange represents an account range query.
-type GetAccountRange snap.GetAccountRangePacket
-
-func (msg GetAccountRange) Code() int { return 33 }
-func (msg GetAccountRange) ReqID() uint64 { return msg.ID }
-
-type AccountRange snap.AccountRangePacket
-
-func (msg AccountRange) Code() int { return 34 }
-func (msg AccountRange) ReqID() uint64 { return msg.ID }
-
-type GetStorageRanges snap.GetStorageRangesPacket
-
-func (msg GetStorageRanges) Code() int { return 35 }
-func (msg GetStorageRanges) ReqID() uint64 { return msg.ID }
-
-type StorageRanges snap.StorageRangesPacket
-
-func (msg StorageRanges) Code() int { return 36 }
-func (msg StorageRanges) ReqID() uint64 { return msg.ID }
-
-type GetByteCodes snap.GetByteCodesPacket
-
-func (msg GetByteCodes) Code() int { return 37 }
-func (msg GetByteCodes) ReqID() uint64 { return msg.ID }
-
-type ByteCodes snap.ByteCodesPacket
-
-func (msg ByteCodes) Code() int { return 38 }
-func (msg ByteCodes) ReqID() uint64 { return msg.ID }
-
-type GetTrieNodes snap.GetTrieNodesPacket
-
-func (msg GetTrieNodes) Code() int { return 39 }
-func (msg GetTrieNodes) ReqID() uint64 { return msg.ID }
-
-type TrieNodes snap.TrieNodesPacket
-
-func (msg TrieNodes) Code() int { return 40 }
-func (msg TrieNodes) ReqID() uint64 { return msg.ID }
diff --git a/cmd/devp2p/internal/ethtest/suite.go b/cmd/devp2p/internal/ethtest/suite.go
index 815353be72..4f499d41d8 100644
--- a/cmd/devp2p/internal/ethtest/suite.go
+++ b/cmd/devp2p/internal/ethtest/suite.go
@@ -17,35 +17,47 @@
package ethtest
import (
- "time"
+ "crypto/rand"
+ "math/big"
+ "reflect"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/internal/utesting"
+ "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
+ "github.com/holiman/uint256"
)
// Suite represents a structure used to test a node's conformance
// to the eth protocol.
type Suite struct {
- Dest *enode.Node
-
- chain *Chain
- fullChain *Chain
+ Dest *enode.Node
+ chain *Chain
+ engine *EngineClient
}
// NewSuite creates and returns a new eth-test suite that can
// be used to test the given node against the given blockchain
// data.
-func NewSuite(dest *enode.Node, chainfile string, genesisfile string) (*Suite, error) {
- chain, err := loadChain(chainfile, genesisfile)
+func NewSuite(dest *enode.Node, chainDir, engineURL, jwt string) (*Suite, error) {
+ chain, err := NewChain(chainDir)
if err != nil {
return nil, err
}
+ engine, err := NewEngineClient(chainDir, engineURL, jwt)
+ if err != nil {
+ return nil, err
+ }
+
return &Suite{
- Dest: dest,
- chain: chain.Shorten(1000),
- fullChain: chain,
+ Dest: dest,
+ chain: chain,
+ engine: engine,
}, nil
}
@@ -60,34 +72,30 @@ func (s *Suite) EthTests() []utesting.Test {
{Name: "TestZeroRequestID", Fn: s.TestZeroRequestID},
// get block bodies
{Name: "TestGetBlockBodies", Fn: s.TestGetBlockBodies},
- // broadcast
- {Name: "TestBroadcast", Fn: s.TestBroadcast},
- {Name: "TestLargeAnnounce", Fn: s.TestLargeAnnounce},
- {Name: "TestOldAnnounce", Fn: s.TestOldAnnounce},
- {Name: "TestBlockHashAnnounce", Fn: s.TestBlockHashAnnounce},
- // malicious handshakes + status
+ // // malicious handshakes + status
{Name: "TestMaliciousHandshake", Fn: s.TestMaliciousHandshake},
{Name: "TestMaliciousStatus", Fn: s.TestMaliciousStatus},
// test transactions
+ {Name: "TestLargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true},
{Name: "TestTransaction", Fn: s.TestTransaction},
- {Name: "TestMaliciousTx", Fn: s.TestMaliciousTx},
- {Name: "TestLargeTxRequest", Fn: s.TestLargeTxRequest},
+ {Name: "TestInvalidTxs", Fn: s.TestInvalidTxs},
{Name: "TestNewPooledTxs", Fn: s.TestNewPooledTxs},
+ {Name: "TestBlobViolations", Fn: s.TestBlobViolations},
}
}
func (s *Suite) SnapTests() []utesting.Test {
return []utesting.Test{
- {Name: "TestSnapStatus", Fn: s.TestSnapStatus},
- {Name: "TestSnapAccountRange", Fn: s.TestSnapGetAccountRange},
- {Name: "TestSnapGetByteCodes", Fn: s.TestSnapGetByteCodes},
- {Name: "TestSnapGetTrieNodes", Fn: s.TestSnapTrieNodes},
- {Name: "TestSnapGetStorageRanges", Fn: s.TestSnapGetStorageRanges},
+ {Name: "Status", Fn: s.TestSnapStatus},
+ {Name: "AccountRange", Fn: s.TestSnapGetAccountRange},
+ {Name: "GetByteCodes", Fn: s.TestSnapGetByteCodes},
+ {Name: "GetTrieNodes", Fn: s.TestSnapTrieNodes},
+ {Name: "GetStorageRanges", Fn: s.TestSnapGetStorageRanges},
}
}
-// TestStatus attempts to connect to the given node and exchange
-// a status message with it on the eth protocol.
+// TestStatus attempts to connect to the given node and exchange a status
+// message with it on the eth protocol.
func (s *Suite) TestStatus(t *utesting.T) {
conn, err := s.dial()
if err != nil {
@@ -99,8 +107,13 @@ func (s *Suite) TestStatus(t *utesting.T) {
}
}
-// TestGetBlockHeaders tests whether the given node can respond to
-// an eth `GetBlockHeaders` request and that the response is accurate.
+// headersMatch returns whether the received headers match the given request
+func headersMatch(expected []*types.Header, headers []*types.Header) bool {
+ return reflect.DeepEqual(expected, headers)
+}
+
+// TestGetBlockHeaders tests whether the given node can respond to an eth
+// `GetBlockHeaders` request and that the response is accurate.
func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
conn, err := s.dial()
if err != nil {
@@ -110,34 +123,41 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // write request
- req := &GetBlockHeaders{
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ // Send headers request.
+ req := ð.GetBlockHeadersPacket{
+ RequestId: 33,
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()},
Amount: 2,
Skip: 1,
Reverse: false,
},
}
- headers, err := conn.headersRequest(req, s.chain, 33)
- if err != nil {
- t.Fatalf("could not get block headers: %v", err)
+ // Read headers response.
+ if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req); err != nil {
+ t.Fatalf("could not write to connection: %v", err)
+ }
+ headers := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers); err != nil {
+ t.Fatalf("error reading msg: %v", err)
}
- // check for correct headers
+ if got, want := headers.RequestId, req.RequestId; got != want {
+ t.Fatalf("unexpected request id")
+ }
+ // Check for correct headers.
expected, err := s.chain.GetHeaders(req)
if err != nil {
t.Fatalf("failed to get headers for given request: %v", err)
}
- if !headersMatch(expected, headers) {
+ if !headersMatch(expected, headers.BlockHeadersRequest) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
}
}
-// TestSimultaneousRequests sends two simultaneous `GetBlockHeader` requests from
-// the same connection with different request IDs and checks to make sure the node
-// responds with the correct headers per request.
+// TestSimultaneousRequests sends two simultaneous `GetBlockHeader` requests
+// from the same connection with different request IDs and checks to make sure
+// the node responds with the correct headers per request.
func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
- // create a connection
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -147,10 +167,10 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
t.Fatalf("peering failed: %v", err)
}
- // create two requests
- req1 := &GetBlockHeaders{
+ // Create two different requests.
+ req1 := ð.GetBlockHeadersPacket{
RequestId: uint64(111),
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
Hash: s.chain.blocks[1].Hash(),
},
@@ -159,9 +179,9 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
Reverse: false,
},
}
- req2 := &GetBlockHeaders{
+ req2 := ð.GetBlockHeadersPacket{
RequestId: uint64(222),
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
Hash: s.chain.blocks[1].Hash(),
},
@@ -171,46 +191,45 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
},
}
- // write the first request
- if err := conn.Write(req1); err != nil {
+ // Send both requests.
+ if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req1); err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- // write the second request
- if err := conn.Write(req2); err != nil {
+ if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req2); err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- // wait for responses
- msg := conn.waitForResponse(s.chain, timeout, req1.RequestId)
- headers1, ok := msg.(*BlockHeaders)
- if !ok {
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
+ // Wait for responses.
+ headers1 := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers1); err != nil {
+ t.Fatalf("error reading block headers msg: %v", err)
+ }
+ if got, want := headers1.RequestId, req1.RequestId; got != want {
+ t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
+ }
+ headers2 := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers2); err != nil {
+ t.Fatalf("error reading block headers msg: %v", err)
}
- msg = conn.waitForResponse(s.chain, timeout, req2.RequestId)
- headers2, ok := msg.(*BlockHeaders)
- if !ok {
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
+ if got, want := headers2.RequestId, req2.RequestId; got != want {
+ t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
}
- // check received headers for accuracy
- expected1, err := s.chain.GetHeaders(req1)
- if err != nil {
+ // Check received headers for accuracy.
+ if expected, err := s.chain.GetHeaders(req1); err != nil {
t.Fatalf("failed to get expected headers for request 1: %v", err)
+ } else if !headersMatch(expected, headers1.BlockHeadersRequest) {
+ t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers1)
}
- expected2, err := s.chain.GetHeaders(req2)
- if err != nil {
+ if expected, err := s.chain.GetHeaders(req2); err != nil {
t.Fatalf("failed to get expected headers for request 2: %v", err)
- }
- if !headersMatch(expected1, headers1.BlockHeadersPacket) {
- t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
- }
- if !headersMatch(expected2, headers2.BlockHeadersPacket) {
- t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
+ } else if !headersMatch(expected, headers2.BlockHeadersRequest) {
+ t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers2)
}
}
-// TestSameRequestID sends two requests with the same request ID to a
-// single node.
+// TestSameRequestID sends two requests with the same request ID to a single
+// node.
func (s *Suite) TestSameRequestID(t *utesting.T) {
conn, err := s.dial()
if err != nil {
@@ -220,20 +239,21 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // create requests
+
+ // Create two different requests with the same ID.
reqID := uint64(1234)
- request1 := &GetBlockHeaders{
+ request1 := ð.GetBlockHeadersPacket{
RequestId: reqID,
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
Number: 1,
},
Amount: 2,
},
}
- request2 := &GetBlockHeaders{
+ request2 := ð.GetBlockHeadersPacket{
RequestId: reqID,
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
Number: 33,
},
@@ -241,40 +261,40 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
},
}
- // write the requests
- if err = conn.Write(request1); err != nil {
+ // Send the requests.
+ if err = conn.Write(ethProto, eth.GetBlockHeadersMsg, request1); err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- if err = conn.Write(request2); err != nil {
+ if err = conn.Write(ethProto, eth.GetBlockHeadersMsg, request2); err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- // wait for responses
- msg := conn.waitForResponse(s.chain, timeout, reqID)
- headers1, ok := msg.(*BlockHeaders)
- if !ok {
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
+ // Wait for the responses.
+ headers1 := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers1); err != nil {
+ t.Fatalf("error reading from connection: %v", err)
+ }
+ if got, want := headers1.RequestId, request1.RequestId; got != want {
+ t.Fatalf("unexpected request id: got %d, want %d", got, want)
+ }
+ headers2 := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers2); err != nil {
+ t.Fatalf("error reading from connection: %v", err)
}
- msg = conn.waitForResponse(s.chain, timeout, reqID)
- headers2, ok := msg.(*BlockHeaders)
- if !ok {
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
+ if got, want := headers2.RequestId, request2.RequestId; got != want {
+ t.Fatalf("unexpected request id: got %d, want %d", got, want)
}
- // check if headers match
- expected1, err := s.chain.GetHeaders(request1)
- if err != nil {
+ // Check if headers match.
+ if expected, err := s.chain.GetHeaders(request1); err != nil {
t.Fatalf("failed to get expected block headers: %v", err)
+ } else if !headersMatch(expected, headers1.BlockHeadersRequest) {
+ t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers1)
}
- expected2, err := s.chain.GetHeaders(request2)
- if err != nil {
+ if expected, err := s.chain.GetHeaders(request2); err != nil {
t.Fatalf("failed to get expected block headers: %v", err)
- }
- if !headersMatch(expected1, headers1.BlockHeadersPacket) {
- t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
- }
- if !headersMatch(expected2, headers2.BlockHeadersPacket) {
- t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
+ } else if !headersMatch(expected, headers2.BlockHeadersRequest) {
+ t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers2)
}
}
@@ -289,27 +309,32 @@ func (s *Suite) TestZeroRequestID(t *utesting.T) {
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- req := &GetBlockHeaders{
- GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
+ req := ð.GetBlockHeadersPacket{
+ GetBlockHeadersRequest: ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Number: 0},
Amount: 2,
},
}
- headers, err := conn.headersRequest(req, s.chain, 0)
- if err != nil {
- t.Fatalf("failed to get block headers: %v", err)
+ // Read headers response.
+ if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req); err != nil {
+ t.Fatalf("could not write to connection: %v", err)
}
- expected, err := s.chain.GetHeaders(req)
- if err != nil {
- t.Fatalf("failed to get expected block headers: %v", err)
+ headers := new(eth.BlockHeadersPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers); err != nil {
+ t.Fatalf("error reading msg: %v", err)
+ }
+ if got, want := headers.RequestId, req.RequestId; got != want {
+ t.Fatalf("unexpected request id")
}
- if !headersMatch(expected, headers) {
+ if expected, err := s.chain.GetHeaders(req); err != nil {
+ t.Fatalf("failed to get expected block headers: %v", err)
+ } else if !headersMatch(expected, headers.BlockHeadersRequest) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
}
}
-// TestGetBlockBodies tests whether the given node can respond to
-// a `GetBlockBodies` request and that the response is accurate.
+// TestGetBlockBodies tests whether the given node can respond to a
+// `GetBlockBodies` request and that the response is accurate.
func (s *Suite) TestGetBlockBodies(t *utesting.T) {
conn, err := s.dial()
if err != nil {
@@ -319,104 +344,110 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) {
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // create block bodies request
- req := &GetBlockBodies{
- RequestId: uint64(55),
- GetBlockBodiesPacket: eth.GetBlockBodiesPacket{
+ // Create block bodies request.
+ req := ð.GetBlockBodiesPacket{
+ RequestId: 55,
+ GetBlockBodiesRequest: eth.GetBlockBodiesRequest{
s.chain.blocks[54].Hash(),
s.chain.blocks[75].Hash(),
},
}
- if err := conn.Write(req); err != nil {
+ if err := conn.Write(ethProto, eth.GetBlockBodiesMsg, req); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
- // wait for block bodies response
- msg := conn.waitForResponse(s.chain, timeout, req.RequestId)
- resp, ok := msg.(*BlockBodies)
- if !ok {
- t.Fatalf("unexpected: %s", pretty.Sdump(msg))
+ // Wait for response.
+ resp := new(eth.BlockBodiesPacket)
+ if err := conn.ReadMsg(ethProto, eth.BlockBodiesMsg, &resp); err != nil {
+ t.Fatalf("error reading block bodies msg: %v", err)
+ }
+ if got, want := resp.RequestId, req.RequestId; got != want {
+ t.Fatalf("unexpected request id in respond", got, want)
}
- bodies := resp.BlockBodiesPacket
- t.Logf("received %d block bodies", len(bodies))
- if len(bodies) != len(req.GetBlockBodiesPacket) {
- t.Fatalf("wrong bodies in response: expected %d bodies, "+
- "got %d", len(req.GetBlockBodiesPacket), len(bodies))
+ bodies := resp.BlockBodiesResponse
+ if len(bodies) != len(req.GetBlockBodiesRequest) {
+ t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetBlockBodiesRequest), len(bodies))
}
}
-// TestBroadcast tests whether a block announcement is correctly
-// propagated to the node's peers.
-func (s *Suite) TestBroadcast(t *utesting.T) {
- if err := s.sendNextBlock(); err != nil {
- t.Fatalf("block broadcast failed: %v", err)
- }
+// randBuf makes a random buffer size kilobytes large.
+func randBuf(size int) []byte {
+ buf := make([]byte, size*1024)
+ rand.Read(buf)
+ return buf
}
-// TestLargeAnnounce tests the announcement mechanism with a large block.
-func (s *Suite) TestLargeAnnounce(t *utesting.T) {
- nextBlock := len(s.chain.blocks)
- blocks := []*NewBlock{
+// TestMaliciousHandshake tries to send malicious data during the handshake.
+func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
+ key, _ := crypto.GenerateKey()
+
+ // Write hello to client.
+ var (
+ pub0 = crypto.FromECDSAPub(&key.PublicKey)[1:]
+ version = eth.ProtocolVersions[0]
+ )
+ handshakes := []*protoHandshake{
{
- Block: largeBlock(),
- TD: s.fullChain.TotalDifficultyAt(nextBlock),
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: string(randBuf(2)), Version: version},
+ },
+ ID: pub0,
},
{
- Block: s.fullChain.blocks[nextBlock],
- TD: largeNumber(2),
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: "eth", Version: version},
+ },
+ ID: append(pub0, byte(0)),
},
{
- Block: largeBlock(),
- TD: largeNumber(2),
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: "eth", Version: version},
+ },
+ ID: append(pub0, pub0...),
+ },
+ {
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: "eth", Version: version},
+ },
+ ID: randBuf(2),
+ },
+ {
+ Version: 5,
+ Caps: []p2p.Cap{
+ {Name: string(randBuf(2)), Version: version},
+ },
+ ID: randBuf(2),
},
}
-
- for i, blockAnnouncement := range blocks[0:3] {
- t.Logf("Testing malicious announcement: %v\n", i)
- conn, err := s.dial()
+ for _, handshake := range handshakes {
+ conn, err := s.dialAs(key)
if err != nil {
t.Fatalf("dial failed: %v", err)
}
- if err := conn.peer(s.chain, nil); err != nil {
- t.Fatalf("peering failed: %v", err)
- }
- if err := conn.Write(blockAnnouncement); err != nil {
+ defer conn.Close()
+
+ if err := conn.Write(ethProto, handshakeMsg, handshake); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
- // Invalid announcement, check that peer disconnected
- switch msg := conn.readAndServe(s.chain, 8*time.Second).(type) {
- case *Disconnect:
- case *Error:
- break
- default:
- t.Fatalf("unexpected: %s wanted disconnect", pretty.Sdump(msg))
+ // Check that the peer disconnected
+ for i := 0; i < 2; i++ {
+ code, _, err := conn.Read()
+ if err != nil {
+ // Client may have disconnected without sending disconnect msg.
+ continue
+ }
+ switch code {
+ case discMsg:
+ case handshakeMsg:
+ // Discard one hello as Hello's are sent concurrently
+ continue
+ default:
+ t.Fatalf("unexpected msg: code %d", code)
+ }
}
- conn.Close()
- }
- // Test the last block as a valid block
- if err := s.sendNextBlock(); err != nil {
- t.Fatalf("failed to broadcast next block: %v", err)
- }
-}
-
-// TestOldAnnounce tests the announcement mechanism with an old block.
-func (s *Suite) TestOldAnnounce(t *utesting.T) {
- if err := s.oldAnnounce(); err != nil {
- t.Fatal(err)
- }
-}
-
-// TestBlockHashAnnounce sends a new block hash announcement and expects
-// the node to perform a `GetBlockHeaders` request.
-func (s *Suite) TestBlockHashAnnounce(t *utesting.T) {
- if err := s.hashAnnounce(); err != nil {
- t.Fatalf("block hash announcement failed: %v", err)
- }
-}
-
-// TestMaliciousHandshake tries to send malicious data during the handshake.
-func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
- if err := s.maliciousHandshakes(t); err != nil {
- t.Fatal(err)
}
}
@@ -427,46 +458,184 @@ func (s *Suite) TestMaliciousStatus(t *utesting.T) {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
-
- if err := s.maliciousStatus(conn); err != nil {
- t.Fatal(err)
+ if err := conn.handshake(); err != nil {
+ t.Fatalf("handshake failed: %v", err)
+ }
+ // Create status with large total difficulty.
+ status := ð.StatusPacket{
+ ProtocolVersion: uint32(conn.negotiatedProtoVersion),
+ NetworkID: s.chain.config.ChainID.Uint64(),
+ TD: new(big.Int).SetBytes(randBuf(2048)),
+ Head: s.chain.Head().Hash(),
+ Genesis: s.chain.GetBlock(0).Hash(),
+ ForkID: s.chain.ForkID(),
+ }
+ if err := conn.statusExchange(s.chain, status); err != nil {
+ t.Fatalf("status exchange failed: %v", err)
+ }
+ // Wait for disconnect.
+ code, _, err := conn.Read()
+ if err != nil {
+ t.Fatalf("error reading from connection: %v", err)
+ }
+ switch code {
+ case discMsg:
+ break
+ default:
+ t.Fatalf("expected disconnect, got: %d", code)
}
}
-// TestTransaction sends a valid transaction to the node and
-// checks if the transaction gets propagated.
+// TestTransaction sends a valid transaction to the node and checks if the
+// transaction gets propagated.
func (s *Suite) TestTransaction(t *utesting.T) {
- if err := s.sendSuccessfulTxs(t); err != nil {
+ // Nudge client out of syncing mode to accept pending txs.
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
+ t.Fatalf("failed to send next block: %v", err)
+ }
+ from, nonce := s.chain.GetSender(0)
+ inner := &types.DynamicFeeTx{
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 30000,
+ To: &common.Address{0xaa},
+ Value: common.Big1,
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+ if err := s.sendTxs([]*types.Transaction{tx}); err != nil {
t.Fatal(err)
}
+ s.chain.IncNonce(from, 1)
}
-// TestMaliciousTx sends several invalid transactions and tests whether
+// TestInvalidTxs sends several invalid transactions and tests whether
// the node will propagate them.
-func (s *Suite) TestMaliciousTx(t *utesting.T) {
- if err := s.sendMaliciousTxs(t); err != nil {
- t.Fatal(err)
+func (s *Suite) TestInvalidTxs(t *utesting.T) {
+ // Nudge client out of syncing mode to accept pending txs.
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
+ t.Fatalf("failed to send next block: %v", err)
+ }
+
+ from, nonce := s.chain.GetSender(0)
+ inner := &types.DynamicFeeTx{
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 30000,
+ To: &common.Address{0xaa},
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+ if err := s.sendTxs([]*types.Transaction{tx}); err != nil {
+ t.Fatalf("failed to send txs: %v", err)
+ }
+ s.chain.IncNonce(from, 1)
+
+ inners := []*types.DynamicFeeTx{
+ // Nonce already used
+ {
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce - 1,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 100000,
+ },
+ // Value exceeds balance
+ {
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 100000,
+ Value: s.chain.Balance(from),
+ },
+ // Gas limit too low
+ {
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 1337,
+ },
+ // Code size too large
+ {
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Data: randBuf(50),
+ Gas: 1_000_000,
+ },
+ // Data too large
+ {
+ Nonce: nonce,
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ To: &common.Address{0xaa},
+ Data: randBuf(128),
+ Gas: 5_000_000,
+ },
+ }
+
+ var txs []*types.Transaction
+ for _, inner := range inners {
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v", err)
+ }
+ txs = append(txs, tx)
+ }
+ if err := s.sendInvalidTxs(txs); err != nil {
+ t.Fatalf("failed to send invalid txs: %v", err)
}
}
// TestLargeTxRequest tests whether a node can fulfill a large GetPooledTransactions
// request.
func (s *Suite) TestLargeTxRequest(t *utesting.T) {
- // send the next block to ensure the node is no longer syncing and
- // is able to accept txs
- if err := s.sendNextBlock(); err != nil {
+ // Nudge client out of syncing mode to accept pending txs.
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
t.Fatalf("failed to send next block: %v", err)
}
- // send 2000 transactions to the node
- hashMap, txs, err := generateTxs(s, 2000)
- if err != nil {
- t.Fatalf("failed to generate transactions: %v", err)
+
+ // Generate many transactions to seed target with.
+ var (
+ from, nonce = s.chain.GetSender(1)
+ count = 2000
+ txs []*types.Transaction
+ hashes []common.Hash
+ set = make(map[common.Hash]struct{})
+ )
+ for i := 0; i < count; i++ {
+ inner := &types.DynamicFeeTx{
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce + uint64(i),
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 75000,
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: err")
+ }
+ txs = append(txs, tx)
+ set[tx.Hash()] = struct{}{}
+ hashes = append(hashes, tx.Hash())
}
- if err = sendMultipleSuccessfulTxs(t, s, txs); err != nil {
- t.Fatalf("failed to send multiple txs: %v", err)
+ s.chain.IncNonce(from, uint64(count))
+
+ // Send txs.
+ if err := s.sendTxs(txs); err != nil {
+ t.Fatalf("failed to send txs: %v", err)
}
- // set up connection to receive to ensure node is peered with the receiving connection
- // before tx request is sent
+
+ // Set up receive connection to ensure node is peered with the receiving
+ // connection before tx request is sent.
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -475,55 +644,62 @@ func (s *Suite) TestLargeTxRequest(t *utesting.T) {
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
- // create and send pooled tx request
- hashes := make([]common.Hash, 0)
- for _, hash := range hashMap {
- hashes = append(hashes, hash)
- }
- getTxReq := &GetPooledTransactions{
- RequestId: 1234,
- GetPooledTransactionsPacket: hashes,
+ // Create and send pooled tx request.
+ req := ð.GetPooledTransactionsPacket{
+ RequestId: 1234,
+ GetPooledTransactionsRequest: hashes,
}
- if err = conn.Write(getTxReq); err != nil {
+ if err = conn.Write(ethProto, eth.GetPooledTransactionsMsg, req); err != nil {
t.Fatalf("could not write to conn: %v", err)
}
- // check that all received transactions match those that were sent to node
- switch msg := conn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) {
- case *PooledTransactions:
- for _, gotTx := range msg.PooledTransactionsPacket {
- if _, exists := hashMap[gotTx.Hash()]; !exists {
- t.Fatalf("unexpected tx received: %v", gotTx.Hash())
- }
+ // Check that all received transactions match those that were sent to node.
+ msg := new(eth.PooledTransactionsPacket)
+ if err := conn.ReadMsg(ethProto, eth.PooledTransactionsMsg, &msg); err != nil {
+ t.Fatalf("error reading from connection: %v", err)
+ }
+ if got, want := msg.RequestId, req.RequestId; got != want {
+ t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
+ }
+ for _, got := range msg.PooledTransactionsResponse {
+ if _, exists := set[got.Hash()]; !exists {
+ t.Fatalf("unexpected tx received: %v", got.Hash())
}
- default:
- t.Fatalf("unexpected %s", pretty.Sdump(msg))
}
}
-// TestNewPooledTxs tests whether a node will do a GetPooledTransactions
-// request upon receiving a NewPooledTransactionHashes announcement.
+// TestNewPooledTxs tests whether a node will do a GetPooledTransactions request
+// upon receiving a NewPooledTransactionHashes announcement.
func (s *Suite) TestNewPooledTxs(t *utesting.T) {
- // send the next block to ensure the node is no longer syncing and
- // is able to accept txs
- if err := s.sendNextBlock(); err != nil {
+ // Nudge client out of syncing mode to accept pending txs.
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
t.Fatalf("failed to send next block: %v", err)
}
-
- // generate 50 txs
- _, txs, err := generateTxs(s, 50)
- if err != nil {
- t.Fatalf("failed to generate transactions: %v", err)
- }
- hashes := make([]common.Hash, len(txs))
- types := make([]byte, len(txs))
- sizes := make([]uint32, len(txs))
- for i, tx := range txs {
+ var (
+ count = 50
+ from, nonce = s.chain.GetSender(1)
+ hashes = make([]common.Hash, count)
+ txTypes = make([]byte, count)
+ sizes = make([]uint32, count)
+ )
+ for i := 0; i < count; i++ {
+ inner := &types.DynamicFeeTx{
+ ChainID: s.chain.config.ChainID,
+ Nonce: nonce + uint64(i),
+ GasTipCap: common.Big1,
+ GasFeeCap: s.chain.Head().BaseFee(),
+ Gas: 75000,
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ t.Fatalf("failed to sign tx: err")
+ }
hashes[i] = tx.Hash()
- types[i] = tx.Type()
+ txTypes[i] = tx.Type()
sizes[i] = uint32(tx.Size())
}
+ s.chain.IncNonce(from, uint64(count))
- // send announcement
+ // Connect to peer.
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
@@ -533,40 +709,138 @@ func (s *Suite) TestNewPooledTxs(t *utesting.T) {
t.Fatalf("peering failed: %v", err)
}
- var ann Message = NewPooledTransactionHashes{Types: types, Sizes: sizes, Hashes: hashes}
- if conn.negotiatedProtoVersion < eth.ETH68 {
- ann = NewPooledTransactionHashes66(hashes)
- }
- err = conn.Write(ann)
+ // Send announcement.
+ ann := eth.NewPooledTransactionHashesPacket68{Types: txTypes, Sizes: sizes, Hashes: hashes}
+ err = conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, ann)
if err != nil {
t.Fatalf("failed to write to connection: %v", err)
}
- // wait for GetPooledTxs request
+ // Wait for GetPooledTxs request.
for {
- msg := conn.readAndServe(s.chain, timeout)
+ msg, err := conn.ReadEth()
+ if err != nil {
+ t.Fatalf("failed to read eth msg: %v", err)
+ }
switch msg := msg.(type) {
- case *GetPooledTransactions:
- if len(msg.GetPooledTransactionsPacket) != len(hashes) {
- t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsPacket))
+ case *eth.GetPooledTransactionsPacket:
+ if len(msg.GetPooledTransactionsRequest) != len(hashes) {
+ t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsRequest))
}
return
-
- // ignore propagated txs from previous tests
- case *NewPooledTransactionHashes66:
+ case *eth.NewPooledTransactionHashesPacket68:
continue
- case *NewPooledTransactionHashes:
- continue
- case *Transactions:
- continue
-
- // ignore block announcements from previous tests
- case *NewBlockHashes:
- continue
- case *NewBlock:
+ case *eth.TransactionsPacket:
continue
default:
t.Fatalf("unexpected %s", pretty.Sdump(msg))
}
}
}
+
+func makeSidecar(data ...byte) *types.BlobTxSidecar {
+ var (
+ blobs = make([]kzg4844.Blob, len(data))
+ commitments []kzg4844.Commitment
+ proofs []kzg4844.Proof
+ )
+ for i := range blobs {
+ blobs[i][0] = data[i]
+ c, _ := kzg4844.BlobToCommitment(blobs[i])
+ p, _ := kzg4844.ComputeBlobProof(blobs[i], c)
+ commitments = append(commitments, c)
+ proofs = append(proofs, p)
+ }
+ return &types.BlobTxSidecar{
+ Blobs: blobs,
+ Commitments: commitments,
+ Proofs: proofs,
+ }
+}
+
+func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Transactions) {
+ from, nonce := s.chain.GetSender(5)
+ for i := 0; i < count; i++ {
+ // Make blob data, max of 2 blobs per tx.
+ blobdata := make([]byte, blobs%2)
+ for i := range blobdata {
+ blobdata[i] = discriminator
+ blobs -= 1
+ }
+ inner := &types.BlobTx{
+ ChainID: uint256.MustFromBig(s.chain.config.ChainID),
+ Nonce: nonce + uint64(i),
+ GasTipCap: uint256.NewInt(1),
+ GasFeeCap: uint256.MustFromBig(s.chain.Head().BaseFee()),
+ Gas: 100000,
+ BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(*s.chain.Head().ExcessBlobGas())),
+ BlobHashes: makeSidecar(blobdata...).BlobHashes(),
+ Sidecar: makeSidecar(blobdata...),
+ }
+ tx, err := s.chain.SignTx(from, types.NewTx(inner))
+ if err != nil {
+ panic("blob tx signing failed")
+ }
+ txs = append(txs, tx)
+ }
+ return txs
+}
+
+func (s *Suite) TestBlobViolations(t *utesting.T) {
+ if err := s.engine.sendForkchoiceUpdated(); err != nil {
+ t.Fatalf("send fcu failed: %v", err)
+ }
+ // Create blob txs for each tests with unique tx hashes.
+ var (
+ t1 = s.makeBlobTxs(2, 3, 0x1)
+ t2 = s.makeBlobTxs(2, 3, 0x2)
+ )
+ for _, test := range []struct {
+ ann eth.NewPooledTransactionHashesPacket68
+ resp eth.PooledTransactionsResponse
+ }{
+ // Invalid tx size.
+ {
+ ann: eth.NewPooledTransactionHashesPacket68{
+ Types: []byte{types.BlobTxType, types.BlobTxType},
+ Sizes: []uint32{uint32(t1[0].Size()), uint32(t1[1].Size() + 10)},
+ Hashes: []common.Hash{t1[0].Hash(), t1[1].Hash()},
+ },
+ resp: eth.PooledTransactionsResponse(t1),
+ },
+ // Wrong tx type.
+ {
+ ann: eth.NewPooledTransactionHashesPacket68{
+ Types: []byte{types.DynamicFeeTxType, types.BlobTxType},
+ Sizes: []uint32{uint32(t2[0].Size()), uint32(t2[1].Size())},
+ Hashes: []common.Hash{t2[0].Hash(), t2[1].Hash()},
+ },
+ resp: eth.PooledTransactionsResponse(t2),
+ },
+ } {
+ conn, err := s.dial()
+ if err != nil {
+ t.Fatalf("dial fail: %v", err)
+ }
+ if err := conn.peer(s.chain, nil); err != nil {
+ t.Fatalf("peering failed: %v", err)
+ }
+ if err := conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, test.ann); err != nil {
+ t.Fatalf("sending announcement failed: %v", err)
+ }
+ req := new(eth.GetPooledTransactionsPacket)
+ if err := conn.ReadMsg(ethProto, eth.GetPooledTransactionsMsg, req); err != nil {
+ t.Fatalf("reading pooled tx request failed: %v", err)
+ }
+ resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, PooledTransactionsResponse: test.resp}
+ if err := conn.Write(ethProto, eth.PooledTransactionsMsg, resp); err != nil {
+ t.Fatalf("writing pooled tx response failed: %v", err)
+ }
+ if code, _, err := conn.Read(); err != nil {
+ t.Fatalf("expected disconnect on blob violation, got err: %v", err)
+ } else if code != discMsg {
+ t.Fatalf("expected disconnect on blob violation, got msg code: %d", code)
+ }
+ conn.Close()
+ }
+}
diff --git a/cmd/devp2p/internal/ethtest/suite_test.go b/cmd/devp2p/internal/ethtest/suite_test.go
index 46a78073f7..c8479fd3aa 100644
--- a/cmd/devp2p/internal/ethtest/suite_test.go
+++ b/cmd/devp2p/internal/ethtest/suite_test.go
@@ -17,37 +17,56 @@
package ethtest // TOFIX
import (
+ crand "crypto/rand"
+ "fmt"
"os"
+ "path"
"testing"
"time"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/utesting"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
)
-var (
- genesisFile = "./testdata/genesis.json"
- halfchainFile = "./testdata/halfchain.rlp"
- fullchainFile = "./testdata/chain.rlp"
-)
+func makeJWTSecret() (string, [32]byte, error) {
+ var secret [32]byte
+ if _, err := crand.Read(secret[:]); err != nil {
+ return "", secret, fmt.Errorf("failed to create jwt secret: %v", err)
+ }
+ jwtPath := path.Join(os.TempDir(), "jwt_secret")
+ if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(secret[:])), 0600); err != nil {
+ return "", secret, fmt.Errorf("failed to prepare jwt secret file: %v", err)
+ }
+ return jwtPath, secret, nil
+}
func TestEthSuite(t *testing.T) {
- geth, err := runGeth()
+ jwtPath, secret, err := makeJWTSecret()
+ if err != nil {
+ t.Fatalf("could not make jwt secret: %v", err)
+ }
+ geth, err := runGeth("./testdata", jwtPath)
if err != nil {
t.Fatalf("could not run geth: %v", err)
}
defer geth.Close()
- suite, err := NewSuite(geth.Server().Self(), fullchainFile, genesisFile)
+ suite, err := NewSuite(geth.Server().Self(), "./testdata", geth.HTTPAuthEndpoint(), common.Bytes2Hex(secret[:]))
if err != nil {
t.Fatalf("could not create new test suite: %v", err)
}
for _, test := range suite.EthTests() {
t.Run(test.Name, func(t *testing.T) {
- result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
+ if test.Slow && testing.Short() {
+ t.Skipf("%s: skipping in -short mode", test.Name)
+ }
+ result := utesting.RunTests([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
if result[0].Failed {
t.Fatal()
}
@@ -56,19 +75,23 @@ func TestEthSuite(t *testing.T) {
}
func TestSnapSuite(t *testing.T) {
- geth, err := runGeth()
+ jwtPath, secret, err := makeJWTSecret()
+ if err != nil {
+ t.Fatalf("could not make jwt secret: %v", err)
+ }
+ geth, err := runGeth("./testdata", jwtPath)
if err != nil {
t.Fatalf("could not run geth: %v", err)
}
defer geth.Close()
- suite, err := NewSuite(geth.Server().Self(), fullchainFile, genesisFile)
+ suite, err := NewSuite(geth.Server().Self(), "./testdata", geth.HTTPAuthEndpoint(), common.Bytes2Hex(secret[:]))
if err != nil {
t.Fatalf("could not create new test suite: %v", err)
}
for _, test := range suite.SnapTests() {
t.Run(test.Name, func(t *testing.T) {
- result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
+ result := utesting.RunTests([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
if result[0].Failed {
t.Fatal()
}
@@ -77,8 +100,10 @@ func TestSnapSuite(t *testing.T) {
}
// runGeth creates and starts a geth node
-func runGeth() (*node.Node, error) {
+func runGeth(dir string, jwtPath string) (*node.Node, error) {
stack, err := node.New(&node.Config{
+ AuthAddr: "127.0.0.1",
+ AuthPort: 0,
P2P: p2p.Config{
ListenAddr: "127.0.0.1:0",
NoDiscovery: true,
@@ -86,12 +111,13 @@ func runGeth() (*node.Node, error) {
MaxPeersPerIP: 10,
NoDial: true,
},
+ JWTSecret: jwtPath,
})
if err != nil {
return nil, err
}
- err = setupGeth(stack)
+ err = setupGeth(stack, dir)
if err != nil {
stack.Close()
return nil, err
@@ -103,12 +129,11 @@ func runGeth() (*node.Node, error) {
return stack, nil
}
-func setupGeth(stack *node.Node) error {
- chain, err := loadChain(halfchainFile, genesisFile)
+func setupGeth(stack *node.Node, dir string) error {
+ chain, err := NewChain(dir)
if err != nil {
return err
}
-
backend, err := eth.New(stack, ðconfig.Config{
Genesis: &chain.genesis,
NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763
@@ -122,7 +147,9 @@ func setupGeth(stack *node.Node) error {
if err != nil {
return err
}
-
+ if err := catalyst.Register(stack, backend); err != nil {
+ return fmt.Errorf("failed to register catalyst service: %v", err)
+ }
_, err = backend.BlockChain().InsertChain(chain.blocks[1:])
return err
}
diff --git a/cmd/devp2p/internal/ethtest/testdata/accounts.json b/cmd/devp2p/internal/ethtest/testdata/accounts.json
new file mode 100644
index 0000000000..c9666235a8
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/accounts.json
@@ -0,0 +1,62 @@
+{
+ "0x0c2c51a0990aee1d73c1228de158688341557508": {
+ "key": "0xbfcd0e032489319f4e5ca03e643b2025db624be6cf99cbfed90c4502e3754850"
+ },
+ "0x14e46043e63d0e3cdcf2530519f4cfaf35058cb2": {
+ "key": "0x457075f6822ac29481154792f65c5f1ec335b4fea9ca20f3fea8fa1d78a12c68"
+ },
+ "0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": {
+ "key": "0x865898edcf43206d138c93f1bbd86311f4657b057658558888aa5ac4309626a6"
+ },
+ "0x1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": {
+ "key": "0xee7f7875d826d7443ccc5c174e38b2c436095018774248a8074ee92d8914dcdb"
+ },
+ "0x1f5bde34b4afc686f136c7a3cb6ec376f7357759": {
+ "key": "0x25e6ce8611cefb5cd338aeaa9292ed2139714668d123a4fb156cabb42051b5b7"
+ },
+ "0x2d389075be5be9f2246ad654ce152cf05990b209": {
+ "key": "0x19168cd7767604b3d19b99dc3da1302b9ccb6ee9ad61660859e07acd4a2625dd"
+ },
+ "0x3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": {
+ "key": "0x71aa7d299c7607dabfc3d0e5213d612b5e4a97455b596c2f642daac43fa5eeaa"
+ },
+ "0x4340ee1b812acb40a1eb561c019c327b243b92df": {
+ "key": "0x47f666f20e2175606355acec0ea1b37870c15e5797e962340da7ad7972a537e8"
+ },
+ "0x4a0f1452281bcec5bd90c3dce6162a5995bfe9df": {
+ "key": "0xa88293fefc623644969e2ce6919fb0dbd0fd64f640293b4bf7e1a81c97e7fc7f"
+ },
+ "0x4dde844b71bcdf95512fb4dc94e84fb67b512ed8": {
+ "key": "0x6e1e16a9c15641c73bf6e237f9293ab1d4e7c12b9adf83cfc94bcf969670f72d"
+ },
+ "0x5f552da00dfb4d3749d9e62dcee3c918855a86a0": {
+ "key": "0x41be4e00aac79f7ffbb3455053ec05e971645440d594c047cdcc56a3c7458bd6"
+ },
+ "0x654aa64f5fbefb84c270ec74211b81ca8c44a72e": {
+ "key": "0xc825f31cd8792851e33a290b3d749e553983111fc1f36dfbbdb45f101973f6a9"
+ },
+ "0x717f8aa2b982bee0e29f573d31df288663e1ce16": {
+ "key": "0x8d0faa04ae0f9bc3cd4c890aa025d5f40916f4729538b19471c0beefe11d9e19"
+ },
+ "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": {
+ "key": "0x4552dbe6ca4699322b5d923d0c9bcdd24644f5db8bf89a085b67c6c49b8a1b91"
+ },
+ "0x83c7e323d189f18725ac510004fdc2941f8c4a78": {
+ "key": "0x34391cbbf06956bb506f45ec179cdd84df526aa364e27bbde65db9c15d866d00"
+ },
+ "0x84e75c28348fb86acea1a93a39426d7d60f4cc46": {
+ "key": "0xf6a8f1603b8368f3ca373292b7310c53bec7b508aecacd442554ebc1c5d0c856"
+ },
+ "0xc7b99a164efd027a93f147376cc7da7c67c6bbe0": {
+ "key": "0x8d56bcbcf2c1b7109e1396a28d7a0234e33544ade74ea32c460ce4a443b239b1"
+ },
+ "0xd803681e487e6ac18053afc5a6cd813c86ec3e4d": {
+ "key": "0xfc39d1c9ddbba176d806ebb42d7460189fe56ca163ad3eb6143bfc6beb6f6f72"
+ },
+ "0xe7d13f7aa2a838d24c59b40186a0aca1e21cffcc": {
+ "key": "0x9ee3fd550664b246ad7cdba07162dd25530a3b1d51476dd1d85bbc29f0592684"
+ },
+ "0xeda8645ba6948855e3b3cd596bbb07596d59c603": {
+ "key": "0x14cdde09d1640eb8c3cda063891b0453073f57719583381ff78811efa6d4199f"
+ }
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/chain.rlp b/cmd/devp2p/internal/ethtest/testdata/chain.rlp
index 5ebc2f3bb7..2964c02bb1 100644
Binary files a/cmd/devp2p/internal/ethtest/testdata/chain.rlp and b/cmd/devp2p/internal/ethtest/testdata/chain.rlp differ
diff --git a/cmd/devp2p/internal/ethtest/testdata/forkenv.json b/cmd/devp2p/internal/ethtest/testdata/forkenv.json
new file mode 100644
index 0000000000..86c49e2b97
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/forkenv.json
@@ -0,0 +1,20 @@
+{
+ "HIVE_CANCUN_TIMESTAMP": "840",
+ "HIVE_CHAIN_ID": "3503995874084926",
+ "HIVE_FORK_ARROW_GLACIER": "60",
+ "HIVE_FORK_BERLIN": "48",
+ "HIVE_FORK_BYZANTIUM": "18",
+ "HIVE_FORK_CONSTANTINOPLE": "24",
+ "HIVE_FORK_GRAY_GLACIER": "66",
+ "HIVE_FORK_HOMESTEAD": "0",
+ "HIVE_FORK_ISTANBUL": "36",
+ "HIVE_FORK_LONDON": "54",
+ "HIVE_FORK_MUIR_GLACIER": "42",
+ "HIVE_FORK_PETERSBURG": "30",
+ "HIVE_FORK_SPURIOUS": "12",
+ "HIVE_FORK_TANGERINE": "6",
+ "HIVE_MERGE_BLOCK_ID": "72",
+ "HIVE_NETWORK_ID": "3503995874084926",
+ "HIVE_SHANGHAI_TIMESTAMP": "780",
+ "HIVE_TERMINAL_TOTAL_DIFFICULTY": "9454784"
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/genesis.json b/cmd/devp2p/internal/ethtest/testdata/genesis.json
index b4de6e85a5..e8bb66bb3c 100644
--- a/cmd/devp2p/internal/ethtest/testdata/genesis.json
+++ b/cmd/devp2p/internal/ethtest/testdata/genesis.json
@@ -1,27 +1,112 @@
{
- "config": {
- "chainId": 19763,
- "homesteadBlock": 0,
- "eip150Block": 0,
- "eip155Block": 0,
- "eip158Block": 0,
- "byzantiumBlock": 0,
- "terminalTotalDifficultyPassed": true,
- "ethash": {}
- },
- "nonce": "0xdeadbeefdeadbeef",
- "timestamp": "0x0",
- "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "gasLimit": "0x80000000",
- "difficulty": "0x20000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "coinbase": "0x0000000000000000000000000000000000000000",
- "alloc": {
- "71562b71999873db5b286df957af199ec94617f7": {
- "balance": "0xffffffffffffffffffffffffff"
- }
- },
- "number": "0x0",
- "gasUsed": "0x0",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
-}
+ "config": {
+ "chainId": 3503995874084926,
+ "homesteadBlock": 0,
+ "eip150Block": 6,
+ "eip155Block": 12,
+ "eip158Block": 12,
+ "byzantiumBlock": 18,
+ "constantinopleBlock": 24,
+ "petersburgBlock": 30,
+ "istanbulBlock": 36,
+ "muirGlacierBlock": 42,
+ "berlinBlock": 48,
+ "londonBlock": 54,
+ "arrowGlacierBlock": 60,
+ "grayGlacierBlock": 66,
+ "mergeNetsplitBlock": 72,
+ "shanghaiTime": 780,
+ "cancunTime": 840,
+ "terminalTotalDifficulty": 9454784,
+ "terminalTotalDifficultyPassed": true,
+ "ethash": {}
+ },
+ "nonce": "0x0",
+ "timestamp": "0x0",
+ "extraData": "0x68697665636861696e",
+ "gasLimit": "0x23f3e20",
+ "difficulty": "0x20000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase": "0x0000000000000000000000000000000000000000",
+ "alloc": {
+ "000f3df6d732807ef1319fb7b8bb8522d0beac02": {
+ "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500",
+ "balance": "0x2a"
+ },
+ "0c2c51a0990aee1d73c1228de158688341557508": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "14e46043e63d0e3cdcf2530519f4cfaf35058cb2": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "1f5bde34b4afc686f136c7a3cb6ec376f7357759": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "2d389075be5be9f2246ad654ce152cf05990b209": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "4340ee1b812acb40a1eb561c019c327b243b92df": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "4a0f1452281bcec5bd90c3dce6162a5995bfe9df": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "4dde844b71bcdf95512fb4dc94e84fb67b512ed8": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "5f552da00dfb4d3749d9e62dcee3c918855a86a0": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "654aa64f5fbefb84c270ec74211b81ca8c44a72e": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "717f8aa2b982bee0e29f573d31df288663e1ce16": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "83c7e323d189f18725ac510004fdc2941f8c4a78": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "84e75c28348fb86acea1a93a39426d7d60f4cc46": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "8bebc8ba651aee624937e7d897853ac30c95a067": {
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000003"
+ },
+ "balance": "0x1",
+ "nonce": "0x1"
+ },
+ "c7b99a164efd027a93f147376cc7da7c67c6bbe0": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "d803681e487e6ac18053afc5a6cd813c86ec3e4d": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "e7d13f7aa2a838d24c59b40186a0aca1e21cffcc": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ },
+ "eda8645ba6948855e3b3cd596bbb07596d59c603": {
+ "balance": "0xc097ce7bc90715b34b9f1000000000"
+ }
+ },
+ "number": "0x0",
+ "gasUsed": "0x0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "baseFeePerGas": null,
+ "excessBlobGas": null,
+ "blobGasUsed": null
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/halfchain.rlp b/cmd/devp2p/internal/ethtest/testdata/halfchain.rlp
deleted file mode 100644
index 1a820734e1..0000000000
Binary files a/cmd/devp2p/internal/ethtest/testdata/halfchain.rlp and /dev/null differ
diff --git a/cmd/devp2p/internal/ethtest/testdata/headblock.json b/cmd/devp2p/internal/ethtest/testdata/headblock.json
new file mode 100644
index 0000000000..e84e96b0f0
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/headblock.json
@@ -0,0 +1,23 @@
+{
+ "parentHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94",
+ "transactionsRoot": "0xecda39025fc4c609ce778d75eed0aa53b65ce1e3d1373b34bad8578cc31e5b48",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "difficulty": "0x0",
+ "number": "0x1f4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1388",
+ "extraData": "0x",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "baseFeePerGas": "0x7",
+ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0",
+ "parentBeaconBlockRoot": "0xf653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c",
+ "hash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7"
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/headfcu.json b/cmd/devp2p/internal/ethtest/testdata/headfcu.json
new file mode 100644
index 0000000000..920212d0c0
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/headfcu.json
@@ -0,0 +1,13 @@
+{
+ "jsonrpc": "2.0",
+ "id": "fcu500",
+ "method": "engine_forkchoiceUpdatedV3",
+ "params": [
+ {
+ "headBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7",
+ "safeBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7",
+ "finalizedBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7"
+ },
+ null
+ ]
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/headstate.json b/cmd/devp2p/internal/ethtest/testdata/headstate.json
new file mode 100644
index 0000000000..f7b076af69
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/headstate.json
@@ -0,0 +1,4204 @@
+{
+ "root": "ea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94",
+ "accounts": {
+ "0x0000000000000000000000000000000000000000": {
+ "balance": "233437500000029008737",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a"
+ },
+ "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": {
+ "balance": "42",
+ "nonce": 0,
+ "root": "0xac3162a8b9dbb4318b84219f3140e7a9ec35126234120297dde10f51b25f6a26",
+ "codeHash": "0xf57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c",
+ "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000348": "0348",
+ "0x0000000000000000000000000000000000000000000000000000000000000352": "0352",
+ "0x000000000000000000000000000000000000000000000000000000000000035c": "035c",
+ "0x0000000000000000000000000000000000000000000000000000000000000366": "0366",
+ "0x0000000000000000000000000000000000000000000000000000000000000370": "0370",
+ "0x000000000000000000000000000000000000000000000000000000000000037a": "037a",
+ "0x0000000000000000000000000000000000000000000000000000000000000384": "0384",
+ "0x000000000000000000000000000000000000000000000000000000000000038e": "038e",
+ "0x0000000000000000000000000000000000000000000000000000000000000398": "0398",
+ "0x00000000000000000000000000000000000000000000000000000000000003a2": "03a2",
+ "0x00000000000000000000000000000000000000000000000000000000000003ac": "03ac",
+ "0x00000000000000000000000000000000000000000000000000000000000003b6": "03b6",
+ "0x00000000000000000000000000000000000000000000000000000000000003c0": "03c0",
+ "0x00000000000000000000000000000000000000000000000000000000000003ca": "03ca",
+ "0x00000000000000000000000000000000000000000000000000000000000003d4": "03d4",
+ "0x00000000000000000000000000000000000000000000000000000000000003de": "03de",
+ "0x00000000000000000000000000000000000000000000000000000000000003e8": "03e8",
+ "0x00000000000000000000000000000000000000000000000000000000000003f2": "03f2",
+ "0x00000000000000000000000000000000000000000000000000000000000003fc": "03fc",
+ "0x0000000000000000000000000000000000000000000000000000000000000406": "0406",
+ "0x0000000000000000000000000000000000000000000000000000000000000410": "0410",
+ "0x000000000000000000000000000000000000000000000000000000000000041a": "041a",
+ "0x0000000000000000000000000000000000000000000000000000000000000424": "0424",
+ "0x000000000000000000000000000000000000000000000000000000000000042e": "042e",
+ "0x0000000000000000000000000000000000000000000000000000000000000438": "0438",
+ "0x0000000000000000000000000000000000000000000000000000000000000442": "0442",
+ "0x000000000000000000000000000000000000000000000000000000000000044c": "044c",
+ "0x0000000000000000000000000000000000000000000000000000000000000456": "0456",
+ "0x0000000000000000000000000000000000000000000000000000000000000460": "0460",
+ "0x000000000000000000000000000000000000000000000000000000000000046a": "046a",
+ "0x0000000000000000000000000000000000000000000000000000000000000474": "0474",
+ "0x000000000000000000000000000000000000000000000000000000000000047e": "047e",
+ "0x0000000000000000000000000000000000000000000000000000000000000488": "0488",
+ "0x0000000000000000000000000000000000000000000000000000000000000492": "0492",
+ "0x000000000000000000000000000000000000000000000000000000000000049c": "049c",
+ "0x00000000000000000000000000000000000000000000000000000000000004a6": "04a6",
+ "0x00000000000000000000000000000000000000000000000000000000000004b0": "04b0",
+ "0x00000000000000000000000000000000000000000000000000000000000004ba": "04ba",
+ "0x00000000000000000000000000000000000000000000000000000000000004c4": "04c4",
+ "0x00000000000000000000000000000000000000000000000000000000000004ce": "04ce",
+ "0x00000000000000000000000000000000000000000000000000000000000004d8": "04d8",
+ "0x00000000000000000000000000000000000000000000000000000000000004e2": "04e2",
+ "0x00000000000000000000000000000000000000000000000000000000000004ec": "04ec",
+ "0x00000000000000000000000000000000000000000000000000000000000004f6": "04f6",
+ "0x0000000000000000000000000000000000000000000000000000000000000500": "0500",
+ "0x000000000000000000000000000000000000000000000000000000000000050a": "050a",
+ "0x0000000000000000000000000000000000000000000000000000000000000514": "0514",
+ "0x000000000000000000000000000000000000000000000000000000000000051e": "051e",
+ "0x0000000000000000000000000000000000000000000000000000000000000528": "0528",
+ "0x0000000000000000000000000000000000000000000000000000000000000532": "0532",
+ "0x000000000000000000000000000000000000000000000000000000000000053c": "053c",
+ "0x0000000000000000000000000000000000000000000000000000000000000546": "0546",
+ "0x0000000000000000000000000000000000000000000000000000000000000550": "0550",
+ "0x000000000000000000000000000000000000000000000000000000000000055a": "055a",
+ "0x0000000000000000000000000000000000000000000000000000000000000564": "0564",
+ "0x000000000000000000000000000000000000000000000000000000000000056e": "056e",
+ "0x0000000000000000000000000000000000000000000000000000000000000578": "0578",
+ "0x0000000000000000000000000000000000000000000000000000000000000582": "0582",
+ "0x000000000000000000000000000000000000000000000000000000000000058c": "058c",
+ "0x0000000000000000000000000000000000000000000000000000000000000596": "0596",
+ "0x00000000000000000000000000000000000000000000000000000000000005a0": "05a0",
+ "0x00000000000000000000000000000000000000000000000000000000000005aa": "05aa",
+ "0x00000000000000000000000000000000000000000000000000000000000005b4": "05b4",
+ "0x00000000000000000000000000000000000000000000000000000000000005be": "05be",
+ "0x00000000000000000000000000000000000000000000000000000000000005c8": "05c8",
+ "0x00000000000000000000000000000000000000000000000000000000000005d2": "05d2",
+ "0x00000000000000000000000000000000000000000000000000000000000005dc": "05dc",
+ "0x00000000000000000000000000000000000000000000000000000000000005e6": "05e6",
+ "0x00000000000000000000000000000000000000000000000000000000000005f0": "05f0",
+ "0x00000000000000000000000000000000000000000000000000000000000005fa": "05fa",
+ "0x0000000000000000000000000000000000000000000000000000000000000604": "0604",
+ "0x000000000000000000000000000000000000000000000000000000000000060e": "060e",
+ "0x0000000000000000000000000000000000000000000000000000000000000618": "0618",
+ "0x0000000000000000000000000000000000000000000000000000000000000622": "0622",
+ "0x000000000000000000000000000000000000000000000000000000000000062c": "062c",
+ "0x0000000000000000000000000000000000000000000000000000000000000636": "0636",
+ "0x0000000000000000000000000000000000000000000000000000000000000640": "0640",
+ "0x000000000000000000000000000000000000000000000000000000000000064a": "064a",
+ "0x0000000000000000000000000000000000000000000000000000000000000654": "0654",
+ "0x000000000000000000000000000000000000000000000000000000000000065e": "065e",
+ "0x0000000000000000000000000000000000000000000000000000000000000668": "0668",
+ "0x0000000000000000000000000000000000000000000000000000000000000672": "0672",
+ "0x000000000000000000000000000000000000000000000000000000000000067c": "067c",
+ "0x0000000000000000000000000000000000000000000000000000000000000686": "0686",
+ "0x0000000000000000000000000000000000000000000000000000000000000690": "0690",
+ "0x000000000000000000000000000000000000000000000000000000000000069a": "069a",
+ "0x00000000000000000000000000000000000000000000000000000000000006a4": "06a4",
+ "0x00000000000000000000000000000000000000000000000000000000000006ae": "06ae",
+ "0x00000000000000000000000000000000000000000000000000000000000006b8": "06b8",
+ "0x00000000000000000000000000000000000000000000000000000000000006c2": "06c2",
+ "0x00000000000000000000000000000000000000000000000000000000000006cc": "06cc",
+ "0x00000000000000000000000000000000000000000000000000000000000006d6": "06d6",
+ "0x00000000000000000000000000000000000000000000000000000000000006e0": "06e0",
+ "0x00000000000000000000000000000000000000000000000000000000000006ea": "06ea",
+ "0x00000000000000000000000000000000000000000000000000000000000006f4": "06f4",
+ "0x00000000000000000000000000000000000000000000000000000000000006fe": "06fe",
+ "0x0000000000000000000000000000000000000000000000000000000000000708": "0708",
+ "0x0000000000000000000000000000000000000000000000000000000000000712": "0712",
+ "0x000000000000000000000000000000000000000000000000000000000000071c": "071c",
+ "0x0000000000000000000000000000000000000000000000000000000000000726": "0726",
+ "0x0000000000000000000000000000000000000000000000000000000000000730": "0730",
+ "0x000000000000000000000000000000000000000000000000000000000000073a": "073a",
+ "0x0000000000000000000000000000000000000000000000000000000000000744": "0744",
+ "0x000000000000000000000000000000000000000000000000000000000000074e": "074e",
+ "0x0000000000000000000000000000000000000000000000000000000000000758": "0758",
+ "0x0000000000000000000000000000000000000000000000000000000000000762": "0762",
+ "0x000000000000000000000000000000000000000000000000000000000000076c": "076c",
+ "0x0000000000000000000000000000000000000000000000000000000000000776": "0776",
+ "0x0000000000000000000000000000000000000000000000000000000000000780": "0780",
+ "0x000000000000000000000000000000000000000000000000000000000000078a": "078a",
+ "0x0000000000000000000000000000000000000000000000000000000000000794": "0794",
+ "0x000000000000000000000000000000000000000000000000000000000000079e": "079e",
+ "0x00000000000000000000000000000000000000000000000000000000000007a8": "07a8",
+ "0x00000000000000000000000000000000000000000000000000000000000007b2": "07b2",
+ "0x00000000000000000000000000000000000000000000000000000000000007bc": "07bc",
+ "0x00000000000000000000000000000000000000000000000000000000000007c6": "07c6",
+ "0x00000000000000000000000000000000000000000000000000000000000007d0": "07d0",
+ "0x00000000000000000000000000000000000000000000000000000000000007da": "07da",
+ "0x00000000000000000000000000000000000000000000000000000000000007e4": "07e4",
+ "0x00000000000000000000000000000000000000000000000000000000000007ee": "07ee",
+ "0x00000000000000000000000000000000000000000000000000000000000007f8": "07f8",
+ "0x0000000000000000000000000000000000000000000000000000000000000802": "0802",
+ "0x000000000000000000000000000000000000000000000000000000000000080c": "080c",
+ "0x0000000000000000000000000000000000000000000000000000000000000816": "0816",
+ "0x0000000000000000000000000000000000000000000000000000000000000820": "0820",
+ "0x000000000000000000000000000000000000000000000000000000000000082a": "082a",
+ "0x0000000000000000000000000000000000000000000000000000000000000834": "0834",
+ "0x000000000000000000000000000000000000000000000000000000000000083e": "083e",
+ "0x0000000000000000000000000000000000000000000000000000000000000848": "0848",
+ "0x0000000000000000000000000000000000000000000000000000000000000852": "0852",
+ "0x000000000000000000000000000000000000000000000000000000000000085c": "085c",
+ "0x0000000000000000000000000000000000000000000000000000000000000866": "0866",
+ "0x0000000000000000000000000000000000000000000000000000000000000870": "0870",
+ "0x000000000000000000000000000000000000000000000000000000000000087a": "087a",
+ "0x0000000000000000000000000000000000000000000000000000000000000884": "0884",
+ "0x000000000000000000000000000000000000000000000000000000000000088e": "088e",
+ "0x0000000000000000000000000000000000000000000000000000000000000898": "0898",
+ "0x00000000000000000000000000000000000000000000000000000000000008a2": "08a2",
+ "0x00000000000000000000000000000000000000000000000000000000000008ac": "08ac",
+ "0x00000000000000000000000000000000000000000000000000000000000008b6": "08b6",
+ "0x00000000000000000000000000000000000000000000000000000000000008c0": "08c0",
+ "0x00000000000000000000000000000000000000000000000000000000000008ca": "08ca",
+ "0x00000000000000000000000000000000000000000000000000000000000008d4": "08d4",
+ "0x00000000000000000000000000000000000000000000000000000000000008de": "08de",
+ "0x00000000000000000000000000000000000000000000000000000000000008e8": "08e8",
+ "0x00000000000000000000000000000000000000000000000000000000000008f2": "08f2",
+ "0x00000000000000000000000000000000000000000000000000000000000008fc": "08fc",
+ "0x0000000000000000000000000000000000000000000000000000000000000906": "0906",
+ "0x0000000000000000000000000000000000000000000000000000000000000910": "0910",
+ "0x000000000000000000000000000000000000000000000000000000000000091a": "091a",
+ "0x0000000000000000000000000000000000000000000000000000000000000924": "0924",
+ "0x000000000000000000000000000000000000000000000000000000000000092e": "092e",
+ "0x0000000000000000000000000000000000000000000000000000000000000938": "0938",
+ "0x0000000000000000000000000000000000000000000000000000000000000942": "0942",
+ "0x000000000000000000000000000000000000000000000000000000000000094c": "094c",
+ "0x0000000000000000000000000000000000000000000000000000000000000956": "0956",
+ "0x0000000000000000000000000000000000000000000000000000000000000960": "0960",
+ "0x000000000000000000000000000000000000000000000000000000000000096a": "096a",
+ "0x0000000000000000000000000000000000000000000000000000000000000974": "0974",
+ "0x000000000000000000000000000000000000000000000000000000000000097e": "097e",
+ "0x0000000000000000000000000000000000000000000000000000000000000988": "0988",
+ "0x0000000000000000000000000000000000000000000000000000000000000992": "0992",
+ "0x000000000000000000000000000000000000000000000000000000000000099c": "099c",
+ "0x00000000000000000000000000000000000000000000000000000000000009a6": "09a6",
+ "0x00000000000000000000000000000000000000000000000000000000000009b0": "09b0",
+ "0x00000000000000000000000000000000000000000000000000000000000009ba": "09ba",
+ "0x00000000000000000000000000000000000000000000000000000000000009c4": "09c4",
+ "0x00000000000000000000000000000000000000000000000000000000000009ce": "09ce",
+ "0x00000000000000000000000000000000000000000000000000000000000009d8": "09d8",
+ "0x00000000000000000000000000000000000000000000000000000000000009e2": "09e2",
+ "0x00000000000000000000000000000000000000000000000000000000000009ec": "09ec",
+ "0x00000000000000000000000000000000000000000000000000000000000009f6": "09f6",
+ "0x0000000000000000000000000000000000000000000000000000000000000a00": "0a00",
+ "0x0000000000000000000000000000000000000000000000000000000000000a0a": "0a0a",
+ "0x0000000000000000000000000000000000000000000000000000000000000a14": "0a14",
+ "0x0000000000000000000000000000000000000000000000000000000000000a1e": "0a1e",
+ "0x0000000000000000000000000000000000000000000000000000000000000a28": "0a28",
+ "0x0000000000000000000000000000000000000000000000000000000000000a32": "0a32",
+ "0x0000000000000000000000000000000000000000000000000000000000000a3c": "0a3c",
+ "0x0000000000000000000000000000000000000000000000000000000000000a46": "0a46",
+ "0x0000000000000000000000000000000000000000000000000000000000000a50": "0a50",
+ "0x0000000000000000000000000000000000000000000000000000000000000a5a": "0a5a",
+ "0x0000000000000000000000000000000000000000000000000000000000000a64": "0a64",
+ "0x0000000000000000000000000000000000000000000000000000000000000a6e": "0a6e",
+ "0x0000000000000000000000000000000000000000000000000000000000000a78": "0a78",
+ "0x0000000000000000000000000000000000000000000000000000000000000a82": "0a82",
+ "0x0000000000000000000000000000000000000000000000000000000000000a8c": "0a8c",
+ "0x0000000000000000000000000000000000000000000000000000000000000a96": "0a96",
+ "0x0000000000000000000000000000000000000000000000000000000000000aa0": "0aa0",
+ "0x0000000000000000000000000000000000000000000000000000000000000aaa": "0aaa",
+ "0x0000000000000000000000000000000000000000000000000000000000000ab4": "0ab4",
+ "0x0000000000000000000000000000000000000000000000000000000000000abe": "0abe",
+ "0x0000000000000000000000000000000000000000000000000000000000000ac8": "0ac8",
+ "0x0000000000000000000000000000000000000000000000000000000000000ad2": "0ad2",
+ "0x0000000000000000000000000000000000000000000000000000000000000adc": "0adc",
+ "0x0000000000000000000000000000000000000000000000000000000000000ae6": "0ae6",
+ "0x0000000000000000000000000000000000000000000000000000000000000af0": "0af0",
+ "0x0000000000000000000000000000000000000000000000000000000000000afa": "0afa",
+ "0x0000000000000000000000000000000000000000000000000000000000000b04": "0b04",
+ "0x0000000000000000000000000000000000000000000000000000000000000b0e": "0b0e",
+ "0x0000000000000000000000000000000000000000000000000000000000000b18": "0b18",
+ "0x0000000000000000000000000000000000000000000000000000000000000b22": "0b22",
+ "0x0000000000000000000000000000000000000000000000000000000000000b2c": "0b2c",
+ "0x0000000000000000000000000000000000000000000000000000000000000b36": "0b36",
+ "0x0000000000000000000000000000000000000000000000000000000000000b40": "0b40",
+ "0x0000000000000000000000000000000000000000000000000000000000000b4a": "0b4a",
+ "0x0000000000000000000000000000000000000000000000000000000000000b54": "0b54",
+ "0x0000000000000000000000000000000000000000000000000000000000000b5e": "0b5e",
+ "0x0000000000000000000000000000000000000000000000000000000000000b68": "0b68",
+ "0x0000000000000000000000000000000000000000000000000000000000000b72": "0b72",
+ "0x0000000000000000000000000000000000000000000000000000000000000b7c": "0b7c",
+ "0x0000000000000000000000000000000000000000000000000000000000000b86": "0b86",
+ "0x0000000000000000000000000000000000000000000000000000000000000b90": "0b90",
+ "0x0000000000000000000000000000000000000000000000000000000000000b9a": "0b9a",
+ "0x0000000000000000000000000000000000000000000000000000000000000ba4": "0ba4",
+ "0x0000000000000000000000000000000000000000000000000000000000000bae": "0bae",
+ "0x0000000000000000000000000000000000000000000000000000000000000bb8": "0bb8",
+ "0x0000000000000000000000000000000000000000000000000000000000000bc2": "0bc2",
+ "0x0000000000000000000000000000000000000000000000000000000000000bcc": "0bcc",
+ "0x0000000000000000000000000000000000000000000000000000000000000bd6": "0bd6",
+ "0x0000000000000000000000000000000000000000000000000000000000000be0": "0be0",
+ "0x0000000000000000000000000000000000000000000000000000000000000bea": "0bea",
+ "0x0000000000000000000000000000000000000000000000000000000000000bf4": "0bf4",
+ "0x0000000000000000000000000000000000000000000000000000000000000bfe": "0bfe",
+ "0x0000000000000000000000000000000000000000000000000000000000000c08": "0c08",
+ "0x0000000000000000000000000000000000000000000000000000000000000c12": "0c12",
+ "0x0000000000000000000000000000000000000000000000000000000000000c1c": "0c1c",
+ "0x0000000000000000000000000000000000000000000000000000000000000c26": "0c26",
+ "0x0000000000000000000000000000000000000000000000000000000000000c30": "0c30",
+ "0x0000000000000000000000000000000000000000000000000000000000000c3a": "0c3a",
+ "0x0000000000000000000000000000000000000000000000000000000000000c44": "0c44",
+ "0x0000000000000000000000000000000000000000000000000000000000000c4e": "0c4e",
+ "0x0000000000000000000000000000000000000000000000000000000000000c58": "0c58",
+ "0x0000000000000000000000000000000000000000000000000000000000000c62": "0c62",
+ "0x0000000000000000000000000000000000000000000000000000000000000c6c": "0c6c",
+ "0x0000000000000000000000000000000000000000000000000000000000000c76": "0c76",
+ "0x0000000000000000000000000000000000000000000000000000000000000c80": "0c80",
+ "0x0000000000000000000000000000000000000000000000000000000000000c8a": "0c8a",
+ "0x0000000000000000000000000000000000000000000000000000000000000c94": "0c94",
+ "0x0000000000000000000000000000000000000000000000000000000000000c9e": "0c9e",
+ "0x0000000000000000000000000000000000000000000000000000000000000ca8": "0ca8",
+ "0x0000000000000000000000000000000000000000000000000000000000000cb2": "0cb2",
+ "0x0000000000000000000000000000000000000000000000000000000000000cbc": "0cbc",
+ "0x0000000000000000000000000000000000000000000000000000000000000cc6": "0cc6",
+ "0x0000000000000000000000000000000000000000000000000000000000000cd0": "0cd0",
+ "0x0000000000000000000000000000000000000000000000000000000000000cda": "0cda",
+ "0x0000000000000000000000000000000000000000000000000000000000000ce4": "0ce4",
+ "0x0000000000000000000000000000000000000000000000000000000000000cee": "0cee",
+ "0x0000000000000000000000000000000000000000000000000000000000000cf8": "0cf8",
+ "0x0000000000000000000000000000000000000000000000000000000000000d02": "0d02",
+ "0x0000000000000000000000000000000000000000000000000000000000000d0c": "0d0c",
+ "0x0000000000000000000000000000000000000000000000000000000000000d16": "0d16",
+ "0x0000000000000000000000000000000000000000000000000000000000000d20": "0d20",
+ "0x0000000000000000000000000000000000000000000000000000000000000d2a": "0d2a",
+ "0x0000000000000000000000000000000000000000000000000000000000000d34": "0d34",
+ "0x0000000000000000000000000000000000000000000000000000000000000d3e": "0d3e",
+ "0x0000000000000000000000000000000000000000000000000000000000000d48": "0d48",
+ "0x0000000000000000000000000000000000000000000000000000000000000d52": "0d52",
+ "0x0000000000000000000000000000000000000000000000000000000000000d5c": "0d5c",
+ "0x0000000000000000000000000000000000000000000000000000000000000d66": "0d66",
+ "0x0000000000000000000000000000000000000000000000000000000000000d70": "0d70",
+ "0x0000000000000000000000000000000000000000000000000000000000000d7a": "0d7a",
+ "0x0000000000000000000000000000000000000000000000000000000000000d84": "0d84",
+ "0x0000000000000000000000000000000000000000000000000000000000000d8e": "0d8e",
+ "0x0000000000000000000000000000000000000000000000000000000000000d98": "0d98",
+ "0x0000000000000000000000000000000000000000000000000000000000000da2": "0da2",
+ "0x0000000000000000000000000000000000000000000000000000000000000dac": "0dac",
+ "0x0000000000000000000000000000000000000000000000000000000000000db6": "0db6",
+ "0x0000000000000000000000000000000000000000000000000000000000000dc0": "0dc0",
+ "0x0000000000000000000000000000000000000000000000000000000000000dca": "0dca",
+ "0x0000000000000000000000000000000000000000000000000000000000000dd4": "0dd4",
+ "0x0000000000000000000000000000000000000000000000000000000000000dde": "0dde",
+ "0x0000000000000000000000000000000000000000000000000000000000000de8": "0de8",
+ "0x0000000000000000000000000000000000000000000000000000000000000df2": "0df2",
+ "0x0000000000000000000000000000000000000000000000000000000000000dfc": "0dfc",
+ "0x0000000000000000000000000000000000000000000000000000000000000e06": "0e06",
+ "0x0000000000000000000000000000000000000000000000000000000000000e10": "0e10",
+ "0x0000000000000000000000000000000000000000000000000000000000000e1a": "0e1a",
+ "0x0000000000000000000000000000000000000000000000000000000000000e24": "0e24",
+ "0x0000000000000000000000000000000000000000000000000000000000000e2e": "0e2e",
+ "0x0000000000000000000000000000000000000000000000000000000000000e38": "0e38",
+ "0x0000000000000000000000000000000000000000000000000000000000000e42": "0e42",
+ "0x0000000000000000000000000000000000000000000000000000000000000e4c": "0e4c",
+ "0x0000000000000000000000000000000000000000000000000000000000000e56": "0e56",
+ "0x0000000000000000000000000000000000000000000000000000000000000e60": "0e60",
+ "0x0000000000000000000000000000000000000000000000000000000000000e6a": "0e6a",
+ "0x0000000000000000000000000000000000000000000000000000000000000e74": "0e74",
+ "0x0000000000000000000000000000000000000000000000000000000000000e7e": "0e7e",
+ "0x0000000000000000000000000000000000000000000000000000000000000e88": "0e88",
+ "0x0000000000000000000000000000000000000000000000000000000000000e92": "0e92",
+ "0x0000000000000000000000000000000000000000000000000000000000000e9c": "0e9c",
+ "0x0000000000000000000000000000000000000000000000000000000000000ea6": "0ea6",
+ "0x0000000000000000000000000000000000000000000000000000000000000eb0": "0eb0",
+ "0x0000000000000000000000000000000000000000000000000000000000000eba": "0eba",
+ "0x0000000000000000000000000000000000000000000000000000000000000ec4": "0ec4",
+ "0x0000000000000000000000000000000000000000000000000000000000000ece": "0ece",
+ "0x0000000000000000000000000000000000000000000000000000000000000ed8": "0ed8",
+ "0x0000000000000000000000000000000000000000000000000000000000000ee2": "0ee2",
+ "0x0000000000000000000000000000000000000000000000000000000000000eec": "0eec",
+ "0x0000000000000000000000000000000000000000000000000000000000000ef6": "0ef6",
+ "0x0000000000000000000000000000000000000000000000000000000000000f00": "0f00",
+ "0x0000000000000000000000000000000000000000000000000000000000000f0a": "0f0a",
+ "0x0000000000000000000000000000000000000000000000000000000000000f14": "0f14",
+ "0x0000000000000000000000000000000000000000000000000000000000000f1e": "0f1e",
+ "0x0000000000000000000000000000000000000000000000000000000000000f28": "0f28",
+ "0x0000000000000000000000000000000000000000000000000000000000000f32": "0f32",
+ "0x0000000000000000000000000000000000000000000000000000000000000f3c": "0f3c",
+ "0x0000000000000000000000000000000000000000000000000000000000000f46": "0f46",
+ "0x0000000000000000000000000000000000000000000000000000000000000f50": "0f50",
+ "0x0000000000000000000000000000000000000000000000000000000000000f5a": "0f5a",
+ "0x0000000000000000000000000000000000000000000000000000000000000f64": "0f64",
+ "0x0000000000000000000000000000000000000000000000000000000000000f6e": "0f6e",
+ "0x0000000000000000000000000000000000000000000000000000000000000f78": "0f78",
+ "0x0000000000000000000000000000000000000000000000000000000000000f82": "0f82",
+ "0x0000000000000000000000000000000000000000000000000000000000000f8c": "0f8c",
+ "0x0000000000000000000000000000000000000000000000000000000000000f96": "0f96",
+ "0x0000000000000000000000000000000000000000000000000000000000000fa0": "0fa0",
+ "0x0000000000000000000000000000000000000000000000000000000000000faa": "0faa",
+ "0x0000000000000000000000000000000000000000000000000000000000000fb4": "0fb4",
+ "0x0000000000000000000000000000000000000000000000000000000000000fbe": "0fbe",
+ "0x0000000000000000000000000000000000000000000000000000000000000fc8": "0fc8",
+ "0x0000000000000000000000000000000000000000000000000000000000000fd2": "0fd2",
+ "0x0000000000000000000000000000000000000000000000000000000000000fdc": "0fdc",
+ "0x0000000000000000000000000000000000000000000000000000000000000fe6": "0fe6",
+ "0x0000000000000000000000000000000000000000000000000000000000000ff0": "0ff0",
+ "0x0000000000000000000000000000000000000000000000000000000000000ffa": "0ffa",
+ "0x0000000000000000000000000000000000000000000000000000000000001004": "1004",
+ "0x000000000000000000000000000000000000000000000000000000000000100e": "100e",
+ "0x0000000000000000000000000000000000000000000000000000000000001018": "1018",
+ "0x0000000000000000000000000000000000000000000000000000000000001022": "1022",
+ "0x000000000000000000000000000000000000000000000000000000000000102c": "102c",
+ "0x0000000000000000000000000000000000000000000000000000000000001036": "1036",
+ "0x0000000000000000000000000000000000000000000000000000000000001040": "1040",
+ "0x000000000000000000000000000000000000000000000000000000000000104a": "104a",
+ "0x0000000000000000000000000000000000000000000000000000000000001054": "1054",
+ "0x000000000000000000000000000000000000000000000000000000000000105e": "105e",
+ "0x0000000000000000000000000000000000000000000000000000000000001068": "1068",
+ "0x0000000000000000000000000000000000000000000000000000000000001072": "1072",
+ "0x000000000000000000000000000000000000000000000000000000000000107c": "107c",
+ "0x0000000000000000000000000000000000000000000000000000000000001086": "1086",
+ "0x0000000000000000000000000000000000000000000000000000000000001090": "1090",
+ "0x000000000000000000000000000000000000000000000000000000000000109a": "109a",
+ "0x00000000000000000000000000000000000000000000000000000000000010a4": "10a4",
+ "0x00000000000000000000000000000000000000000000000000000000000010ae": "10ae",
+ "0x00000000000000000000000000000000000000000000000000000000000010b8": "10b8",
+ "0x00000000000000000000000000000000000000000000000000000000000010c2": "10c2",
+ "0x00000000000000000000000000000000000000000000000000000000000010cc": "10cc",
+ "0x00000000000000000000000000000000000000000000000000000000000010d6": "10d6",
+ "0x00000000000000000000000000000000000000000000000000000000000010e0": "10e0",
+ "0x00000000000000000000000000000000000000000000000000000000000010ea": "10ea",
+ "0x00000000000000000000000000000000000000000000000000000000000010f4": "10f4",
+ "0x00000000000000000000000000000000000000000000000000000000000010fe": "10fe",
+ "0x0000000000000000000000000000000000000000000000000000000000001108": "1108",
+ "0x0000000000000000000000000000000000000000000000000000000000001112": "1112",
+ "0x000000000000000000000000000000000000000000000000000000000000111c": "111c",
+ "0x0000000000000000000000000000000000000000000000000000000000001126": "1126",
+ "0x0000000000000000000000000000000000000000000000000000000000001130": "1130",
+ "0x000000000000000000000000000000000000000000000000000000000000113a": "113a",
+ "0x0000000000000000000000000000000000000000000000000000000000001144": "1144",
+ "0x000000000000000000000000000000000000000000000000000000000000114e": "114e",
+ "0x0000000000000000000000000000000000000000000000000000000000001158": "1158",
+ "0x0000000000000000000000000000000000000000000000000000000000001162": "1162",
+ "0x000000000000000000000000000000000000000000000000000000000000116c": "116c",
+ "0x0000000000000000000000000000000000000000000000000000000000001176": "1176",
+ "0x0000000000000000000000000000000000000000000000000000000000001180": "1180",
+ "0x000000000000000000000000000000000000000000000000000000000000118a": "118a",
+ "0x0000000000000000000000000000000000000000000000000000000000001194": "1194",
+ "0x000000000000000000000000000000000000000000000000000000000000119e": "119e",
+ "0x00000000000000000000000000000000000000000000000000000000000011a8": "11a8",
+ "0x00000000000000000000000000000000000000000000000000000000000011b2": "11b2",
+ "0x00000000000000000000000000000000000000000000000000000000000011bc": "11bc",
+ "0x00000000000000000000000000000000000000000000000000000000000011c6": "11c6",
+ "0x00000000000000000000000000000000000000000000000000000000000011d0": "11d0",
+ "0x00000000000000000000000000000000000000000000000000000000000011da": "11da",
+ "0x00000000000000000000000000000000000000000000000000000000000011e4": "11e4",
+ "0x00000000000000000000000000000000000000000000000000000000000011ee": "11ee",
+ "0x00000000000000000000000000000000000000000000000000000000000011f8": "11f8",
+ "0x0000000000000000000000000000000000000000000000000000000000001202": "1202",
+ "0x000000000000000000000000000000000000000000000000000000000000120c": "120c",
+ "0x0000000000000000000000000000000000000000000000000000000000001216": "1216",
+ "0x0000000000000000000000000000000000000000000000000000000000001220": "1220",
+ "0x000000000000000000000000000000000000000000000000000000000000122a": "122a",
+ "0x0000000000000000000000000000000000000000000000000000000000001234": "1234",
+ "0x000000000000000000000000000000000000000000000000000000000000123e": "123e",
+ "0x0000000000000000000000000000000000000000000000000000000000001248": "1248",
+ "0x0000000000000000000000000000000000000000000000000000000000001252": "1252",
+ "0x000000000000000000000000000000000000000000000000000000000000125c": "125c",
+ "0x0000000000000000000000000000000000000000000000000000000000001266": "1266",
+ "0x0000000000000000000000000000000000000000000000000000000000001270": "1270",
+ "0x000000000000000000000000000000000000000000000000000000000000127a": "127a",
+ "0x0000000000000000000000000000000000000000000000000000000000001284": "1284",
+ "0x000000000000000000000000000000000000000000000000000000000000128e": "128e",
+ "0x0000000000000000000000000000000000000000000000000000000000001298": "1298",
+ "0x00000000000000000000000000000000000000000000000000000000000012a2": "12a2",
+ "0x00000000000000000000000000000000000000000000000000000000000012ac": "12ac",
+ "0x00000000000000000000000000000000000000000000000000000000000012b6": "12b6",
+ "0x00000000000000000000000000000000000000000000000000000000000012c0": "12c0",
+ "0x00000000000000000000000000000000000000000000000000000000000012ca": "12ca",
+ "0x00000000000000000000000000000000000000000000000000000000000012d4": "12d4",
+ "0x00000000000000000000000000000000000000000000000000000000000012de": "12de",
+ "0x00000000000000000000000000000000000000000000000000000000000012e8": "12e8",
+ "0x00000000000000000000000000000000000000000000000000000000000012f2": "12f2",
+ "0x00000000000000000000000000000000000000000000000000000000000012fc": "12fc",
+ "0x0000000000000000000000000000000000000000000000000000000000001306": "1306",
+ "0x0000000000000000000000000000000000000000000000000000000000001310": "1310",
+ "0x000000000000000000000000000000000000000000000000000000000000131a": "131a",
+ "0x0000000000000000000000000000000000000000000000000000000000001324": "1324",
+ "0x000000000000000000000000000000000000000000000000000000000000132e": "132e",
+ "0x0000000000000000000000000000000000000000000000000000000000001338": "1338",
+ "0x0000000000000000000000000000000000000000000000000000000000001342": "1342",
+ "0x000000000000000000000000000000000000000000000000000000000000134c": "134c",
+ "0x0000000000000000000000000000000000000000000000000000000000001356": "1356",
+ "0x0000000000000000000000000000000000000000000000000000000000001360": "1360",
+ "0x000000000000000000000000000000000000000000000000000000000000136a": "136a",
+ "0x0000000000000000000000000000000000000000000000000000000000001374": "1374",
+ "0x000000000000000000000000000000000000000000000000000000000000137e": "137e",
+ "0x0000000000000000000000000000000000000000000000000000000000001388": "1388",
+ "0x0000000000000000000000000000000000000000000000000000000000002347": "83472eda6eb475906aeeb7f09e757ba9f6663b9f6a5bf8611d6306f677f67ebd",
+ "0x0000000000000000000000000000000000000000000000000000000000002351": "2c809fbc7e3991c8ab560d1431fa8b6f25be4ab50977f0294dfeca9677866b6e",
+ "0x000000000000000000000000000000000000000000000000000000000000235b": "756e335a8778f6aadb2cc18c5bc68892da05a4d8b458eee5ce3335a024000c67",
+ "0x0000000000000000000000000000000000000000000000000000000000002365": "4b118bd31ed2c4eeb81dc9e3919e9989994333fe36f147c2930f12c53f0d3c78",
+ "0x000000000000000000000000000000000000000000000000000000000000236f": "d0122166752d729620d41114ff5a94d36e5d3e01b449c23844900c023d1650a5",
+ "0x0000000000000000000000000000000000000000000000000000000000002379": "60c606c4c44709ac87b367f42d2453744639fc5bee099a11f170de98408c8089",
+ "0x0000000000000000000000000000000000000000000000000000000000002383": "6ee04e1c27edad89a8e5a2253e4d9cca06e4f57d063ed4fe7cc1c478bb57eeca",
+ "0x000000000000000000000000000000000000000000000000000000000000238d": "36616354a17658eb3c3e8e5adda6253660e3744cb8b213006f04302b723749a8",
+ "0x0000000000000000000000000000000000000000000000000000000000002397": "c13802d4378dcb9c616f0c60ea0edd90e6c2dacf61f39ca06add0eaa67473b94",
+ "0x00000000000000000000000000000000000000000000000000000000000023a1": "8b345497936c51d077f414534be3f70472e4df101dee8820eaaff91a6624557b",
+ "0x00000000000000000000000000000000000000000000000000000000000023ab": "e958485d4b3e47b38014cc4eaeb75f13228072e7b362a56fc3ffe10155882629",
+ "0x00000000000000000000000000000000000000000000000000000000000023b5": "3346706b38a2331556153113383581bc6f66f209fdef502f9fc9b6daf6ea555e",
+ "0x00000000000000000000000000000000000000000000000000000000000023bf": "346910f7e777c596be32f0dcf46ccfda2efe8d6c5d3abbfe0f76dba7437f5dad",
+ "0x00000000000000000000000000000000000000000000000000000000000023c9": "e62a7bd9263534b752176d1ff1d428fcc370a3b176c4a6312b6016c2d5f8d546",
+ "0x00000000000000000000000000000000000000000000000000000000000023d3": "ffe267d11268388fd0426a627dedddeb075d68327df9172c0445cd2979ec7e4d",
+ "0x00000000000000000000000000000000000000000000000000000000000023dd": "23cc648c9cd82c08214882b7e28e026d6eb56920f90f64731bb09b6acf515427",
+ "0x00000000000000000000000000000000000000000000000000000000000023e7": "47c896f5986ec29f58ec60eec56ed176910779e9fc9cf45c3c090126aeb21acd",
+ "0x00000000000000000000000000000000000000000000000000000000000023f1": "6d19894928a3ab44077bb85dcb47e0865ce1c4c187bba26bad059aa774c03cfe",
+ "0x00000000000000000000000000000000000000000000000000000000000023fb": "efc50f4fc1430b6d5d043065201692a4a02252fef0699394631f5213a5667547",
+ "0x0000000000000000000000000000000000000000000000000000000000002405": "3cc9f65fc1f46927eb46fbf6d14bc94af078fe8ff982a984bdd117152cd1549f",
+ "0x000000000000000000000000000000000000000000000000000000000000240f": "63eb547e9325bc34fbbbdfda327a71dc929fd8ab6509795e56479e95dbd40a80",
+ "0x0000000000000000000000000000000000000000000000000000000000002419": "67317288cf707b0325748c7947e2dda5e8b41e45e62330d00d80e9be403e5c4c",
+ "0x0000000000000000000000000000000000000000000000000000000000002423": "7fc37e0d22626f96f345b05516c8a3676b9e1de01d354e5eb9524f6776966885",
+ "0x000000000000000000000000000000000000000000000000000000000000242d": "c8c5ffb6f192e9bda046ecd4ebb995af53c9dd6040f4ba8d8db9292c1310e43f",
+ "0x0000000000000000000000000000000000000000000000000000000000002437": "e40a9cfd9babe862d482ca0c07c0a4086641d16c066620cb048c6e673c5a4f91",
+ "0x0000000000000000000000000000000000000000000000000000000000002441": "e82e7cff48aea45fb3f7b199b0b173497bf4c5ea66ff840e2ec618d7eb3d7470",
+ "0x000000000000000000000000000000000000000000000000000000000000244b": "84ceda57767ea709da7ab17897a70da1868c9670931da38f2438519a5249534d",
+ "0x0000000000000000000000000000000000000000000000000000000000002455": "e9dcf640383969359c944cff24b75f71740627f596110ee8568fa09f9a06db1c",
+ "0x000000000000000000000000000000000000000000000000000000000000245f": "430ef678bb92f1af44dcd77af9c5b59fb87d0fc4a09901a54398ad5b7e19a8f4",
+ "0x0000000000000000000000000000000000000000000000000000000000002469": "f7af0b8b729cd17b7826259bc183b196dbd318bd7229d5e8085bf4849c0b12bf",
+ "0x0000000000000000000000000000000000000000000000000000000000002473": "e134e19217f1b4c7e11f193561056303a1f67b69dac96ff79a6d0aafa994f7cb",
+ "0x000000000000000000000000000000000000000000000000000000000000247d": "9cc58ab1a8cb0e983550e61f754aea1dd4f58ac6482a816dc50658de750de613",
+ "0x0000000000000000000000000000000000000000000000000000000000002487": "79c2b067779a94fd3756070885fc8eab5e45033bde69ab17c0173d553df02978",
+ "0x0000000000000000000000000000000000000000000000000000000000002491": "d908ef75d05b895600d3f9938cb5259612c71223b68d30469ff657d61c6b1611",
+ "0x000000000000000000000000000000000000000000000000000000000000249b": "e0d31906b7c46ac7f38478c0872d3c634f7113d54ef0b57ebfaf7f993959f5a3",
+ "0x00000000000000000000000000000000000000000000000000000000000024a5": "2318f5c5e6865200ad890e0a8db21c780a226bec0b2e29af1cb3a0d9b40196ae",
+ "0x00000000000000000000000000000000000000000000000000000000000024af": "523997f8d8fed954658f547954fdeceab818b411862647f2b61a3619f6a4d4bc",
+ "0x00000000000000000000000000000000000000000000000000000000000024b9": "be3396540ea36c6928cccdcfe6c669666edbbbcd4be5e703f59de0e3c2720da7",
+ "0x00000000000000000000000000000000000000000000000000000000000024c3": "2d3fcfd65d0a6881a2e8684d03c2aa27aee6176514d9f6d8ebb3b766f85e1039",
+ "0x00000000000000000000000000000000000000000000000000000000000024cd": "7ce0d5c253a7f910cca7416e949ac04fdaec20a518ab6fcbe4a63d8b439a5cfc",
+ "0x00000000000000000000000000000000000000000000000000000000000024d7": "4da13d835ea44926ee13f34ce8fcd4b9d3dc65be0a351115cf404234c7fbd256",
+ "0x00000000000000000000000000000000000000000000000000000000000024e1": "c5ee7483802009b45feabf4c5f701ec485f27bf7d2c4477b200ac53e210e9844",
+ "0x00000000000000000000000000000000000000000000000000000000000024eb": "0fc71295326a7ae8e0776c61be67f3ed8770311df88e186405b8d75bd0be552b",
+ "0x00000000000000000000000000000000000000000000000000000000000024f5": "7313b4315dd27586f940f8f2bf8af76825d8f24d2ae2c24d885dcb0cdd8d50f5",
+ "0x00000000000000000000000000000000000000000000000000000000000024ff": "2739473baa23a9bca4e8d0f4f221cfa48440b4b73e2bae7386c14caccc6c2059",
+ "0x0000000000000000000000000000000000000000000000000000000000002509": "d4da00e33a11ee18f67b25ad5ff574cddcdccaa30e6743e01a531336b16cbf8f",
+ "0x0000000000000000000000000000000000000000000000000000000000002513": "e651765d4860f0c46f191212c8193e7c82708e5d8bef1ed6f19bdde577f980cf",
+ "0x000000000000000000000000000000000000000000000000000000000000251d": "5b5b49487967b3b60bd859ba2fb13290c6eaf67e97e9f9f9dda935c08564b5f6",
+ "0x0000000000000000000000000000000000000000000000000000000000002527": "57b73780cc42a6a36676ce7008459d5ba206389dc9300f1aecbd77c4b90277fa",
+ "0x0000000000000000000000000000000000000000000000000000000000002531": "217e8514ea30f1431dc3cd006fe730df721f961cebb5d0b52069d1b4e1ae5d13",
+ "0x000000000000000000000000000000000000000000000000000000000000253b": "14b775119c252908bb10b13de9f8ae988302e1ea8b2e7a1b6d3c8ae24ba9396b",
+ "0x0000000000000000000000000000000000000000000000000000000000002545": "e736f0b3c5672f76332a38a6c1e66e5f39e0d01f1ddede2c24671f48e78daf63",
+ "0x000000000000000000000000000000000000000000000000000000000000254f": "7d112c85b58c64c576d34ea7a7c18287981885892fbf95110e62add156ca572e",
+ "0x0000000000000000000000000000000000000000000000000000000000002559": "28fbeedc649ed9d2a6feda6e5a2576949da6812235ebdfd030f8105d012f5074",
+ "0x0000000000000000000000000000000000000000000000000000000000002563": "6f7410cf59e390abe233de2a3e3fe022b63b78a92f6f4e3c54aced57b6c3daa6",
+ "0x000000000000000000000000000000000000000000000000000000000000256d": "d5edc3d8781deea3b577e772f51949a8866f2aa933149f622f05cde2ebba9adb",
+ "0x0000000000000000000000000000000000000000000000000000000000002577": "20308d99bc1e1b1b0717f32b9a3a869f4318f5f0eb4ed81fddd10696c9746c6b",
+ "0x0000000000000000000000000000000000000000000000000000000000002581": "91f7a302057a2e21d5e0ef4b8eea75dfb8b37f2c2db05c5a84517aaebc9d5131",
+ "0x000000000000000000000000000000000000000000000000000000000000258b": "743e5d0a5be47d489b121edb9f98dad7d0a85fc260909083656fabaf6d404774",
+ "0x0000000000000000000000000000000000000000000000000000000000002595": "cdcf99c6e2e7d0951f762e787bdbe0e2b3b320815c9d2be91e9cd0848653e839",
+ "0x000000000000000000000000000000000000000000000000000000000000259f": "cc9476183d27810e9738f382c7f2124976735ed89bbafc7dc19c99db8cfa9ad1",
+ "0x00000000000000000000000000000000000000000000000000000000000025a9": "f67e5fab2e7cacf5b89acd75ec53b0527d45435adddac6ee7523a345dcbcdceb",
+ "0x00000000000000000000000000000000000000000000000000000000000025b3": "e20f8ab522b2f0d12c068043852139965161851ad910b840db53604c8774a579",
+ "0x00000000000000000000000000000000000000000000000000000000000025bd": "f982160785861cb970559d980208dd00e6a2ec315f5857df175891b171438eeb",
+ "0x00000000000000000000000000000000000000000000000000000000000025c7": "230954c737211b72d5c7dcfe420bb07d5d72f2b4868c5976dd22c00d3df0c0b6",
+ "0x00000000000000000000000000000000000000000000000000000000000025d1": "b7743e65d6bbe09d5531f1bc98964f75943d8c13e27527ca6afd40ca069265d4",
+ "0x00000000000000000000000000000000000000000000000000000000000025db": "31ac943dc649c639fa6221400183ca827c07b812a6fbfc1795eb835aa280adf3",
+ "0x00000000000000000000000000000000000000000000000000000000000025e5": "ded49c937c48d466987a4130f4b6d04ef658029673c3afc99f70f33b552e178d",
+ "0x00000000000000000000000000000000000000000000000000000000000025ef": "a0effc449cab515020d2012897155a792bce529cbd8d5a4cf94d0bbf141afeb6",
+ "0x00000000000000000000000000000000000000000000000000000000000025f9": "1f36d9c66a0d437d8e49ffaeaa00f341e9630791b374e8bc0c16059c7445721f",
+ "0x0000000000000000000000000000000000000000000000000000000000002603": "34f89e6134f26e7110b47ffc942a847d8c03deeed1b33b9c041218c4e1a1a4e6",
+ "0x000000000000000000000000000000000000000000000000000000000000260d": "774404c430041ca4a58fdc281e99bf6fcb014973165370556d9e73fdec6d597b",
+ "0x0000000000000000000000000000000000000000000000000000000000002617": "d616971210c381584bf4846ab5837b53e062cbbb89d112c758b4bd00ce577f09",
+ "0x0000000000000000000000000000000000000000000000000000000000002621": "cdf6383634b0431468f6f5af19a2b7a087478b42489608c64555ea1ae0a7ee19",
+ "0x000000000000000000000000000000000000000000000000000000000000262b": "ec22e5df77320b4142c54fceaf2fe7ea30d1a72dc9c969a22acf66858d582b",
+ "0x0000000000000000000000000000000000000000000000000000000000002635": "cb32d77facfda4decff9e08df5a5810fa42585fdf96f0db9b63b196116fbb6af",
+ "0x000000000000000000000000000000000000000000000000000000000000263f": "6d76316f272f0212123d0b4b21d16835fe6f7a2b4d1960386d8a161da2b7c6a2",
+ "0x0000000000000000000000000000000000000000000000000000000000002649": "2de2da72ae329e359b655fc6311a707b06dc930126a27261b0e8ec803bdb5cbf",
+ "0x0000000000000000000000000000000000000000000000000000000000002653": "08bed4b39d14dc1e72e80f605573cde6145b12693204f9af18bbc94a82389500",
+ "0x000000000000000000000000000000000000000000000000000000000000265d": "e437f0465ac29b0e889ef4f577c939dd39363c08fcfc81ee61aa0b4f55805f69",
+ "0x0000000000000000000000000000000000000000000000000000000000002667": "89ca120183cc7085b6d4674d779fc4fbc9de520779bfbc3ebf65f9663cb88080",
+ "0x0000000000000000000000000000000000000000000000000000000000002671": "b15d5954c7b78ab09ede922684487c7a60368e82fdc7b5a0916842e58a44422b",
+ "0x000000000000000000000000000000000000000000000000000000000000267b": "ad13055a49d2b6a4ffc8b781998ff79086adad2fd6470a0563a43b740128c5f2",
+ "0x0000000000000000000000000000000000000000000000000000000000002685": "9e9909e4ed44f5539427ee3bc70ee8b630ccdaea4d0f1ed5337a067e8337119f",
+ "0x000000000000000000000000000000000000000000000000000000000000268f": "bf1f3aba184e08d4c650f05fe3d948bdda6c2d6982f277f2cd6b1a60cd4f3dac",
+ "0x0000000000000000000000000000000000000000000000000000000000002699": "bb70fe131f94783dba356c8d4d9d319247ef61c768134303f0db85ee3ef0496f",
+ "0x00000000000000000000000000000000000000000000000000000000000026a3": "6a81ebd3bde6cc54a2521aa72de29ef191e3b56d94953439a72cafdaa2996da0",
+ "0x00000000000000000000000000000000000000000000000000000000000026ad": "4c83e809a52ac52a587d94590c35c71b72742bd15915fca466a9aaec4f2dbfed",
+ "0x00000000000000000000000000000000000000000000000000000000000026b7": "268fc70790f00ad0759497585267fbdc92afba63ba01e211faae932f0639854a",
+ "0x00000000000000000000000000000000000000000000000000000000000026c1": "7e544f42df99d5666085b70bc57b3ca175be50b7a9643f26f464124df632d562",
+ "0x00000000000000000000000000000000000000000000000000000000000026cb": "d59cf5f55903ba577be835706b27d78a50cacb25271f35a5f57fcb88a3b576f3",
+ "0x00000000000000000000000000000000000000000000000000000000000026d5": "551cced461be11efdeaf8e47f3a91bb66d532af7294c4461c8009c5833bdbf57",
+ "0x00000000000000000000000000000000000000000000000000000000000026df": "c1e0e6907a57eefd12f1f95d28967146c836d72d281e7609de23d0a02351e978",
+ "0x00000000000000000000000000000000000000000000000000000000000026e9": "9d580c0ac3a7f00fdc3b135b758ae7c80ab135e907793fcf9621a3a3023ca205",
+ "0x00000000000000000000000000000000000000000000000000000000000026f3": "a7fd4dbac4bb62307ac7ad285ffa6a11ec679d950de2bd41839b8a846e239886",
+ "0x00000000000000000000000000000000000000000000000000000000000026fd": "6ba7b0ac30a04e11a3116b43700d91359e6b06a49058e543198d4b21e75fb165",
+ "0x0000000000000000000000000000000000000000000000000000000000002707": "8835104ed35ffd4db64660b9049e1c0328e502fd4f3744749e69183677b8474b",
+ "0x0000000000000000000000000000000000000000000000000000000000002711": "562f276b9f9ed46303e700c8863ad75fadff5fc8df27a90744ea04ad1fe8e801",
+ "0x000000000000000000000000000000000000000000000000000000000000271b": "d19f68026d22ae0f60215cfe4a160986c60378f554c763651d872ed82ad69ebb",
+ "0x0000000000000000000000000000000000000000000000000000000000002725": "f087a515b4b62d707991988eb912d082b85ecdd52effc9e8a1ddf15a74388860",
+ "0x000000000000000000000000000000000000000000000000000000000000272f": "f7e28b7daff5fad40ec1ef6a2b7e9066558126f62309a2ab0d0d775d892a06d6",
+ "0x0000000000000000000000000000000000000000000000000000000000002739": "77361844a8f4dd2451e6218d336378b837ba3fab921709708655e3f1ea91a435",
+ "0x0000000000000000000000000000000000000000000000000000000000002743": "e3cb33c7b05692a6f25470fbd63ab9c986970190729fab43191379da38bc0d8c",
+ "0x000000000000000000000000000000000000000000000000000000000000274d": "c893f9de119ec83fe37b178b5671d63448e9b5cde4de9a88cace3f52c2591194",
+ "0x0000000000000000000000000000000000000000000000000000000000002757": "39c96a6461782ac2efbcb5aaac2e133079b86fb29cb5ea69b0101bdad684ef0d",
+ "0x0000000000000000000000000000000000000000000000000000000000002761": "72a2724cdf77138638a109f691465e55d32759d3c044a6cb41ab091c574e3bdb",
+ "0x000000000000000000000000000000000000000000000000000000000000276b": "178ba15f24f0a8c33eed561d7927979c1215ddec20e1aef318db697ccfad0e03",
+ "0x0000000000000000000000000000000000000000000000000000000000002775": "f7b2c01b7c625588c9596972fdebae61db89f0d0f2b21286d4c0fa76683ff946",
+ "0x000000000000000000000000000000000000000000000000000000000000277f": "16e43284b041a4086ad1cbab9283d4ad3e8cc7c3a162f60b3df5538344ecdf54",
+ "0x0000000000000000000000000000000000000000000000000000000000002789": "0a98ea7f737e17706432eba283d50dde10891b49c3424d46918ed2b6af8ecf90",
+ "0x0000000000000000000000000000000000000000000000000000000000002793": "7637225dd61f90c3cb05fae157272985993b34d6c369bfe8372720339fe4ffd2",
+ "0x000000000000000000000000000000000000000000000000000000000000279d": "6a7d064bc053c0f437707df7c36b820cca4a2e9653dd1761941af4070f5273b6",
+ "0x00000000000000000000000000000000000000000000000000000000000027a7": "91c1e6eec8f7944fd6aafdce5477f45d4f6e29298c9ef628a59e441a5e071fae",
+ "0x00000000000000000000000000000000000000000000000000000000000027b1": "a1c227db9bbd2e49934bef01cbb506dd1e1c0671a81aabb1f90a90025980a3c3",
+ "0x00000000000000000000000000000000000000000000000000000000000027bb": "8fcfc1af10f3e8671505afadfd459287ae98be634083b5a35a400cc9186694cf",
+ "0x00000000000000000000000000000000000000000000000000000000000027c5": "cc1ea9c015bd3a6470669f85c5c13e42c1161fc79704143df347c4a621dff44f",
+ "0x00000000000000000000000000000000000000000000000000000000000027cf": "b0a22c625dd0c6534e29bccc9ebf94a550736e2c68140b9afe3ddc7216f797de",
+ "0x00000000000000000000000000000000000000000000000000000000000027d9": "92b8e6ca20622e5fd91a8f58d0d4faaf7be48a53ea262e963bcf26a1698f9df3",
+ "0x00000000000000000000000000000000000000000000000000000000000027e3": "f6253b8e2f31df6ca7a97086c3b4d49d9cbbbdfc5be731b0c3040a4381161c53",
+ "0x00000000000000000000000000000000000000000000000000000000000027ed": "ea8d762903bd24b80037d7ffe80019a086398608ead66208c18f0a5778620e67",
+ "0x00000000000000000000000000000000000000000000000000000000000027f7": "543382975e955588ba19809cfe126ea15dc43c0bfe6a43d861d7ad40eac2c2f4",
+ "0x0000000000000000000000000000000000000000000000000000000000002801": "095294f7fe3eb90cf23b3127d40842f61b85da2f48f71234fb94d957d865a8a2",
+ "0x000000000000000000000000000000000000000000000000000000000000280b": "144c2dd25fd12003ccd2678d69d30245b0222ce2d2bfead687931a7f6688482f",
+ "0x0000000000000000000000000000000000000000000000000000000000002815": "7295f7d57a3547b191f55951f548479cbb9a60b47ba38beb8d85c4ccf0e4ae4c",
+ "0x000000000000000000000000000000000000000000000000000000000000281f": "9e8e241e13f76a4e6d777a2dc64072de4737ac39272bb4987bcecbf60739ccf4",
+ "0x0000000000000000000000000000000000000000000000000000000000002829": "fc753bcea3e720490efded4853ef1a1924665883de46c21039ec43e371e96bb9",
+ "0x0000000000000000000000000000000000000000000000000000000000002833": "5f5204c264b5967682836ed773aee0ea209840fe628fd1c8d61702c416b427ca",
+ "0x000000000000000000000000000000000000000000000000000000000000283d": "5ba9a0326069e000b65b759236f46e54a0e052f379a876d242740c24f6c47aed",
+ "0x0000000000000000000000000000000000000000000000000000000000002847": "b40e9621d5634cd21f70274c345704af2e060c5befaeb2df109a78c7638167c2",
+ "0x0000000000000000000000000000000000000000000000000000000000002851": "70e26b74456e6fea452e04f8144be099b0af0e279febdff17dd4cdf9281e12a7",
+ "0x000000000000000000000000000000000000000000000000000000000000285b": "43d7158f48fb1f124b2962dff613c5b4b8ea415967f2b528af6e7ae280d658e5",
+ "0x0000000000000000000000000000000000000000000000000000000000002865": "b50b2b14efba477dddca9682df1eafc66a9811c9c5bd1ae796abbef27ba14eb4",
+ "0x000000000000000000000000000000000000000000000000000000000000286f": "c14936902147e9a121121f424ecd4d90313ce7fc603f3922cebb7d628ab2c8dd",
+ "0x0000000000000000000000000000000000000000000000000000000000002879": "86609ed192561602f181a9833573213eb7077ee69d65107fa94f657f33b144d2",
+ "0x0000000000000000000000000000000000000000000000000000000000002883": "0a71a6dbc360e176a0f665787ed3e092541c655024d0b136a04ceedf572c57c5",
+ "0x000000000000000000000000000000000000000000000000000000000000288d": "a4bcbab632ddd52cb85f039e48c111a521e8944b9bdbaf79dd7c80b20221e4d6",
+ "0x0000000000000000000000000000000000000000000000000000000000002897": "2bc468eab4fad397f9136f80179729b54caa2cb47c06b0695aab85cf9813620d",
+ "0x00000000000000000000000000000000000000000000000000000000000028a1": "fc7f9a432e6fd69aaf025f64a326ab7221311147dd99d558633579a4d8a0667b",
+ "0x00000000000000000000000000000000000000000000000000000000000028ab": "949613bd67fb0a68cf58a22e60e7b9b2ccbabb60d1d58c64c15e27a9dec2fb35",
+ "0x00000000000000000000000000000000000000000000000000000000000028b5": "289ddb1aee772ad60043ecf17a882c36a988101af91ac177954862e62012fc0e",
+ "0x00000000000000000000000000000000000000000000000000000000000028bf": "bfa48b05faa1a2ee14b3eaed0b75f0d265686b6ce3f2b7fa051b8dc98bc23d6a",
+ "0x00000000000000000000000000000000000000000000000000000000000028c9": "7bf49590a866893dc77444d89717942e09acc299eea972e8a7908e9d694a1150",
+ "0x00000000000000000000000000000000000000000000000000000000000028d3": "992f76aee242737eb21f14b65827f3ebc42524fb422b17f414f33c35a24092db",
+ "0x00000000000000000000000000000000000000000000000000000000000028dd": "da6e4f935d966e90dffc6ac0f6d137d9e9c97d65396627e5486d0089b94076fa",
+ "0x00000000000000000000000000000000000000000000000000000000000028e7": "65467514ed80f25b299dcf74fb74e21e9bb929832a349711cf327c2f8b60b57f",
+ "0x00000000000000000000000000000000000000000000000000000000000028f1": "cc2ac03d7a26ff16c990c5f67fa03dabda95641a988deec72ed2fe38c0f289d6",
+ "0x00000000000000000000000000000000000000000000000000000000000028fb": "096dbe9a0190c6badf79de3747abfd4d5eda3ab95b439922cae7ec0cfcd79290",
+ "0x0000000000000000000000000000000000000000000000000000000000002905": "0c659c769744094f60332ec247799d7ed5ae311d5738daa5dcead3f47ca7a8a2",
+ "0x000000000000000000000000000000000000000000000000000000000000290f": "9cb8a0d41ede6b951c29182422db215e22aedfa1a3549cd27b960a768f6ed522",
+ "0x0000000000000000000000000000000000000000000000000000000000002919": "2510f8256a020f4735e2be224e3bc3e8c14e56f7588315f069630fe24ce2fa26",
+ "0x0000000000000000000000000000000000000000000000000000000000002923": "2d3deb2385a2d230512707ece0bc6098ea788e3d5debb3911abe9a710dd332ea",
+ "0x000000000000000000000000000000000000000000000000000000000000292d": "1cec4b230f3bccfff7ca197c4a35cb5b95ff7785d064be3628235971b7aff27c",
+ "0x0000000000000000000000000000000000000000000000000000000000002937": "18e4a4238d43929180c7a626ae6f8c87a88d723b661549f2f76ff51726833598",
+ "0x0000000000000000000000000000000000000000000000000000000000002941": "700e1755641a437c8dc888df24a5d80f80f9eaa0d17ddab17db4eb364432a1f5",
+ "0x000000000000000000000000000000000000000000000000000000000000294b": "cad29ceb73b2f3c90d864a2c27a464b36b980458e2d8c4c7f32f70afad707312",
+ "0x0000000000000000000000000000000000000000000000000000000000002955": "a85e892063a7fd41d37142ae38037967eb047436c727fcf0bad813d316efe09f",
+ "0x000000000000000000000000000000000000000000000000000000000000295f": "040100f17208bcbd9456c62d98846859f7a5efa0e45a5b3a6f0b763b9c700fec",
+ "0x0000000000000000000000000000000000000000000000000000000000002969": "49d54a5147de1f5208c509b194af6d64b509398e4f255c20315131e921f7bd04",
+ "0x0000000000000000000000000000000000000000000000000000000000002973": "810ff6fcafb9373a4df3e91ab1ca64a2955c9e42ad8af964f829e38e0ea4ee20",
+ "0x000000000000000000000000000000000000000000000000000000000000297d": "9b72096b8b672ac6ff5362c56f5d06446d1693c5d2daa94a30755aa636320e78",
+ "0x0000000000000000000000000000000000000000000000000000000000002987": "f68bff777db51db5f29afc4afe38bd1bf5cdec29caa0dc52535b529e6d99b742",
+ "0x0000000000000000000000000000000000000000000000000000000000002991": "9566690bde717eec59f828a2dba90988fa268a98ed224f8bc02b77bce10443c4",
+ "0x000000000000000000000000000000000000000000000000000000000000299b": "d0e821fbd57a4d382edd638b5c1e6deefb81352d41aa97da52db13f330e03097",
+ "0x00000000000000000000000000000000000000000000000000000000000029a5": "43f9aa6fa63739abec56c4604874523ac6dabfcc08bb283195072aeb29d38dfe",
+ "0x00000000000000000000000000000000000000000000000000000000000029af": "54ebfa924e887a63d643a8277c3394317de0e02e63651b58b6eb0e90df8a20cd",
+ "0x00000000000000000000000000000000000000000000000000000000000029b9": "9e414c994ee35162d3b718c47f8435edc2c93394a378cb41037b671366791fc8",
+ "0x00000000000000000000000000000000000000000000000000000000000029c3": "4356f072bb235238abefb3330465814821097327842b6e0dc4a0ef95680c4d34",
+ "0x00000000000000000000000000000000000000000000000000000000000029cd": "215df775ab368f17ed3f42058861768a3fba25e8d832a00b88559ca5078b8fbc",
+ "0x00000000000000000000000000000000000000000000000000000000000029d7": "d17835a18d61605a04d2e50c4f023966a47036e5c59356a0463db90a76f06e3e",
+ "0x00000000000000000000000000000000000000000000000000000000000029e1": "875032d74e62dbfd73d4617754d36cd88088d1e5a7c5354bf3e0906c749e6637",
+ "0x00000000000000000000000000000000000000000000000000000000000029eb": "6f22ae25f70f4b03a2a2b17f370ace1f2b15d17fc7c2457824348a8f2a1eff9f",
+ "0x00000000000000000000000000000000000000000000000000000000000029f5": "f11fdf2cb985ce7472dc7c6b422c3a8bf2dfbbc6b86b15a1fa62cf9ebae8f6cf",
+ "0x00000000000000000000000000000000000000000000000000000000000029ff": "bbc97696e588f80fbe0316ad430fd4146a29c19b926248febe757cd9408deddc",
+ "0x0000000000000000000000000000000000000000000000000000000000002a09": "71dd15be02efd9f3d5d94d0ed9b5e60a205f439bb46abe6226879e857668881e",
+ "0x0000000000000000000000000000000000000000000000000000000000002a13": "b90e98bd91f1f7cc5c4456bb7a8868a2bb2cd3dda4b5dd6463b88728526dceea",
+ "0x0000000000000000000000000000000000000000000000000000000000002a1d": "4e80fd3123fda9b404a737c9210ccb0bacc95ef93ac40e06ce9f7511012426c4",
+ "0x0000000000000000000000000000000000000000000000000000000000002a27": "afb50d96b2543048dc93045b62357cc18b64d0e103756ce3ad0e04689dd88282",
+ "0x0000000000000000000000000000000000000000000000000000000000002a31": "d73341a1c9edd04a890f949ede6cc1e942ad62b63b6a60177f0f692f141a7e95",
+ "0x0000000000000000000000000000000000000000000000000000000000002a3b": "c26601e9613493118999d9268b401707e42496944ccdbfa91d5d7b791a6d18f1",
+ "0x0000000000000000000000000000000000000000000000000000000000002a45": "fb4619fb12e1b9c4b508797833eef7df65fcf255488660d502def2a7ddceef6d",
+ "0x0000000000000000000000000000000000000000000000000000000000002a4f": "d08b7458cd9d52905403f6f4e9dac15ad18bea1f834858bf48ecae36bf854f98",
+ "0x0000000000000000000000000000000000000000000000000000000000002a59": "df979da2784a3bb9e07c368094dc640aafc514502a62a58b464e50e5e50a34bd",
+ "0x0000000000000000000000000000000000000000000000000000000000002a63": "15855037d4712ce0019f0169dcd58b58493be8373d29decfa80b8df046e3d6ba",
+ "0x0000000000000000000000000000000000000000000000000000000000002a6d": "fd1462a68630956a33e4b65c8e171a08a131097bc7faf5d7f90b5503ab30b69c",
+ "0x0000000000000000000000000000000000000000000000000000000000002a77": "edad57fee633c4b696e519f84ad1765afbef5d2781b382acd9b8dfcf6cd6d572",
+ "0x0000000000000000000000000000000000000000000000000000000000002a81": "c2641ba296c2daa6edf09b63d0f1cfcefd51451fbbc283b6802cbd5392fb145c",
+ "0x0000000000000000000000000000000000000000000000000000000000002a8b": "5615d64e1d3a10972cdea4e4b106b4b6e832bc261129f9ab1d10a670383ae446",
+ "0x0000000000000000000000000000000000000000000000000000000000002a95": "0757c6141fad938002092ff251a64190b060d0e31c31b08fb56b0f993cc4ef0d",
+ "0x0000000000000000000000000000000000000000000000000000000000002a9f": "14ddc31bc9f9c877ae92ca1958e6f3affca7cc3064537d0bbe8ba4d2072c0961",
+ "0x0000000000000000000000000000000000000000000000000000000000002aa9": "490b0f08777ad4364f523f94dccb3f56f4aacb2fb4db1bb042a786ecfd248c79",
+ "0x0000000000000000000000000000000000000000000000000000000000002ab3": "4a37c0e55f539f2ecafa0ce71ee3d80bc9fe33fb841583073c9f524cc5a2615a",
+ "0x0000000000000000000000000000000000000000000000000000000000002abd": "133295fdf94e5e4570e27125807a77272f24622750bcf408be0360ba0dcc89f2",
+ "0x0000000000000000000000000000000000000000000000000000000000002ac7": "a73eb87c45c96b121f9ab081c095bff9a49cfe5a374f316e9a6a66096f532972",
+ "0x0000000000000000000000000000000000000000000000000000000000002ad1": "9040bc28f6e830ca50f459fc3dac39a6cd261ccc8cd1cca5429d59230c10f34c",
+ "0x0000000000000000000000000000000000000000000000000000000000002adb": "ec1d134c49cde6046ee295672a8f11663b6403fb71338181a89dc6bc92f7dea8",
+ "0x0000000000000000000000000000000000000000000000000000000000002ae5": "3130a4c80497c65a7ee6ac20f6888a95bd5b05636d6b4bd13d616dcb01591e16",
+ "0x0000000000000000000000000000000000000000000000000000000000002aef": "ccdfd5b42f2cbd29ab125769380fc1b18a9d272ac5d3508a6bbe4c82360ebcca",
+ "0x0000000000000000000000000000000000000000000000000000000000002af9": "74342c7f25ee7dd1ae6eb9cf4e5ce5bcab56c798aea36b554ccb31a660e123af",
+ "0x0000000000000000000000000000000000000000000000000000000000002b03": "f6f75f51a452481c30509e5de96edae82892a61f8c02c88d710dc782b5f01fc7",
+ "0x0000000000000000000000000000000000000000000000000000000000002b0d": "7ce6539cc82db9730b8c21b12d6773925ff7d1a46c9e8f6c986ada96351f36e9",
+ "0x0000000000000000000000000000000000000000000000000000000000002b17": "1983684da5e48936b761c5e5882bbeb5e42c3a7efe92989281367fa5ab25e918",
+ "0x0000000000000000000000000000000000000000000000000000000000002b21": "c564aa993f2b446325ee674146307601dd87eb7409266a97e695e4bb09dd8bf5",
+ "0x0000000000000000000000000000000000000000000000000000000000002b2b": "9ca2ff57d59decb7670d5f49bcca68fdaf494ba7dc06214d8e838bfcf7a2824e",
+ "0x0000000000000000000000000000000000000000000000000000000000002b35": "6d7b7476cecc036d470a691755f9988409059bd104579c0a2ded58f144236045",
+ "0x0000000000000000000000000000000000000000000000000000000000002b3f": "417504d79d00b85a29f58473a7ad643f88e9cdfe5da2ed25a5965411390fda4a",
+ "0x0000000000000000000000000000000000000000000000000000000000002b49": "e910eb040bf32e56e9447d63497799419957ed7df2572e89768b9139c6fa6a23",
+ "0x0000000000000000000000000000000000000000000000000000000000002b53": "8e462d3d5b17f0157bc100e785e1b8d2ad3262e6f27238fa7e9c62ba29e9c692",
+ "0x0000000000000000000000000000000000000000000000000000000000002b5d": "3e6f040dc96b2e05961c4e28df076fa654761f4b0e2e30f5e36b06f65d1893c1",
+ "0x0000000000000000000000000000000000000000000000000000000000002b67": "07e71d03691704a4bd83c728529642884fc1b1a8cfeb1ddcbf659c9b71367637",
+ "0x0000000000000000000000000000000000000000000000000000000000002b71": "f4d05f5986e4b92a845467d2ae6209ca9b7c6c63ff9cdef3df180660158163ef",
+ "0x0000000000000000000000000000000000000000000000000000000000002b7b": "5ca251408392b25af49419f1ecd9338d1f4b5afa536dc579ab54e1e3ee6914d4",
+ "0x0000000000000000000000000000000000000000000000000000000000002b85": "e98b64599520cf62e68ce0e2cdf03a21d3712c81fa74b5ade4885b7d8aec531b",
+ "0x0000000000000000000000000000000000000000000000000000000000002b8f": "d62ec5a2650450e26aac71a21d45ef795e57c231d28a18d077a01f761bc648fe",
+ "0x0000000000000000000000000000000000000000000000000000000000002b99": "4d3fb38cf24faf44f5b37f248553713af2aa9c3d99ddad4a534e49cd06bb8098",
+ "0x0000000000000000000000000000000000000000000000000000000000002ba3": "36e90abacae8fbe712658e705ac28fa9d00118ef55fe56ea893633680147148a",
+ "0x0000000000000000000000000000000000000000000000000000000000002bad": "164177f08412f7e294fae37457d238c4dd76775263e2c7c9f39e8a7ceca9028a",
+ "0x0000000000000000000000000000000000000000000000000000000000002bb7": "aa5a5586bf2f68df5c206dbe45a9498de0a9b5a2ee92235b740971819838a010",
+ "0x0000000000000000000000000000000000000000000000000000000000002bc1": "99d001850f513efdc613fb7c8ede12a943ff543c578a54bebbb16daecc56cec5",
+ "0x0000000000000000000000000000000000000000000000000000000000002bcb": "30a4501d58b23fc7eee5310f5262783b2dd36a94922d11e5e173ec763be8accb",
+ "0x0000000000000000000000000000000000000000000000000000000000002bd5": "a804188a0434260c0825a988483de064ae01d3e50cb111642c4cfb65bfc2dfb7",
+ "0x0000000000000000000000000000000000000000000000000000000000002bdf": "c554c79292c950bce95e9ef57136684fffb847188607705454909aa5790edc64",
+ "0x0000000000000000000000000000000000000000000000000000000000002be9": "c89e3673025beff5031d48a885098da23d716b743449fd5533a04f25bd2cd203",
+ "0x0000000000000000000000000000000000000000000000000000000000002bf3": "44c310142a326a3822abeb9161413f91010858432d27c9185c800c9c2d92aea6",
+ "0x0000000000000000000000000000000000000000000000000000000000002bfd": "ae3f497ee4bd619d651097d3e04f50caac1f6af55b31b4cbde4faf1c5ddc21e8",
+ "0x0000000000000000000000000000000000000000000000000000000000002c07": "3287d70a7b87db98964e828d5c45a4fa4cd7907be3538a5e990d7a3573ccb9c1",
+ "0x0000000000000000000000000000000000000000000000000000000000002c11": "b52bb578e25d833410fcca7aa6f35f79844537361a43192dce8dcbc72d15e09b",
+ "0x0000000000000000000000000000000000000000000000000000000000002c1b": "ff8f6f17c0f6d208d27dd8b9147586037086b70baf4f70c3629e73f8f053d34f",
+ "0x0000000000000000000000000000000000000000000000000000000000002c25": "70bccc358ad584aacb115076c8aded45961f41920ffedf69ffa0483e0e91fa52",
+ "0x0000000000000000000000000000000000000000000000000000000000002c2f": "e3881eba45a97335a6d450cc37e7f82b81d297c111569e38b6ba0c5fb0ae5d71",
+ "0x0000000000000000000000000000000000000000000000000000000000002c39": "2217beb48c71769d8bf9caaac2858237552fd68cd4ddefb66d04551e7beaa176",
+ "0x0000000000000000000000000000000000000000000000000000000000002c43": "06b56638d2545a02757e7f268b25a0cd3bce792fcb1e88da21b0cc21883b9720",
+ "0x0000000000000000000000000000000000000000000000000000000000002c4d": "ebdc8c9e2a85a1fb6582ca30616a685ec8ec25e9c020a65a85671e8b9dacc6eb",
+ "0x0000000000000000000000000000000000000000000000000000000000002c57": "738f3edb9d8d273aac79f95f3877fd885e1db732e86115fa3d0da18e6c89e9cf",
+ "0x0000000000000000000000000000000000000000000000000000000000002c61": "ae5ccfc8201288b0c5981cdb60e16bc832ac92edc51149bfe40ff4a935a0c13a",
+ "0x0000000000000000000000000000000000000000000000000000000000002c6b": "69a7a19c159c0534e50a98e460707c6c280e7e355fb97cf2b5e0fd56c45a0a97",
+ "0x0000000000000000000000000000000000000000000000000000000000002c75": "4d2a1e9207a1466593e5903c5481a579e38e247afe5e80bd41d629ac3342e6a4",
+ "0x0000000000000000000000000000000000000000000000000000000000002c7f": "d3e7d679c0d232629818cbb94251c24797ce36dd2a45dbe8c77a6a345231c3b3",
+ "0x0000000000000000000000000000000000000000000000000000000000002c89": "d1835b94166e1856dddb6eaa1cfdcc6979193f2ff4541ab274738bd48072899c",
+ "0x0000000000000000000000000000000000000000000000000000000000002c93": "1f12c89436a94d427a69bca5a080edc328bd2424896f3f37223186b440deb45e",
+ "0x0000000000000000000000000000000000000000000000000000000000002c9d": "ccb765890b7107fd98056a257381b6b1d10a83474bbf1bdf8e6b0b8eb9cef2a9",
+ "0x0000000000000000000000000000000000000000000000000000000000002ca7": "8bbf4e534dbf4580edc5a973194a725b7283f7b9fbb7d7d8deb386aaceebfa84",
+ "0x0000000000000000000000000000000000000000000000000000000000002cb1": "85a0516088f78d837352dcf12547ee3c598dda398e78a9f4d95acfbef19f5e19",
+ "0x0000000000000000000000000000000000000000000000000000000000002cbb": "0f669bc7780e2e5719f9c05872a112f6511e7f189a8649cda5d8dda88d6b8ac3",
+ "0x0000000000000000000000000000000000000000000000000000000000002cc5": "a7816288f9712fcab6a2b6fbd0b941b8f48c2acb635580ed80c27bed7e840a57",
+ "0x0000000000000000000000000000000000000000000000000000000000002ccf": "da5168c8c83ac67dfc2772af49d689f11974e960dee4c4351bac637db1a39e82",
+ "0x0000000000000000000000000000000000000000000000000000000000002cd9": "3f720ecec02446f1af948de4eb0f54775562f2d615726375c377114515ac545b",
+ "0x0000000000000000000000000000000000000000000000000000000000002ce3": "273830a0087f6cef0fdb42179aa1c6c8c19f7bc83c3dc7aa1a56e4e05ca473ea",
+ "0x0000000000000000000000000000000000000000000000000000000000002ced": "7044f700543fd542e87e7cdb94f0126b0f6ad9488d0874a8ac903a72bade34e9",
+ "0x0000000000000000000000000000000000000000000000000000000000002cf7": "f63a7ff76bb9713bea8d47831a1510d2c8971accd22a403d5bbfaaa3dc310616",
+ "0x0000000000000000000000000000000000000000000000000000000000002d01": "a68dbd9898dd1589501ca3220784c44d41852ad997a270e215539d461ec090f8",
+ "0x0000000000000000000000000000000000000000000000000000000000002d0b": "59e501ae3ba9e0c3adafdf0f696d2e6a358e1bec43cbe9b0258c2335dd8d764f",
+ "0x0000000000000000000000000000000000000000000000000000000000002d15": "4f19cff0003bdc03c2fee20db950f0efb323be170f0b09c491a20abcf26ecf43",
+ "0x0000000000000000000000000000000000000000000000000000000000002d1f": "52b1b89795a8fabd3c8594bd571b44fd72279979aaa1d49ea7105c787f8f5fa6",
+ "0x0000000000000000000000000000000000000000000000000000000000002d29": "7c1416bd4838b93bc87990c9dcca108675bafab950dd0faf111d9eddc4e54327",
+ "0x0000000000000000000000000000000000000000000000000000000000002d33": "ef87a35bb6e56e7d5a1f804c63c978bbd1c1516c4eb70edad2b8143169262c9f",
+ "0x0000000000000000000000000000000000000000000000000000000000002d3d": "e978f25d16f468c0a0b585994d1e912837f55e1cd8849e140f484a2702385ef2",
+ "0x0000000000000000000000000000000000000000000000000000000000002d47": "c3e85e9260b6fad139e3c42587cc2df7a9da07fadaacaf2381ca0d4a0c91c819",
+ "0x0000000000000000000000000000000000000000000000000000000000002d51": "bd2647c989abfd1d340fd05add92800064ad742cd82be8c2ec5cc7df20eb0351",
+ "0x0000000000000000000000000000000000000000000000000000000000002d5b": "99ac5ad7b62dd843abca85e485a6d4331e006ef9d391b0e89fb2eeccef1d29a2",
+ "0x0000000000000000000000000000000000000000000000000000000000002d65": "02a4349c3ee7403fe2f23cad9cf2fb6933b1ae37e34c9d414dc4f64516ea9f97",
+ "0x0000000000000000000000000000000000000000000000000000000000002d6f": "627b41fdbdf4a95381da5e5186123bf808c119b849dfdd3f515fa8d54c19c771",
+ "0x0000000000000000000000000000000000000000000000000000000000002d79": "c087b16d7caa58e1361a7b158159469975f55582a4ef760465703a40123226d7",
+ "0x0000000000000000000000000000000000000000000000000000000000002d83": "f7a477c0c27d4890e3fb56eb2dc0386e7409d1c59cab6c7f22b84de45b4c6867",
+ "0x0000000000000000000000000000000000000000000000000000000000002d8d": "1cb440b7d88e98ceb953bc46b003fde2150860be05e11b9a5abae2c814a71571",
+ "0x0000000000000000000000000000000000000000000000000000000000002d97": "72613e3e30445e37af38976f6bb3e3bf7debbcf70156eb37c5ac4e41834f9dd2",
+ "0x0000000000000000000000000000000000000000000000000000000000002da1": "e69e7568b9e70ee7e71ebad9548fc8afad5ff4435df5d55624b39df9e8826c91",
+ "0x0000000000000000000000000000000000000000000000000000000000002dab": "c3f1682f65ee45ce7019ee7059d65f8f1b0c0a8f68f94383410f7e6f46f26577",
+ "0x0000000000000000000000000000000000000000000000000000000000002db5": "93ee1e4480ed7935097467737e54c595a2a6424cf8eaed5eacc2bf23ce368192",
+ "0x0000000000000000000000000000000000000000000000000000000000002dbf": "b07f8855348b496166d3906437b8b76fdf7918f2e87858d8a78b1deece6e2558",
+ "0x0000000000000000000000000000000000000000000000000000000000002dc9": "ec60e51de32061c531b80d2c515bfa8f81600b9b50fc02beaf4dc01dd6e0c9ca",
+ "0x0000000000000000000000000000000000000000000000000000000000002dd3": "2fc9f34b3ed6b3cabd7b2b65b4a21381ad4419670eed745007f9efa8dd365ef1",
+ "0x0000000000000000000000000000000000000000000000000000000000002ddd": "f4af3b701f9b088d23f93bb6d5868370ed1cdcb19532ddd164ed3f411f3e5a95",
+ "0x0000000000000000000000000000000000000000000000000000000000002de7": "8272e509366a028b8d6bbae2a411eb3818b5be7dac69104a4e72317e55a9e697",
+ "0x0000000000000000000000000000000000000000000000000000000000002df1": "a194d76f417dafe27d02a6044a913c0b494fe893840b5b745386ae6078a44e9c",
+ "0x0000000000000000000000000000000000000000000000000000000000002dfb": "a255e59e9a27c16430219b18984594fc1edaf88fe47dd427911020fbc0d92507",
+ "0x0000000000000000000000000000000000000000000000000000000000002e05": "7996946b8891ebd0623c7887dd09f50a939f6f29dea4ca3c3630f50ec3c575cb",
+ "0x0000000000000000000000000000000000000000000000000000000000002e0f": "b04cbab069405f18839e6c6cf85cc19beeb9ee98c159510fcb67cb84652b7db9",
+ "0x0000000000000000000000000000000000000000000000000000000000002e19": "6f241a5e530d1e261ef0f5800d7ff252c33ce148865926e6231d4718f0b9eded",
+ "0x0000000000000000000000000000000000000000000000000000000000002e23": "fcfa9f1759f8db6a7e452af747a972cf3b1b493a216dbd32db21f7c2ce279cce",
+ "0x0000000000000000000000000000000000000000000000000000000000002e2d": "df880227742710ac4f31c0466a6da7c56ec54caccfdb8f58e5d3f72e40e800f3",
+ "0x0000000000000000000000000000000000000000000000000000000000002e37": "adfe28a0f8afc89c371dc7b724c78c2e3677904d03580c7141d32ba32f0ed46f",
+ "0x0000000000000000000000000000000000000000000000000000000000002e41": "b264d19d2daf7d5fcf8d2214eba0aacf72cabbc7a2617219e535242258d43a31",
+ "0x0000000000000000000000000000000000000000000000000000000000002e4b": "f2207420648dccc4f01992831e219c717076ff3c74fb88a96676bbcfe1e63f38",
+ "0x0000000000000000000000000000000000000000000000000000000000002e55": "41e8fae73b31870db8546eea6e11b792e0c9daf74d2fbb6471f4f6c6aaead362",
+ "0x0000000000000000000000000000000000000000000000000000000000002e5f": "4e7a5876c1ee2f1833267b5bd85ac35744a258cc3d7171a8a8cd5c87811078a2",
+ "0x0000000000000000000000000000000000000000000000000000000000002e69": "8d4a424d1a0ee910ccdfc38c7e7f421780c337232d061e3528e025d74b362315",
+ "0x0000000000000000000000000000000000000000000000000000000000002e73": "fa65829d54aba84896370599f041413d50f1acdc8a178211b2960827c1f85cbf",
+ "0x0000000000000000000000000000000000000000000000000000000000002e7d": "da5dfc12da14eafad2ac2a1456c241c4683c6e7e40a7c3569bc618cfc9d6dca3",
+ "0x0000000000000000000000000000000000000000000000000000000000002e87": "16243e7995312ffa3983c5858c6560b2abc637c481746003b6c2b58c62e9a547",
+ "0x0000000000000000000000000000000000000000000000000000000000002e91": "b75f0189b31abbbd88cd32c47ed311c93ec429f1253ee715a1b00d1ca6a1e094",
+ "0x0000000000000000000000000000000000000000000000000000000000002e9b": "d087eb94d6347da9322e3904add7ff7dd0fd72b924b917a8e10dae208251b49d",
+ "0x0000000000000000000000000000000000000000000000000000000000002ea5": "bc17244b8519292d8fbb455f6253e57ecc16b5803bd58f62b0d94da7f8b2a1d6",
+ "0x0000000000000000000000000000000000000000000000000000000000002eaf": "3ff8b39a3c6de6646124497b27e8d4e657d103c72f2001bdd4c554208a0566e3",
+ "0x0000000000000000000000000000000000000000000000000000000000002eb9": "4d0f765d2b6a01f0c787bbb13b1360c1624704883e2fd420ea36037fa7e3a563",
+ "0x0000000000000000000000000000000000000000000000000000000000002ec3": "f6f1dc891258163196785ce9516a14056cbe823b17eb9b90eeee7a299c1ce0e0",
+ "0x0000000000000000000000000000000000000000000000000000000000002ecd": "1dbf19b70c0298507d20fb338cc167d9b07b8747351785047e1a736b42d999d1",
+ "0x0000000000000000000000000000000000000000000000000000000000002ed7": "c3b71007b20abbe908fdb7ea11e3a3f0abff3b7c1ced865f82b07f100167de57",
+ "0x0000000000000000000000000000000000000000000000000000000000002ee1": "3f45edc424499d0d4bbc0fd5837d1790cb41c08f0269273fdf66d682429c25cc",
+ "0x0000000000000000000000000000000000000000000000000000000000002eeb": "cb8f5db9446c485eaae7edbc03e3afed72892fa7f11ad8eb7fa9dffbe3c220eb",
+ "0x0000000000000000000000000000000000000000000000000000000000002ef5": "3d151527b5ba165352a450bee69f0afc78cf2ea9645bb5d8f36fb04435f0b67c",
+ "0x0000000000000000000000000000000000000000000000000000000000002eff": "dd96b35b4ffabce80d377420a0b00b7fbf0eff6a910210155d22d9bd981be5d3",
+ "0x0000000000000000000000000000000000000000000000000000000000002f09": "ace0c30b543d3f92f37eaac45d6f8730fb15fcaaaad4097ea42218abe57cb9f4",
+ "0x0000000000000000000000000000000000000000000000000000000000002f13": "f6342dd31867c9bef6ffa06b6cf192db23d0891ed8fe610eb8d1aaa79726da01",
+ "0x0000000000000000000000000000000000000000000000000000000000002f1d": "a6589e823979c2c2ac55e034d547b0c63aa02109133575d9f159e8a7677f03cb",
+ "0x0000000000000000000000000000000000000000000000000000000000002f27": "9ce48bc641cc1d54ffdb409aab7da1304d5ee08042596b3542ca9737bb2b79a8",
+ "0x0000000000000000000000000000000000000000000000000000000000002f31": "a44be801bd978629775c00d70df6d70b76d0ba918595e81415a27d1e3d6fdee9",
+ "0x0000000000000000000000000000000000000000000000000000000000002f3b": "ce17f1e7af9f7ea8a99b2780d87b15d8b80a68fb29ea52f962b00fecfc6634e0",
+ "0x0000000000000000000000000000000000000000000000000000000000002f45": "4bd91febab8df3770c957560e6185e8af59d2a42078756c525cd7769eb943894",
+ "0x0000000000000000000000000000000000000000000000000000000000002f4f": "414c2a52de31de93a3c69531247b016ac578435243073acc516d4ea673c8dd80",
+ "0x0000000000000000000000000000000000000000000000000000000000002f59": "647fb60bdf2683bd46b63d6884745782364a5522282ed1dc67d9e17c4aaab17d",
+ "0x0000000000000000000000000000000000000000000000000000000000002f63": "fa681ffd0b0dd6f6775e99a681241b86a3a24446bc8a69cdae915701243e3855",
+ "0x0000000000000000000000000000000000000000000000000000000000002f6d": "106ca692777b30cb2aa23ca59f5591514b28196ee8e9b06aa2b4deaea30d9ef6",
+ "0x0000000000000000000000000000000000000000000000000000000000002f77": "494ac6d09377eb6a07ff759df61c2508e65e5671373d756c82e648bd9086d91a",
+ "0x0000000000000000000000000000000000000000000000000000000000002f81": "0ae4ccd2bffa603714cc453bfd92f769dce6c9731c03ac3e2083f35388e6c795",
+ "0x0000000000000000000000000000000000000000000000000000000000002f8b": "d860c999490d9836cc00326207393c78445b7fb90b12aa1d3607e3662b3d32cd",
+ "0x0000000000000000000000000000000000000000000000000000000000002f95": "9587384f876dfec24da857c0bcdb3ded17f3328f28a4d59aa35ca7c25c8102cf",
+ "0x0000000000000000000000000000000000000000000000000000000000002f9f": "4df8093d29bc0ec4e2a82be427771e77a206566194734a73c23477e1a9e451f8",
+ "0x0000000000000000000000000000000000000000000000000000000000002fa9": "c56640f78acbd1da07701c365369766f09a19800ba70276f1f1d3cd1cf6e0686",
+ "0x0000000000000000000000000000000000000000000000000000000000002fb3": "7173d4210aa525eece6b4b19b16bab23686ff9ac71bb9d16008bb114365e79f2",
+ "0x0000000000000000000000000000000000000000000000000000000000002fbd": "89698b41d7ac70e767976a9f72ae6a46701456bc5ad8d146c248548409c90015",
+ "0x0000000000000000000000000000000000000000000000000000000000002fc7": "5b605ab5048d9e4a51ca181ac3fa7001ef5d415cb20335b095c54a40c621dbff",
+ "0x0000000000000000000000000000000000000000000000000000000000002fd1": "9129a84b729e7f69a5522a7020db57e27bf8cbb6042e030106c0cbd185bf0ab8",
+ "0x0000000000000000000000000000000000000000000000000000000000002fdb": "31a63d6d54153ab35fc57068db205a3e68908be238658ca82d8bee9873f82159",
+ "0x0000000000000000000000000000000000000000000000000000000000002fe5": "828641bcea1bc6ee1329bc39dca0afddc11e6867f3da13d4bb5170c54158860d",
+ "0x0000000000000000000000000000000000000000000000000000000000002fef": "7e0752ddd86339f512ec1b647d3bf4b9b50c45e309ab9e70911da7716454b053",
+ "0x0000000000000000000000000000000000000000000000000000000000002ff9": "31d973051189456d5998e05b500da6552138644f8cdbe4ec63f96f21173cb6a1",
+ "0x0000000000000000000000000000000000000000000000000000000000003003": "e33e65b3d29c3b55b2d7b584c5d0540eb5c00c9f157287863b0b619339c302f0",
+ "0x000000000000000000000000000000000000000000000000000000000000300d": "78d55514bcef24b40c7eb0fbe55f922d4468c194f313898f28ba85d8534df82c",
+ "0x0000000000000000000000000000000000000000000000000000000000003017": "2e0f4be4d8adf8690fd64deddbc543f35c5b4f3c3a27b10a77b1fdb8d590f1ee",
+ "0x0000000000000000000000000000000000000000000000000000000000003021": "e1b83ea8c4329f421296387826c89100d82bdc2263ffd8eb9368806a55d9b83b",
+ "0x000000000000000000000000000000000000000000000000000000000000302b": "4ddad36d7262dd9201c5bdd58523f4724e3b740fddbed2185e32687fecacdf6b",
+ "0x0000000000000000000000000000000000000000000000000000000000003035": "156c0674e46cdec70505443c5269d42c7bb14ee6c00f86a23962f08906cbb846",
+ "0x000000000000000000000000000000000000000000000000000000000000303f": "dfc56ec6c218a08b471d757e0e7de8dddec9e82f401cb7d77df1f2a9ca54c607",
+ "0x0000000000000000000000000000000000000000000000000000000000003049": "395d660f77c4360705cdc0be895907ec183097f749fac18b6eaa0245c1009074",
+ "0x0000000000000000000000000000000000000000000000000000000000003053": "84c0060087da2c95dbd517d0f2dd4dfba70691a5952fe4048c310e88e9c06e4f",
+ "0x000000000000000000000000000000000000000000000000000000000000305d": "f4df943c52b1d5fb9c1f73294ca743577d83914ec26d6e339b272cdeb62de586",
+ "0x0000000000000000000000000000000000000000000000000000000000003067": "0bb47661741695863ef89d5c2b56666772f871be1cc1dccf695bd357e4bb26d6",
+ "0x0000000000000000000000000000000000000000000000000000000000003071": "4a1f7691f29900287c6931545884881143ecae44cb26fdd644892844fde65dac",
+ "0x000000000000000000000000000000000000000000000000000000000000307b": "9b133cc50cbc46d55ce2910eebaf8a09ab6d4e606062c94aac906da1646bc33f",
+ "0x0000000000000000000000000000000000000000000000000000000000003085": "473b076b542da72798f9de31c282cb1dcd76cba2a22adc7391670ffdbc910766",
+ "0x000000000000000000000000000000000000000000000000000000000000308f": "225dd472ef6b36a51de5c322a31a9f71c80f0f350432884526d9844bb2e676d3",
+ "0x0000000000000000000000000000000000000000000000000000000000003099": "31df97b2c9fc65b5520b89540a42050212e487f46fac67685868f1c3e652a9aa",
+ "0x00000000000000000000000000000000000000000000000000000000000030a3": "4416d885f34ad479409bb9e05e8846456a9be7e74655b9a4d7568a8d710aa06a",
+ "0x00000000000000000000000000000000000000000000000000000000000030ad": "ae627f8802a46c1357fa42a8290fd1366ea21b8ccec1cc624e42022647c53802",
+ "0x00000000000000000000000000000000000000000000000000000000000030b7": "8961e8b83d91487fc32b3d6af26b1d5e7b4010dd8d028fe165187cdfb04e151c",
+ "0x00000000000000000000000000000000000000000000000000000000000030c1": "c22e39f021605c6f3d967aef37f0bf40b09d776bac3edb4264d0dc07389b9845",
+ "0x00000000000000000000000000000000000000000000000000000000000030cb": "7cfa4c7066c690c12b9e8727551bef5fe05b750ac6637a5af632fce4ceb4e2ce",
+ "0x00000000000000000000000000000000000000000000000000000000000030d5": "943d79e4329b86f8e53e8058961955f2b0a205fc3edeea2aae54ba0c22b40c31",
+ "0x00000000000000000000000000000000000000000000000000000000000030df": "66598070dab784e48a153bf9c6c3e57d8ca92bed6592f0b9e9abe308a17aedf0",
+ "0x00000000000000000000000000000000000000000000000000000000000030e9": "ac8fe4eb91577288510a9bdae0d5a8c40b8225172379cd70988465d8b98cfa70",
+ "0x00000000000000000000000000000000000000000000000000000000000030f3": "2b0018a8548e5ce2a6b6b879f56e3236cc69d2efff80f48add54efd53681dfce",
+ "0x00000000000000000000000000000000000000000000000000000000000030fd": "823445936237e14452e253a6692290c1be2e1be529ddbeecc35c9f54f7ea9887",
+ "0x0000000000000000000000000000000000000000000000000000000000003107": "3051a0d0701d233836b2c802060d6ee629816c856a25a62dc73bb2f2fc93b918",
+ "0x0000000000000000000000000000000000000000000000000000000000003111": "44a50fda08d2f7ca96034186475a285a8a570f42891f72d256a52849cb188c85",
+ "0x000000000000000000000000000000000000000000000000000000000000311b": "6e60069a12990ef960c0ac825fd0d9eb44aec9eb419d0df0c25d7a1d16c282e7",
+ "0x0000000000000000000000000000000000000000000000000000000000003125": "581ddf7753c91af00c894f8d5ab22b4733cfeb4e75c763725ebf46fb889fa76a",
+ "0x000000000000000000000000000000000000000000000000000000000000312f": "9a1dfba8b68440fcc9e89b86e2e290367c5e5fb0833b34612d1f4cfc53189526",
+ "0x0000000000000000000000000000000000000000000000000000000000003139": "54a623060b74d56f3c0d6793e40a9269c56f90bcd19898855113e5f9e42abc2d",
+ "0x0000000000000000000000000000000000000000000000000000000000003143": "1cfeb8cd5d56e1d202b4ec2851f22e99d6ad89af8a4e001eb014b724d2d64924",
+ "0x000000000000000000000000000000000000000000000000000000000000314d": "ad223cbf591f71ffd29e2f1c676428643313e3a8e8a7d0b0e623181b3047be92",
+ "0x0000000000000000000000000000000000000000000000000000000000003157": "e13f31f026d42cad54958ad2941f133d8bd85ee159f364a633a79472f7843b67",
+ "0x0000000000000000000000000000000000000000000000000000000000003161": "b45099ae3bbe17f4417d7d42951bd4425bce65f1db69a354a64fead61b56306d",
+ "0x000000000000000000000000000000000000000000000000000000000000316b": "9d2b65379c5561a607df4dae8b36eca78818acec4455eb47cfa437a0b1941707",
+ "0x0000000000000000000000000000000000000000000000000000000000003175": "5855b3546d3becda6d5dd78c6440f879340a5734a18b06340576a3ce6a48d9a0",
+ "0x000000000000000000000000000000000000000000000000000000000000317f": "d6a61c76ae029bb5bca86d68422c55e8241d9fd9b616556b375c91fb7224b79e",
+ "0x0000000000000000000000000000000000000000000000000000000000003189": "96ac5006561083735919ae3cc8d0762a9cba2bdefd4a73b8e69f447f689fba31",
+ "0x0000000000000000000000000000000000000000000000000000000000003193": "4ced18f55676b924d39aa7bcd7170bac6ff4fbf00f6a800d1489924c2a091412",
+ "0x000000000000000000000000000000000000000000000000000000000000319d": "c95a6a7efdbefa710a525085bcb57ea2bf2d4ae9ebfcee4be3777cfcc3e534ea",
+ "0x00000000000000000000000000000000000000000000000000000000000031a7": "2b2917b5b755eb6af226e16781382bd22a907c9c7411c34a248af2b5a0439079",
+ "0x00000000000000000000000000000000000000000000000000000000000031b1": "18d5804f2e9ad3f891ecf05e0bfc2142c2a9f7b4de03aebd1cf18067a1ec6490",
+ "0x00000000000000000000000000000000000000000000000000000000000031bb": "b47682f0ce3783700cbe5ffbb95d22c943cc74af12b9c79908c5a43f10677478",
+ "0x00000000000000000000000000000000000000000000000000000000000031c5": "e4b60e5cfb31d238ec412b0d0e3ad9e1eb00e029c2ded4fea89288f900f7db0e",
+ "0x00000000000000000000000000000000000000000000000000000000000031cf": "fc0ea3604298899c10287bba84c02b9ec5d6289c1493e9fc8d58920e4eaef659",
+ "0x00000000000000000000000000000000000000000000000000000000000031d9": "4c3301a70611b34e423cf713bda7f6f75bd2070f909681d3e54e3a9a6d202e5a",
+ "0x00000000000000000000000000000000000000000000000000000000000031e3": "84a5b4e32a62bf3298d846e64b3896dffbbcc1fafb236df3a047b5223577d07b",
+ "0x00000000000000000000000000000000000000000000000000000000000031ed": "ff70b97d34af8e2ae984ada7bc6f21ed294d9b392a903ad8bbb1be8b44083612",
+ "0x00000000000000000000000000000000000000000000000000000000000031f7": "73e186de72ef30e4be4aeebe3eaec84222f8a325d2d07cd0bd1a49f3939915ce",
+ "0x0000000000000000000000000000000000000000000000000000000000003201": "ed185ec518c0459392b274a3d10554e452577d33ecb72910f613941873e61215",
+ "0x000000000000000000000000000000000000000000000000000000000000320b": "5cfbad3e509733bce64e0f6492b3886300758c47a38e9edec4b279074c7966d4",
+ "0x0000000000000000000000000000000000000000000000000000000000003215": "867a7ab4c504e836dd175bd6a00e8489f36edaeda95db9ce4acbf9fb8df28926",
+ "0x000000000000000000000000000000000000000000000000000000000000321f": "0d01993fd605f101c950c68b4cc2b8096ef7d0009395dec6129f86f195eb2217",
+ "0x0000000000000000000000000000000000000000000000000000000000003229": "8e14fd675e72f78bca934e1ffad52b46fd26913063e7e937bce3fa11aed29075",
+ "0x0000000000000000000000000000000000000000000000000000000000003233": "4ec1847e4361c22cdecc67633e244b9e6d04ec103f4019137f9ba1ecc90198f4",
+ "0x000000000000000000000000000000000000000000000000000000000000323d": "ec69e9bbb0184bf0889df50ec7579fa4029651658d639af456a1f6a7543930ef",
+ "0x0000000000000000000000000000000000000000000000000000000000003247": "efdd626048ad0aa6fcf806c7c2ad7b9ae138136f10a3c2001dc5b6c920db1554",
+ "0x0000000000000000000000000000000000000000000000000000000000003251": "551de1e4cafd706535d77625558f8d3898173273b4353143e5e1c7e859848d6b",
+ "0x000000000000000000000000000000000000000000000000000000000000325b": "137efe559a31d9c5468259102cd8634bba72b0d7a0c7d5bcfc449c5f4bdb997a",
+ "0x0000000000000000000000000000000000000000000000000000000000003265": "fb0a1b66acf5f6bc2393564580d74637945891687e61535aae345dca0b0f5e78",
+ "0x000000000000000000000000000000000000000000000000000000000000326f": "96eea2615f9111ee8386319943898f15c50c0120b8f3263fab029123c5fff80c",
+ "0x0000000000000000000000000000000000000000000000000000000000003279": "68725bebed18cd052386fd6af9b398438c01356223c5cc15f49093b92b673eff",
+ "0x0000000000000000000000000000000000000000000000000000000000003283": "e2f1e4557ed105cf3bd8bc51ebaa4446f554dcb38c005619bd9f203f4494f5dd",
+ "0x000000000000000000000000000000000000000000000000000000000000328d": "48ef06d84d5ad34fe56ce62e095a34ea4a903bf597a8640868706af7b4de7288",
+ "0x0000000000000000000000000000000000000000000000000000000000003297": "5c57714b2a85d0d9331ce1ee539a231b33406ec19adcf1d8f4c88ab8c1f4fbae",
+ "0x00000000000000000000000000000000000000000000000000000000000032a1": "204299e7aa8dfe5328a0b863b20b6b4cea53a469d6dc8d4b31c7873848a93f33",
+ "0x00000000000000000000000000000000000000000000000000000000000032ab": "b74eea6df3ce54ee9f069bebb188f4023673f8230081811ab78ce1c9719879e5",
+ "0x00000000000000000000000000000000000000000000000000000000000032b5": "af5624a3927117b6f1055893330bdf07a64e96041241d3731b9315b5cd6d14d7",
+ "0x00000000000000000000000000000000000000000000000000000000000032bf": "c657b0e79c166b6fdb87c67c7fe2b085f52d12c6843b7d6090e8f230d8306cda",
+ "0x00000000000000000000000000000000000000000000000000000000000032c9": "a0e08ceff3f3c426ab2c30881eff2c2fc1edf04b28e1fb38e622648224ffbc6b",
+ "0x00000000000000000000000000000000000000000000000000000000000032d3": "c9792da588df98731dfcbf54a6264082e791540265acc2b3ccca5cbd5c0c16de",
+ "0x00000000000000000000000000000000000000000000000000000000000032dd": "c74f4bb0f324f42c06e7aeacb9446cd5ea500c3b014d5888d467610eafb69297",
+ "0x00000000000000000000000000000000000000000000000000000000000032e7": "1acd960a8e1dc68da5b1db467e80301438300e720a450ab371483252529a409b",
+ "0x00000000000000000000000000000000000000000000000000000000000032f1": "6cef279ba63cbac953676e889e4fe1b040994f044078196a6ec4e6d868b79aa1",
+ "0x00000000000000000000000000000000000000000000000000000000000032fb": "60eb986cb497a0642b684852f009a1da143adb3128764b772daf51f6efaae90a",
+ "0x0000000000000000000000000000000000000000000000000000000000003305": "c50024557485d98123c9d0e728db4fc392091f366e1639e752dd677901681acc",
+ "0x000000000000000000000000000000000000000000000000000000000000330f": "b860632e22f3e4feb0fdf969b4241442eae0ccf08f345a1cc4bb62076a92d93f",
+ "0x0000000000000000000000000000000000000000000000000000000000003319": "21085bf2d264529bd68f206abc87ac741a2b796919eeee6292ed043e36d23edb",
+ "0x0000000000000000000000000000000000000000000000000000000000003323": "80052afb1f39f11c67be59aef7fe6551a74f6b7d155a73e3d91b3a18392120a7",
+ "0x000000000000000000000000000000000000000000000000000000000000332d": "a3b0793132ed37459f24d6376ecfa8827c4b1d42afcd0a8c60f9066f230d7675",
+ "0x0000000000000000000000000000000000000000000000000000000000003337": "e69d353f4bc38681b4be8cd5bbce5eb4e819399688b0b6225b95384b08dcc8b0",
+ "0x0000000000000000000000000000000000000000000000000000000000003341": "221e784d42a121cd1d13d111128fcae99330408511609ca8b987cc6eecafefc4",
+ "0x000000000000000000000000000000000000000000000000000000000000334b": "dcd669ebef3fb5bebc952ce1c87ae4033b13f37d99cf887022428d024f3a3d2e",
+ "0x0000000000000000000000000000000000000000000000000000000000003355": "4dd1eb9319d86a31fd56007317e059808f7a76eead67aecc1f80597344975f46",
+ "0x000000000000000000000000000000000000000000000000000000000000335f": "5e1834c653d853d146db4ab6d17509579497c5f4c2f9004598bcd83172f07a5f",
+ "0x0000000000000000000000000000000000000000000000000000000000003369": "9f78a30e124d21168645b9196d752a63166a1cf7bbbb9342d0b8fee3363ca8de",
+ "0x0000000000000000000000000000000000000000000000000000000000003373": "1f7c1081e4c48cef7d3cb5fd64b05135775f533ae4dabb934ed198c7e97e7dd8",
+ "0x000000000000000000000000000000000000000000000000000000000000337d": "4d40a7ec354a68cf405cc57404d76de768ad71446e8951da553c91b06c7c2d51",
+ "0x0000000000000000000000000000000000000000000000000000000000003387": "f653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c"
+ },
+ "key": "0x37d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e42"
+ },
+ "0x00f691ca9e1403d01344ebbaca0201380cacc99c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7c48e400de1f24b4de94c59068fcd91a028576d13a22f900a7fcbd8f4845bcf4"
+ },
+ "0x0300100f529a704d19736a8714837adbc934db7f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x97b25febb46f44607c87a3498088c605086df207c7ddcd8ee718836a516a9153"
+ },
+ "0x043a718774c572bd8a25adbeb1bfcd5c0256ae11": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4c310e1f5d2f2e03562c4a5c473ae044b9ee19411f07097ced41e85bd99c3364"
+ },
+ "0x046dc70a4eba21473beb6d9460d880b8cfd66613": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4fd7c8d583447b937576211163a542d945ac8c0a6e22d0c42ac54e2cbaff9281"
+ },
+ "0x04b85539570fb9501f65453dbfad410a467becdd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x9e53f0a2ddb430d27f6fffa0a68b5f75db1d68e24113dcca6e33918cdae80846",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000019": "19",
+ "0x000000000000000000000000000000000000000000000000000000000000001a": "1a",
+ "0x000000000000000000000000000000000000000000000000000000000000001b": "1b"
+ },
+ "key": "0xd84f7711be2f8eca69c742153230995afb483855b7c555b08da330139cdb9579"
+ },
+ "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe99460a483f3369006e3edeb356b3653699f246ec71f30568617ebc702058f59"
+ },
+ "0x04d6c0c946716aac894fc1653383543a91faab60": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x98bb9ba48fda7bb8091271ab0e53d7e0022fb1f1fa8fa00814e193c7d4b91eb3"
+ },
+ "0x050c9c302e904c7786b69caa9dd5b27a6e571b72": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x818eaf5adb56c6728889ba66b6980cd66b41199f0007cdd905ae739405e3c630",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000077": "77",
+ "0x0000000000000000000000000000000000000000000000000000000000000078": "78",
+ "0x0000000000000000000000000000000000000000000000000000000000000079": "79"
+ },
+ "key": "0xc3ac56e9e7f2f2c2c089e966d1b83414951586c3afeb86300531dfa350e38929"
+ },
+ "0x06f647b157b8557a12979ba04cf5ba222b9747cf": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaf38e0e6a4a4005507b5d3e9470e8ccc0273b74b6971f768cbdf85abeab8a95b"
+ },
+ "0x075198bfe61765d35f990debe90959d438a943ce": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1d38ada74301c31f3fd7d92dd5ce52dc37ae633e82ac29c4ef18dfc141298e26"
+ },
+ "0x075db7ab5778cd5491d3ed7ab64c1ec0818148f3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf84223f460140ad56af9836cfa6c1c58c1397abf599c214689bc881066020ff7"
+ },
+ "0x08037e79bb41c0f1eda6751f0dabb5293ca2d5bf": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcd07379b0120ad9a9c7fa47e77190be321ab107670f3115fec485bebb467307d"
+ },
+ "0x087d80f7f182dd44f184aa86ca34488853ebcc04": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x867bc89cf8d5b39f1712fbc77414bbd93012af454c226dcee0fb34ccc0017498"
+ },
+ "0x08d3b23dbfe8ef7965a8b5e4d9c21feddbc11491": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x9a4a33f978d84e0aceb3ac3670c2e2df6c8ae27c189a96ed00b806d10ed7b4ee",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001c6": "01c6",
+ "0x00000000000000000000000000000000000000000000000000000000000001c7": "01c7",
+ "0x00000000000000000000000000000000000000000000000000000000000001c8": "01c8"
+ },
+ "key": "0x792cc9f20a61c16646d5b6136693e7789549adb7d8e35503d0004130ea6528b0"
+ },
+ "0x09b9c1875399cd724b1017f155a193713cb23732": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x47fa48e25d3669a9bb190c59938f4be49de2d083696eb939c3b4072ec67e43b1",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000005e": "5e",
+ "0x000000000000000000000000000000000000000000000000000000000000005f": "5f",
+ "0x0000000000000000000000000000000000000000000000000000000000000060": "60"
+ },
+ "key": "0x23ddaac09188c12e5d88009afa4a34041175c5531f45be53f1560a1cbfec4e8a"
+ },
+ "0x0a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc7fc033fe9f00d24cb9c479ddc0598e592737c305263d088001d7419d16feffa"
+ },
+ "0x0badc617ca1bcb1cb1d5272f64b168cbf0e8f86f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xca39f5f4ee3c6b33efe7bc485439f97f9dc62f65852c7a1cdf54fab1e3b70429",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000002d": "2d",
+ "0x000000000000000000000000000000000000000000000000000000000000002e": "2e",
+ "0x000000000000000000000000000000000000000000000000000000000000002f": "2f"
+ },
+ "key": "0xc250f30c01f4b7910c2eb8cdcd697cf493f6417bb2ed61d637d625a85a400912"
+ },
+ "0x0c2c51a0990aee1d73c1228de158688341557508": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x28f25652ec67d8df6a2e33730e5d0983443e3f759792a0128c06756e8eb6c37f"
+ },
+ "0x0d336bc3778662a1252d29a6f7216055f7a582bf": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa5a91cf9e815fb55df14b3ee8c1325a988cb3b6dd34796c901385c3cc2992073",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000013f": "013f",
+ "0x0000000000000000000000000000000000000000000000000000000000000140": "0140",
+ "0x0000000000000000000000000000000000000000000000000000000000000141": "0141"
+ },
+ "key": "0x86a73e3c668eb065ecac3402c6dc912e8eb886788ea147c770f119dcd30780c6"
+ },
+ "0x0e4aea2bbb2ae557728f2661ee3639360f1d787a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x74ed78eb16016d7ff3a173ab1bbcee9daa8e358a9d6c9be5e84ba6f4a34cf96a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000d1": "d1",
+ "0x00000000000000000000000000000000000000000000000000000000000000d2": "d2",
+ "0x00000000000000000000000000000000000000000000000000000000000000d3": "d3"
+ },
+ "key": "0x517bd5fbe28e4368b0b9fcba13d5e81fb51babdf4ed63bd83885235ee67a8fa0"
+ },
+ "0x0ef32dec5f88a96c2eb042126e8ab982406e0267": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x181abdd5e212171007e085fdc284a84d42d5bfc160960d881ccb6a10005ff089"
+ },
+ "0x0ef96a52f4510f82b049ba991c401a8f5eb823e5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x59312f89c13e9e24c1cb8b103aa39a9b2800348d97a92c2c9e2a78fa02b70025"
+ },
+ "0x0f228c3ba41142e702ee7306859026c99d3d2df5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xedd9b1f966f1dfe50234523b479a45e95a1a8ec4a057ba5bfa7b69a13768197c"
+ },
+ "0x0fdcca8fde6d69ecbc9bfadb056ecf62d1966370": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x493f90435402df0907019bffc6dd25a17ce4acd6eb6077ef94c1626f0d77c9f0",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000f9": "f9",
+ "0x00000000000000000000000000000000000000000000000000000000000000fa": "fa",
+ "0x00000000000000000000000000000000000000000000000000000000000000fb": "fb"
+ },
+ "key": "0xfb5a31c5cfd33dce2c80a30c5efc28e5f4025624adcc2205a2504a78c57bdd1c"
+ },
+ "0x0fe037febcc3adf9185b4e2ad4ea43c125f05049": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb7d9d175039df1ba52c734547844f8805252893c029f7dbba9a63f8bce3ee306"
+ },
+ "0x0fed138ec52bab88db6c068df9125936c7c3e11b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x66eb16071ba379bf0c632fcb52f9175a656bef62adf0bef5349a7f5a6aad5d88",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000176": "0176",
+ "0x0000000000000000000000000000000000000000000000000000000000000177": "0177",
+ "0x0000000000000000000000000000000000000000000000000000000000000178": "0178"
+ },
+ "key": "0x255ec86eac03ba59f6dfcaa02128adbb22c561ae0c49e9e62e4fff363750626e"
+ },
+ "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9d42947ac5e61285567f65d4b400d90343dbd3192534c4c1f9d941c04f48f17c"
+ },
+ "0x1037044fabf0421617c47c74681d7cc9c59f136c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2290ea88cc63f09ab5e8c989a67e2e06613311801e39c84aae3badd8bb38409c"
+ },
+ "0x1042d41ee3def49e70df4e6c2be307b8015111e5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xdf3c1bfab8f7e70a8edf94792f91e4b6b2c2aa61caf687e4f6cb689d180adb80",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000095": "95",
+ "0x0000000000000000000000000000000000000000000000000000000000000096": "96",
+ "0x0000000000000000000000000000000000000000000000000000000000000097": "97"
+ },
+ "key": "0xc0ce77c6a355e57b89cca643e70450612c0744c9f0f8bf7dee51d6633dc850b1"
+ },
+ "0x104eb07eb9517a895828ab01a3595d3b94c766d5": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfab4c6889992a3f4e96b005dfd851021e9e1ec2631a7ccd2a001433e35077968"
+ },
+ "0x1219c38638722b91f3a909f930d3acc16e309804": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd63070208c85e91c4c8c942cf52c416f0f3004c392a15f579350168f178dba2e"
+ },
+ "0x132432ce1ce64304f1d145eba1772f6edd6cdd17": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x729953a43ed6c913df957172680a17e5735143ad767bda8f58ac84ec62fbec5e"
+ },
+ "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x99e56541f21039c9b7c63655333841a3415de0d27b79d18ade9ec7ecde7a1139"
+ },
+ "0x14e46043e63d0e3cdcf2530519f4cfaf35058cb2": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9feaf0bd45df0fbf327c964c243b2fbc2f0a3cb48fedfeea1ae87ac1e66bc02f"
+ },
+ "0x1534b43c6dfa3695446aaf2aa07d123132cceceb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2a248c1755e977920284c8054fceeb20530dc07cd8bbe876f3ce02000818cc3a"
+ },
+ "0x15af6900147a8730b5ce3e1db6333f33f64ebb2c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5264e880ecf7b80afda6cc2a151bac470601ff8e376af91aaf913a36a30c4009"
+ },
+ "0x16032a66fc011dab75416d2449fe1a3d5f4319d8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe3c79e424fd3a7e5bf8e0426383abd518604272fda87ecd94e1633d36f55bbb6"
+ },
+ "0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xda81833ff053aff243d305449775c3fb1bd7f62c4a3c95dc9fb91b85e032faee"
+ },
+ "0x17333b15b4a5afd16cac55a104b554fc63cc8731": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4ceaf2371fcfb54a4d8bc1c804d90b06b3c32c9f17112b57c29b30a25cf8ca12"
+ },
+ "0x17b917f9d79d922b33e41582984712e32b3ad366": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x944f095afbd1383e5d0f91ef02895d398f4f76fdb6d86adf4765f25bdc304f5f",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000081": "81",
+ "0x0000000000000000000000000000000000000000000000000000000000000082": "82",
+ "0x0000000000000000000000000000000000000000000000000000000000000083": "83"
+ },
+ "key": "0x13cfc46f6bdb7a1c30448d41880d061c3b8d36c55a29f1c0c8d95a8e882b8c25"
+ },
+ "0x18291b5f568e45ef0f16709b20c810e08750791f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x315ccc15883d06b4e743f8252c999bf1ee994583ff6114d89c0f3ddee828302b"
+ },
+ "0x189f40034be7a199f1fa9891668ee3ab6049f82d": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6225e8f52719d564e8217b5f5260b1d1aac2bcb959e54bc60c5f479116c321b8"
+ },
+ "0x18ac3e7343f016890c510e93f935261169d9e3f5": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xeba984db32038d7f4d71859a9a2fc6e19dde2e23f34b7cedf0c4bf228c319f17"
+ },
+ "0x19041ad672875015bc4041c24b581eafc0869aab": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfc8d513d1615c763865b984ea9c381032c14a983f80e5b2bd90b20b518329ed7"
+ },
+ "0x19129f84d987b13468846f822882dba0c50ca07d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2b8d12301a8af18405b3c826b6edcc60e8e034810f00716ca48bebb84c4ce7ab"
+ },
+ "0x194e49be24c1a94159f127aa9257ded12a0027db": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe0a3d3b839fca0f54745d0c50a048e424c9259f063b7416410a4422eeb7f837e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000180": "0180",
+ "0x0000000000000000000000000000000000000000000000000000000000000181": "0181",
+ "0x0000000000000000000000000000000000000000000000000000000000000182": "0182"
+ },
+ "key": "0xd57eafe6d4c5b91fe7114e199318ab640e55d67a1e9e3c7833253808b7dca75f"
+ },
+ "0x19581e27de7ced00ff1ce50b2047e7a567c76b1c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7bac5af423cb5e417fa6c103c7cb9777e80660ce3735ca830c238b0d41610186"
+ },
+ "0x196d4a4c50eb47562596429fdecb4e3ac6b2a5fd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4e258aa445a0e2a8704cbc57bbe32b859a502cd6f99190162236300fabd86c4a"
+ },
+ "0x1a0eae9b9214d9269a4cff4982c45a67f4ca63aa": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x5622801b1011de8403e44308bbf89a5809b7ad6586268cd72164523587f9b0e4",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000007c": "7c",
+ "0x000000000000000000000000000000000000000000000000000000000000007d": "7d",
+ "0x000000000000000000000000000000000000000000000000000000000000007e": "7e"
+ },
+ "key": "0x6a2c8498657ae4f0f7b1a02492c554f7f8a077e454550727890188f7423ba014"
+ },
+ "0x1ae59138ad95812304b117ee7b0d502bcb885af5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf164775805f47d8970d3282188009d4d7a2da1574fe97e5d7bc9836a2eed1d5b"
+ },
+ "0x1b16b1df538ba12dc3f97edbb85caa7050d46c14": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8ee17a1ec4bae15d8650323b996c55d5fa11a14ceec17ff1d77d725183904914"
+ },
+ "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa9fd2e3a6de5a9da5badd719bd6e048acefa6d29399d8a99e19fd9626805b60b"
+ },
+ "0x1c972398125398a3665f212930758ae9518a8c94": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5d97d758e8800d37b6d452a1b1812d0afedba11f3411a17a8d51ee13a38d73f0"
+ },
+ "0x1e345d32d0864f75b16bde837543aa44fac35935": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xd91acf305934a60c960a93fb00f927ec79308b8a919d2449faede722c2324cb3",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000153": "0153",
+ "0x0000000000000000000000000000000000000000000000000000000000000154": "0154",
+ "0x0000000000000000000000000000000000000000000000000000000000000155": "0155"
+ },
+ "key": "0x961508ac3c93b30ee9a5a34a862c9fe1659e570546ac6c2e35da20f6d2bb5393"
+ },
+ "0x1e8ce8258fb47f55bf2c1473acb89a10074b9d0e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfb2ab315988de92dcf6ba848e756676265b56e4b84778a2c955fb2b3c848c51c"
+ },
+ "0x1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7963685967117ffb6fd019663dc9e782ebb1234a38501bffc2eb5380f8dc303b"
+ },
+ "0x1f5746736c7741ae3e8fa0c6e947cade81559a86": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4e5bab4ebd077c3bbd8239995455989ea2e95427ddeed47d0618d9773332bb05"
+ },
+ "0x1f5bde34b4afc686f136c7a3cb6ec376f7357759": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc3791fc487a84f3731eb5a8129a7e26f357089971657813b48a821f5582514b3"
+ },
+ "0x2143e52a9d8ad4c55c8fdda755f4889e3e3e7721": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd9fa858992bc92386a7cebcd748eedd602bf432cb4b31607566bc92b85179624"
+ },
+ "0x2144780b7d04d82239c6570f84ab66376b63dfc9": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x59936c15c454933ebc4989afa77e350f7640301b07341aead5f1b2668eeb1dad",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000db": "db",
+ "0x00000000000000000000000000000000000000000000000000000000000000dc": "dc",
+ "0x00000000000000000000000000000000000000000000000000000000000000dd": "dd"
+ },
+ "key": "0xd37b6f5e5f0fa6a1b3fd15c9b3cf0fb595ba245ab912ad8059e672fa55f061b8"
+ },
+ "0x22694f8f2d0c62f63a25bd0057a80b89084c3b47": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2369a492b6cddcc0218617a060b40df0e7dda26abe48ba4e4108c532d3f2b84f"
+ },
+ "0x22b3f17adeb5f2ec22135d275fcc6e29f4989401": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa3abdaefbb886078dc6c5c72e4bc8d12e117dbbd588236c3fa7e0c69420eb24a"
+ },
+ "0x23262ad5ae496588bd793910b55ccf178fbd73f9": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x3437803101a8040aca273fb734d7965a87f823ff1ef78c7edcaad358eb98dee3",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000171": "0171",
+ "0x0000000000000000000000000000000000000000000000000000000000000172": "0172",
+ "0x0000000000000000000000000000000000000000000000000000000000000173": "0173"
+ },
+ "key": "0xd8489fd0ce5e1806b24d1a7ce0e4ba8f0856b87696456539fcbb625a9bed2ccc"
+ },
+ "0x23b17315554bd2928c1f86dd526f7ee065a9607d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x12e394ad62e51261b4b95c431496e46a39055d7ada7dbf243f938b6d79054630"
+ },
+ "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd72e318c1cea7baf503950c9b1bd67cf7caf2f663061fcde48d379047a38d075"
+ },
+ "0x23e6931c964e77b02506b08ebf115bad0e1eca66": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x174f1a19ff1d9ef72d0988653f31074cb59e2cf37cd9d2992c7b0dd3d77d84f9"
+ },
+ "0x24255ef5d941493b9978f3aabb0ed07d084ade19": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7583557e4e3918c95965fb610dc1424976c0eee606151b6dfc13640e69e5cb15"
+ },
+ "0x245843abef9e72e7efac30138a994bf6301e7e1d": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfe6e594c507ec0ac14917f7a8032f83cd0c3c58b461d459b822190290852c0e1"
+ },
+ "0x25261a7e8395b6e798e9b411c962fccc0fb31e38": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1017b10a7cc3732d729fe1f71ced25e5b7bc73dc62ca61309a8c7e5ac0af2f72"
+ },
+ "0x2553ec67bc75f75d7de13db86b14290f0f76e342": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x8078f3259d8199b7ca39d51e35d5b58d71ff148606731060386d323c5d19182c",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000185": "0185",
+ "0x0000000000000000000000000000000000000000000000000000000000000186": "0186",
+ "0x0000000000000000000000000000000000000000000000000000000000000187": "0187"
+ },
+ "key": "0x0f30822f90f33f1d1ba6d1521a00935630d2c81ab12fa03d4a0f4915033134f3"
+ },
+ "0x2604439a795970de2047e339293a450c0565f625": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8678559b30b321b0f0420a4a3e8cecfde90c6e56766b78c1723062c93c1f041f"
+ },
+ "0x26704bf05b1da795939788ef05c8804dcf4b9009": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xd60ee4ad5abbe759622fca5c536109b11e85aa2b48c0be2aebf01df597e74dba",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000015d": "015d",
+ "0x000000000000000000000000000000000000000000000000000000000000015e": "015e",
+ "0x000000000000000000000000000000000000000000000000000000000000015f": "015f"
+ },
+ "key": "0xd1691564c6a5ab1391f0495634e749b9782de33756b6a058f4a9536c1b37bca6"
+ },
+ "0x2727d12b98783b2c3641b5672bcfcdf007971d28": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x59739ba3b156eb78f8bbb14bbf3dacdebfde95140f586db66f72e3117b94bb67",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000112": "0112",
+ "0x0000000000000000000000000000000000000000000000000000000000000113": "0113",
+ "0x0000000000000000000000000000000000000000000000000000000000000114": "0114"
+ },
+ "key": "0x88bf4121c2d189670cb4d0a16e68bdf06246034fd0a59d0d46fb5cec0209831e"
+ },
+ "0x2795044ce0f83f718bc79c5f2add1e52521978df": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xee9186a01e5e1122b61223b0e6acc6a069c9dcdb7307b0a296421272275f821b"
+ },
+ "0x27952171c7fcdf0ddc765ab4f4e1c537cb29e5e5": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0a93a7231976ad485379a3b66c2d8983ba0b2ca87abaf0ca44836b2a06a2b102"
+ },
+ "0x27abdeddfe8503496adeb623466caa47da5f63ab": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x482814ea8f103c39dcf6ba7e75df37145bde813964d82e81e5d7e3747b95303d"
+ },
+ "0x281c93990bac2c69cf372c9a3b66c406c86cca82": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x81c0c51e15c9679ef12d02729c09db84220ba007efe7ced37a57132f6f0e83c9"
+ },
+ "0x2847213288f0988543a76512fab09684131809d9": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe1b86a365b0f1583a07fc014602efc3f7dedfa90c66e738e9850719d34ac194e"
+ },
+ "0x28969cdfa74a12c82f3bad960b0b000aca2ac329": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x96d7104053877823b058fd9248e0bba2a540328e52ffad9bb18805e89ff579dc"
+ },
+ "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5e88e876a3af177e6daafe173b67f186a53f1771a663747f26b278c5acb4c219"
+ },
+ "0x2aac4746638ae1457010747a5b0fd2380a388f4f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x5a82aff126ffebff76002b1e4de03c40ba494b81cb3fbc528f23e4be35a9afe6",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000004b": "4b",
+ "0x000000000000000000000000000000000000000000000000000000000000004c": "4c",
+ "0x000000000000000000000000000000000000000000000000000000000000004d": "4d"
+ },
+ "key": "0x96c43ef9dce3410b78df97be69e7ccef8ed40d6e5bfe6582ea4cd7d577aa4569"
+ },
+ "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x303f57a0355c50bf1a0e1cf0fa8f9bdbc8d443b70f2ad93ac1c6b9c1d1fe29a2"
+ },
+ "0x2c0cd3c60f41d56ed7664dbce39630395614bf4b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x92d0f0954f4ec68bd32163a2bd7bc69f933c7cdbfc6f3d2457e065f841666b1c"
+ },
+ "0x2c1287779024c3a2f0924b54816d79b7e378907d": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x09d6e6745d272389182a510994e2b54d14b731fac96b9c9ef434bc1924315371"
+ },
+ "0x2c582db705c5721bb3ba59f4ec8e44fb4ef6b920": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe02ec497b66cb57679eb01de1bed2ad385a3d18130441a9d337bd14897e85d39"
+ },
+ "0x2d389075be5be9f2246ad654ce152cf05990b209": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa9233a729f0468c9c309c48b82934c99ba1fd18447947b3bc0621adb7a5fc643"
+ },
+ "0x2d711642b726b04401627ca9fbac32f5c8530fb1": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfe2149c5c256a5eb2578c013d33e3af6a87a514965c7ddf4a8131e2d978f09f9"
+ },
+ "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf33a7b66489679fa665dbfb4e6dd4b673495f853850eedc81d5f28bd2f4bd3b5"
+ },
+ "0x2e5f413fd8d378ed081a76e1468dad8cbf6e9ed5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe69f40f00148bf0d4dfa28b3f3f5a0297790555eca01a00e49517c6645096a6c"
+ },
+ "0x2eb6db4e06119ab31a3acf4f406ccbaa85e39c66": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaeaf19d38b69be4fb41cc89e4888708daa6b9b1c3f519fa28fe9a0da70cd8697"
+ },
+ "0x2f01c1c8c735a9a1b89898d3f14bbf61c91bf0fd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd2f394b4549b085fb9b9a8b313a874ea660808a4323ab2598ee15ddd1eb7e897"
+ },
+ "0x2fb64110da9389ce8567938a78f21b79222332f9": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x415ded122ff7b6fe5862f5c443ea0375e372862b9001c5fe527d276a3a420280"
+ },
+ "0x2fc7b26c1fd501c57e57db3e876dc6ae7af6979b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x3d20fedd270b3771706fe00a580a155439be57e8d550762def10906e83ed58bb",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000009f": "9f",
+ "0x00000000000000000000000000000000000000000000000000000000000000a0": "a0",
+ "0x00000000000000000000000000000000000000000000000000000000000000a1": "a1"
+ },
+ "key": "0xb9cddc73dfdacd009e55f27bdfd1cd37eef022ded5ce686ab0ffe890e6bf311e"
+ },
+ "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe1eb1e18ae510d0066d60db5c2752e8c33604d4da24c38d2bda07c0cb6ad19e4"
+ },
+ "0x30c72b4fb390ff1d387821e210f3ab04fbe86d13": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xdf97f94bc47471870606f626fb7a0b42eed2d45fcc84dc1200ce62f7831da990",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000d6": "d6",
+ "0x00000000000000000000000000000000000000000000000000000000000000d7": "d7",
+ "0x00000000000000000000000000000000000000000000000000000000000000d8": "d8"
+ },
+ "key": "0x005e94bf632e80cde11add7d3447cd4ca93a5f2205d9874261484ae180718bd6"
+ },
+ "0x311df588ca5f412f970891e4cc3ac23648968ca2": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x974a4800ec4c0e998f581c6ee8c3972530989e97a179c6b2d40b8710c036e7b1"
+ },
+ "0x312e8fca5ac7dfc591031831bff6fede6ecf12a8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x64bfba8a4688bdee41c4b998e101567b8b56fea53d30ab85393f2d5b70c5da90"
+ },
+ "0x32c417b98c3d9bdd37550c0070310526347b4648": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x80cd4a7b601d4ba0cb09e527a246c2b5dd25b6dbf862ac4e87c6b189bfce82d7"
+ },
+ "0x33afd8244c9c1a37f5bddb3254cd08779a196458": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x210ce6d692a21d75de3764b6c0356c63a51550ebec2c01f56c154c24b1cf8888"
+ },
+ "0x33fc6e8ad066231eb5527d1a39214c1eb390985d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x87e33f70e1dd3c6ff68e3b71757d697fbeb20daae7a3cc8a7b1b3aa894592c50"
+ },
+ "0x360671abc40afd33ae0091e87e589fc320bf9e3d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x12c1bb3dddf0f06f62d70ed5b7f7db7d89b591b3f23a838062631c4809c37196"
+ },
+ "0x3632d1763078069ca77b90e27061147a3b17ddc3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0463e52cda557221b0b66bd7285b043071df4c2ab146260f4e010970f3a0cccf"
+ },
+ "0x368b766f1e4d7bf437d2a709577a5210a99002b6": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4845aac9f26fcd628b39b83d1ccb5c554450b9666b66f83aa93a1523f4db0ab6"
+ },
+ "0x36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a43": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcac96145454c46255fccca35343d9505164dabe319c17d81fda93cf1171e4c6e"
+ },
+ "0x38d0bd409abe8d78f9f0e0a03671e44e81c41c27": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x23a888c0a464ce461651fc1be2cfa0cb6ba4d1b125abe5b447eeadf9c5adf1f1",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000167": "0167",
+ "0x0000000000000000000000000000000000000000000000000000000000000168": "0168",
+ "0x0000000000000000000000000000000000000000000000000000000000000169": "0169"
+ },
+ "key": "0xb58e67c536550fdf7140c8333ca62128df469a7270b16d528bc778909e0ac9a5"
+ },
+ "0x3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x878040f46b1b4a065e6b82abd35421eb69eededc0c9598b82e3587ae47c8a651"
+ },
+ "0x3bcc2d6d48ffeade5ac5af3ee7acd7875082e50a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb5bca5e9ccef948c2431372315acc3b96e098d0e962b0c99d634a0475b670dc3"
+ },
+ "0x3c204ccddfebae334988367b5cf372387dc49ebd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xc7bf2b34294065afb9a2c15f906cba1f7a1a9f0da34ea9c46603b52cae9028ec",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000194": "0194",
+ "0x0000000000000000000000000000000000000000000000000000000000000195": "0195",
+ "0x0000000000000000000000000000000000000000000000000000000000000196": "0196"
+ },
+ "key": "0x5ec55391e89ac4c3cf9e61801cd13609e8757ab6ed08687237b789f666ea781b"
+ },
+ "0x3c2572436de9a5f3c450071e391c8a9410ba517d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xbfba1bc2ac42655f5a97450be62b9430822232f1ce4998eaf5239b0c243b2b84",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000090": "90",
+ "0x0000000000000000000000000000000000000000000000000000000000000091": "91",
+ "0x0000000000000000000000000000000000000000000000000000000000000092": "92"
+ },
+ "key": "0x606059a65065e5f41347f38754e6ddb99b2d709fbff259343d399a4f9832b48f"
+ },
+ "0x3c5c4713708c72b519144ba8e595a8865505000d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x52d6d2913ae44bca11b5a116021db97c91a13e385ed48ba06628e74201231dba",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001c1": "01c1",
+ "0x00000000000000000000000000000000000000000000000000000000000001c2": "01c2",
+ "0x00000000000000000000000000000000000000000000000000000000000001c3": "01c3"
+ },
+ "key": "0x37ddfcbcb4b2498578f90e0fcfef9965dcde4d4dfabe2f2836d2257faa169947"
+ },
+ "0x3cf2e7052ebd484a8d6fbca579ddb3cf920de9d3": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa95c88d7dc0f2373287c3b2407ba8e7419063833c424b06d8bb3b29181bb632e"
+ },
+ "0x3ee253436fc50e5a136ee01489a318afe2bbd572": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xc57604a461c94ecdac12dbb706a52b32913d72253baffb8906e742724ae12449",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001b2": "01b2",
+ "0x00000000000000000000000000000000000000000000000000000000000001b3": "01b3",
+ "0x00000000000000000000000000000000000000000000000000000000000001b4": "01b4"
+ },
+ "key": "0xaf7c37d08a73483eff9ef5054477fb5d836a184aa07c3edb4409b9eb22dd56ca"
+ },
+ "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb40cc623b26a22203675787ca05b3be2c2af34b6b565bab95d43e7057e458684"
+ },
+ "0x3f79bb7b435b05321651daefd374cdc681dc06fa": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8c7bfaa19ea367dec5272872114c46802724a27d9b67ea3eed85431df664664e"
+ },
+ "0x3fba9ae304c21d19f50c23db133073f4f9665fc1": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0b564e4a0203cbcec8301709a7449e2e7371910778df64c89f48507390f2d129"
+ },
+ "0x402f57de890877def439a753fcc0c37ac7808ef5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5c20f6ee05edbb60beeab752d87412b2f6e12c8feefa2079e6bd989f814ed4da"
+ },
+ "0x40b7ab67fb92dbcb4ff4e39e1155cad2fa066523": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd352b05571154d9a2061143fe6df190a740a2d321c59eb94a54acb7f3054e489"
+ },
+ "0x414a21e525a759e3ffeb22556be6348a92d5a13e": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x15293aec87177f6c88f58bc51274ba75f1331f5cb94f0c973b1deab8b3524dfe"
+ },
+ "0x417fe11f58b6a2d089826b60722fbed1d2db96dd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd5e252ab2fba10107258010f154445cf7dffc42b7d8c5476de9a7adb533d73f1"
+ },
+ "0x41b45640640c98c953feef23468e0d275515f82f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x82b326641825378faa11c641c916f2e22c01080f487de0463e30d5e32b960f97",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000013a": "013a",
+ "0x000000000000000000000000000000000000000000000000000000000000013b": "013b",
+ "0x000000000000000000000000000000000000000000000000000000000000013c": "013c"
+ },
+ "key": "0xc2406cbd93e511ef493ac81ebe2b6a3fbecd05a3ba52d82a23a88eeb9d8604f0"
+ },
+ "0x426fcdc383c8becb38926ec0569ec4a810105fab": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6bd9fb206b22c76b4f9630248940855b842c684db89adff0eb9371846ea625a9"
+ },
+ "0x4340ee1b812acb40a1eb561c019c327b243b92df": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa13bfef92e05edee891599aa5e447ff2baa1708d9a6473a04ef66ab94f2a11e4"
+ },
+ "0x44bd7ae60f478fae1061e11a7739f4b94d1daf91": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb66092bc3624d84ff94ee42b097e846baf6142197d2c31245734d56a275c8eb9"
+ },
+ "0x452705f08c621987b14d5f729ca81829041f6373": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xac7183ebb421005a660509b070d3d47fc4e134cb7379c31dc35dc03ebd02e1cf"
+ },
+ "0x45dcb3e20af2d8ba583d774404ee8fedcd97672b": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x465311df0bf146d43750ed7d11b0451b5f6d5bfc69b8a216ef2f1c79c93cd848"
+ },
+ "0x45f83d17e10b34fca01eb8f4454dac34a777d940": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6dc09fdec00aa9a30dd8db984406a33e3ca15e35222a74773071207a5e56d2c2"
+ },
+ "0x469542b3ece7ae501372a11c673d7627294a85ca": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6dbe5551f50400859d14228606bf221beff07238bfa3866454304abb572f9512"
+ },
+ "0x469dacecdef1d68cb354c4a5c015df7cb6d655bf": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8b76305d3f00d33f77bd41496b4144fd3d113a2ec032983bd5830a8b73f61cf0"
+ },
+ "0x46b61db0aac95a332cecadad86e52531e578cf1f": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5677600b2af87d21fdab2ac8ed39bd1be2f790c04600de0400c1989040d9879c"
+ },
+ "0x478508483cbb05defd7dcdac355dadf06282a6f2": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5fc13d7452287b5a8e3c3be9e4f9057b5c2dd82aeaff4ed892c96fc944ec31e7"
+ },
+ "0x47ce7195b6d53aaa737ff17d57db20d0d4874ef1": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x3d0e2ba537f35941068709450f25fee45aaf4dc6ae2ed22ad12e0743ac7c54a7",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000108": "0108",
+ "0x0000000000000000000000000000000000000000000000000000000000000109": "0109",
+ "0x000000000000000000000000000000000000000000000000000000000000010a": "010a"
+ },
+ "key": "0x0579e46a5ed8a88504ac7d579b12eb346fbe4fd7e281bdd226b891f8abed4789"
+ },
+ "0x47dc540c94ceb704a23875c11273e16bb0b8a87a": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x025f478d53bf78add6fa3708d9e061d59bfe14b21329b2a4cf1156d4f81b3d2d"
+ },
+ "0x47e642c9a2f80499964cfda089e0b1f52ed0f57d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x05f6de281d8c2b5d98e8e01cd529bd76416b248caf11e0552047c5f1d516aab6"
+ },
+ "0x4816ce9dd68c07ab1e12b5ddc4dbef38792751c5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x93843d6fa1fe5709a3035573f61cc06832f0377544d16d3a0725e78a0fa0267c"
+ },
+ "0x48701721ec0115f04bc7404058f6c0f386946e09": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x12be3bf1f9b1dab5f908ca964115bee3bcff5371f84ede45bc60591b21117c51"
+ },
+ "0x494d799e953876ac6022c3f7da5e0f3c04b549be": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x04d9aa4f67f8b24d70a0ffd757e82456d9184113106b7d9e8eb6c3e8a8df27ee"
+ },
+ "0x4a0f1452281bcec5bd90c3dce6162a5995bfe9df": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5c1d92594d6377fe6423257781b382f94dffcde4fadbf571aa328f6eb18f8fcd"
+ },
+ "0x4a64a107f0cb32536e5bce6c98c393db21cca7f4": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf16522fc36907ee1e9948240b0c1d1d105a75cc63b71006f16c20d79ad469bd7"
+ },
+ "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2116ab29b4cb8547af547fe472b7ce30713f234ed49cb1801ea6d3cf9c796d57"
+ },
+ "0x4b227777d4dd1fc61c6f884f48641d02b4d121d3": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x246cc8a2b79a30ec71390d829d0cb37cce1b953e89cb14deae4945526714a71c"
+ },
+ "0x4ba91e785d2361ddb198bcd71d6038305021a9b8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x99ce1680f73f2adfa8e6bed135baa3360e3d17f185521918f9341fc236526321"
+ },
+ "0x4bfa260a661d68110a7a0a45264d2d43af9727de": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6f358b4e903d31fdd5c05cddaa174296bb30b6b2f72f1ff6410e6c1069198989"
+ },
+ "0x4dde844b71bcdf95512fb4dc94e84fb67b512ed8": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5602444769b5fd1ddfca48e3c38f2ecad326fe2433f22b90f6566a38496bd426"
+ },
+ "0x4f362f9093bb8e7012f466224ff1237c0746d8c8": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcb6f450b4720c6b36d3a12271e35ace27f1d527d46b073771541ad39cc59398d"
+ },
+ "0x4f3e7da249f34e3cc8b261a7dc5b2d8e1cd85b78": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4d79fea6c7fef10cb0b5a8b3d85b66836a131bec0b04d891864e6fdb9794af75"
+ },
+ "0x4fb733bedb74fec8d65bedf056b935189a289e92": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa02abeb418f26179beafd96457bda8c690c6b1f3fbabac392d0920863edddbc6"
+ },
+ "0x4fffb6fbd0372228cb5e4d1f033a29f30cb668c8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xcd3e75299e967d5f88d306be905a134343b224d3fd5a861b1a690de0e2dfe1ba",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000b3": "b3",
+ "0x00000000000000000000000000000000000000000000000000000000000000b4": "b4",
+ "0x00000000000000000000000000000000000000000000000000000000000000b5": "b5"
+ },
+ "key": "0xf19ee923ed66b7b9264c2644aa20e5268a251b4914ca81b1dffee96ecb074cb1"
+ },
+ "0x50996999ff63a9a1a07da880af8f8c745a7fe72c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0e57ffa6cc6cbd96c1400150417dd9b30d958c58f63c36230a90a02b076f78b5"
+ },
+ "0x5123198d8a827fe0c788c409e7d2068afde64339": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa15773c9bfabef49e9825460ed95bf67b22b67d7806c840e0eb546d73c424768"
+ },
+ "0x526e1ff4cddb5033849a114c54eb71a176f6440c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x834718111121e2058fdb90a51f448028071857e11fbd55d43256174df56af01a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000c7": "c7",
+ "0x00000000000000000000000000000000000000000000000000000000000000c8": "c8",
+ "0x00000000000000000000000000000000000000000000000000000000000000c9": "c9"
+ },
+ "key": "0xb3a33a7f35ca5d08552516f58e9f76219716f9930a3a11ce9ae5db3e7a81445d"
+ },
+ "0x5371ac01baa0b8aa9cbfcd36a49e0b5f7fb7109d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x385b84d27059a3c78e7ea63a691eeb9c5376f77af11336762f8c18882ff7471a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000028": "28",
+ "0x0000000000000000000000000000000000000000000000000000000000000029": "29",
+ "0x000000000000000000000000000000000000000000000000000000000000002a": "2a"
+ },
+ "key": "0x7a08bb8417e6b18da3ba926568f1022c15553b2b0f1a32f2fd9e5a605469e54f"
+ },
+ "0x54314225e5efd5b8283d6ec2f7a03d5a92106374": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcade985c7fb6d371d0c7f7cb40178e7873d623eadcc37545798ec33a04bb2173"
+ },
+ "0x549abf1ae8db6de0d131a7b2b094c813ec1c6731": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x73bffc68a947fa19b7becd45661d22c870fac8dbf2b25703e1bdab5367f29543",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000086": "86",
+ "0x0000000000000000000000000000000000000000000000000000000000000087": "87",
+ "0x0000000000000000000000000000000000000000000000000000000000000088": "88"
+ },
+ "key": "0x910fb8b22867289cb57531ad39070ef8dbdbbe7aee941886a0e9f572b63ae9ee"
+ },
+ "0x5502b2da1a3a08ad258aa08c0c6e0312cf047e64": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xf73591e791af4c7c5fa039c33dd9d169cab14b1d9b0ca78bcc4e740d553b1acf",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000f4": "f4",
+ "0x00000000000000000000000000000000000000000000000000000000000000f5": "f5",
+ "0x00000000000000000000000000000000000000000000000000000000000000f6": "f6"
+ },
+ "key": "0x1d6ee979097e29141ad6b97ae19bb592420652b7000003c55eb52d5225c3307d"
+ },
+ "0x553f68e60e9f8ea74c831449525dc1bc4f6fc58e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x14f9f4b9445c7547d5a4671a38b0b12bbc0e7198c3b2934b82b695c8630d4972",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000126": "0126",
+ "0x0000000000000000000000000000000000000000000000000000000000000127": "0127",
+ "0x0000000000000000000000000000000000000000000000000000000000000128": "0128"
+ },
+ "key": "0x6ad3ba011e031431dc057c808b85346d58001b85b32a4b5c90ccccea0f82e170"
+ },
+ "0x56270eccd88bcd5ad8d2b08f82d96cd8dace4eb3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xb0700fe13dbaf94be50bcbec13a7b53e6cba034b29a3daba98fa861f5897213f",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000063": "63",
+ "0x0000000000000000000000000000000000000000000000000000000000000064": "64",
+ "0x0000000000000000000000000000000000000000000000000000000000000065": "65"
+ },
+ "key": "0xcd6b3739d4dbce17dafc156790f2a3936eb75ce95e9bba039dd76661f40ea309"
+ },
+ "0x56d3f289b889e65c4268a1b56b3da2d3860d0afb": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x207f6c3e450546b0d1f3bc6a6faf5bfa0bff80396c55d567b834cf0e7c760347",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000000a": "0a",
+ "0x000000000000000000000000000000000000000000000000000000000000000b": "0b",
+ "0x000000000000000000000000000000000000000000000000000000000000000c": "0c"
+ },
+ "key": "0xdc9ea08bdea052acab7c990edbb85551f2af3e1f1a236356ab345ac5bcc84562"
+ },
+ "0x56dc3a6c5ca1e1b773e5fdfc8a92e9a42feaa6e9": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xdbd66b6a89e01c76ae5f8cb0dcd8a24e787f58f015c9b08972bfabefa2eae0d5"
+ },
+ "0x579ab019e6b461188300c7fb202448d34669e5ff": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x18f4256a59e1b2e01e96ac465e1d14a45d789ce49728f42082289fc25cf32b8d"
+ },
+ "0x5820871100e656b0d84b950f0a557e37419bf17d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4615e5f5df5b25349a00ad313c6cd0436b6c08ee5826e33a018661997f85ebaa"
+ },
+ "0x58d77a134c11f45f9573d5c105fa6c8ae9b4237a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd9f987fec216556304eba05bcdae47bb736eea5a4183eb3e2c3a5045734ae8c7"
+ },
+ "0x591317752b32e45c9d44d925a4bcb4898f6b51fb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x89bde89df7f2d83344a503944bb347b847f208df837228bb2cdfd6c3228ca3df",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000011c": "011c",
+ "0x000000000000000000000000000000000000000000000000000000000000011d": "011d",
+ "0x000000000000000000000000000000000000000000000000000000000000011e": "011e"
+ },
+ "key": "0x88a5635dabc83e4e021167be484b62cbed0ecdaa9ac282dab2cd9405e97ed602"
+ },
+ "0x5a6e7a4754af8e7f47fc9493040d853e7b01e39d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3e57e37bc3f588c244ffe4da1f48a360fa540b77c92f0c76919ec4ee22b63599"
+ },
+ "0x5b35d3e1ac7a2c61d247046d38773decf4f2839a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x55cab9586acb40e66f66147ff3a059cfcbbad785dddd5c0cc31cb43edf98a5d5"
+ },
+ "0x5c019738b38feae2a8944bd644f7acd5e6f40e5c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xea83389383152270104093ed5dfe34ba403c75308133aa1be8f51ad804b3e9ee",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000103": "0103",
+ "0x0000000000000000000000000000000000000000000000000000000000000104": "0104",
+ "0x0000000000000000000000000000000000000000000000000000000000000105": "0105"
+ },
+ "key": "0xbccd85b63dba6300f84c561c5f52ce08a240564421e382e6f550ce0c12f2f632"
+ },
+ "0x5c04401b6f6a5e318c7b6f3106a6217d20008427": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6c37093a34016ae687da7aabb18e42009b71edff70a94733c904aea51a4853c1"
+ },
+ "0x5c23d95614dce3317e7be72de3c81479c3172a8a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x4f446329b5ee3d13d4f6b5e5f210ddc2d90fedba384b950e36a1d19af95c5cb1",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000000f": "0f",
+ "0x0000000000000000000000000000000000000000000000000000000000000010": "10",
+ "0x0000000000000000000000000000000000000000000000000000000000000011": "11"
+ },
+ "key": "0x34a715e08b77afd68cde30b62e222542f3db90758370400c94d0563959a1d1a0"
+ },
+ "0x5c62e091b8c0565f1bafad0dad5934276143ae2c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1bf7626cec5330a127e439e68e6ee1a1537e73b2de1aa6d6f7e06bc0f1e9d763"
+ },
+ "0x5d6bc8f87dd221a9f8c4144a256391979ff6426b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcc74930e1ee0e71a8081f247ec47442a3e5d00897966754a5b3ee8beb2c1160c"
+ },
+ "0x5df7504bc193ee4c3deadede1459eccca172e87c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4f458f480644b18c0e8207f405b82da7f75c7b3b5a34fe6771a0ecf644677f33"
+ },
+ "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3848b7da914222540b71e398081d04e3849d2ee0d328168a3cc173a1cd4e783b"
+ },
+ "0x5f4755a4bd689dc90425fb2fdb64a4b191a7264d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xaf867e6cbae810caa924b8b6ac3d8c0891831491a6906dd0be7ad324dcd1533d",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000016c": "016c",
+ "0x000000000000000000000000000000000000000000000000000000000000016d": "016d",
+ "0x000000000000000000000000000000000000000000000000000000000000016e": "016e"
+ },
+ "key": "0x1c3f74249a4892081ba0634a819aec9ed25f34c7653f5719b9098487e65ab595"
+ },
+ "0x5f552da00dfb4d3749d9e62dcee3c918855a86a0": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd52564daf6d32a6ae29470732726859261f5a7409b4858101bd233ed5cc2f662"
+ },
+ "0x5f553e0d115af809cfc1396b4823378b2c7cced5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xcc48f8d1c0dd6ec8ab7bbd792d94f6a74c8876b41bc859cee2228e8dad8207a4",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000ae": "ae",
+ "0x00000000000000000000000000000000000000000000000000000000000000af": "af",
+ "0x00000000000000000000000000000000000000000000000000000000000000b0": "b0"
+ },
+ "key": "0xe3c2e12be28e2e36dc852e76dd32e091954f99f2a6480853cd7b9e01ec6cd889"
+ },
+ "0x6096d8459f8e424f514468098e6a0f2a871c815d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa20e6a21244af8ffccd5442297ad9b7a76ac72d7d8ac9e16f12fcc50e90b734e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000018f": "018f",
+ "0x0000000000000000000000000000000000000000000000000000000000000190": "0190",
+ "0x0000000000000000000000000000000000000000000000000000000000000191": "0191"
+ },
+ "key": "0x67cc0bf5341efbb7c8e1bdbf83d812b72170e6edec0263eeebdea6f107bbef0d"
+ },
+ "0x60d0debc5c81432ee294b9a06dcf58964224bbc2": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x5446b818f4c669669cd3314726ff134cf18c58a9a536df13c700610705a8b7c8",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000041": "41",
+ "0x0000000000000000000000000000000000000000000000000000000000000042": "42",
+ "0x0000000000000000000000000000000000000000000000000000000000000043": "43"
+ },
+ "key": "0x395b92f75f8e06b5378a84ba03379f025d785d8b626b2b6a1c84b718244b9a91"
+ },
+ "0x61774970e93c00a3e206a26c64707d3e33f89972": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x869acb929f591c54cb85842a51f296635e7d895798c547a293afe43e7bf7f417",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000006d": "6d",
+ "0x000000000000000000000000000000000000000000000000000000000000006e": "6e",
+ "0x000000000000000000000000000000000000000000000000000000000000006f": "6f"
+ },
+ "key": "0x07b49045c401bcc408f983d91a199c908cdf0d646049b5b83629a70b0117e295"
+ },
+ "0x6269e930eee66e89863db1ff8e4744d65e1fb6bf": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x419809ad1512ed1ab3fb570f98ceb2f1d1b5dea39578583cd2b03e9378bbe418"
+ },
+ "0x62b67e1f685b7fef51102005dddd27774be3fee3": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf462aaa112b195c148974ff796a81c0e7f9a972d04e60c178ac109102d593a88"
+ },
+ "0x6325c46e45d96f775754b39a17d733c4920d0038": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7c463797c90e9ba42b45ae061ffaa6bbd0dad48bb4998f761e81859f2a904a49"
+ },
+ "0x63eb2d6ec7c526fd386631f71824bad098f39813": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfdaf2549ea901a469b3e91cd1c4290fab376ef687547046751e10b7b461ff297"
+ },
+ "0x6510225e743d73828aa4f73a3133818490bd8820": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe6d72f72fd2fc8af227f75ab3ab199f12dfb939bdcff5f0acdac06a90084def8"
+ },
+ "0x653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc2c26fbc0b7893d872fa528d6c235caab9164feb5b54c48381ff3d82c8244e77"
+ },
+ "0x654aa64f5fbefb84c270ec74211b81ca8c44a72e": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x00aa781aff39a8284ef43790e3a511b2caa50803613c5096bc782e8de08fa4c5"
+ },
+ "0x65c74c15a686187bb6bbf9958f494fc6b8006803": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x570210539713235b442bbbad50c58bee81b70efd2dad78f99e41a6c462faeb43"
+ },
+ "0x662fb906c0fb671022f9914d6bba12250ea6adfb": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb58e22a9ece8f9b3fdbaa7d17fe5fc92345df11d6863db4159647d64a34ff10b"
+ },
+ "0x66378d2edcc2176820e951f080dd6e9e15a0e695": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa02c8b02efb52fad3056fc96029467937c38c96d922250f6d2c0f77b923c85aa"
+ },
+ "0x670dc376ecca46823e13bab90acab2004fb1706c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xae440143d21e24a931b6756f6b3d50d337eaf0db3e6c34e36ab46fe2d99ef83e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000199": "0199",
+ "0x000000000000000000000000000000000000000000000000000000000000019a": "019a",
+ "0x000000000000000000000000000000000000000000000000000000000000019b": "019b"
+ },
+ "key": "0xdcda5b5203c2257997a574bdf85b2bea6d04829e8d7e048a709badc0fb99288c"
+ },
+ "0x6741149452787eb4384ebbd8456643f246217034": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x37e51740ad994839549a56ef8606d71ace79adc5f55c988958d1c450eea5ac2d"
+ },
+ "0x684888c0ebb17f374298b65ee2807526c066094c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb062c716d86a832649bccd53e9b11c77fc8a2a00ef0cc0dd2f561688a69d54f7"
+ },
+ "0x6922e93e3827642ce4b883c756b31abf80036649": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3be526914a7d688e00adca06a0c47c580cb7aa934115ca26006a1ed5455dd2ce"
+ },
+ "0x6a632187a3abf9bebb66d43368fccd612f631cbc": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9de451c4f48bdb56c6df198ff8e1f5e349a84a4dc11de924707718e6ac897aa6"
+ },
+ "0x6b23c0d5f35d1b11f9b683f0b0a617355deb1127": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x099d5081762b8b265e8ba4cd8e43f08be4715d903a0b1d96b3d9c4e811cbfb33"
+ },
+ "0x6b2884fef44bd4288621a2cda9f88ca07b480861": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe6c5edf6a0fbdcff100e5ceafb63cba9aea355ba397a93fdb42a1a67b91375f8"
+ },
+ "0x6c49c19c40a44bbf1cf9d2d8741ec1126e815fc6": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe00c49a65849d05cbf27a4d7788a68bc7b6013ae33411d40bc89282fc064f33d",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001ad": "01ad",
+ "0x00000000000000000000000000000000000000000000000000000000000001ae": "01ae",
+ "0x00000000000000000000000000000000000000000000000000000000000001af": "01af"
+ },
+ "key": "0x0304d8eaccf0b942c468074250cbcb625ec5c4688b6b5d17d2a9bdd8dd565d5a"
+ },
+ "0x6ca60a92cbf88c7f527978dc183a22e774755551": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x52d034ca6ebd21c7ba62a2ad3b6359aa4a1cdc88bdaa64bb2271d898777293ab"
+ },
+ "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaa0ac2f707a3dc131374839d4ee969eeb1cb55adea878f56e7b5b83d187d925c"
+ },
+ "0x6d09a879576c0d941bea7833fb2285051b10d511": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaa0ffaa57269b865dccce764bf412de1dff3e7bba22ce319ef09e5907317b3e7"
+ },
+ "0x6d8b8f27857e10b21c0ff227110d7533cea03d0e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xd3d9839f87c29fb007fd9928d38bbf84ef089f0cd640c838f4a42631e828c667",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000117": "0117",
+ "0x0000000000000000000000000000000000000000000000000000000000000118": "0118",
+ "0x0000000000000000000000000000000000000000000000000000000000000119": "0119"
+ },
+ "key": "0xfdbb8ddca8cecfe275da1ea1c36e494536f581d64ddf0c4f2e6dae9c7d891427"
+ },
+ "0x6e09a59a69b41abca97268b05595c074ad157872": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7a3870cc1ed4fc29e9ab4dd3218dbb239dd32c9bf05bff03e325b7ba68486c47"
+ },
+ "0x6e3d512a9328fa42c7ca1e20064071f88958ed93": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc1a6a0bf60ee7b3228ecf6cb7c9e5491fbf62642a3650d73314e976d9eb9a966"
+ },
+ "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x97f72ff641eb40ee1f1163544931635acb7550a0d44bfb9f4cc3aeae829b6d7d"
+ },
+ "0x6f80f6a318ea88bf0115d693f564139a5fb488f6": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe73b3367629c8cb991f244ac073c0863ad1d8d88c2e180dd582cefda2de4415e"
+ },
+ "0x7021bf21ecdbefcb33d09e4b812a47b273aa1d5c": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb9400acf38453fd206bc18f67ba04f55b807b20e4efc2157909d91d3a9f7bed2"
+ },
+ "0x706be462488699e89b722822dcec9822ad7d05a7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x78948842ff476b87544c189ce744d4d924ffd0907107a0dbaa4b71d0514f2225"
+ },
+ "0x717f8aa2b982bee0e29f573d31df288663e1ce16": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc3c8e2dc64e67baa83b844263fe31bfe24de17bb72bfed790ab345b97b007816"
+ },
+ "0x7212449475dcc75d408ad62a9acc121d94288f6d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe333845edc60ed469a894c43ed8c06ec807dafd079b3c948077da56e18436290"
+ },
+ "0x72dfcfb0c470ac255cde83fb8fe38de8a128188e": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2fe5767f605b7b821675b223a22e4e5055154f75e7f3041fdffaa02e4787fab8"
+ },
+ "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": {
+ "balance": "999999999999999999999518871495454239",
+ "nonce": 402,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4363d332a0d4df8582a84932729892387c623fe1ec42e2cfcbe85c183ed98e0e"
+ },
+ "0x75b9236dfe7d0e12eb21b6d175276a7c5d4e851d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc54ffffcbaa5b566a7cf37386c4ce5a338d558612343caaa99788343d516aa5f"
+ },
+ "0x77adfc95029e73b173f60e556f915b0cd8850848": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0993fd5b750fe4414f93c7880b89744abb96f7af1171ed5f47026bdf01df1874"
+ },
+ "0x788adf954fc28a524008ea1f2d0e87ae8893afdc": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x903f24b3d3d45bc50c082b2e71c7339c7060f633f868db2065ef611885abe37e"
+ },
+ "0x7a19252e8c9b457eb07f52d0ddbe16820b5b7830": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xab7bdc41a80ae9c8fcb9426ba716d8d47e523f94ffb4b9823512d259c9eca8cd"
+ },
+ "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x71dee9adfef0940a36336903bd6830964865180b98c0506f9bf7ba8f2740fbf9"
+ },
+ "0x7c5bd2d144fdde498406edcb9fe60ce65b0dfa5f": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfcc08928955d4e5e17e17e46d5adbb8011e0a8a74cabbdd3e138c367e89a4428"
+ },
+ "0x7cb7c4547cf2653590d7a9ace60cc623d25148ad": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x55d0609468d8d4147a942e88cfc5f667daff850788d821889fbb03298924767c"
+ },
+ "0x7d80ad47bf8699f49853640b12ee55b1f51691f1": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x65cf42efacdee07ed87a1c2de0752a4e3b959f33f9f9f8c77424ba759e01fcf2"
+ },
+ "0x7da59d0dfbe21f43e842e8afb43e12a6445bbac0": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7c3e44534b1398abc786e4591364c329e976dbde3b3ed3a4d55589de84bcb9a6"
+ },
+ "0x7dcef881c305fb208500cc9509db689047ed0967": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x6d2b8a074c78a0e5a8095d7a010d4961c639c541cf56fbb7049480cc8f199765",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001bc": "01bc",
+ "0x00000000000000000000000000000000000000000000000000000000000001bd": "01bd",
+ "0x00000000000000000000000000000000000000000000000000000000000001be": "01be"
+ },
+ "key": "0x68fc814efedf52ac8032da358ddcb61eab4138cb56b536884b86e229c995689c"
+ },
+ "0x7f2dce06acdeea2633ff324e5cb502ee2a42d979": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe04fdefc4f2eefd22721d5944411b282d0fcb1f9ac218f54793a35bca8199c25"
+ },
+ "0x7f774bb46e7e342a2d9d0514b27cee622012f741": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x720f25b62fc39426f70eb219c9dd481c1621821c8c0fa5367a1df6e59e3edf59"
+ },
+ "0x7fd02a3bb5d5926d4981efbf63b66de2a7b1aa63": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x7bf542bdaff5bfe3d33c26a88777773b5e525461093c36acb0dab591a319e509",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000032": "32",
+ "0x0000000000000000000000000000000000000000000000000000000000000033": "33",
+ "0x0000000000000000000000000000000000000000000000000000000000000034": "34"
+ },
+ "key": "0xfc3d2e27841c0913d10aa11fc4af4793bf376efe3d90ce8360aa392d0ecefa24"
+ },
+ "0x8074971c7d405ba1e70af34f5af7d564ddc495df": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x60fc69100d8e632667c80b94d434008823ed75416b71cbd112b4d0b02f563027",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000a4": "a4",
+ "0x00000000000000000000000000000000000000000000000000000000000000a5": "a5",
+ "0x00000000000000000000000000000000000000000000000000000000000000a6": "a6"
+ },
+ "key": "0x0e0e4646090b881949ec9991e48dec768ccd1980896aefd0d51fd56fd5689790"
+ },
+ "0x8120ff763f8283e574fc767702056b57fcc89003": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa2e7084ba9cec179519c7e8950c66ad3cba8586a60cff9f4d60c188dd621522a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000037": "37",
+ "0x0000000000000000000000000000000000000000000000000000000000000038": "38",
+ "0x0000000000000000000000000000000000000000000000000000000000000039": "39"
+ },
+ "key": "0x48e291f8a256ab15da8401c8cae555d5417a992dff3848926fa5b71655740059"
+ },
+ "0x8176caac8654abc74a905b137a37ecf7be2a9e95": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc4bab059ee8f7b36c82ada44d22129671d8f47f254ca6a48fded94a8ff591c88"
+ },
+ "0x81bda6e29da8c3e4806b64dfa1cd32cd9c8fa70e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd5e5e7be8a61bb5bfa271dfc265aa9744dea85de957b6cffff0ecb403f9697db"
+ },
+ "0x828a91cb304a669deff703bb8506a19eba28e250": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x936ac6251848da69a191cc91174e4b7583a12a43d896e243841ea98b65f264ad",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000017b": "017b",
+ "0x000000000000000000000000000000000000000000000000000000000000017c": "017c",
+ "0x000000000000000000000000000000000000000000000000000000000000017d": "017d"
+ },
+ "key": "0xea810ea64a420acfa917346a4a02580a50483890cba1d8d1d158d11f1c59ed02"
+ },
+ "0x82c291ed50c5f02d7e15e655c6353c9278e1bbec": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x12de4544640fc8a027e1a912d776b90675bebfd50710c2876b2a24ec9eced367",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000cc": "cc",
+ "0x00000000000000000000000000000000000000000000000000000000000000cd": "cd",
+ "0x00000000000000000000000000000000000000000000000000000000000000ce": "ce"
+ },
+ "key": "0xa9970b3744a0e46b248aaf080a001441d24175b5534ad80755661d271b976d67"
+ },
+ "0x83c7e323d189f18725ac510004fdc2941f8c4a78": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb17ea61d092bd5d77edd9d5214e9483607689cdcc35a30f7ea49071b3be88c64"
+ },
+ "0x847f88846c35337cbf57e37ffc18316a99ac2f14": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x310a2ac83d7e3e4d333102b1f7153bb0416b38427eb2e335dc6632d779a8b4af",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000bd": "bd",
+ "0x00000000000000000000000000000000000000000000000000000000000000be": "be",
+ "0x00000000000000000000000000000000000000000000000000000000000000bf": "bf"
+ },
+ "key": "0xbea55c1dc9f4a9fb50cbedc70448a4e162792b9502bb28b936c7e0a2fd7fe41d"
+ },
+ "0x84873854dba02cf6a765a6277a311301b2656a7f": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3197690074092fe51694bdb96aaab9ae94dac87f129785e498ab171a363d3b40"
+ },
+ "0x84e75c28348fb86acea1a93a39426d7d60f4cc46": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5162f18d40405c59ef279ad71d87fbec2bbfedc57139d56986fbf47daf8bcbf2"
+ },
+ "0x85f97e04d754c81dac21f0ce857adc81170d08c6": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2baa718b760c0cbd0ec40a3c6df7f2948b40ba096e6e4b116b636f0cca023bde"
+ },
+ "0x8642821710100a9a3ab10cd4223278a713318096": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4fbc5fc8df4f0a578c3be3549f1cb3ef135cbcdf75f620c7a1d412462e9b3b94"
+ },
+ "0x8749e96779cd1b9fa62b2a19870d9efc28acae09": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa3d8baf7ae7c96b1020753d12154e28cc7206402037c28c49c332a08cf7c4b51"
+ },
+ "0x87610688d55c08238eacf52864b5a5920a00b764": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2da86eb3d4ffdd895170bc7ef02b69a116fe21ac2ce45a3ed8e0bb8af17cf92b",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000fe": "fe",
+ "0x00000000000000000000000000000000000000000000000000000000000000ff": "ff",
+ "0x0000000000000000000000000000000000000000000000000000000000000100": "0100"
+ },
+ "key": "0x80a2c1f38f8e2721079a0de39f187adedcb81b2ab5ae718ec1b8d64e4aa6930e"
+ },
+ "0x878dedd9474cfa24d91bccc8b771e180cf01ac40": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7e1ef9f8d2fa6d4f8e6717c3dcccff352ea9b8b46b57f6106cdbeed109441799"
+ },
+ "0x882e7e5d12617c267a72948e716f231fa79e6d51": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x491b2cfba976b2e78bd9be3bc15c9964927205fc34c9954a4d61bbe8170ba533",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000005": "05",
+ "0x0000000000000000000000000000000000000000000000000000000000000006": "06",
+ "0x0000000000000000000000000000000000000000000000000000000000000007": "07"
+ },
+ "key": "0xd2501ae11a14bf0c2283a24b7e77c846c00a63e71908c6a5e1caff201bad0762"
+ },
+ "0x88654f0e7be1751967bba901ed70257a3cb79940": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x30ce5b7591126d5464dfb4fc576a970b1368475ce097e244132b06d8cc8ccffe"
+ },
+ "0x892f60b39450a0e770f00a836761c8e964fd7467": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x74614a0c4ba7d7c70b162dad186b6cc77984ab4070534ad9757e04a5b776dcc8"
+ },
+ "0x8a5edab282632443219e051e4ade2d1d5bbc671c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc251a3acb75a90ff0cdca31da1408a27ef7dcaa42f18e648f2be1a28b35eac32"
+ },
+ "0x8a817bc42b2e2146dc4ca4dc686db0a4051d2944": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x17984cc4b4aac0492699d37662b53ec2acf8cbe540c968b817061e4ed27026d0"
+ },
+ "0x8a8950f7623663222542c9469c73be3c4c81bbdf": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xaef83ad0ab332330a20e88cd3b5a4bcf6ac6c175ee780ed4183d11340df17833"
+ },
+ "0x8ba7e4a56d8d4a4a2fd7d0c8b9e6f032dc76cefb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x72e962dfe7e2828809f5906996dedeba50950140555b193fceb94f12fd6f0a22"
+ },
+ "0x8bebc8ba651aee624937e7d897853ac30c95a067": {
+ "balance": "1",
+ "nonce": 1,
+ "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000001": "01",
+ "0x0000000000000000000000000000000000000000000000000000000000000002": "02",
+ "0x0000000000000000000000000000000000000000000000000000000000000003": "03"
+ },
+ "key": "0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"
+ },
+ "0x8cf42eb93b1426f22a30bd22539503bdf838830c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0267c643f67b47cac9efacf6fcf0e4f4e1b273a727ded155db60eb9907939eb6"
+ },
+ "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb8d9b988ed60dbf5dca3e9d169343ca667498605f34fb6c30b45b2ed0f996f1a"
+ },
+ "0x8d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f2": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc13c19f53ce8b6411d6cdaafd8480dfa462ffdf39e2eb68df90181a128d88992"
+ },
+ "0x8fa24283a8c1cc8a0f76ac69362139a173592567": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xefaff7acc3ad3417517b21a92187d2e63d7a77bc284290ed406d1bc07ab3d885"
+ },
+ "0x8fb778e47caf2df14eca7a389955ca74ac8f4924": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xae2e7f1c933c6ca84ce8be811ef411dee773fb69508056d72448048ea1db5c47",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001ee": "01ee",
+ "0x00000000000000000000000000000000000000000000000000000000000001ef": "01ef",
+ "0x00000000000000000000000000000000000000000000000000000000000001f0": "01f0"
+ },
+ "key": "0x4973f6aa8cf5b1190fc95379aa01cff99570ee6b670725880217237fb49e4b24"
+ },
+ "0x90fd8e600ae1a7c69fa6ef2c537b533ca77366e8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xee9821621aa5ec9ab7d5878b2a995228adcdcacb710df522d2f91b434d3bdc79",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000c2": "c2",
+ "0x00000000000000000000000000000000000000000000000000000000000000c3": "c3",
+ "0x00000000000000000000000000000000000000000000000000000000000000c4": "c4"
+ },
+ "key": "0xbfaac98225451c56b2f9aec858cffc1eb253909615f3d9617627c793b938694f"
+ },
+ "0x913f841dfc8703ae76a4e1b8b84cd67aab15f17a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xcb54add475a18ea02ab1adf9e2e73da7f23ecd3e92c4fa8ca4e8f588258cb5d3"
+ },
+ "0x923f800cf288500f8e53f04e4698c9b885dcf030": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb91824b28183c95881ada12404d5ee8af8123689a98054d41aaf4dd5bec50e90"
+ },
+ "0x9344b07175800259691961298ca11c824e65032d": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0x8e0388ecf64cfa76b3a6af159f77451519a7f9bb862e4cce24175c791fdcb0df",
+ "code": "0x60004381526020014681526020014181526020014881526020014481526020013281526020013481526020016000f3",
+ "key": "0x2e6fe1362b3e388184fd7bf08e99e74170b26361624ffd1c5f646da7067b58b6"
+ },
+ "0x93747f73c18356c6b202f527f552436a0e06116a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x73cd1b7cd355f3f77c570a01100a616757408bb7abb78fe9ee1262b99688fcc4"
+ },
+ "0x9380b994c5738f68312f0e517902da81f63cdcfa": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x51b829f0f2c3de9cfbd94e47828a89940c329a49cd59540ca3c6d751a8d214d6",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000135": "0135",
+ "0x0000000000000000000000000000000000000000000000000000000000000136": "0136",
+ "0x0000000000000000000000000000000000000000000000000000000000000137": "0137"
+ },
+ "key": "0x50d83ef5194d06752cd5594b57e809b135f24eedd124a51137feaaf049bc2efd"
+ },
+ "0x94d068bff1af651dd9d9c2e75adfb7eec6f66be7": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x0754035aa4073381a211342b507de8e775c97c961096e6e2275df0bfcbb3a01c",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000059": "59",
+ "0x000000000000000000000000000000000000000000000000000000000000005a": "5a",
+ "0x000000000000000000000000000000000000000000000000000000000000005b": "5b"
+ },
+ "key": "0x0cd2a7c53c76f228ed3aa7a29644b1915fde9ec22e0433808bf5467d914e7c7a"
+ },
+ "0x956062137518b270d730d4753000896de17c100a": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5aa3b4a2ebdd402721c3953b724f4fe90900250bb4ef89ce417ec440da318cd6"
+ },
+ "0x96a1cabb97e1434a6e23e684dd4572e044c243ea": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe7c6828e1fe8c586b263a81aafc9587d313c609c6db8665a42ae1267cd9ade59"
+ },
+ "0x984c16459ded76438d98ce9b608f175c28a910a0": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4b9f335ce0bdffdd77fdb9830961c5bc7090ae94703d0392d3f0ff10e6a4fbab"
+ },
+ "0x99a1c0703485b331fa0302d6077b583082e242ea": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2cf292c1e382bdd0e72e126701d7b02484e6e272f4c0d814f5a6fae233fc7935",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000121": "0121",
+ "0x0000000000000000000000000000000000000000000000000000000000000122": "0122",
+ "0x0000000000000000000000000000000000000000000000000000000000000123": "0123"
+ },
+ "key": "0x734ee4981754a3f1403c4e8887d35addfb31717d93de3e00ede78368c230861e"
+ },
+ "0x99d40a710cb552eaaee1599d4040055859b1610d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x946bfb429d90f1b39bb47ada75376a8d90a5778068027d4b8b8514ac13f53eca"
+ },
+ "0x9a7b7b3a5d50781b4f4768cd7ce223168f6b449b": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd16e029e8c67c3f330cddaa86f82d31f523028404dfccd16d288645d718eb9da"
+ },
+ "0x9ae62b6d840756c238b5ce936b910bb99d565047": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8989651e80c20af78b37fdb693d74ecafc9239426ff1315e1fb7b674dcdbdb75"
+ },
+ "0x9b3cf956056937dfb6f9e3dc02e3979a4e421c0a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb1b2c1c59637202bb0e0d21255e44e0df719fe990be05f213b1b813e3d8179d7"
+ },
+ "0x9bb981f592bc1f9c31db67f30bbf1ff44b649886": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1ee7e0292fba90d9733f619f976a2655c484adb30135ef0c5153b5a2f32169df"
+ },
+ "0x9bfb328671c108c9ba4d45734d9f4462d8c9a9cb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xc15b43e5f4853ec8da53ebde03de87b94afce42a9c02f648ad8bdb224604c4ad",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001da": "01da",
+ "0x00000000000000000000000000000000000000000000000000000000000001db": "01db",
+ "0x00000000000000000000000000000000000000000000000000000000000001dc": "01dc"
+ },
+ "key": "0xa683478d0c949580d5738b490fac8129275bb6e921dfe5eae37292be3ee281b9"
+ },
+ "0x9defb0a9e163278be0e05aa01b312ec78cfa3726": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb31919583a759b75e83c14d00d0a89bb36adc452f73cee2933a346ccebaa8e31"
+ },
+ "0x9e59004e909ff011e5882332e421b6772e68ed10": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x3897cb9b6f68765022f3c74f84a9f2833132858f661f4bc91ccd7a98f4e5b1ee"
+ },
+ "0x9f50ec6c8a595869d71ce8c3b1c17c02599a5cc3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2705244734f69af78e16c74784e1dc921cb8b6a98fe76f577cc441c831e973bf"
+ },
+ "0xa0794cd73f564baeeda23fa4ce635a3f8ae39621": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xfb79021e7fa54b9bd2df64f6db57897d52ae85f7c195af518de48200a1325e2c",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000ef": "ef",
+ "0x00000000000000000000000000000000000000000000000000000000000000f0": "f0",
+ "0x00000000000000000000000000000000000000000000000000000000000000f1": "f1"
+ },
+ "key": "0x60535eeb3ffb721c1688b879368c61a54e13f8881bdef6bd4a17b8b92e050e06"
+ },
+ "0xa12b147dd542518f44f821a4d436066c64932b0d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xae88076d02b19c4d09cb13fca14303687417b632444f3e30fc4880c225867be3"
+ },
+ "0xa179dbdd51c56d0988551f92535797bcf47ca0e7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6d1da4cf1127d654ed731a93105f481b315ecfc2f62b1ccb5f6d2717d6a40f9b"
+ },
+ "0xa1fce4363854ff888cff4b8e7875d600c2682390": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xad99b5bc38016547d5859f96be59bf18f994314116454def33ebfe9a892c508a"
+ },
+ "0xa225fe6df11a4f364234dd6a785a17cd38309acb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xc1686045288a5952ad57de0e971bd25007723c9f749f49f391e715c27bf526c8",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000072": "72",
+ "0x0000000000000000000000000000000000000000000000000000000000000073": "73",
+ "0x0000000000000000000000000000000000000000000000000000000000000074": "74"
+ },
+ "key": "0x4e0ab2902f57bf2a250c0f87f088acc325d55f2320f2e33abd8e50ba273c9244"
+ },
+ "0xa25513c7e0f6eaa80a3337ee18081b9e2ed09e00": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfb9474d0e5538fcd99e8d8d024db335b4e057f4bcd359e85d78f4a5226b33272"
+ },
+ "0xa5ab782c805e8bfbe34cb65742a0471cf5a53a97": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6188c4510d25576535a642b15b1dbdb8922fe572b099f504390f923c19799777"
+ },
+ "0xa64f449891f282b87e566036f981023dba4ed477": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x61176dbc05a8537d8de85f82a03b8e1049cea7ad0a9f0e5b60ee15fca6fe0d42",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000012b": "012b",
+ "0x000000000000000000000000000000000000000000000000000000000000012c": "012c",
+ "0x000000000000000000000000000000000000000000000000000000000000012d": "012d"
+ },
+ "key": "0x7c1edabb98857d64572f03c64ac803e4a14b1698fccffffd51675d99ee3ba217"
+ },
+ "0xa6515a495ec7723416665ebb54fc002bf1e9a873": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbbdc59572cc62c338fb6e027ab00c57cdeed233c8732680a56a5747141d20c7c"
+ },
+ "0xa6a54695341f038ad15e9e32f1096f5201236512": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe2a72f5bfbeba70fc9ab506237ba27c096a4e96c3968cabf5b1b2fb54431b5cf",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000023": "23",
+ "0x0000000000000000000000000000000000000000000000000000000000000024": "24",
+ "0x0000000000000000000000000000000000000000000000000000000000000025": "25"
+ },
+ "key": "0xa87387b50b481431c6ccdb9ae99a54d4dcdd4a3eff75d7b17b4818f7bbfc21e9"
+ },
+ "0xa8100ae6aa1940d0b663bb31cd466142ebbdbd51": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x02547b56492bfe767f3d18be2aab96441c449cd945770ef7ef8555acc505b2e4"
+ },
+ "0xa8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x913e2a02a28d71d595d7216a12311f6921a4caf40aeabf0f28edf937f1df72b4"
+ },
+ "0xa92bb60b61e305ddd888015189d6591b0eab0233": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xdd1589b1fe1d9b4ca947f98ff324de7887af299d5490ed92ae40e95eec944118"
+ },
+ "0xa956ca63bf28e7da621475d6b077da1ab9812b3a": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa090b66fbca46cb71abd1daa8d419d2c6e291094f52872978dfcb1c31ad7a900",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001e4": "01e4",
+ "0x00000000000000000000000000000000000000000000000000000000000001e5": "01e5",
+ "0x00000000000000000000000000000000000000000000000000000000000001e6": "01e6"
+ },
+ "key": "0xaad7b91d085a94c11a2f7e77dc95cfcfc5daf4f509ca4e0c0e493b86c6cbff78"
+ },
+ "0xaa0d6dfdb7588017c80ea088768a5f3d0cdeacdb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x89ecb0ceeea20ccd7d1b18cf1d35b7a2fd7b76ddc8d627f43304ed8b31b01248",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000144": "0144",
+ "0x0000000000000000000000000000000000000000000000000000000000000145": "0145",
+ "0x0000000000000000000000000000000000000000000000000000000000000146": "0146"
+ },
+ "key": "0xb990eaca858ea15fda296f3f47baa2939e8aa8bbccc12ca0c3746d9b5d5fb2ae"
+ },
+ "0xaa53ff4bb2334faf9f4447197ef69c39c0bb1379": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe547c0050253075b1be4210608bc639cffe70110194c316481235e738be961e7",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000ea": "ea",
+ "0x00000000000000000000000000000000000000000000000000000000000000eb": "eb",
+ "0x00000000000000000000000000000000000000000000000000000000000000ec": "ec"
+ },
+ "key": "0xed263a22f0e8be37bcc1873e589c54fe37fdde92902dc75d656997a7158a9d8c"
+ },
+ "0xaa7225e7d5b0a2552bbb58880b3ec00c286995b8": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5a4a3feecfc77b402e938e28df0c4cbb874771cb3c5a92524f303cffb82a2862"
+ },
+ "0xab12a5f97f03edbff03eded9d1a2a1179d2fc69e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xba1d0afdfee510e8852f24dff964afd824bf36d458cf5f5d45f02f04b7c0b35d"
+ },
+ "0xab557835ab3e5c43bf34ac9b2ab730c5e0bc9967": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc9ea69dc9e84712b1349c9b271956cc0cb9473106be92d7a937b29e78e7e970e"
+ },
+ "0xab9025d4a9f93c65cd4fe978d38526860af0aa62": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x4ce79cd9645650f0a00effa86f6fea733cecea9ea26964828ff25cf0577bc974",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000009a": "9a",
+ "0x000000000000000000000000000000000000000000000000000000000000009b": "9b",
+ "0x000000000000000000000000000000000000000000000000000000000000009c": "9c"
+ },
+ "key": "0x17350c7adae7f08d7bbb8befcc97234462831638443cd6dfea186cbf5a08b7c7"
+ },
+ "0xabd693b23d55dec7d0d0cba2ecbc9298dc4edf02": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xafd54e81f3e415407f0812a678856f1b4068ed64a08b3f3bf5b2190fcfb2322d",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001b7": "01b7",
+ "0x00000000000000000000000000000000000000000000000000000000000001b8": "01b8",
+ "0x00000000000000000000000000000000000000000000000000000000000001b9": "01b9"
+ },
+ "key": "0xbe7d987a9265c0e44e9c5736fb2eb38c41973ce96e5e8e6c3c713f9d50a079ff"
+ },
+ "0xabe2b033c497e091c1e494c98c178e8aa06bcb00": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x2374954008440ca3d17b1472d34cc52a6493a94fb490d5fb427184d7d5fd1cbf"
+ },
+ "0xac4d51af4cb7bab4743fa57bc80b144d7a091268": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xfb00729a5f4f9a2436b999aa7159497a9cd88d155770f873a818b55052c5f067",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000149": "0149",
+ "0x000000000000000000000000000000000000000000000000000000000000014a": "014a",
+ "0x000000000000000000000000000000000000000000000000000000000000014b": "014b"
+ },
+ "key": "0xe42a85d04a1d0d9fe0703020ef98fa89ecdeb241a48de2db73f2feeaa2e49b0f"
+ },
+ "0xac7d8d5f6be7d251ec843ddbc09095150df59965": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa9580109be2f7d35b5360050c2ced74e5d4dea2f82d46e8d266ed89157636004",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000046": "46",
+ "0x0000000000000000000000000000000000000000000000000000000000000047": "47",
+ "0x0000000000000000000000000000000000000000000000000000000000000048": "48"
+ },
+ "key": "0x943f42ad91e8019f75695946d491bb95729f0dfc5dbbb953a7239ac73f208943"
+ },
+ "0xac9e61d54eb6967e212c06aab15408292f8558c4": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf2b9bc1163840284f3eb15c539972edad583cda91946f344f4cb57be15af9c8f"
+ },
+ "0xaceac762ff518b4cf93a6eebbc55987e7b79b2ce": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1960414a11f8896c7fc4243aba7ed8179b0bc6979b7c25da7557b17f5dee7bf7"
+ },
+ "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x58e416a0dd96454bd2b1fe3138c3642f5dee52e011305c5c3416d97bc8ba5cf0"
+ },
+ "0xad108e31c9632ad9e20614b3ca40644d32948dbb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2625f8a23d24a5dff6a79f632b1020593362a6ac622fa5237460bc67b0aa0ed3",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001a3": "01a3",
+ "0x00000000000000000000000000000000000000000000000000000000000001a4": "01a4",
+ "0x00000000000000000000000000000000000000000000000000000000000001a5": "01a5"
+ },
+ "key": "0xdce547cc70c79575ef72c061502d6066db1cbce200bd904d5d2b20d4f1cb5963"
+ },
+ "0xae3f4619b0413d70d3004b9131c3752153074e45": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb1b2fd7758f73e25a2f9e72edde82995b2b32ab798bcffd2c7143f2fc8196fd8"
+ },
+ "0xae58b7e08e266680e93e46639a2a7e89fde78a6f": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe09e5f27b8a7bf61805df6e5fefc24eb6894281550c2d06250adecfe1e6581d7"
+ },
+ "0xaf17b30f5ab8e6a4d7a563bdb0194f3e0bd50209": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2434bfc643ec364116cd71519a397662b20c52d1adcff0b830e80a738e19f30e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000b8": "b8",
+ "0x00000000000000000000000000000000000000000000000000000000000000b9": "b9",
+ "0x00000000000000000000000000000000000000000000000000000000000000ba": "ba"
+ },
+ "key": "0x26ce7d83dfb0ab0e7f15c42aeb9e8c0c5dba538b07c8e64b35fb64a37267dd96"
+ },
+ "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1a28912018f78f7e754df6b9fcec33bea25e5a232224db622e0c3343cf079eff"
+ },
+ "0xaf2c6f1512d1cabedeaf129e0643863c57419732": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xad6a4a6ebd5166c9b5cc8cfbaec176cced40fa88c73d83c67f0c3ed426121ebc"
+ },
+ "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x053df2c3b574026812b154a99b13b626220af85cd01bb1693b1d42591054bce6"
+ },
+ "0xb0ee91ba61e8a3914a7eab120786e9e61bfe4faf": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xa14913d548ac1d3f9962a21a569fe52f1436b6d2f5ea4e36de13ea855ede54e0",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000068": "68",
+ "0x0000000000000000000000000000000000000000000000000000000000000069": "69",
+ "0x000000000000000000000000000000000000000000000000000000000000006a": "6a"
+ },
+ "key": "0x4bd8ef9873a5e85d4805dbcb0dbf6810e558ea175167549ef80545a9cafbb0e1"
+ },
+ "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4ccd31891378d2025ef58980481608f11f5b35a988e877652e7cbb0a6127287c"
+ },
+ "0xb47f70b774d780c3ec5ac411f2f9198293b9df7a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xdef989cb85107747de11222bd7418411f8f3264855e1939ef6bef9447e42076d"
+ },
+ "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb7c2ef96238f635f86f9950700e36368efaaa70e764865dddc43ff6e96f6b346"
+ },
+ "0xb519be874447e0f0a38ee8ec84ecd2198a9fac77": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x92b13a73440c6421da22e848d23f9af80610085ab05662437d850c97a012d8d3"
+ },
+ "0xb55a3d332d267493105927b892545d2cd4c83bd6": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc781c7c3babeb06adfe8f09ecb61dbe0eb671e41f3a1163faac82fdfa2bc83e8"
+ },
+ "0xb609bc528052bd9669595a35f6eb6a4d7a30ac3d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe6388bfcbbd6000e90a10633c72c43b0b0fed7cf38eab785a71e6f0c5b80a26a"
+ },
+ "0xb68176634dde4d9402ecb148265db047d17cb4ab": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf4a1c4554b186a354b3e0c467eef03df9907cd5a5d96086c1a542b9e5160ca78"
+ },
+ "0xb70654fead634e1ede4518ef34872c9d4f083a53": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7f9726a7b2f5f3a501b2d7b18ec726f25f22c86348fae0f459d882ec5fd7d0c7"
+ },
+ "0xb71de80778f2783383f5d5a3028af84eab2f18a4": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x64d0de66ea29cbcf7f237dae1c5f883fa6ff0ba52b90f696bb0348224dbc82ce"
+ },
+ "0xb787c848479278cfdb56950cda545cd45881722d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1098f06082dc467088ecedb143f9464ebb02f19dc10bd7491b03ba68d751ce45"
+ },
+ "0xb911abeead298d03c21c6c5ff397cd80eb375d73": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x54abcdbc8b04bc9b70e9bd46cb9db9b8eb08cfd4addba4c941dacc34dd28648e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000054": "54",
+ "0x0000000000000000000000000000000000000000000000000000000000000055": "55",
+ "0x0000000000000000000000000000000000000000000000000000000000000056": "56"
+ },
+ "key": "0x873429def7829ff8227e4ef554591291907892fc8f3a1a0667dada3dc2a3eb84"
+ },
+ "0xb917b7f3d49770d3d2f0ad2f497e5bfe0f25dc5f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x11d4eec7df52cd54e74690a487884e56371976c2b8c49ffc4c8f34831166bf4e",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000162": "0162",
+ "0x0000000000000000000000000000000000000000000000000000000000000163": "0163",
+ "0x0000000000000000000000000000000000000000000000000000000000000164": "0164"
+ },
+ "key": "0x65e6b6521e4f1f97e80710581f42063392c9b33e0aeea4081a102a32238992ea"
+ },
+ "0xb9b85616fc8ed95979a5e31b8968847e7518b165": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6a5e43139d88da6cfba857e458ae0b5359c3fde36e362b6e5f782a90ce351f14"
+ },
+ "0xbac9d93678c9b032c393a23e4c013e37641ad850": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8a8266874b43f78d4097f27b2842132faed7e7e430469eec7354541eb97c3ea0"
+ },
+ "0xbbeebd879e1dff6918546dc0c179fdde505f2a21": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x170c927130fe8f1db3ae682c22b57f33f54eb987a7902ec251fe5dba358a2b25"
+ },
+ "0xbbf3f11cb5b43e700273a78d12de55e4a7eab741": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe74ac72f03e8c514c2c75f3c4f54ba31e920374ea7744ef1c33937e64c7d54f1"
+ },
+ "0xbc5959f43bc6e47175374b6716e53c9a7d72c594": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfd3a8bacd3b2061cbe54f8d38cf13c5c87a92816937683652886dee936dfae10"
+ },
+ "0xbceef655b5a034911f1c3718ce056531b45ef03b": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6c05d8abc81143ce7c7568c98aadfe6561635c049c07b2b4bce3019cef328cb9"
+ },
+ "0xbd079b0337a29cccd2ec95b395ef5c01e992b6a5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf0877d51b7712e08f2a3c96cddf50ff61b8b90f80b8b9817ea613a8a157b0c45"
+ },
+ "0xbe3eea9a483308cb3134ce068e77b56e7c25af19": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7026c939a9158beedff127a64f07a98b328c3d1770690437afdb21c34560fc57"
+ },
+ "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x72d91596112f9d7e61d09ffa7575f3587ad9636172ae09641882761cc369ecc0"
+ },
+ "0xc18d2be47547904f88a4f46cee75f8f4a94e1807": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x9c32ffd5059115bba9aed9174f5ab8b4352e3f51a85dde33000f703c9b9fe7c2",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000018a": "018a",
+ "0x000000000000000000000000000000000000000000000000000000000000018b": "018b",
+ "0x000000000000000000000000000000000000000000000000000000000000018c": "018c"
+ },
+ "key": "0xa601eb611972ca80636bc39087a1dae7be5a189b94bda392f84d6ce0d3c866b9"
+ },
+ "0xc19a797fa1fd590cd2e5b42d1cf5f246e29b9168": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x99dba7e9230d5151cc37ff592fa1592f27c7c81d203760dfaf62ddc9f3a6b8fd"
+ },
+ "0xc305dd6cfc073cfe5e194fc817536c419410a27d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x016d92531f4754834b0502de5b0342ceff21cde5bef386a83d2292f4445782c2"
+ },
+ "0xc337ded6f56c07205fb7b391654d7d463c9e0c72": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7c608293e741d1eb5ae6916c249a87b6540cf0c2369e96d293b1a7b5b9bd8b31"
+ },
+ "0xc57aa6a4279377063b17c554d3e33a3490e67a9a": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc192ea2d2bb89e9bb7f17f3a282ebe8d1dd672355b5555f516b99b91799b01f6"
+ },
+ "0xc5eaec262d853fbdaccca406cdcada6fa6dd0944": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x471bf8988ad0d7602d6bd5493c08733096c116ac788b76f22a682bc4558e3aa7",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000158": "0158",
+ "0x0000000000000000000000000000000000000000000000000000000000000159": "0159",
+ "0x000000000000000000000000000000000000000000000000000000000000015a": "015a"
+ },
+ "key": "0x580aa878e2f92d113a12c0a3ce3c21972b03dbe80786858d49a72097e2c491a3"
+ },
+ "0xc7a0a19ea8fc63cc6021af2e11ac0584d75c97b7": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xe2a164e2c30cf30391c88ff32a0e202194b08f2a61a9cd2927ea5ed6dfbf1056",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000e5": "e5",
+ "0x00000000000000000000000000000000000000000000000000000000000000e6": "e6",
+ "0x00000000000000000000000000000000000000000000000000000000000000e7": "e7"
+ },
+ "key": "0x86d03d0f6bed220d046a4712ec4f451583b276df1aed33f96495d22569dc3485"
+ },
+ "0xc7b99a164efd027a93f147376cc7da7c67c6bbe0": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x8e11480987056c309d7064ebbd887f086d815353cdbaadb796891ed25f8dcf61"
+ },
+ "0xc7d4ef05550c226c50cf0d4231ba1566d03fa98d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x3a2985c6ada67e5604b99fa2fc1a302abd0dc241ee7f14c428fa67d476868bb6",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000010d": "010d",
+ "0x000000000000000000000000000000000000000000000000000000000000010e": "010e",
+ "0x000000000000000000000000000000000000000000000000000000000000010f": "010f"
+ },
+ "key": "0x5a356862c79afffd6a01af752d950e11490146e4d86dfb8ab1531e9aef4945a1"
+ },
+ "0xca358758f6d27e6cf45272937977a748fd88391d": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbccd3d2f920dfb8d70a38c9ccd5ed68c2ef6e3372199381767ce222f13f36c87"
+ },
+ "0xca87240ef598bd6e4b8f67b3761af07d5f575514": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x11f5d399ca8fb7a9af5ad481be60cf61d45493cd20206c9d0a237ce7d7571e5f",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001f3": "01f3",
+ "0x00000000000000000000000000000000000000000000000000000000000001f4": "01f4",
+ "0x00000000000000000000000000000000000000000000000000000000000001f5": "01f5"
+ },
+ "key": "0x4b238e08b80378d0815e109f350a08e5d41ec4094df2cfce7bc8b9e3115bda70"
+ },
+ "0xcb925b74da97bdff2130523c2a788d4beff7b3c3": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe0c5acf66bda927704953fdf7fb4b99e116857121c069eca7fb9bd8acfc25434"
+ },
+ "0xcccc369c5141675a9e9b1925164f30cdd60992dc": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfe2511e8a33ac9973b773aaedcb4daa73ae82481fe5a1bf78b41281924260cf5"
+ },
+ "0xce24f30695b735e48b67467d76f5185ee3c7a0c5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x5442e0279d3f1149de4ce8d9e2d3f01d1854755038ac1a0fae5c48749bf71f20",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001e9": "01e9",
+ "0x00000000000000000000000000000000000000000000000000000000000001ea": "01ea",
+ "0x00000000000000000000000000000000000000000000000000000000000001eb": "01eb"
+ },
+ "key": "0x47450e5beefbd5e3a3f80cbbac474bb3db98d5e609aa8d15485c3f0d733dea3a"
+ },
+ "0xd048d242574c45095c72eaf58d2808778117afcb": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x7217cb747054306f826e78aa3fc68fe4441299a337ecea1d62582f2da8a7f336",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001a8": "01a8",
+ "0x00000000000000000000000000000000000000000000000000000000000001a9": "01a9",
+ "0x00000000000000000000000000000000000000000000000000000000000001aa": "01aa"
+ },
+ "key": "0xa9656c0192bb27f0ef3f93ecc6cc990dd146da97ac11f3d8d0899fba68d5749a"
+ },
+ "0xd0752b60adb148ca0b3b4d2591874e2dabd34637": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x625e5c85d5f4b6385574b572709d0f704b097527a251b7c658c0c4441aef2af6"
+ },
+ "0xd089c853b406be547d8e331d31cbd5c4d472a349": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x389093badcaa24c3a8cbb4461f262fba44c4f178a162664087924e85f3d55710"
+ },
+ "0xd0918e2e24c5ddc0557a61ca11e055d2ac210fe5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x25b42ec5480843a0328c63bc50eff8595d90f1d1b0afcab2f4a19b888c794f37",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000a9": "a9",
+ "0x00000000000000000000000000000000000000000000000000000000000000aa": "aa",
+ "0x00000000000000000000000000000000000000000000000000000000000000ab": "ab"
+ },
+ "key": "0xbaae09901e990935de19456ac6a6c8bc1e339d0b80ca129b8622d989b5c79120"
+ },
+ "0xd10b36aa74a59bcf4a88185837f658afaf3646ef": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9fe8b6e43098a4df56e206d479c06480801485dfd8ec3da4ccc3cebf5fba89a1"
+ },
+ "0xd1211001882d2ce16a8553e449b6c8b7f71e6183": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x61088707d2910974000e63c2d1a376f4480ba19dde19c4e6a757aeb3d62d5439"
+ },
+ "0xd1347bfa3d09ec56b821e17c905605cd5225069f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x287acc7869421fb9f49a3549b902fb01b7accc032243bd7e1accd8965d95d915",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000019e": "019e",
+ "0x000000000000000000000000000000000000000000000000000000000000019f": "019f",
+ "0x00000000000000000000000000000000000000000000000000000000000001a0": "01a0"
+ },
+ "key": "0x5b90bb05df9514b2d8e3a8feb3d6c8c22526b02398f289b42111426edc4fe6cf"
+ },
+ "0xd20b702303d7d7c8afe50344d66a8a711bae1425": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4d67d989fdb264fa4b2524d306f7b3f70ddce0b723411581d1740407da325462"
+ },
+ "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x0e27113c09de0a0cb0ff268c677aba17d39a3190fe15aec0ff7f54184955cba4"
+ },
+ "0xd2e2adf7177b7a8afddbc12d1634cf23ea1a7102": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x79afb7a5ffe6ccd537f9adff8287b78f75c37d97ea8a4dd504a08bc09926c3fa"
+ },
+ "0xd39b94587711196640659ec81855bcf397e419ff": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa9de128e7d4347403eb97f45e969cd1882dfe22c1abe8857aab3af6d0f9e9b92"
+ },
+ "0xd48171b7166f5e467abcba12698df579328e637d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x188111c233bf6516bb9da8b5c4c31809a42e8604cd0158d933435cfd8e06e413"
+ },
+ "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe1068e9986da7636501d8893f67aa94f5d73df849feab36505fd990e2d6240e9"
+ },
+ "0xd803681e487e6ac18053afc5a6cd813c86ec3e4d": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe5302e42ca6111d3515cbbb2225265077da41d997f069a6c492fa3fcb0fdf284"
+ },
+ "0xd854d6dd2b74dc45c9b883677584c3ac7854e01a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9a1896e612ca43ecb7601990af0c3bc135b9012c50d132769dfb75d0038cc3be"
+ },
+ "0xd8c50d6282a1ba47f0a23430d177bbfbb72e2b84": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xfc4870c3cd21d694424c88f0f31f75b2426e1530fdea26a14031ccf9baed84c4"
+ },
+ "0xd917458e88a37b9ae35f72d4cc315ef2020b2418": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x4c2765139cace1d217e238cc7ccfbb751ef200e0eae7ec244e77f37e92dfaee5"
+ },
+ "0xdbe726e81a7221a385e007ef9e834a975a4b528c": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x5fcd9b6fce3394ad1d44733056b3e5f6306240974a16f9de8e96ebdd14ae06b1"
+ },
+ "0xdc60d4434411b2608150f68c4c1b818b6208acc2": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x27e9b6a54cf0fb188499c508bd96d450946cd6ba1cf76cf5343b5c74450f6690",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001df": "01df",
+ "0x00000000000000000000000000000000000000000000000000000000000001e0": "01e0",
+ "0x00000000000000000000000000000000000000000000000000000000000001e1": "01e1"
+ },
+ "key": "0x8510660ad5e3d35a30d4fb7c2615c040f9f698faae2ac48022e366deaeecbe77"
+ },
+ "0xdd1e2826c0124a6d4f7397a5a71f633928926c06": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf0a51b55aadfa3cafdd214b0676816e574931a683f51218207c625375884e785"
+ },
+ "0xdd9ee108e8d5d2e8937e9fd029ec3a6640708af0": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x8289b558865f2ca1f54c98b5ff5df95f07c24ec605e247b58c7798605dcd794f",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001cb": "01cb",
+ "0x00000000000000000000000000000000000000000000000000000000000001cc": "01cc",
+ "0x00000000000000000000000000000000000000000000000000000000000001cd": "01cd"
+ },
+ "key": "0x2a39afbe88f572c23c90da2d059af3de125f1da5c3753c530dc5619a4857119f"
+ },
+ "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbb861b82d884a70666afeb78bbf30cab7fdccf838f4d5ce5f4e5ca1be6be61b1"
+ },
+ "0xde7d1b721a1e0632b7cf04edf5032c8ecffa9f9a": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x9966a8b4cd856b175855258fa7e412ffef06d9e92b519050fa7ac06d8952ac84"
+ },
+ "0xdfe052578c96df94fa617102199e66110181ed2c": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x54c12444ede3e2567dd7f4d9a06d4db8c6ab800d5b3863f8ff22a0db6d09bf24"
+ },
+ "0xe3a71b4caf54df7d2480743c5a6770a1a5a9bcda": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe4d9c31cc9b4a9050bbbf77cc08ac26d134253dcb6fd994275c5c3468f5b7810"
+ },
+ "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x70aae390a762a4347a4d167a2431874554edf1d77579213e55fea3ec39a1257c"
+ },
+ "0xe439e4ea04e52cf38d0925f0722d341097378b88": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x6c00e091dae3d4226facd6be802c865d5db0f524754d22666406138b54fab0e6",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000008b": "8b",
+ "0x000000000000000000000000000000000000000000000000000000000000008c": "8c",
+ "0x000000000000000000000000000000000000000000000000000000000000008d": "8d"
+ },
+ "key": "0x38152bce526b7e1c2bedfc9d297250fcead02818be7806638564377af145103b"
+ },
+ "0xe43ce33cdb88a2efe8a3d652bfb252fd91a950a7": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xc157e0d637d64b90e2c59bc8bed2acd75696ea1ac6b633661c12ce8f2bce0d62"
+ },
+ "0xe52c0f008957444c48eba77467eaf2b7c127e3c5": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb888c9946a84be90a9e77539b5ac68a3c459761950a460f3e671b708bb39c41f"
+ },
+ "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x519abb269c3c5710f1979ca84192e020ba5c838bdd267b2d07436a187f171232"
+ },
+ "0xe6dddbffde545e58030d4b8ca9e00cfb68975b5d": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x2afe93e1b0f26e588d2809127e4360ad7e28cf552498b2bc4847d6bcda738cdb",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000130": "0130",
+ "0x0000000000000000000000000000000000000000000000000000000000000131": "0131",
+ "0x0000000000000000000000000000000000000000000000000000000000000132": "0132"
+ },
+ "key": "0xa0f5dc2d18608f8e522ffffd86828e3d792b36d924d5505c614383ddff9be2eb"
+ },
+ "0xe75db02929f3d5d7c28ecdb064ece929602c06bd": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x9eda8eb6ca03d7c4afe47279acc90a45d1b2ca6a11afd95206f8868d20520d06",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000001e": "1e",
+ "0x000000000000000000000000000000000000000000000000000000000000001f": "1f",
+ "0x0000000000000000000000000000000000000000000000000000000000000020": "20"
+ },
+ "key": "0x600a7a5f41a67f6f759dcb664198f1c5d9b657fb51a870ce9e234e686dff008e"
+ },
+ "0xe7b2ceb8674516c4aeb43979808b237656ab3b6b": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xcd31ed5d5da79990afed0d993cb725c4e34dd97544b03466ed34212e42c28d68",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000014e": "014e",
+ "0x000000000000000000000000000000000000000000000000000000000000014f": "014f",
+ "0x0000000000000000000000000000000000000000000000000000000000000150": "0150"
+ },
+ "key": "0x75d231f57a1a9751f58769d5691f4807ab31ac0e802b1a1f6bfc77f5dff0adbf"
+ },
+ "0xe7d13f7aa2a838d24c59b40186a0aca1e21cffcc": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xec3e92967d10ac66eff64a5697258b8acf87e661962b2938a0edcd78788f360d"
+ },
+ "0xe82c38488eded9fb72a5ed9e039404c537f20b13": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7a2464bc24d90557940e93a3b73308ea354ed7d988be720c545974a17959f93f"
+ },
+ "0xe920ab4e34595482e98b2c0d16be164c49190546": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd623b1845175b206c127c08046281c013e4a3316402a771f1b3b77a9831143f5"
+ },
+ "0xe99c76a6c3b831a926ab623476d2ec14560c09b4": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x0fd8e99b1b4ab4eb8c6c2218221ae6978cc67433341ed8a1ad6185d34fa82c61",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000014": "14",
+ "0x0000000000000000000000000000000000000000000000000000000000000015": "15",
+ "0x0000000000000000000000000000000000000000000000000000000000000016": "16"
+ },
+ "key": "0x6641e3ed1f264cf275b53bb7012dabecf4c1fca700e3db989e314c24cc167074"
+ },
+ "0xe9b17e54dba3344a23160cb2b64f88024648c53e": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xb4f179efc346197df9c3a1cb3e95ea743ddde97c27b31ad472d352dba09ee1f5"
+ },
+ "0xebe708edc62858621542b7354bb478228eb95577": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7bff1b6b56891e66584ced453d09450c2fed9453b1644e8509bef9f9dd081bbb"
+ },
+ "0xebf37af41b6d7913aed3b9cc650d1e8f58a3d785": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x209b102e507b8dfc6acfe2cf55f4133b9209357af679a6d507e6ee87112bfe10"
+ },
+ "0xeda8645ba6948855e3b3cd596bbb07596d59c603": {
+ "balance": "1000000000000000000000000000000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xabd8afe9fbf5eaa36c506d7c8a2d48a35d013472f8182816be9c833be35e50da"
+ },
+ "0xef6cbd2161eaea7943ce8693b9824d23d1793ffb": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xce732a5e3b88ae26790aeb390a2bc02c449fdf57665c6d2c2b0dbce338c4377e"
+ },
+ "0xf031efa58744e97a34555ca98621d4e8a52ceb5f": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x00748bacab20da9ae19dd26a33bd10bbf825e28b3de84fc8fe1d15a21645067f"
+ },
+ "0xf068ae4089a66c79afe47d6e513f718838d8f73f": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x72c89221daedccdd3fbba66c1b081b3634ce89d5a069be97ff7832778f7b023a",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000003c": "3c",
+ "0x000000000000000000000000000000000000000000000000000000000000003d": "3d",
+ "0x000000000000000000000000000000000000000000000000000000000000003e": "3e"
+ },
+ "key": "0x37310559ceaade42e45b3e3f05925aadca9e60aeeb9dd60d824875d9e9e71e26"
+ },
+ "0xf0a279d2276de583ebcd7f69a6532f13349ad656": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x11eb0304c1baa92e67239f6947cb93e485a7db05e2b477e1167a8960458fa8cc"
+ },
+ "0xf0a5f15ef71424b5d543394ec46c46bfd2817747": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xbefe55b606a865c3898ec2093bd160b37c3976011516f43736cac2a9a7ecd4ca",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000000e0": "e0",
+ "0x00000000000000000000000000000000000000000000000000000000000000e1": "e1",
+ "0x00000000000000000000000000000000000000000000000000000000000000e2": "e2"
+ },
+ "key": "0xdbea1fd70fe1c93dfef412ce5d8565d87d6843aac044d3a015fc3db4d20a351b"
+ },
+ "0xf14d90dc2815f1fc7536fc66ca8f73562feeedd1": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xabdc44a9bc7ccf1ce76b942d25cd9d731425cd04989597d7a2e36423e2dac7ee"
+ },
+ "0xf16ba6fa61da3398815be2a6c0f7cb1351982dbc": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x728325587fa336e318b54298e1701d246c4f90d6094eb95635d8a47f080f4603"
+ },
+ "0xf1fc98c0060f0d12ae263986be65770e2ae42eae": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xca7ad42d3c4fe14ddb81bf27d4679725a1f6c3f23b688681bb6f24262d63212f"
+ },
+ "0xf4f97c88c409dcf3789b5b518da3f7d266c48806": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x84c7ee50e102d0abf5750e781c1635d60346f20ab0d5e5f9830db1a592c658ff"
+ },
+ "0xf5347043ae5fca9412ca2c72aee17a1d3ba37691": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xf390264acaf1433c0ea670b2c094a30076641469524ae24f5fddc44e99c5b032",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000004f": "4f",
+ "0x0000000000000000000000000000000000000000000000000000000000000050": "50",
+ "0x0000000000000000000000000000000000000000000000000000000000000051": "51"
+ },
+ "key": "0xa5541b637a896d30688a80b7affda987d9597aac7ccd9799c15999a1d7d094e2"
+ },
+ "0xf57fd44ccea35d9c530ef23f3e55de2f6e5415bf": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x6d4162ce16817e46fa2ddc5e70cee790b80abc3d6f7778cfbaed327c5d2af36c"
+ },
+ "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x7e839d9fd8a767e90a8b2f48a571f111dd2451bc5910cf2bf3ae79963e47e34d"
+ },
+ "0xf61ac2a10b7981a12822e3e48671ebd969bce9c2": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbfe5dee42bddd2860a8ebbcdd09f9c52a588ba38659cf5e74b07d20f396e04d4"
+ },
+ "0xf7eaadcf76ffcf006a86deb2f17d0b8fe0b211a8": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1dff76635b74ddba16bba3054cc568eed2571ea6becaabd0592b980463f157e2"
+ },
+ "0xf83af0ceb5f72a5725ffb7e5a6963647be7d8847": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x662d147a16d7c23a2ba6d3940133e65044a90985e26207501bfca9ae47a2468c"
+ },
+ "0xf8d20e598df20877e4d826246fc31ffb4615cbc0": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa248850a2e0d6fe62259d33fc498203389fa754c3bd098163e86946888e455bd"
+ },
+ "0xf91193b7442e274125c63003ee53f4ce5836f424": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xb25f9e4f6f913a4a1e8debf7d4752bfa521d147bb67c69d5855301e76dd80633",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001d5": "01d5",
+ "0x00000000000000000000000000000000000000000000000000000000000001d6": "01d6",
+ "0x00000000000000000000000000000000000000000000000000000000000001d7": "01d7"
+ },
+ "key": "0xbfe731f071443795cef55325f32e6e03c8c0d0398671548dfd5bc96b5a6555c0"
+ },
+ "0xf997ed224012b1323eb2a6a0c0044a956c6b8070": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xbcebc35bfc663ecd6d4410ee2363e5b7741ee953c7d3359aa585095e503d20c8"
+ },
+ "0xfb7b49bc3178263f3a205349c0e8060f44584500": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xa03fe040e4264070290e95ffe06bf9da0006556091f17c5df5abaa041de0c2f7"
+ },
+ "0xfb95aa98d6e6c5827a57ec17b978d647fcc01d98": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xf63360f8bb23f88b0a564f9e07631c38c73b4074ba4192d6131336ef02ee9cf2"
+ },
+ "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xd3443fa37ee617edc09a9c930be4873c21af2c47c99601d5e20483ce6d01960a"
+ },
+ "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0x1c248f110218eaae2feb51bc82e9dcc2844bf93b88172c52afcb86383d262323"
+ },
+ "0xfde502858306c235a3121e42326b53228b7ef469": {
+ "balance": "1",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe3d7213321be060ae2e1ff70871131ab3e4c9f4214a17fe9441453745c29365b"
+ },
+ "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6": {
+ "balance": "100000000000",
+ "nonce": 0,
+ "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "key": "0xe31747e6542bf4351087edfbeb23e225e4217b5fa25d385f33cd024df0c9ae12"
+ },
+ "0xfe96089d9b79f2d10f3e8b0fb9629aeb6cc7cde6": {
+ "balance": "0",
+ "nonce": 1,
+ "root": "0xcf2123d110997f426821d3e541334e43fdd6b5286c3c33252c24b5f8aafc7aa2",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {
+ "0x00000000000000000000000000000000000000000000000000000000000001d0": "01d0",
+ "0x00000000000000000000000000000000000000000000000000000000000001d1": "01d1",
+ "0x00000000000000000000000000000000000000000000000000000000000001d2": "01d2"
+ },
+ "key": "0xbf632670b6fa18a8ad174a36180202bfef9a92c2eeda55412460491ae0f6a969"
+ }
+ }
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/newpayload.json b/cmd/devp2p/internal/ethtest/testdata/newpayload.json
new file mode 100644
index 0000000000..7f8c99afa9
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/newpayload.json
@@ -0,0 +1,13268 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": "np72",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0x9e8a444b740df016941ecc815fe9eebeaa04a047db6569855573a52a8cb78cdd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x74035b613e4ea1072fd029f35d0fa5b26fbfaa54cabebcec88b9ee07cca321ae",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x48",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x2d0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x568d2f9",
+ "blockHash": "0xf0a50b18d597552b6ad8a711f4ac1f7ab225d59daa74137f689256a16a0ff809",
+ "transactions": [
+ "0xf86a39840568d2fa8252089444bd7ae60f478fae1061e11a7739f4b94d1daf9101808718e5bb3abd10a0a050fc2310f542cf90b3376f54d296158f5be7ad852db200f9956e3210c0f8125ca04f880fe872915a7843c37147a69758eff0a93cfaf8ce54f36502190e54b6e5c7"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np73",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0xf0a50b18d597552b6ad8a711f4ac1f7ab225d59daa74137f689256a16a0ff809",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x18b68edcdfc835d5db51310e7960eaf0c0afcc5a6611282d2085f3282b2f9e3f",
+ "receiptsRoot": "0xabc882591cb5b81b276a4e5cd873e1be7e1b4a69f630d2127f06d63c8db5acb2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x49",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146e8",
+ "timestamp": "0x2da",
+ "extraData": "0x",
+ "baseFeePerGas": "0x4bbd14a",
+ "blockHash": "0x662ab680f6b14375e7642874a16a514d1ecffc9921a9d8e143b5ade129ad554b",
+ "transactions": [
+ "0xf8853a8404bbd14b830146e88080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a027748abc264040530bca00d1cc86b199586c1fe26955cd5e250b97e2b9ca3128a050a822d9df3b63e6911766d4ae8c722f5afee7a6c06a7b5eb73772a5b137ca36"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np74",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0x662ab680f6b14375e7642874a16a514d1ecffc9921a9d8e143b5ade129ad554b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6fb7295e0a62bff03ddeba56ba643cd817fab6bc8df11309f8e8a3dbcf7d502e",
+ "receiptsRoot": "0x7b9d8080a095524251324dc00e77d3ecf4c249c48eebed2e4a5acedc678c70b4",
+ "logsBloom": "0x000800000000000000000000000000000900000000000000000000000000c0080000000000000010000000020000000000000004100000000480008020100000000000000000000000000000001000200000000000000010000010000000000000000000000000000000000000000000000000000000000200000000000000800001000000000000000000000000000000000004000000000000000800000000008000000000000001000000000002000000000000000000000000000000080000000000000000200404000000000000000000000000000000000000000000000000080100000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc61",
+ "timestamp": "0x2e4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x424ad37",
+ "blockHash": "0x9981d4e953d402b0b1554ef62ebbeb7760790a5e53191c9753329b6a3eab3d13",
+ "transactions": [
+ "0xf87c3b840424ad3883011f548080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a050e3677064fe82b08a8fae8cea250fbaf00dbca1b6921cffd311ca17c7979865a051e738138eab4b31f1ba163b8ed2cfd778af98eff583cd5a26fcd9bd673fe027"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np75",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0x9981d4e953d402b0b1554ef62ebbeb7760790a5e53191c9753329b6a3eab3d13",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x65038690e44bf1ee49d47beb6efc7cc84d7f01d2ba645768e3a584a50979b36d",
+ "receiptsRoot": "0xf5419129ce2f36d1b2206d4723f3e499691ad9aee741223426cda1b22e601a19",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36c",
+ "timestamp": "0x2ee",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3a051bc",
+ "blockHash": "0xc5e8361f3f3ba7bfbed66940c015f351d498ed34d48f8de6e020ffffbcbbec61",
+ "transactions": [
+ "0xf8673c8403a051bd83020888808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0dd01417c1ac62f9e593b07848f93c1f5ab729e73a493e22141f6e1c6e8a4f94fa00b9e979c6bae8ab4a90b7b2ba61d590d800e5411bc12be320efc3fb7310506e3"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np76",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0xc5e8361f3f3ba7bfbed66940c015f351d498ed34d48f8de6e020ffffbcbbec61",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b8d5706f2e3d66bb968de876e2683d75dce76d04118bc0184d6af44fb10196f",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x2f8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x32ca5cf",
+ "blockHash": "0xcb51fdebc936f135546a0ff78a7ce246aee0a5c73b41b7accdc547825bb97766",
+ "transactions": [
+ "0x02f86d870c72dd9d5e883e3d0184032ca5d08252089472dfcfb0c470ac255cde83fb8fe38de8a128188e0180c080a0116da1fc19daf120ddc2cc3fa0a834f9c176028e65d5f5d4c86834a0b4fe2a36a017001c3ad456650dd1b28c12f41c94f50b4571da5b62e9f2a95dff4c8c3f61fd"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np77",
+ "method": "engine_newPayloadV1",
+ "params": [
+ {
+ "parentHash": "0xcb51fdebc936f135546a0ff78a7ce246aee0a5c73b41b7accdc547825bb97766",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b8d17721b733ce2b6e7607a69fb6bf678dbabcb708f64cb5d211915b3238090",
+ "receiptsRoot": "0xabc882591cb5b81b276a4e5cd873e1be7e1b4a69f630d2127f06d63c8db5acb2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146e8",
+ "timestamp": "0x302",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2c71f92",
+ "blockHash": "0x49b74bc0dea88f3125f95f1eb9c0503e90440f7f23b362c4f66269a14a2dcc3e",
+ "transactions": [
+ "0xf8853e8402c71f93830146e88080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00cb7fb1bba811ea1948e035550c66840f0491d29d0ae9a6e4726e77a57ca8058a041523fc7133a6473784720a68d7f7f1d54d8a5a1f868640783a0284fb22f4309"
+ ],
+ "withdrawals": null,
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np78",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x49b74bc0dea88f3125f95f1eb9c0503e90440f7f23b362c4f66269a14a2dcc3e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf21b9b380d6c5833270617a17ea187e1f85a6556f1c1dfaf6bcb0700c88abe24",
+ "receiptsRoot": "0xb08f0ccb7116304320035e77c514c9234f2d5a916d68de82ba20f0a24ab6d9e4",
+ "logsBloom": "0x00000000000000400000000000200000000000000000000000000000000000000000200010000000000000000000000000000040000400000010000000000020000000000000000000000000000000000000000000000000000000900000000000800000000800000010000008000000000000000000000102000000000000100000080000000100000000000000000000000000000008000000000000008000800800000000000000000000400000000008200000000200200000000000000000000000000000200000000000000000000000000000000000000000000000000000000011000000000000800000000000000000000000000000000000000008",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x30c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x26e6e24",
+ "blockHash": "0x157062b78da942ff0b0e892142e8230ffdf9330f60c5f82c2d66291a6472fd7c",
+ "transactions": [
+ "0xf87c3f84026e6e2583011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0fa1ba7a3639ec15944466d72a2e972d5eda143fc54f07aa47ecd56769ba5fbf8a041018f9af7a55685cbfa25d35f353e4bccef32a5e0bcdb373191d34cfed9a8db"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np79",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x157062b78da942ff0b0e892142e8230ffdf9330f60c5f82c2d66291a6472fd7c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8bb2c279cf46bd7eb856cc00fdce9bb396b21f65da47fdf0f13b41e0c0e0aa7f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x4f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x316",
+ "extraData": "0x",
+ "baseFeePerGas": "0x220c283",
+ "blockHash": "0x39a05d1b50f4334060d2b37724df159784c5cbfe1a679f3b99d9f725aed4d619",
+ "transactions": [
+ "0xf86740840220c2848302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0bcd36ef6498fd3ce093febc53b3e35004a9d9200816306515f5ffad98140426fa00656b7e75310845c1d2e47495ed7765d687f0a943a604644d9cf7b97b01f300f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np80",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x39a05d1b50f4334060d2b37724df159784c5cbfe1a679f3b99d9f725aed4d619",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x62b57c9d164c28bc924ec89b1fe49adc736ee45e171f759f697899a766e3f7a4",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x50",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x320",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1dce188",
+ "blockHash": "0xa7806a3f4d0f3d523bf65b89164372b524c897688d22d2ef2e218f7abb9cbddb",
+ "transactions": [
+ "0xf869418401dce189825208945c62e091b8c0565f1bafad0dad5934276143ae2c01808718e5bb3abd10a0a0b82a5be85322581d1e611c5871123983563adb99e97980574d63257ab98807d59fdd49901bf0b0077d71c9922c4bd8449a78e2918c6d183a6653be9aaa334148"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np81",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0xa7806a3f4d0f3d523bf65b89164372b524c897688d22d2ef2e218f7abb9cbddb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1820989c0844509c8b60af1baa9030bdcc357bc9462b8612493af9d17c76eb3d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x51",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x32a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1a14dd8",
+ "blockHash": "0x7ec45b0f5667acb560d6e0fee704bb74f7738deb2711e5f380e4a9b2528d29c1",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x0",
+ "validatorIndex": "0x5",
+ "address": "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np82",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x7ec45b0f5667acb560d6e0fee704bb74f7738deb2711e5f380e4a9b2528d29c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8145365a52eb3a4b608966d28a8ed05598c13af426c7ab24f28f2bdc7a00b12b",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x52",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x334",
+ "extraData": "0x",
+ "baseFeePerGas": "0x16d241d",
+ "blockHash": "0x8dbcafaa0e32cd9f71f1d5b0f22f549aee0fddce3bda577ac200e24c7dc8ba62",
+ "transactions": [
+ "0xf8854284016d241e830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a061c5ecaf5f73e89370f5b35c31bce60d04c7417cc70cc897beae6429cb6d3880a02271644378271ec296459da5181507d52bdbd4489600690c32998cdb4b032042"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np83",
+ "method": "engine_newPayloadV2",
+ "params": [
+ {
+ "parentHash": "0x8dbcafaa0e32cd9f71f1d5b0f22f549aee0fddce3bda577ac200e24c7dc8ba62",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x07cc0bca2e8f3b243635dc6f988372dd2427b6090f1035d06f2eff2e99315170",
+ "receiptsRoot": "0xace7ae7e3c226cecca4b33082b19cd1023960138a576ef77fddadcc223b4250a",
+ "logsBloom": "0x40000010010000000000000100000c00000001000000000000000000000000000000000200000000000042000000000000001000000000000000000000000000000000000000000000000820040000800000000000004000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000800000001000000000000000000000000000000000000000004000004000000000000000410000000000000000000000040000000000000000004000000000000000000000000000400001000000000000000000400000000000000000000200080000000000000000000000010000000040000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x53",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x33e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x13f998a",
+ "blockHash": "0x686c223412a42d17a7fe0fe2a8b15d6181afa366cccd26a0b35a7581c0686721",
+ "transactions": [
+ "0xf87c4384013f998b83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a01001f6f02c9dac33915eb5d0fe81d88599a29341d84ee6f46b1ef05d270a0c1fa05ea1dbc664d9f4a83b4743bc40579e6b727ff8b5e78c4249bd59aa47c33d770f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": null,
+ "excessBlobGas": null
+ }
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np84",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x686c223412a42d17a7fe0fe2a8b15d6181afa366cccd26a0b35a7581c0686721",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe1a71059650ccefaf7d0a407c43a87ccc9fe63a6369a46509074658f714c54ad",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x54",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x348",
+ "extraData": "0x",
+ "baseFeePerGas": "0x117b7e1",
+ "blockHash": "0x8a76d39e76bdf6ccf937b5253ae5c1db1bdc80ca64a71edccd41ba0c35b17b84",
+ "transactions": [
+ "0xf86744840117b7e28302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0b4a7e6c791f457a428f870b8df8ee0148acac74050aeea658c3dad552a7e8140a0793951ba22a6f628dd86ec8964b09c74e0f77306a28dd276dfe42f40ee76c73c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x83472eda6eb475906aeeb7f09e757ba9f6663b9f6a5bf8611d6306f677f67ebd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np85",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8a76d39e76bdf6ccf937b5253ae5c1db1bdc80ca64a71edccd41ba0c35b17b84",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x198575d6df4370febe3a96865e4a2280a5caa2f7bd55058b27ea5f3082db8d99",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x55",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x352",
+ "extraData": "0x",
+ "baseFeePerGas": "0xf4dd4f",
+ "blockHash": "0xc0d03736d9e3c2d4e14115f9702497daf53b39875122e51932f4b9b752ba7059",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e450183f4dd5082520894a25513c7e0f6eaa80a3337ee18081b9e2ed09e000180c080a0e8ac7cb5028b3e20e8fc1ec90520dab2be89c8f50f4a14e315f6aa2229d33ce8a07c2504ac2e5b2fe4d430db81a923f6cc2d73b8fd71281d9f4e75ee9fc18759b9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2c809fbc7e3991c8ab560d1431fa8b6f25be4ab50977f0294dfeca9677866b6e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np86",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc0d03736d9e3c2d4e14115f9702497daf53b39875122e51932f4b9b752ba7059",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x90c402a8569aae0c095540a9762aefac4f43df4e97fc7a24df1d4051c555bc2c",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x56",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x35c",
+ "extraData": "0x",
+ "baseFeePerGas": "0xd64603",
+ "blockHash": "0xa7323a02aa9acf63f26368292292d4bcb9dc7ef33296bbd98f423b24db3408bd",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1",
+ "validatorIndex": "0x5",
+ "address": "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x756e335a8778f6aadb2cc18c5bc68892da05a4d8b458eee5ce3335a024000c67"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np87",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa7323a02aa9acf63f26368292292d4bcb9dc7ef33296bbd98f423b24db3408bd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7e1765cf5abdf835814ee20c9e401b0e99e2b31f2ad8ea14c62ef732c6e63d2d",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x57",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x366",
+ "extraData": "0x",
+ "baseFeePerGas": "0xbb7d43",
+ "blockHash": "0xbbd89c9c2805888d9d1397d066495db1ce1c570e23b5b6f853dc0ff698575a04",
+ "transactions": [
+ "0xf8844683bb7d44830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a052c928a2062b214d44b9a641faf87e439fbc5a07f571021f0f3c8fd2a2087a57a0650c77ab1cd522a7d3a435058f53636b6ae86d19fd4f691bf61c13fd8b7de69a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4b118bd31ed2c4eeb81dc9e3919e9989994333fe36f147c2930f12c53f0d3c78"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np88",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbbd89c9c2805888d9d1397d066495db1ce1c570e23b5b6f853dc0ff698575a04",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3ec8183c28814317cb7a7b86633041db40de94b45a47dab5614b21087c308648",
+ "receiptsRoot": "0xe2e7a47b1c0009f35c3a46c96e604a459822fe9f02929afa823f2c514f1fbd39",
+ "logsBloom": "0x00000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000200000000008000000000000000000000000000000800000000000000800000000000000000000002000000000100000000000000000000000000000000000000001000000000400000000000000000000000000000000001000000000000000000000000000000000000000000000020000000000000400000000000000100000000000100000000000000000000100200000000000000000000000000000010400000000000000050080004000000400000000010000000800030001000000000000000004000000000000000000a00",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x58",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x370",
+ "extraData": "0x",
+ "baseFeePerGas": "0xa41aed",
+ "blockHash": "0xe67371f91330dd937081250eeda098394453c2ced0b6ffd31a67f8d95261d849",
+ "transactions": [
+ "0xf87b4783a41aee83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa09799e22509fcf203235570e7ba0df80bad6124b89b812146b50bca27f03161a9a0118a4f264815d7cf1a069009bff736f04369e19e364bd1a409a4c4865ec7d81f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd0122166752d729620d41114ff5a94d36e5d3e01b449c23844900c023d1650a5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np89",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe67371f91330dd937081250eeda098394453c2ced0b6ffd31a67f8d95261d849",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x07118ca8999c49a924f92b54d21cecad7cbcc27401d16181bbcdee05b613399c",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x59",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x37a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8fa090",
+ "blockHash": "0x395eda9767326b57bbab88abee96eea91286c412a7297bedc3f1956f56db8b18",
+ "transactions": [
+ "0xf86648838fa0918302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0fd5a86a96cbf94d2bba5c7fb6efd2bf501dd30c8b37e896ae360b40ab693272aa0331e570a5b3ce2cef67731c331bba3e6de2ede8145dd0719ce6dfcca587c64ba"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x60c606c4c44709ac87b367f42d2453744639fc5bee099a11f170de98408c8089"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np90",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x395eda9767326b57bbab88abee96eea91286c412a7297bedc3f1956f56db8b18",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0d9d080dde44cc511dc9dc457b9839409e1b3a186e6b9a5ae642b5354acc6cc4",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x384",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7dbb15",
+ "blockHash": "0x919c92e04181d139a4860cce64252ab9c14a5be9fa6adfc76b4b27f804fce2b9",
+ "transactions": [
+ "0xf86949837dbb1682520894bbeebd879e1dff6918546dc0c179fdde505f2a2101808718e5bb3abd10a0a002f0119acaae03520f87748a1a855d0ef7ac4d5d1961d8f72f42734b5316a849a0182ad3a9efddba6be75007e91afe800869a18a36a11feee4743dde2ab6cc54d9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6ee04e1c27edad89a8e5a2253e4d9cca06e4f57d063ed4fe7cc1c478bb57eeca"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np91",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x919c92e04181d139a4860cce64252ab9c14a5be9fa6adfc76b4b27f804fce2b9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa5aea2e2c617a5a3a341e01c72fbf960e809dd589b4a988a04d50f6fb666b6c8",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x38e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x6e05f1",
+ "blockHash": "0x17a574ee7489840acc4a8aecd1d7b540ba9b033b7236c13d0b0a5403ff07f7f3",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2",
+ "validatorIndex": "0x5",
+ "address": "0x245843abef9e72e7efac30138a994bf6301e7e1d",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x36616354a17658eb3c3e8e5adda6253660e3744cb8b213006f04302b723749a8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np92",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x17a574ee7489840acc4a8aecd1d7b540ba9b033b7236c13d0b0a5403ff07f7f3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd1e927e1a7106591aa46d3e327e9e7d493248786b4c6284bd138d329c6cb1fbb",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x398",
+ "extraData": "0x",
+ "baseFeePerGas": "0x604533",
+ "blockHash": "0x7848fe02daea45d47101fbe84b6d94576452c2d0cb9261bc346343b5b2df844f",
+ "transactions": [
+ "0xf8844a83604534830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0667955bfddc6500ad6a0a298d08a0fdeb453d483be41f7496f557039c99d5b8ea06ad5f6871f3d78ea543484d51590454f8a65b5b1b89f58992ff94a02a30c0c93"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc13802d4378dcb9c616f0c60ea0edd90e6c2dacf61f39ca06add0eaa67473b94"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np93",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7848fe02daea45d47101fbe84b6d94576452c2d0cb9261bc346343b5b2df844f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8d4e68f0a1ad7578b1627d665263c04856efa4eb4938014a8c794547d597f89b",
+ "receiptsRoot": "0xa37a62134a71ef21b16f2eee431b806a4d13c0a80a11ddeb5cbb18e3707aecdf",
+ "logsBloom": "0x00000000000000000000000002000000000021000000000000000000240000000000000000000000000004000000010000000000000000000000000000000000000008000000000000000000000000000020000000000000000400000400000000000400000000000000000000000000000000000080000004000000000000000000000000000800000000000000000000000000000000000000000000002000000080000002010000420000000000000000000000000040402002000200000000000000000000000000008000000000000000000000000100000000000000000000000000000000000084000000000080000000000000000000040000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x3a2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x544364",
+ "blockHash": "0x6c5d29870c54d8c4e318523a7ea7fb9756b6633bbdf70dcb1e4659ff3564615b",
+ "transactions": [
+ "0xf87b4b8354436583011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09662003f67b0c146ecaa0c074b010d1f27d0803dc1809fd4f6ea80a5f09c34aea0100a5c0fbfdbee733f1baecb893a33ce2d42316303a5ddf1515645dfbb40d103"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8b345497936c51d077f414534be3f70472e4df101dee8820eaaff91a6624557b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np94",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6c5d29870c54d8c4e318523a7ea7fb9756b6633bbdf70dcb1e4659ff3564615b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbd07ab096fc1b3e50229bcff0fc5fca9e9f7d368e77fe43a71e468b7b0adb133",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x3ac",
+ "extraData": "0x",
+ "baseFeePerGas": "0x49bf97",
+ "blockHash": "0xe7b8c1ca432a521b1e7f0cf3cb63be25da67e3364cc0b02b0a28e06ba8deed80",
+ "transactions": [
+ "0xf8664c8349bf988302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa03b3113a7b1919311fbc03ee25c4829b60f07341c72107de061da06eef7ec0856a01bc4eeb29301e1610984ee042f8236863ad78402d3d55c69a6922d67238dde75"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe958485d4b3e47b38014cc4eaeb75f13228072e7b362a56fc3ffe10155882629"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np95",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe7b8c1ca432a521b1e7f0cf3cb63be25da67e3364cc0b02b0a28e06ba8deed80",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4a154c665e5b68adadf9455bd905da607f0279b5d2b4bfb0c1a3db5b6a908d4d",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x3b6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x408f22",
+ "blockHash": "0xaa62b2faefe50fe1562f3fb5bf96a765ca7c92164465e226fc9a8ba75cabc387",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e4d0183408f2382520894d2e2adf7177b7a8afddbc12d1634cf23ea1a71020180c001a08556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6a01cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3346706b38a2331556153113383581bc6f66f209fdef502f9fc9b6daf6ea555e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np96",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaa62b2faefe50fe1562f3fb5bf96a765ca7c92164465e226fc9a8ba75cabc387",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b2adb11488a7634a20bc6f81bcc0211993fe790f75eeb1f4889a98d1bdbcb37",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x60",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x3c0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x387e65",
+ "blockHash": "0x6a6df67e09c4411bb89664cbc78f78237bb6a2fc299bc6a682cca406feb8dd4d",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3",
+ "validatorIndex": "0x5",
+ "address": "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x346910f7e777c596be32f0dcf46ccfda2efe8d6c5d3abbfe0f76dba7437f5dad"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np97",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6a6df67e09c4411bb89664cbc78f78237bb6a2fc299bc6a682cca406feb8dd4d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd67c810501ca4f4ee4262e86dcaf793ca75637249bf157dee4800274372f236f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x61",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x3ca",
+ "extraData": "0x",
+ "baseFeePerGas": "0x316e99",
+ "blockHash": "0xfec8ebc1c3d312ec3537d860b406110aeac3980763165d0026ecab156a377bdf",
+ "transactions": [
+ "0xf8844e83316e9a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a036b2adb5bbd4d43198587067bf0b669e00862b0807adb947ee4c9869d79f9d8ca063e0b200645435853dceed29fd3b4c55d94b868a0aa6513ca6bd730705f2c9ef"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe62a7bd9263534b752176d1ff1d428fcc370a3b176c4a6312b6016c2d5f8d546"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np98",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfec8ebc1c3d312ec3537d860b406110aeac3980763165d0026ecab156a377bdf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xae82dda9df38bcc8d99e311b63ae055591953577b6b560840658eca24ecacee9",
+ "receiptsRoot": "0x675ab823f90b9bdd3d04afb108bc1a1dcd77654a0de4c8a539e355b6d24f29f4",
+ "logsBloom": "0x10000000000000000010000000000020000000000008000000000000000000000000000000000000000000020000000000000000000000000000040000010000000000000000000000000000000000000000000000008000000000000000000000000080000110000000000800000002000000800040800000000040000000000000004000000000001000000000000000000000000000000000008000000000000000000000000000000020010080001000000000000000000000000004008000004000008000000000000000040000000400000000000001000000000000000000000008000000000000000000000200000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x62",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x3d4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2b4449",
+ "blockHash": "0x3124d842afa1334bb72f0a8f058d7d3ad489d6c6bd684f81d3ecdf71d287f517",
+ "transactions": [
+ "0xf87b4f832b444a83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0824522ae97a912dd75a883798f4f296d960f6a7be8510e2a4a121d85f496da16a008cade93390e31f7b0e6615b4defe3bd4225b7a4d97a7835c02ad0b4d004fb5b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xffe267d11268388fd0426a627dedddeb075d68327df9172c0445cd2979ec7e4d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np99",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3124d842afa1334bb72f0a8f058d7d3ad489d6c6bd684f81d3ecdf71d287f517",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x588419f24b32499745bbae81eb1a303d563c31b2743c8621d39b820c2affb3cb",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x63",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x3de",
+ "extraData": "0x",
+ "baseFeePerGas": "0x25de20",
+ "blockHash": "0x53d785a42c58a40edbc18e6bee93d4072a4281c744f697f9b5cae1d0b3bf2962",
+ "transactions": [
+ "0xf866508325de218302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0744b7f5fb26cc6dd16b1849d0c04236e3b4e993f37e5b91de6e55f5f899450baa0456225c91372bddd4e3a1dde449e59ad62d63f0c850f9b869870ea2621494fd7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x23cc648c9cd82c08214882b7e28e026d6eb56920f90f64731bb09b6acf515427"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np100",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x53d785a42c58a40edbc18e6bee93d4072a4281c744f697f9b5cae1d0b3bf2962",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfee7a27147c7984caec35dc4cee4f3a38fee046e5d8f17ce7ec82b982decd9aa",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x64",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x3e8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x212635",
+ "blockHash": "0x96d2a59527aa149efe64eef6b2fbf4722c9c833aba48e0c7cb0cb4033fa1af5e",
+ "transactions": [
+ "0xf86951832126368252089418ac3e7343f016890c510e93f935261169d9e3f501808718e5bb3abd10a0a099aba91f70df4d53679a578ed17e955f944dc96c7c449506b577ac1288dac6d4a0582c7577f2343dd5a7c7892e723e98122227fca8486debd9a43cd86f65d4448a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x47c896f5986ec29f58ec60eec56ed176910779e9fc9cf45c3c090126aeb21acd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np101",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x96d2a59527aa149efe64eef6b2fbf4722c9c833aba48e0c7cb0cb4033fa1af5e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb1600603ea31446c716fece48a379fb946eab40182133a8032914e868bb4929e",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x65",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x3f2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1d0206",
+ "blockHash": "0xf2750d7772a6dcdcad79562ddf2dee24c1c2b7862905024a8468adfb62f8ef14",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4",
+ "validatorIndex": "0x5",
+ "address": "0x3f79bb7b435b05321651daefd374cdc681dc06fa",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6d19894928a3ab44077bb85dcb47e0865ce1c4c187bba26bad059aa774c03cfe"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np102",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf2750d7772a6dcdcad79562ddf2dee24c1c2b7862905024a8468adfb62f8ef14",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd3908889240ecc36175f7ac23e9596230ea200b98ee9c9ca078154288b69c637",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x66",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x3fc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1961c6",
+ "blockHash": "0x57054aa8d635c98b3b71d24e11e22e9235bc384995b7b7b4acd5ca271d0898b4",
+ "transactions": [
+ "0xf88452831961c7830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0c43b4e8ddaecaadfc1fd4b35659ced2bbaa2ab24b1cff975685cd35f486a723fa056a91d2ff05b4eae02ee1d87442ec57759e66ec13bfd3ea2655cf4f04b6e863d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xefc50f4fc1430b6d5d043065201692a4a02252fef0699394631f5213a5667547"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np103",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x57054aa8d635c98b3b71d24e11e22e9235bc384995b7b7b4acd5ca271d0898b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd66957c43447a6edfb6b9bc9c4e985f28c24e6ce3253c68e5937c31c5d376f94",
+ "receiptsRoot": "0xd99d12e61c8e9be69f1eb49cea2f72664c7e569463415b064954bf5e0dbc6a01",
+ "logsBloom": "0x00000000000000000000100000000000200000000000000000200000000000000000000000040000000000200000000000000000000000000200000000000000000018000000000000000000010000000000000000000000000000000000100000000000000000000000000000000000000000000000000000800200000000021000000000002000000000002088400000000000000000000000000000000000000000000000000000000010000000000800000080000000000000000000000008000000000000000020000100001000000000080000002000400000000400000000000000002200000000000000000000000000000000000000000020000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x67",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x406",
+ "extraData": "0x",
+ "baseFeePerGas": "0x16375b",
+ "blockHash": "0xf4f1f726bcb9a3db29481be3a2e00c6ab4bf594ae85927414540ec9ede649d4d",
+ "transactions": [
+ "0xf87b538316375c83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0e59d36f30ed2dfc5eb71433457547f63bf4ad98e0a2181c4373a5e7ddf04d17ea06dce4f88f48f6fd93c2c834537a8baef27bb2965b9e2ce68dc437adb3d657d28"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3cc9f65fc1f46927eb46fbf6d14bc94af078fe8ff982a984bdd117152cd1549f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np104",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf4f1f726bcb9a3db29481be3a2e00c6ab4bf594ae85927414540ec9ede649d4d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe06685d528d0c69051bcf8a6776d6c96c1f1c203da29851979c037be2faac486",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x68",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x410",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1371a8",
+ "blockHash": "0xc8fe6583a2370fa9bda247532a8fb7845fceea9b54c9e81cda787947bb0ad41d",
+ "transactions": [
+ "0xf86654831371a98302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0a427e65413948a8a1cf63c15214525d05bffca4667149c6a4019513defe57e6ba02819aa7d6a404a7f0194ef3ba7ec45b876f4226b278ebbcfa4012a90a1af3905"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x63eb547e9325bc34fbbbdfda327a71dc929fd8ab6509795e56479e95dbd40a80"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np105",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc8fe6583a2370fa9bda247532a8fb7845fceea9b54c9e81cda787947bb0ad41d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x32d5d07d12d91b8b4392872b740f46492fea678e9f5dc334c21101767bd54833",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x69",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x41a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x11056d",
+ "blockHash": "0xb30b266de816c61ef16e4abfc94fbed8b4032710f4275407df2bf716a1f0bbd7",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e55018311056e82520894de7d1b721a1e0632b7cf04edf5032c8ecffa9f9a0180c080a02a6c70afb68bff0d4e452f17042700e1ea43c10fc75e55d842344c1eb55e2e97a027c64f6f48cfa60dc47bfb2063f9f742a0a4f284d6b65cb394871caca2928cde"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x67317288cf707b0325748c7947e2dda5e8b41e45e62330d00d80e9be403e5c4c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np106",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb30b266de816c61ef16e4abfc94fbed8b4032710f4275407df2bf716a1f0bbd7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf89d6d5f7a16d98062e1ef668ee9a1819b0634bd768ece2fc2b687f8968dc373",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x424",
+ "extraData": "0x",
+ "baseFeePerGas": "0xee50e",
+ "blockHash": "0x35221530b572a05628d99d8ca9434287c581e30473f83d612cbbfb7f394c587b",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x5",
+ "validatorIndex": "0x5",
+ "address": "0x189f40034be7a199f1fa9891668ee3ab6049f82d",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7fc37e0d22626f96f345b05516c8a3676b9e1de01d354e5eb9524f6776966885"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np107",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x35221530b572a05628d99d8ca9434287c581e30473f83d612cbbfb7f394c587b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaf4107a57da519d24d0c0e3ae6a5c81f3958ddc49e3f1c2792154b47d58d79a1",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x42e",
+ "extraData": "0x",
+ "baseFeePerGas": "0xd086d",
+ "blockHash": "0xe3981baf40fc5dac54055fab95177a854a37ff2627208247697d5627b8ae3c35",
+ "transactions": [
+ "0xf88456830d086e830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a04c088a3642c3cfad977a0927e6d694bd26be96246f127f03d37fe2b494b99da2a00ef5b6e7aca1ac95ef964978a7ec4bb66688fbb7abace43f90f0c344196379e5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc8c5ffb6f192e9bda046ecd4ebb995af53c9dd6040f4ba8d8db9292c1310e43f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np108",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe3981baf40fc5dac54055fab95177a854a37ff2627208247697d5627b8ae3c35",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9afc46d870489ac06cac1ea0b65c417d8e0086f0fb828dd92dca30da737c827b",
+ "receiptsRoot": "0x9b9c6d15a59d6b1c222cc63abe6aa28d734463877a3c34d4b3d9e80b768b77aa",
+ "logsBloom": "0x00000000000000000000000000000080000000000002000000000002000000000000004000000000000000000000010000000000000000000000000000000000000400000000000000100000000000000000200000000000000000000200000000000000000008000010000000000000000080000000000200000008000400000000000000000400000000000000000008000000001000000001000000000000000000000000008000000200000000000000000008400000000000000000000000001000000000000000000000001000010000000020000000040000000000000000000000000000000200080000000000000000000000040000000200000400",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x438",
+ "extraData": "0x",
+ "baseFeePerGas": "0xb684d",
+ "blockHash": "0x54fcc3af800dbeae5c45ac8acba05313bd8d4c1bb06502702a14a225259367aa",
+ "transactions": [
+ "0xf87b57830b684e83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a06789a9252207970001fd703c22b2b7e5c0388bf018bc070a0469129f80cc5d63a048de0e437b02a8dd3a783892ad1691a1062cd73ddd35c481d9632f5158650317"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe40a9cfd9babe862d482ca0c07c0a4086641d16c066620cb048c6e673c5a4f91"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np109",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x54fcc3af800dbeae5c45ac8acba05313bd8d4c1bb06502702a14a225259367aa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x02324f55d0548cb8743857fe938f91e6f15bfbe94654aadde56c59f83083980a",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x442",
+ "extraData": "0x",
+ "baseFeePerGas": "0x9fbe4",
+ "blockHash": "0x62bb35defc0aac7bfbe789de02062f7ac622e9e354cfea5dceeccb792a61bae3",
+ "transactions": [
+ "0xf866588309fbe58302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07e3ef87807ccd797a0020fade1b7d65a7b190fbe40a6f8bdc35cd6a3a6fbed73a0283ad99e27eb389ca3b389bce3c29b3c711b74b6ecd05b290c7be33389830fab"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe82e7cff48aea45fb3f7b199b0b173497bf4c5ea66ff840e2ec618d7eb3d7470"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np110",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x62bb35defc0aac7bfbe789de02062f7ac622e9e354cfea5dceeccb792a61bae3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9932915761c4c894fc50819df189e875d3b025a7c045406fe415abe61d0e3086",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x44c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8bd6c",
+ "blockHash": "0x2c4731fbb4f4adae94723c078548c510649e8973dfdb229fd6031b1b06eb75c0",
+ "transactions": [
+ "0xf869598308bd6d825208941b16b1df538ba12dc3f97edbb85caa7050d46c1401808718e5bb3abd109fa0abbde17fddcc6495e854f86ae50052db04671ae3b6f502d45ba1363ae68ee62ca03aa20e294b56797a930e48eda73a4b036b0d9389893806f65af26b05f303100f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x84ceda57767ea709da7ab17897a70da1868c9670931da38f2438519a5249534d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np111",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2c4731fbb4f4adae94723c078548c510649e8973dfdb229fd6031b1b06eb75c0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2849b35fb3ec8146f637be768e3eaefda559928f8bb35753584d5b326a400ff5",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x6f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x456",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7a5e7",
+ "blockHash": "0x76b385d3f8a4b6e66ea8c246ed7c6275ad164d028ec5a986f9524bfe7437dcc7",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x6",
+ "validatorIndex": "0x5",
+ "address": "0x65c74c15a686187bb6bbf9958f494fc6b8006803",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe9dcf640383969359c944cff24b75f71740627f596110ee8568fa09f9a06db1c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np112",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x76b385d3f8a4b6e66ea8c246ed7c6275ad164d028ec5a986f9524bfe7437dcc7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2f24b6182543c677e7d1cab81bc020033c64e034571a20ecd632e252c8f202b3",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x70",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x460",
+ "extraData": "0x",
+ "baseFeePerGas": "0x6b12b",
+ "blockHash": "0x33385ec44cfd01ba27c927a3ebe607a27e55fd8e89965af09b991a7cdc127dbc",
+ "transactions": [
+ "0xf8845a8306b12c830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bf8a8863f63a16d43652b12e54dc61bd71c8ab86d88aebb756c6e420fca56a1aa01f62e0032c57f1629ee82b4fefb8d6c59a85c5c2889b1671ce0713581e773b6e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x430ef678bb92f1af44dcd77af9c5b59fb87d0fc4a09901a54398ad5b7e19a8f4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np113",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x33385ec44cfd01ba27c927a3ebe607a27e55fd8e89965af09b991a7cdc127dbc",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6d6c9c24ef7d93db6ba57324fb6f3604b09611301e12d250162c2b2b50871625",
+ "receiptsRoot": "0x257c29f688aaf63db2244378182225d104d84cfbd188c82b92323623d11574e9",
+ "logsBloom": "0x00000000000000000000080040000000000000000000000000008000000000000000000000000000000000000001000000000000000000000040000000040010000100000000000000400000000000000000020000000000000000800000000400000000000000000000000040000000000002000100400000000000000200000000000000000000000008000000010000000000000800000000000000000000000080000000000000000000000000000000080400000000000000000000400000000000010000000004000000000000000000000010020000000000000000000000000000000100000000040000000000000000000000200000001800000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x71",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x46a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x5db80",
+ "blockHash": "0x66ad7aaacf3efede70dda0c82629af2046e67b96713cf3cf02a9a2613ca25b6f",
+ "transactions": [
+ "0xf87b5b8305db8183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0f893fcd21c2a882bc3968ea3c41dd37a8dbfbf07a34a8694a49fdd8081996e25a0502578b516e04b1939fdad45fd0688e636d57f59826a8e252b63f496b919d91c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf7af0b8b729cd17b7826259bc183b196dbd318bd7229d5e8085bf4849c0b12bf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np114",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x66ad7aaacf3efede70dda0c82629af2046e67b96713cf3cf02a9a2613ca25b6f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x61c50266ae62e14edea48c9238f79f6369fd44e7f3d6519c7139aa1e87ee13ba",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x72",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x474",
+ "extraData": "0x",
+ "baseFeePerGas": "0x52063",
+ "blockHash": "0x00fd70a53be9c85c986d3dd87f46e079e4ce4a4a3dd95c1e497457c50bacbe2d",
+ "transactions": [
+ "0xf8665c830520648302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0961de3e3657fdc49c722cc23de35eaf41de51c3aab3ca9a09b3d358fc19195aca060ee48b2fad3f3798111a93038fcb5c9c9791daf3c6acbaf70134fd182b5c663"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe134e19217f1b4c7e11f193561056303a1f67b69dac96ff79a6d0aafa994f7cb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np115",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x00fd70a53be9c85c986d3dd87f46e079e4ce4a4a3dd95c1e497457c50bacbe2d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2bebf2f158ec1b8c7be21ef7c47c63fa5a3eb2292f409f365b40fa41bacb351e",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x73",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x47e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x47cdc",
+ "blockHash": "0xbb9f244470573774df6fca785d3e11e6bd1b896213cacd43cdfcb131f806ca4c",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e5d0183047cdd82520894043a718774c572bd8a25adbeb1bfcd5c0256ae110180c001a02ae4b3f6fa0e08145814f9e8da8305b9ca422e0da5508a7ae82e21f17d8c1196a077a6ea7a39bbfe93f6b43a48be83fa6f9363775a5bdb956c8d36d567216ea648"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9cc58ab1a8cb0e983550e61f754aea1dd4f58ac6482a816dc50658de750de613"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np116",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbb9f244470573774df6fca785d3e11e6bd1b896213cacd43cdfcb131f806ca4c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b359e20c5966cdcbb7b0298480621892d43f8efa58488b3548d84cf2ee514c1",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x74",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x488",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3ed55",
+ "blockHash": "0x6d18b9bca4ee00bd7dc6ec4eb269cd4ba0aceb83a12520e5b825b827cb875fd9",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x7",
+ "validatorIndex": "0x5",
+ "address": "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x79c2b067779a94fd3756070885fc8eab5e45033bde69ab17c0173d553df02978"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np117",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6d18b9bca4ee00bd7dc6ec4eb269cd4ba0aceb83a12520e5b825b827cb875fd9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9776b87f7c94469bd3f80d7d9b639dace4981230bbb7c14df9326aafe66f3da4",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x75",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x492",
+ "extraData": "0x",
+ "baseFeePerGas": "0x36fab",
+ "blockHash": "0xcef84ea2c6fac4a2af80a594bbe5a40bf5f5285efe67fab7ceb858844c593ae9",
+ "transactions": [
+ "0xf8845e83036fac830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08315d9fb30662071b05a4e38240e4b85b8e240c0c3e190f27ada50678236c6e7a00ee07dc873780f17ac9d0c7b3d434f89be92231cfca042ca5f23d3f3d7346861"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd908ef75d05b895600d3f9938cb5259612c71223b68d30469ff657d61c6b1611"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np118",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcef84ea2c6fac4a2af80a594bbe5a40bf5f5285efe67fab7ceb858844c593ae9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcd5cc668a3b28217e9fd05ddaea82d453a6a7394770a888b7d88013a4c9bcb22",
+ "receiptsRoot": "0xe35b2accd70b81901c8d0c931a12687e493a489ed7b82d78ade199815c466d5f",
+ "logsBloom": "0x0000000000000000000000000000000000000a00000000000000000000000000000000000000000000018000000000000000000000000000008000000000000048000000000000004000000000000000000008000000000000000000000020000000000000000002201010000000000000000400000000200000000000000000000000000000000000000000200000000000a200000001000000000000000000000000200000000000000000000400040000000000000000000000800000000000000000001800000000000802000000000000000000000080000000000000000000000000000000000000000000000000400000010800000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x76",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x49c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x301f5",
+ "blockHash": "0x7b65cb3becfab6b30f0d643095b11c6853a33ca064a272f1326adb74e876e305",
+ "transactions": [
+ "0xf87b5f830301f683011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0a3952a3372b48d4ef804b20a0ff5bbd5440156de3b71d37024356a3c1c5205d8a02ff03cae2dc449ca7ed7d25c91f99b17f0bafcdaf0ecc6e20bdeb80895c83e82"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe0d31906b7c46ac7f38478c0872d3c634f7113d54ef0b57ebfaf7f993959f5a3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np119",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7b65cb3becfab6b30f0d643095b11c6853a33ca064a272f1326adb74e876e305",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdd592cc191ae4ba2be51a47d5056c2f0ba8799c74445ea3f294e0fc95a973f16",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x77",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x4a6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2a1e1",
+ "blockHash": "0x5d089bec3bbf3a0c83c7796afaa1ae4d21df034a3e33a6acb80e700e19bcaab0",
+ "transactions": [
+ "0xf866608302a1e28302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0fd1714b8a15fa8a4e3ffe824632ec26f1daa6ce681e92845d1c1dfe60f032b4ea074bd5a60859bd735bbc70c9531a3ff48421f5c3b87e144406ee37ef78b8fda37"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2318f5c5e6865200ad890e0a8db21c780a226bec0b2e29af1cb3a0d9b40196ae"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np120",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5d089bec3bbf3a0c83c7796afaa1ae4d21df034a3e33a6acb80e700e19bcaab0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4b5122bd4713cd58711f405c4bd9a0e924347ffce532693cce1dd51f36094676",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x78",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x4b0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x24dea",
+ "blockHash": "0x02c9511703f78db34f67541d80704165d8a698726ef2cbcfbdc257bcf51594dd",
+ "transactions": [
+ "0xf8696183024deb825208942d711642b726b04401627ca9fbac32f5c8530fb101808718e5bb3abd109fa0b4d70622cd8182ff705beb3dfa5ffa4b8c9e4b6ad5ad00a14613e28b076443f6a0676eb97410d3d70cfa78513f5ac156b9797abbecc7a8c69df814135947dc7d42"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x523997f8d8fed954658f547954fdeceab818b411862647f2b61a3619f6a4d4bc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np121",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x02c9511703f78db34f67541d80704165d8a698726ef2cbcfbdc257bcf51594dd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x18484e0a8e7bcccf7fbf4f6c7e1eff4b4a8c5b5e0ba7c2f2b27da315a0a06f97",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x79",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x4ba",
+ "extraData": "0x",
+ "baseFeePerGas": "0x20438",
+ "blockHash": "0x1edbbce4143b5cb30e707564f7ada75afe632e72b13d7de14224e3ed0044a403",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x8",
+ "validatorIndex": "0x5",
+ "address": "0xa1fce4363854ff888cff4b8e7875d600c2682390",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbe3396540ea36c6928cccdcfe6c669666edbbbcd4be5e703f59de0e3c2720da7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np122",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1edbbce4143b5cb30e707564f7ada75afe632e72b13d7de14224e3ed0044a403",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6c921d64a95659dd6c62a919f2df9da2fda7cb8ec519aeb3b50ffb4e635dc561",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x4c4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1c3b1",
+ "blockHash": "0x38e1ce2b062e29a9dbe5f29a5fc2b3c47bf2eed39c98d2b2689a2e01650e97ca",
+ "transactions": [
+ "0xf884628301c3b2830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f48d056f98b681d69f84fcde715c63b1669b11563164d7c17e03e5d3a4641a0fa010fce327ee99c5206995065cbb134d5458143a34cbc64b326476aeef47ae482a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2d3fcfd65d0a6881a2e8684d03c2aa27aee6176514d9f6d8ebb3b766f85e1039"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np123",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x38e1ce2b062e29a9dbe5f29a5fc2b3c47bf2eed39c98d2b2689a2e01650e97ca",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x09df4733053f80da4904bce8d847883472e20bc3b1378eb1579e2e3df44d3948",
+ "receiptsRoot": "0x03ecb1b96e21ef88b48a9f1a85a170bdb0406e26918c7b14b9602e6f9a7e6937",
+ "logsBloom": "0x00000004000000000000002000000000000000004000000000000000000000000000400000400000000000000000010000080000000024404000000000000000000000000000000800000000020000000001000100000080000000000000000000000000000800000000000000000000000014000000000000000000000000001000000000000002000000100000000000000000000000000000040000000000000000000000000000040000020000000000000000200000000000000000000000000000000000000000000480010000000000000000000000040000000000000000000000000008000000000000000020000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x4ce",
+ "extraData": "0x",
+ "baseFeePerGas": "0x18b5b",
+ "blockHash": "0xda82bddbddc44bf3ce23eb1f6f94ae987861720b6b180176080919015b1e4e90",
+ "transactions": [
+ "0xf87b6383018b5c83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0b223787310f8ba4f9271d98c8bfc4f7e926ced7773cab6b5c856fb4c43b6dad5a07d0edf043f5b767ffd513479a43cbdc3dcbd18f254e3eb11043d4d7aa4dd7445"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7ce0d5c253a7f910cca7416e949ac04fdaec20a518ab6fcbe4a63d8b439a5cfc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np124",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xda82bddbddc44bf3ce23eb1f6f94ae987861720b6b180176080919015b1e4e90",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x15da947afcb1ba68f9fe2328e500881a302de649bd7d37f6e969bf7ec1aca37d",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x4d8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x15a06",
+ "blockHash": "0x8948407592d9c816f63c7194fa010c12115bee74e86c3b7d9e6ca30589830f21",
+ "transactions": [
+ "0xf8666483015a078302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa037c41575c8abba9465870babe53a436d036974edf6a9de15d40fff1b4cca7552a07e815124c036ad7c603e7faa56d1d9e517d60cee33c1e47122a303e42d59b6fa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4da13d835ea44926ee13f34ce8fcd4b9d3dc65be0a351115cf404234c7fbd256"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np125",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8948407592d9c816f63c7194fa010c12115bee74e86c3b7d9e6ca30589830f21",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa085ae940536d1e745cf78acd4001cb88fbc1e939151193c4e792cb659fe1aa0",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x4e2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x12ee9",
+ "blockHash": "0x5f66e4813f2b86dc401a90a05aafd8a2c38f6f1241e8a947bf54d679014a06a5",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e650183012eea82520894d10b36aa74a59bcf4a88185837f658afaf3646ef0180c080a0882e961b849dc71672ce1014a55792da7aa8a43b07175d2b7452302c5b3cac2aa041356d00a158aa670c1a280b28b3bc8bb9d194a159c05812fa0a545f5b4bc57b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc5ee7483802009b45feabf4c5f701ec485f27bf7d2c4477b200ac53e210e9844"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np126",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5f66e4813f2b86dc401a90a05aafd8a2c38f6f1241e8a947bf54d679014a06a5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfb39354666f43e8f8b88f105333d6f595054b2e1b0019f89bf5dbddf7ec9a0ab",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x4ec",
+ "extraData": "0x",
+ "baseFeePerGas": "0x10912",
+ "blockHash": "0x1b452f327c51d7a41d706af9b74ac14ff50b74dcef77fdb94333a8f5c86436a8",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x9",
+ "validatorIndex": "0x5",
+ "address": "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0fc71295326a7ae8e0776c61be67f3ed8770311df88e186405b8d75bd0be552b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np127",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1b452f327c51d7a41d706af9b74ac14ff50b74dcef77fdb94333a8f5c86436a8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb042b6a0d783d5e3757a9799dbc66d75515d0a511e5157650048a883a48d7c75",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x7f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x4f6",
+ "extraData": "0x",
+ "baseFeePerGas": "0xe7f0",
+ "blockHash": "0x4831cdabfa81a5a7c4a8bb9fee309515e2d60dd5e754dfef4456794385771161",
+ "transactions": [
+ "0xf8836682e7f1830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e5232243797a918b702f03aa9ccf4e944ff52293e7f5b7b1cb6874047f064ed6a02ae2cefc3e4fdb15fb4172d6fe04c7d54a312d077dcd15f91bf5f7047c10d079"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7313b4315dd27586f940f8f2bf8af76825d8f24d2ae2c24d885dcb0cdd8d50f5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np128",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4831cdabfa81a5a7c4a8bb9fee309515e2d60dd5e754dfef4456794385771161",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0400502ad286f8ca3e6e362d38ec9f2119eddc480e9af1ec646bc48e5451a379",
+ "receiptsRoot": "0xdcfb036965921ecaf598a6a02e3fb77784da94be9ed9aeee279d085a20342e47",
+ "logsBloom": "0x00000002000041000000000200000200400000000000000008000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00080000000000000000000000000000000000000000000400000000000000008000000000000000000000014800000000000000000000000000000000000000000000000000000000000080000000000008000000000000000000000000000008000000000000000000000100000000000000000200000000000000000000000000000000000000030000800000000000000000000001000000002000000000000000020000400005002000004000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x80",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x500",
+ "extraData": "0x",
+ "baseFeePerGas": "0xcb03",
+ "blockHash": "0xfadcdb29ddbfaed75902beaecb3b9e859bf4faefe78591baf8ac9c99faec09d2",
+ "transactions": [
+ "0xf87a6782cb0483011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa07e94803268c610035c580891ef0c6edd5c21babd8a2bb54d22373e982db9bf46a0375bc266e5e65f0a899b2299ddddbdc0e0d7d40c21e6d254d664abd7d0698076"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2739473baa23a9bca4e8d0f4f221cfa48440b4b73e2bae7386c14caccc6c2059"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np129",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfadcdb29ddbfaed75902beaecb3b9e859bf4faefe78591baf8ac9c99faec09d2",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1f1fc8702bf538caf0df25f854999a44a7583b4339011bc24dadcee848e3daf5",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x81",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x50a",
+ "extraData": "0x",
+ "baseFeePerGas": "0xb1ae",
+ "blockHash": "0x5bc61ce8add484ead933542e385d4592d82aac6d47b46dcb2451390b884b8c3d",
+ "transactions": [
+ "0xf8656882b1af8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a064097d6048ea289fa6b8a002f4a7d53d8381ee46bf0dadd3ac1befa477cef309a0300f780844db5eaa99ff65752886da8b671329d7c12db4e65dd7f525abe9b1d8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd4da00e33a11ee18f67b25ad5ff574cddcdccaa30e6743e01a531336b16cbf8f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np130",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5bc61ce8add484ead933542e385d4592d82aac6d47b46dcb2451390b884b8c3d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb04a7bb7f21e64f23bd415ee3ad1dc8a191975c86e0f0d43a92a4204a32ac090",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x82",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x514",
+ "extraData": "0x",
+ "baseFeePerGas": "0x9b8b",
+ "blockHash": "0x30fcf7ed7c580b55b92289383259c5c1d380d54c1f527bfdc8b062af1e898b8f",
+ "transactions": [
+ "0xf86869829b8c82520894a5ab782c805e8bfbe34cb65742a0471cf5a53a9701808718e5bb3abd10a0a078e180a6afd88ae67d063c032ffa7e1ee629ec053306ce2c0eb305b2fb98245ea07563e1d27126c9294391a71da19044cb964fd6c093e8bc2a606b6cb5a0a604ac"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe651765d4860f0c46f191212c8193e7c82708e5d8bef1ed6f19bdde577f980cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np131",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x30fcf7ed7c580b55b92289383259c5c1d380d54c1f527bfdc8b062af1e898b8f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfd2a1032389a1b7c6221d287a69e56a32d8a618396b8ef829601a9bcb3e91cce",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x83",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x51e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x881d",
+ "blockHash": "0x8b3a8443b32d2085952d89ca1b1ecb7574b37483cb38e71b150c00d001fea498",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xa",
+ "validatorIndex": "0x5",
+ "address": "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5b5b49487967b3b60bd859ba2fb13290c6eaf67e97e9f9f9dda935c08564b5f6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np132",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8b3a8443b32d2085952d89ca1b1ecb7574b37483cb38e71b150c00d001fea498",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x91120613028234db2b47071a122f6ff291d837abe46f1f79830276fd23934c56",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x84",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x528",
+ "extraData": "0x",
+ "baseFeePerGas": "0x771a",
+ "blockHash": "0xc9a9cc06b8a5d6edad0116a50740cb23d1cb130f6c3052bae9f69a20abf639c3",
+ "transactions": [
+ "0xf8836a82771b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0a295fe01d21a6f8ffd36f8415e00da318f965a12155808a0d3b51c2c1914cf65a055022813f479686f077e227f3b00dc983081ad361dd8c8240b84d1cf86721ccf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x57b73780cc42a6a36676ce7008459d5ba206389dc9300f1aecbd77c4b90277fa"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np133",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc9a9cc06b8a5d6edad0116a50740cb23d1cb130f6c3052bae9f69a20abf639c3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1ec4000ab57cb0fec41b7221fff5ad7ec0dd4a042a739349045110b8116650c8",
+ "receiptsRoot": "0x870c88b91d896f4d6c0d6d8d9924dee345e36915e9244af9785f4ca1fea5fda3",
+ "logsBloom": "0x000000000008000000004000000000000000000000000000000000000000000400000000080000000000000000000000000000000000000000000000000c0000000000000000000002000000080000000000000000000004000000000000000000000000000000000000000000020000000400000000010000000040000000000000000000000000000004000000800008000100000202000000000000040000000000000000002000000000200000100000000000010000000000000001010000000000000000000000100000100000000401000000000000000000000000000000000000000000000000000000410000000800000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x85",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x532",
+ "extraData": "0x",
+ "baseFeePerGas": "0x6840",
+ "blockHash": "0x4d61445a8ece151e7938bc9c2f4f819a10afddf32c0f2600d62281ecd6b1af69",
+ "transactions": [
+ "0xf87a6b82684183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa09ce0e0b4fb662dd87cf69350e376568655ce9436941c42e7815a0688db3d8281a037208359ff73e2b9389d9d6e32df5203a0239e5dbbf016e87b3714c122ff081f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x217e8514ea30f1431dc3cd006fe730df721f961cebb5d0b52069d1b4e1ae5d13"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np134",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4d61445a8ece151e7938bc9c2f4f819a10afddf32c0f2600d62281ecd6b1af69",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb078e743044057e03f894971bfc3dca4dc78990d5cba60c7c979182c419528cf",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x86",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x53c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x5b3e",
+ "blockHash": "0xadcc471cc18ae64a1ece9ef42013441477843c72962bcc0f1291df9dc8906324",
+ "transactions": [
+ "0xf8656c825b3f8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0fd01a89a43af89dfba5de6077a24873a459ee0c8de3beaa03e444bb712fdbebda04f920e07882701d12f9016e32bfe5859d3c1bf971e844c6fcd336953190a8aad"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x14b775119c252908bb10b13de9f8ae988302e1ea8b2e7a1b6d3c8ae24ba9396b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np135",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xadcc471cc18ae64a1ece9ef42013441477843c72962bcc0f1291df9dc8906324",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5ed1a679a1844883bb7c09f1349702b93a298fc8a77885f18810230f0322d292",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x87",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x546",
+ "extraData": "0x",
+ "baseFeePerGas": "0x4fe0",
+ "blockHash": "0xd2e3126fb4b0cc3e1e98f8f2201e7a27192a721136d12c808f32a4ff0994601b",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e6d01824fe1825208944bfa260a661d68110a7a0a45264d2d43af9727de0180c001a00bb105cab879992d2769014717857e3c9f036abf31aa59aed2c2da524d938ff8a03b5386a238de98973ff1a9cafa80c90cdcbdfdb4ca0e59ff2f48c925f0ea872e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe736f0b3c5672f76332a38a6c1e66e5f39e0d01f1ddede2c24671f48e78daf63"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np136",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd2e3126fb4b0cc3e1e98f8f2201e7a27192a721136d12c808f32a4ff0994601b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd4db74075dc9ae020d6016214314a7602a834c72ec99e34396e1d326aa112a27",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x88",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x550",
+ "extraData": "0x",
+ "baseFeePerGas": "0x45e6",
+ "blockHash": "0xa503a85bc5c12d4108445d5eab6518f1e4ccaeab30434202b53204a9378419fa",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xb",
+ "validatorIndex": "0x5",
+ "address": "0x4f362f9093bb8e7012f466224ff1237c0746d8c8",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7d112c85b58c64c576d34ea7a7c18287981885892fbf95110e62add156ca572e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np137",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa503a85bc5c12d4108445d5eab6518f1e4ccaeab30434202b53204a9378419fa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfd5f001adc20a6ab7bcb9cd5ce2ea1de26d9ecc573a7b595d2f6d682cf006610",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x89",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x55a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3d2a",
+ "blockHash": "0xe0b036f2df5813e2e265d606ee533cd46924a8a7de2988e0e872c8b92c26399c",
+ "transactions": [
+ "0xf8836e823d2b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e853c07d5aba01cfcacc3a4191551d7b47d2e90aba323bd29b5b552147bc4055a03a7e1dee0d461376b43ac4c0dd1a85cc94e9fa64aa8effec98c026293e47240a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x28fbeedc649ed9d2a6feda6e5a2576949da6812235ebdfd030f8105d012f5074"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np138",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe0b036f2df5813e2e265d606ee533cd46924a8a7de2988e0e872c8b92c26399c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3bf11932c08c5317c7463697409eba5a6904575cc03593cb0eac6c82093d79b7",
+ "receiptsRoot": "0x3ef7cc7ec86f1ace231cdf7c7fadaf27ae84ad4afdd5f2261b60d5be03794001",
+ "logsBloom": "0x00000000000000000000080000000000000000000000000000000000000000000000000010000000004000008000000000000000000000000000000080001000000020000000000000000000000000000000000000000000000010000010200000040220000000000000000000010001000000800000000000400000002000000000000000000000400000000000000800000000000400000000000000080000500000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000004002000000000008000000000002000000400000000000000000000000000002000000000002000000000000002000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x564",
+ "extraData": "0x",
+ "baseFeePerGas": "0x358a",
+ "blockHash": "0xfcca6f4e35f290be297bf6403b84c99d1a7b6d78299b5e2690d915bf834e85da",
+ "transactions": [
+ "0xf87a6f82358b83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0c28b8f557aaf82e47d9e1425824709427513131908ac636f142990468e40909ea05fe11510da000868cfe1a05bdf689a8c1954c87afeb9ef2defbed3075458a6ad"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6f7410cf59e390abe233de2a3e3fe022b63b78a92f6f4e3c54aced57b6c3daa6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np139",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfcca6f4e35f290be297bf6403b84c99d1a7b6d78299b5e2690d915bf834e85da",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe8258bde0dceac7f4b4734c8fa80fe5be662ae7238d9beb9669bc3ae4699efa8",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x56e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2edc",
+ "blockHash": "0x762df3955fc857f4c97acb59e4d7b69779986e20e3a8ea6bc5219dfd9e5a3d7e",
+ "transactions": [
+ "0xf86570822edd8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a02206472edd9c816508c6711c004500028a4a6a206caf23b20c6828dd60e1533fa0186dc116a92a8455d1cb92ed4b599c3f7cade6cf59da63b1aef46936c3a507e9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd5edc3d8781deea3b577e772f51949a8866f2aa933149f622f05cde2ebba9adb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np140",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x762df3955fc857f4c97acb59e4d7b69779986e20e3a8ea6bc5219dfd9e5a3d7e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9ff9a193050e74dfa00105084fa236099def4aa7993691c911db0a3f93422aeb",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x578",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2906",
+ "blockHash": "0xffe6c202961ee6b5098db912c7203b49aa3b303b4482234371b49f7ef7a95f84",
+ "transactions": [
+ "0xf86871822907825208949defb0a9e163278be0e05aa01b312ec78cfa372601808718e5bb3abd109fa04adf7509b10551a97f2cb6262c331096d354c6c8742aca384e63986006b8ac93a0581250d189e9e1557ccc88190cff66de404c99754b4eb3c94bb3c6ce89157281"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x20308d99bc1e1b1b0717f32b9a3a869f4318f5f0eb4ed81fddd10696c9746c6b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np141",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xffe6c202961ee6b5098db912c7203b49aa3b303b4482234371b49f7ef7a95f84",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf63dc083849dc5e722a7ca08620f43fc5cd558669664a485a3933b4dae3b84f4",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x582",
+ "extraData": "0x",
+ "baseFeePerGas": "0x23e6",
+ "blockHash": "0xfa0dcd8b9d6e1c42eeea7bb90a311dd8b7215d858b6c4fb0f64ee01f2be00cfe",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xc",
+ "validatorIndex": "0x5",
+ "address": "0x075198bfe61765d35f990debe90959d438a943ce",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x91f7a302057a2e21d5e0ef4b8eea75dfb8b37f2c2db05c5a84517aaebc9d5131"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np142",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfa0dcd8b9d6e1c42eeea7bb90a311dd8b7215d858b6c4fb0f64ee01f2be00cfe",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6222bb96d397776358dd71f14580f5464202313769960ec680c50d9ccc2fa778",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x58c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1f6a",
+ "blockHash": "0xe501e9f498cd6b1a6d22c96a556c9218e3a7960eea3e9ab4ac2760cc09fdca0d",
+ "transactions": [
+ "0xf88372821f6b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa067091ae37d21fdc5f9eed2877bddb24e52f69e80af27a89608b6fba1c5053f32a04817ab7dc0c3eaac266b08a1683c34fcd43098c6219ea5771d35fa3387b705a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x743e5d0a5be47d489b121edb9f98dad7d0a85fc260909083656fabaf6d404774"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np143",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe501e9f498cd6b1a6d22c96a556c9218e3a7960eea3e9ab4ac2760cc09fdca0d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbe8a51adbc81161927f0b6f3e562cd046f1894145010a1b3d77394780478df3c",
+ "receiptsRoot": "0x8c32e3da3725025cad909cb977e252fd127d54c4f4da3852d18ef3976bfe4610",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000001000000000000004000000000000000000000000000800000000000000000000028000000020008000000008000000000000000000000000010000000000080000100000400100000000000000000000000100000000010000000000000000000000000000004000000000000000000008000000000080008000000000000000000000000000000000000000000080002800000000000120000000000004000000000000000000000004000000400000002000800000020000000080000000000000008000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x8f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x596",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1b7f",
+ "blockHash": "0xdb3eb92355d58f317e762879ec891a76e0d9ba32a43f0a70f862af93780ef078",
+ "transactions": [
+ "0xf87a73821b8083011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0de521643ceaf711d0d3b6cda406ef8fba599658fccc750139851846435eba8afa057f5427948ca8d46609925641f81f72115860c16228821020b8020846a4c3158"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcdcf99c6e2e7d0951f762e787bdbe0e2b3b320815c9d2be91e9cd0848653e839"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np144",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdb3eb92355d58f317e762879ec891a76e0d9ba32a43f0a70f862af93780ef078",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb7933a921b5acf566cc2b8edb815d81a221222a0ac36dac609927aa75744daaf",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x90",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x5a0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1811",
+ "blockHash": "0x6718dc62462698e0df2188c40596275679d2b8a49ab6fd6532a3d7c37efd30a6",
+ "transactions": [
+ "0xf865748218128302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0afbda9fa76936bc6be4d26905bc000b4b14cae781a8e3acb69675b6c5be20835a03858ad4e7e694bf0da56994a1e5f855ff845bae344de14109ae46607aa4172ca"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcc9476183d27810e9738f382c7f2124976735ed89bbafc7dc19c99db8cfa9ad1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np145",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6718dc62462698e0df2188c40596275679d2b8a49ab6fd6532a3d7c37efd30a6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa8a6a6386a956afbc3163f2ccdcaeffeb9b12c10d4bb40f2ef67bcb6df7cf64c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x91",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x5aa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1512",
+ "blockHash": "0x891051fb49d284166b72a30c29b63bfe59994c9db2d89e54ca0791b4dfdb68fb",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e7501821513825208947da59d0dfbe21f43e842e8afb43e12a6445bbac00180c080a06ca026ba6084e875f3ae5220bc6beb1cdb34e8415b4082a23dd2a0f7c13f81eca0568da83b9f5855b786ac46fb241eee56b6165c3cc350d604e155aca72b0e0eb1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf67e5fab2e7cacf5b89acd75ec53b0527d45435adddac6ee7523a345dcbcdceb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np146",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x891051fb49d284166b72a30c29b63bfe59994c9db2d89e54ca0791b4dfdb68fb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9ee7ad908d7c553d62d14ecd6a1e9eac6ed728f9a0d0dd8aa8db149e6e803262",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x92",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x5b4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1271",
+ "blockHash": "0x2ef94fa352357c07d9be6e271d8096b2cbf7dcae9bad922e95bc7c7c24375e7c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xd",
+ "validatorIndex": "0x5",
+ "address": "0x956062137518b270d730d4753000896de17c100a",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe20f8ab522b2f0d12c068043852139965161851ad910b840db53604c8774a579"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np147",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2ef94fa352357c07d9be6e271d8096b2cbf7dcae9bad922e95bc7c7c24375e7c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x14111c2a0f5c36f6b8ea455b9b897ab921a0f530aaee00447af56ffc35940e32",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x93",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x5be",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1023",
+ "blockHash": "0x406fbf5c2aa4db48fce6fe0041d09a3387c2c18c57a4fb77eca5d073586ca3ea",
+ "transactions": [
+ "0xf88376821024830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa08e5e1207971ec2479337fa7c80f843dd80d51224eb9f9d8c37b1758d3d5acae4a04d2f89fb9005dc18fa4c72e8b1b4e611f90ca9c5e346b6201dfe4b83ec39c519"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf982160785861cb970559d980208dd00e6a2ec315f5857df175891b171438eeb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np148",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x406fbf5c2aa4db48fce6fe0041d09a3387c2c18c57a4fb77eca5d073586ca3ea",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc43ae2200cea3bdd1b211157150bd773118c818669e2650659ef3807ac7d2c29",
+ "receiptsRoot": "0x1f4bdefd1b3ded1be79051fe46e6e09f4543d4c983fdc21dee02b1e43fb34959",
+ "logsBloom": "0x00000000000000000000000000000110000000000002000000000000000000020008000000000000000800001000000000000000000000000020000010000400000000000000000000001000000000000000000000000000000020000000000000101000000000800000000000000000080000000000000000000000000000010000080000080000800000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000200000020000000000000000000000000002000001000000000040002000000024000000000280000000000000000000000000020000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x94",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x5c8",
+ "extraData": "0x",
+ "baseFeePerGas": "0xe20",
+ "blockHash": "0x34ca9a29c1cef7e8011dcce6240c1e36ee8e64643fc0ed98cb436d2f9a21baa2",
+ "transactions": [
+ "0xf87a77820e2183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b5b7b281fbe78ca0f9819a9015997a42ee896462db5ea7de089cd7e2cf84b346a02bc85175e51da947f89f947c30d7c1d77daa6e654a0007e56de98812039a76bd"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x230954c737211b72d5c7dcfe420bb07d5d72f2b4868c5976dd22c00d3df0c0b6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np149",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x34ca9a29c1cef7e8011dcce6240c1e36ee8e64643fc0ed98cb436d2f9a21baa2",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x21cafe51bfa7793c9a02f20282b59cbb5156dce1e252ab61f98fdd5cdecf8495",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x95",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x5d2",
+ "extraData": "0x",
+ "baseFeePerGas": "0xc5d",
+ "blockHash": "0xed939dcec9a20516bd7bb357af132b884efb9f6a6fc2bc04d4a1e5063f653031",
+ "transactions": [
+ "0xf86578820c5e8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0371194d9f0d8b28bc888d45cc571dd73c9dd620d54184b9776256d5e07049350a05f7bfb7cdccb54a2f0ea01374f1474e694daa1b128076bdc33efcee9bc0d56a7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb7743e65d6bbe09d5531f1bc98964f75943d8c13e27527ca6afd40ca069265d4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np150",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xed939dcec9a20516bd7bb357af132b884efb9f6a6fc2bc04d4a1e5063f653031",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x503c44cab4d6c0010c3493e219249f1e30cfff1979b9da7268fd1121af73d872",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x96",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x5dc",
+ "extraData": "0x",
+ "baseFeePerGas": "0xad3",
+ "blockHash": "0x136665ab7316f05d4419e1f96315d3386b85ec0baeed10c0233f6e4148815746",
+ "transactions": [
+ "0xf86879820ad48252089484873854dba02cf6a765a6277a311301b2656a7f01808718e5bb3abd10a0a0ab3202c9ba5532322b9d4eb7f4bdf19369f04c97f008cf407a2668f5353e8a1fa05affa251c8d29f1741d26b42a8720c416f7832593cd3b64dff1311a337799e8f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x31ac943dc649c639fa6221400183ca827c07b812a6fbfc1795eb835aa280adf3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np151",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x136665ab7316f05d4419e1f96315d3386b85ec0baeed10c0233f6e4148815746",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2e257bca2ea424f7c304c42fc35b14c8d3fd46c9066c7f895f775a2065a14bab",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x97",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x5e6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x979",
+ "blockHash": "0xefc08cafa0b7c0e0bc67c0dbd563a855ba55f389d947bd9c524be5ef789505ba",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xe",
+ "validatorIndex": "0x5",
+ "address": "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xded49c937c48d466987a4130f4b6d04ef658029673c3afc99f70f33b552e178d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np152",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xefc08cafa0b7c0e0bc67c0dbd563a855ba55f389d947bd9c524be5ef789505ba",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa124fe0abd3682da7263262172c9d2c57fb42d4f131cbc9f24ddea0ec1505e48",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x98",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x5f0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x84a",
+ "blockHash": "0xb7a12ba1b0cd24019d0b9864ed28c0d460425eb1bd32837538d99da90f5c65b7",
+ "transactions": [
+ "0xf8837a82084b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0be58da9e68f28cf1dd209a610214982ba767249f3b92cd8c0fb3850a9ee194d6a0613f59eec6c092b6d2fc55de85bc67b21c261dc48f1ddb74af3aac438b27ccd5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa0effc449cab515020d2012897155a792bce529cbd8d5a4cf94d0bbf141afeb6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np153",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb7a12ba1b0cd24019d0b9864ed28c0d460425eb1bd32837538d99da90f5c65b7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3c05bdceef0bdc9f676a3a0c00151f975e469e5bb08ab08f3eed090987119672",
+ "receiptsRoot": "0x73faa109b88bfbf7e2a71c36d556d9286c0a26988680cbe3058f045fd361b3b0",
+ "logsBloom": "0x00004000000800000000000000000000000000000000000000000000000000000004000000080000000000000800000000000000500000000000000000000200000000001000000800000000000002008000080000000000000000000000000000000000000000000008000200000000000000000000000000000001000000000000000000101000004000000000000000000000000000000000000000000000000000000080000000000000000000008200000000000080000000000000000000000000000000000800000000000000000000000400000080020002000000001040000000000000000000000000004000000000000000008000008000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x99",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x5fa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x742",
+ "blockHash": "0x0292db163d287eeb39bd22b82c483c9b83a9103a0c425a4f3954ef2330cc1718",
+ "transactions": [
+ "0xf87a7b82074383011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b9eb0510fdc334dde88b8ac75869aa2dd53988191ae1df94b7b926eae9b18050a00cbd9e12b7185723ed407175a7a70fa5cc0dbc4014b3040a9ade24a4eb97c8c1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1f36d9c66a0d437d8e49ffaeaa00f341e9630791b374e8bc0c16059c7445721f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np154",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0292db163d287eeb39bd22b82c483c9b83a9103a0c425a4f3954ef2330cc1718",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc2e93862e26d4df238b2b83a3ee0e008f25123aa211d83906fcd77bc9fd226ab",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x604",
+ "extraData": "0x",
+ "baseFeePerGas": "0x65b",
+ "blockHash": "0xaeab3fe4b09329235bd8a0399db4d944fe1b247a91055c7de7f53703c94357ea",
+ "transactions": [
+ "0xf8657c82065c8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0e5959821e9fe4b896ef2559fe6524aadead228d89f923061b6d2d340f6b9307fa02ed2929f37d24a57229f7a579aaab2d9551e71b0822895e91f04e7824da9a861"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x34f89e6134f26e7110b47ffc942a847d8c03deeed1b33b9c041218c4e1a1a4e6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np155",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaeab3fe4b09329235bd8a0399db4d944fe1b247a91055c7de7f53703c94357ea",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0c94e7ea002f7b3bcc5100783e1e792160fb73ff4e836cd295e34423ff72f2a6",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x60e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x591",
+ "blockHash": "0xcc221bd9ee16f8302994c688cd7cc18313e686cf21f29edea5da5ac08a28a9b6",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e7d01820592825208948d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f20180c001a0f9075613b9069dab277505c54e8381b0bb91032f688a6fe036ef83f016771897a04cb4fc2e695439af564635863f0855e1f40865997663d900bc2ab572e78a70a2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x774404c430041ca4a58fdc281e99bf6fcb014973165370556d9e73fdec6d597b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np156",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcc221bd9ee16f8302994c688cd7cc18313e686cf21f29edea5da5ac08a28a9b6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x04ba5addea7916f0483658ea884c052ea6d759eeda62b9b47ee307bd46525bb0",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x618",
+ "extraData": "0x",
+ "baseFeePerGas": "0x4df",
+ "blockHash": "0x8c922bb4a1c7aad6fdc09082e5c90427d0643ffd281d0154cdd71a372108c5da",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0xf",
+ "validatorIndex": "0x5",
+ "address": "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd616971210c381584bf4846ab5837b53e062cbbb89d112c758b4bd00ce577f09"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np157",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8c922bb4a1c7aad6fdc09082e5c90427d0643ffd281d0154cdd71a372108c5da",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3ae465791b7ce8492961c071fc50b34434552a1ab36c1854fbc308f55729e827",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x622",
+ "extraData": "0x",
+ "baseFeePerGas": "0x444",
+ "blockHash": "0x1a883eed15a2f61dc157140d45f50e4bc6cc08ead08adf3ff0804ec9f1104c8a",
+ "transactions": [
+ "0xf8837e820445830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0140e450a0bc12c61bdf6acca1a56178466d88014d00a4a09c1088ce184128327a07daad374bb0d7fe879212bd7bdc8d454b4996bd7bebd6f6d0d4636ec7df28d0b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcdf6383634b0431468f6f5af19a2b7a087478b42489608c64555ea1ae0a7ee19"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np158",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1a883eed15a2f61dc157140d45f50e4bc6cc08ead08adf3ff0804ec9f1104c8a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe01f0f54fba649cdc0d6da6a9f519b6918149d82f134845e99847ff7b362b050",
+ "receiptsRoot": "0x36340e11a5f180862d423a676049d1c934b8d27940fdd50dc8704563ffd27b0f",
+ "logsBloom": "0x00000000000000008000000000800080000000000000000018040000000100100000000000010000000000000000000000000000000000000000000000010000000080080000800000000000010000000010000000000802000000000000000000000000001000000000004000000000000000000000004000000000000000004000000000000000000000000000000000000000000000401000000000010000000000000000000000000000000080000000000000000000000040000240000000000000000000000001000000000000000000000000100000000080000040000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x62c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3bc",
+ "blockHash": "0x5efcd9acd57f0652b1aa46406cf889b0da1f05e34fa9b642f7dec1bd924f3fd0",
+ "transactions": [
+ "0xf87a7f8203bd83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0331dd2ec5bf4bddde96cacb8a28ed1cc577d4a2289bae6da0e6ef3c9b1287fc3a04c2925895dfbed2b00ac9a2040371970da1a7fd333dc1e551e2e268c56717c79"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x00ec22e5df77320b4142c54fceaf2fe7ea30d1a72dc9c969a22acf66858d582b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np159",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5efcd9acd57f0652b1aa46406cf889b0da1f05e34fa9b642f7dec1bd924f3fd0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa6e1d00e54b539beb170e510a8594fdd73ad2bf8e695a0f052291454ee1f3ade",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x9f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x636",
+ "extraData": "0x",
+ "baseFeePerGas": "0x345",
+ "blockHash": "0x97570840bed5a39a4580302a64cbaf7ed55bcc82e9296502c4873d84f8384004",
+ "transactions": [
+ "0xf86681808203468302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0f4a1b0681bb3c513fa757b560ef9cf0f004b8da91d920e157506ebb60d0d3954a0738da3b003ce68a9b4032770c0fe6481f54ea43baba54cad7153369486728790"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcb32d77facfda4decff9e08df5a5810fa42585fdf96f0db9b63b196116fbb6af"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np160",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x97570840bed5a39a4580302a64cbaf7ed55bcc82e9296502c4873d84f8384004",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9277b9454326e993436cef0b9a2e775cff46439f3d683da55a983e9850943a20",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x640",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2dd",
+ "blockHash": "0x4b01a4f9f924e7e386d2c94653c80bab2e3069d744ab107dd181d9b5f5d176d0",
+ "transactions": [
+ "0xf86981818202de82520894c19a797fa1fd590cd2e5b42d1cf5f246e29b916801808718e5bb3abd109fa0857754afc3330f54a3e6400f502ad4a850a968671b641e271dcb9f68aacea291a07d8f3fb2f3062c39d4271535a7d02960be9cb5a0a8de0baef2211604576369bf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6d76316f272f0212123d0b4b21d16835fe6f7a2b4d1960386d8a161da2b7c6a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np161",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4b01a4f9f924e7e386d2c94653c80bab2e3069d744ab107dd181d9b5f5d176d0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc9f74f81ace1e39dd67d9903221e22f1558da032968a4aaff354eaa92289f5c6",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x64a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x282",
+ "blockHash": "0x9431a8d1844da9cc43e8b338de21722e23f78ed5b46391a6d924595759773286",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x10",
+ "validatorIndex": "0x5",
+ "address": "0x8a8950f7623663222542c9469c73be3c4c81bbdf",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2de2da72ae329e359b655fc6311a707b06dc930126a27261b0e8ec803bdb5cbf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np162",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9431a8d1844da9cc43e8b338de21722e23f78ed5b46391a6d924595759773286",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x853c0a8e4e964cc857f2dd40b10de2cefb2294a7da4d83d7b1da2f9581ee0961",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x654",
+ "extraData": "0x",
+ "baseFeePerGas": "0x232",
+ "blockHash": "0x604f361dbc1085fb70812b618e53035d4747c3969a96620e4c179a93be5d124d",
+ "transactions": [
+ "0xf8848182820233830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa01a7b8af754eba43e369957a413a3fef1255659f2bd05f902b29ee213c3989d46a00ca88ac892d58fdb0d9bd7640ca797280081275886cc2ac155a814eb498e7d7b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x08bed4b39d14dc1e72e80f605573cde6145b12693204f9af18bbc94a82389500"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np163",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x604f361dbc1085fb70812b618e53035d4747c3969a96620e4c179a93be5d124d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd89e02bde63bf214ad6a3bc94f3b092bc2a1fbc13f172049c854ecb070630fe6",
+ "receiptsRoot": "0x596413315e1e3fd6fc21e4ce81e618b76ad2bf7babfa040c822a5bcbffeb63be",
+ "logsBloom": "0x00080000001044010000000800000000000000000010000000040000000020000000800000000040000000000000000001008000000000800000000000000000000000001000000000020000080000000000000000000000000000000000000002000044000000000000000000000000000000000000000000000000000000000000002000000000000000800000000000000000000000000000000000104000800000000000000004000004000002000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000800020000000000000000000040000000000000000020",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x65e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1ec",
+ "blockHash": "0x00979cd18ef128aa75a51ad8606b381ce53f72c37d17bc6c6613d8de722abcfa",
+ "transactions": [
+ "0xf87b81838201ed83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06e6e8187c035f2788ba44e3f47b4102a1f263ae2f601b2fbfa9e2cdc3b0c22b1a06c229eebca1bdda1aba424cd8cf296f386cf2d50a6add950fd6cb34aac442c5a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe437f0465ac29b0e889ef4f577c939dd39363c08fcfc81ee61aa0b4f55805f69"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np164",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x00979cd18ef128aa75a51ad8606b381ce53f72c37d17bc6c6613d8de722abcfa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe2672f9ae97aeaeb22f42c389301a3b79ad6c47ad88c54e18e1d7a4ed5e9c903",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x668",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1af",
+ "blockHash": "0xcabf8c1b47839908f6eb28261876b52404f3f8787c94d8aadc0aca721ff35d13",
+ "transactions": [
+ "0xf86681848201b08302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08ab61fe0265afe289954f7c2af8e070f3c40dda39e6cb6ff5c798fc7bc87b55ba00a8a440a7ba5a04a7bb73b093e94734dda228d33a43c640d719aef5ea5e81764"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x89ca120183cc7085b6d4674d779fc4fbc9de520779bfbc3ebf65f9663cb88080"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np165",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcabf8c1b47839908f6eb28261876b52404f3f8787c94d8aadc0aca721ff35d13",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4d9cd7b52c0daaec9a019730c237a2c3424f5d5a004c8bc9fa23997f3ec33768",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x672",
+ "extraData": "0x",
+ "baseFeePerGas": "0x17a",
+ "blockHash": "0x6dcec039f7777c1fd96bbdd342e0ed787211132f753cf73a59847dc6cb30a6ff",
+ "transactions": [
+ "0x02f86c870c72dd9d5e883e81850182017b825208946922e93e3827642ce4b883c756b31abf800366490180c080a089e6d36baf81743f164397205ded9e5b3c807e943610d5b9adb9cfeb71b90299a03d56c57f842a92a5eb71c8f9f394fe106d993960421c711498013806957fdcaf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb15d5954c7b78ab09ede922684487c7a60368e82fdc7b5a0916842e58a44422b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np166",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6dcec039f7777c1fd96bbdd342e0ed787211132f753cf73a59847dc6cb30a6ff",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x03629dac3f669a8262e8246d46bac9acfb7cbca336d02e90c081561fa0b22aba",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x67c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x14b",
+ "blockHash": "0x760da169c77450231e6a0d2dd4aad67de84633eb6918fc8607a3a709eea07bef",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x11",
+ "validatorIndex": "0x5",
+ "address": "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xad13055a49d2b6a4ffc8b781998ff79086adad2fd6470a0563a43b740128c5f2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np167",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x760da169c77450231e6a0d2dd4aad67de84633eb6918fc8607a3a709eea07bef",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4f5e79d4af5565b3b53649b1ddc3a03209cb583e7beb03db8b32924c641e6912",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x686",
+ "extraData": "0x",
+ "baseFeePerGas": "0x122",
+ "blockHash": "0xfcb210229cb48baf3d535e48a7577041268eadd6027942084a56dbec8f8423a9",
+ "transactions": [
+ "0xf8848186820123830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0b2aafb3e2678dd48e6f31874bd478778480815c9d110ec8cc77a42f7d52999daa00705b1266fc1087167cc531caa9d2e0a0c8779e4ad5020d9d3a16500bf5b96a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9e9909e4ed44f5539427ee3bc70ee8b630ccdaea4d0f1ed5337a067e8337119f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np168",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfcb210229cb48baf3d535e48a7577041268eadd6027942084a56dbec8f8423a9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c6c100b7c75ced82b38315fd50c5439478a7ee256073ce17b845e0815912eab",
+ "receiptsRoot": "0xf8f8c85b17ada66c06f8e41b58b45213619bb309a197896adbaff4e9139967b1",
+ "logsBloom": "0x80000000000000000000000000000000800000000004008000200000000000000002820000000000000000000000000000000000000040020400000000000000000000000200000000000000000000000000000040000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000040080000000000000000000000000000000000200000000000000080000200000000000000000000000000000000000000000000000000000100000003000200000000000000000000000000000000000000200000000000000000000000004000000004000000040001010000000080400000000000000040000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x690",
+ "extraData": "0x",
+ "baseFeePerGas": "0xfe",
+ "blockHash": "0x796a4e02d1da9c86b1a2e7b2ef1d82e1ebdac143ec7ff4a67dae2b241b22c3c1",
+ "transactions": [
+ "0xf87a818781ff83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b1e7ca73ef581fc880deb34aa6cf7958f6ce110efd121d48fb2292a747864815a02bf94b17dc034d8934b885faa269a9430a755ebfb4c6e87378376a094704f464"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbf1f3aba184e08d4c650f05fe3d948bdda6c2d6982f277f2cd6b1a60cd4f3dac"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np169",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x796a4e02d1da9c86b1a2e7b2ef1d82e1ebdac143ec7ff4a67dae2b241b22c3c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9f527744fd44cf4c2ba60fe62d25d4f19e64c034cbf24785e0128d5fafa19e2a",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xa9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x69a",
+ "extraData": "0x",
+ "baseFeePerGas": "0xdf",
+ "blockHash": "0x29a0d081e8aec6b2dcb307d73ca48d7d50e434617daf0e81fd28b35be9c7995d",
+ "transactions": [
+ "0xf865818881e08302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0c583bd1010c1e4158466575fb0c09ff710a5ff07c8f7a6e7960d90bffef8bd34a059ea0ba5c6fc64aad73252c780de287599d3100d80f7b1d3201b4865d82c0cad"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbb70fe131f94783dba356c8d4d9d319247ef61c768134303f0db85ee3ef0496f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np170",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x29a0d081e8aec6b2dcb307d73ca48d7d50e434617daf0e81fd28b35be9c7995d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x45c5f07a7d94c320222f43c12b04081fdbe870be18a2b76f7122bd7f4554118b",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xaa",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x6a4",
+ "extraData": "0x",
+ "baseFeePerGas": "0xc4",
+ "blockHash": "0xe878e98d05f60a8fd741a4aaab17a91c538f21552ac41922fe2b755e4f0e534c",
+ "transactions": [
+ "0xf868818981c582520894bceef655b5a034911f1c3718ce056531b45ef03b01808718e5bb3abd109fa0626dfd18ca500eedb8b439667d9b8d965da2f2d8ffcd36a5c5b60b9a05a52d9fa07271175e4b74032edeb9b678ffb5e460edb2986652e45ff9123aece5f6c66838"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6a81ebd3bde6cc54a2521aa72de29ef191e3b56d94953439a72cafdaa2996da0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np171",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe878e98d05f60a8fd741a4aaab17a91c538f21552ac41922fe2b755e4f0e534c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf4a19b9765604687783462dbf36a0063ada2ba7babb4dd1c4857b2449565a41d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xab",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x6ae",
+ "extraData": "0x",
+ "baseFeePerGas": "0xac",
+ "blockHash": "0xc3f33c71274b456303efd80efacba7d5fccb0ed278ee24e5594a38c45a294315",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x12",
+ "validatorIndex": "0x5",
+ "address": "0x087d80f7f182dd44f184aa86ca34488853ebcc04",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4c83e809a52ac52a587d94590c35c71b72742bd15915fca466a9aaec4f2dbfed"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np172",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc3f33c71274b456303efd80efacba7d5fccb0ed278ee24e5594a38c45a294315",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4f9e280291036fb6cd64598fe0517d64d6da264d07d7fc3b8d664221d7af9021",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xac",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x6b8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x97",
+ "blockHash": "0xd785018f59628b9f13cc2d4a45e0b4b3af183acce4e5752346e79dbcdf7de4e5",
+ "transactions": [
+ "0xf883818a8198830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a05f47b0ab77130dcc8f7143a2afaace6a2d1f82e25839cb9adee5aaebfe7dc681a05af90b75de35c90709b83861d8fdfd7805a89b1e76a4bdd5987e578ba72fc37e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x268fc70790f00ad0759497585267fbdc92afba63ba01e211faae932f0639854a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np173",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd785018f59628b9f13cc2d4a45e0b4b3af183acce4e5752346e79dbcdf7de4e5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe01cadedc509806ea9cd7475312a3768de034d1c849abadc46237b8cd4163179",
+ "receiptsRoot": "0x15dc68f6de1b068b96d32dbc11a048b915e7d62bd3662689ae5c095bb6ddab37",
+ "logsBloom": "0x00000100000000004000000004000000000000000000000000000000000000000000000004000000018004000000000000000000000000000002000000000000000020002000400000002000020000000100000000000000000080010000400000000000000200000000040000000000000000000000010000002000000000000000000000000004040000000000000000000000000000000000000000004000000000000000000000080000004000000000000000000000001000000000000100000800040000000000000000000000000000000000000000000000000000000000000000400000000000004001000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xad",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x6c2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x85",
+ "blockHash": "0xbcff8f4e8c3d70d310900cd8246c3456e237ab8ea9fc036601995404b141e3bb",
+ "transactions": [
+ "0xf87a818b818683011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04a74ea0833e42d624ba0d9b589a16e05feae1c2dee89abfb29df95b650d3e756a037135f3e24572eb9d927a02c0c4eee7fd5d8a181e2384ef3b3b04c49c9dbbbe1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7e544f42df99d5666085b70bc57b3ca175be50b7a9643f26f464124df632d562"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np174",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbcff8f4e8c3d70d310900cd8246c3456e237ab8ea9fc036601995404b141e3bb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa862687747ffc388414ee5953589a70f2161a130886348157257a52347be9157",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xae",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x6cc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x75",
+ "blockHash": "0x943b23302ffed329664d45fee15ca334c92aa6195b22cb44c7fdd5bdbbe4e7d4",
+ "transactions": [
+ "0xf864818c768302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a024414367540c94b1bd3ce29dd0b4ee6bdece373f9417e96f0ef8d632e82c4ecba031dae9539e84f7351a5b92f1246dfd909dd5a383011fbd44bb8e87fb6870189b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd59cf5f55903ba577be835706b27d78a50cacb25271f35a5f57fcb88a3b576f3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np175",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x943b23302ffed329664d45fee15ca334c92aa6195b22cb44c7fdd5bdbbe4e7d4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd70339e1158ecc97dc7db86b3177202ffa3dcba386fd52e54e6fe8b728003154",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xaf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x6d6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x67",
+ "blockHash": "0xd2a0fc154d0bb77b346c7bb3532d24581bc1a5b5bf9ced18b419a6309ff84351",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e818d0168825208945a6e7a4754af8e7f47fc9493040d853e7b01e39d0180c001a08c62285d8318f84e669d3a135f99bbfe054422c48e44c5b9ce95891f87a37122a028e75a73707ee665c58ff54791b62bd43a79de1522918f4f13f00ed4bd82b71b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x551cced461be11efdeaf8e47f3a91bb66d532af7294c4461c8009c5833bdbf57"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np176",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd2a0fc154d0bb77b346c7bb3532d24581bc1a5b5bf9ced18b419a6309ff84351",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1bc27508b52de3a750cc928dd89954462b4e4dbfb60707442e60b4b23aabb816",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x6e0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x5b",
+ "blockHash": "0xe3072603b13de812d2c58ece96eeb4f32ff7e3e93c8b9121dd18f0682a750970",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x13",
+ "validatorIndex": "0x5",
+ "address": "0xf4f97c88c409dcf3789b5b518da3f7d266c48806",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc1e0e6907a57eefd12f1f95d28967146c836d72d281e7609de23d0a02351e978"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np177",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe3072603b13de812d2c58ece96eeb4f32ff7e3e93c8b9121dd18f0682a750970",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x78497ebf1fbf03732772a8c96b2fe6902af5ab844e49f2685763b4366ce8ddf6",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x6ea",
+ "extraData": "0x",
+ "baseFeePerGas": "0x50",
+ "blockHash": "0x996acbdde853cdc1e21426f4e53d07c09a13ed50798ee071582f24cc1014e238",
+ "transactions": [
+ "0xf882818e51830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0fd5ea8b7df5c3ecd87220b8ad7d15198722d94a64b0e8e099c8c7384c1d08a33a039707925aba6dad8d06c162fd292df0bf03033b7b6d1204ae4be0ce6f487fa71"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9d580c0ac3a7f00fdc3b135b758ae7c80ab135e907793fcf9621a3a3023ca205"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np178",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x996acbdde853cdc1e21426f4e53d07c09a13ed50798ee071582f24cc1014e238",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x197c4166e7f8f68ee6965c87c8ce720bee776a7b7119870371e6262bc913468d",
+ "receiptsRoot": "0x7c66f99e4434aa19cdf8845c495068fa5be336b71978d6fa90966129f300218a",
+ "logsBloom": "0x00000000000000000000000000400200000000000000800000000000000000008000008000000000000000000000000000000000000000000040000004000041004000000000000000000000000800000000000000000000000000000000080100000000000000000000000020000000004200000000001000000002000000100008080200000004000000000000200000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000800000000200000000000000000000100002000000000000000000002000000000000000000100000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x6f4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x47",
+ "blockHash": "0xf00d6a4f13579131abcd2c856040cf9295caed200698d7cf7a1574690b36b0bf",
+ "transactions": [
+ "0xf879818f4883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03e0f9aa0ca6ec8b4f9e7fccd9b710c0de4414618726e298b36816cd6d689a89aa07d3950b5ebbaa58f5c4e0bc0571499d9d58d563ce2c039664cf210815e43d0e5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa7fd4dbac4bb62307ac7ad285ffa6a11ec679d950de2bd41839b8a846e239886"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np179",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf00d6a4f13579131abcd2c856040cf9295caed200698d7cf7a1574690b36b0bf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf56610f73e08c2ccaaa314c23bc79022214919c02d450cab12975da3546b68fd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x6fe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x3f",
+ "blockHash": "0x5711092388b2fd00bf4234aca7eede2bdc9329ea12e2777893d9001f4f2c8468",
+ "transactions": [
+ "0xf8648190408302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0f41a67e92f032c43cc601daa205026cc5a97affb0f92064991122a1aa92428dfa0237053c462847907c840ada5076caab16adc071da181e9277926a310adcb8e3d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6ba7b0ac30a04e11a3116b43700d91359e6b06a49058e543198d4b21e75fb165"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np180",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5711092388b2fd00bf4234aca7eede2bdc9329ea12e2777893d9001f4f2c8468",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfa57370da0cc72170d7838b8f8198b0ebd949e629ca3a09795b9c344dead4af5",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x708",
+ "extraData": "0x",
+ "baseFeePerGas": "0x38",
+ "blockHash": "0xb58807a37c03cf3b0f1c9104cfd96f6cb02b1e08e0eecdd369cac48d0003b517",
+ "transactions": [
+ "0xf8678191398252089427952171c7fcdf0ddc765ab4f4e1c537cb29e5e501808718e5bb3abd109fa076a045602a7de6b1414bdc881a321db0ce5255e878a65513bad6ac3b7f473aa7a01a33017b5bcf6e059de612293db8e62b4c4a3414a7ba057c08dd6172fb78a86c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8835104ed35ffd4db64660b9049e1c0328e502fd4f3744749e69183677b8474b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np181",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb58807a37c03cf3b0f1c9104cfd96f6cb02b1e08e0eecdd369cac48d0003b517",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6d3f029e56f9ee3db9ed8f9156cd853fb1fcafe05475ec8c2a4dd337a5e3e20e",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x712",
+ "extraData": "0x",
+ "baseFeePerGas": "0x32",
+ "blockHash": "0x56b5aa12ccfcbd86737fe279608cb7585fbc1e48ddfcdac859bb959f4d3aa92a",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x14",
+ "validatorIndex": "0x5",
+ "address": "0x892f60b39450a0e770f00a836761c8e964fd7467",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x562f276b9f9ed46303e700c8863ad75fadff5fc8df27a90744ea04ad1fe8e801"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np182",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x56b5aa12ccfcbd86737fe279608cb7585fbc1e48ddfcdac859bb959f4d3aa92a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x58a6332c9e7b85155106515f20355c54bb03c6682024baa694cbaff31c3b84ff",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x71c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x2c",
+ "blockHash": "0xb0d7fbd46bd67d4c3fa51d0e1b1defaf69237d0f6e2049486c907b049b47e01c",
+ "transactions": [
+ "0xf88281922d830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa01ae40537174a716b5f33d153e9251ae8c1d72852da25823f6d954b9dbc5740cca02ff07812990e0645cab5c9d89028f7255f50d0eee5bee334b3ba10d71485c421"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd19f68026d22ae0f60215cfe4a160986c60378f554c763651d872ed82ad69ebb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np183",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb0d7fbd46bd67d4c3fa51d0e1b1defaf69237d0f6e2049486c907b049b47e01c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x55d4e87d040358926c84414b854fc47a75b9963df75e359a2182464c51201088",
+ "receiptsRoot": "0x1fccfe93768ce1ed60d0f83cbc8bef650cb1d056c35a4b233ae41a1b8219f92d",
+ "logsBloom": "0x00000080000000000000000000000000000000000000004000000000000010000000000000000000000000000000014000800000000000000100102000000000000000000000020000000000200000000000000000100000000000200000002000000000000000000000002000000000000000000000000000000000000000001000002000400020040000000000000200000000000000000000000000000000000000002000000000000000000000100000000000022000000000000000000000000000000004000000080000000000000000000000000004004000000000040002000040000000000000000000000000000000000000000000000000100000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x726",
+ "extraData": "0x",
+ "baseFeePerGas": "0x27",
+ "blockHash": "0x66011454670d5664e8e555d01d612c70cadabfb6a4a317f375495ef3daa9d1b4",
+ "transactions": [
+ "0xf87981932883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa02d1dcc844efba97a51917ab3d79f837680f42e2e76ab51b4b630cbe9a6e4e10ea03d3f624c82de14b23b0c5553621cc9a4c649cd856a616f5a91bad8bf0c0d1709"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf087a515b4b62d707991988eb912d082b85ecdd52effc9e8a1ddf15a74388860"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np184",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x66011454670d5664e8e555d01d612c70cadabfb6a4a317f375495ef3daa9d1b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd3ec16ab633987e17a4e8c573014b1fc9919f004b3cb80da11280d1caad1fe3e",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x730",
+ "extraData": "0x",
+ "baseFeePerGas": "0x23",
+ "blockHash": "0x36e1e3513460407c80dfcfab2d2826ea432dadb99aa7415f9cffcf56faf27f94",
+ "transactions": [
+ "0xf8648194248302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a01e5301a3386e11893c0275367ac5d31fea88f31731e66ee769bfddc3486cff1aa0203dbf8bbfa9df2d635e1889d51e06611e8c2a769609908aeb5e97decb03b141"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf7e28b7daff5fad40ec1ef6a2b7e9066558126f62309a2ab0d0d775d892a06d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np185",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x36e1e3513460407c80dfcfab2d2826ea432dadb99aa7415f9cffcf56faf27f94",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x692ddd6938f00a07474233619f579b30c1eaaef353a2b0cc24b47d7898aa5c49",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xb9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x73a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1f",
+ "blockHash": "0x44e05b6820cf1d7cf9cd2148d6f71a6a649c9a829b861539d2c950f701e27260",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e819501208252089404d6c0c946716aac894fc1653383543a91faab600180c080a0039c18634a9f085ba0cd63685a54ef8f5c5b648856382896c7b0812ee603cd8aa05ecfde61ea3757f59f0d8f0c77df00c0e68392eea1d8b76e726cb94fb5052b8a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x77361844a8f4dd2451e6218d336378b837ba3fab921709708655e3f1ea91a435"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np186",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x44e05b6820cf1d7cf9cd2148d6f71a6a649c9a829b861539d2c950f701e27260",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9eac86abf4371646a564bb6df622644682e5de5bf01fed388ccaf10700e46e88",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xba",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x744",
+ "extraData": "0x",
+ "baseFeePerGas": "0x1c",
+ "blockHash": "0xcc3b1096f3ce63881c77751baec2048561baa2dc84ea0ef9d3a5515061aa74e0",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x15",
+ "validatorIndex": "0x5",
+ "address": "0x281c93990bac2c69cf372c9a3b66c406c86cca82",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe3cb33c7b05692a6f25470fbd63ab9c986970190729fab43191379da38bc0d8c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np187",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcc3b1096f3ce63881c77751baec2048561baa2dc84ea0ef9d3a5515061aa74e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xff13e99ee95ffe82139758f33a816389654a5c73169b82983de9cf2f1f3dbd9f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x74e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x19",
+ "blockHash": "0x871cb66f77db23f8e70541a647329c5ca9b6d40afd3950d48df4915f300e664a",
+ "transactions": [
+ "0xf88281961a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0276782d84f5f6ab0805be5e57923747bae9fa2b06ed4b45bcc364bdb4f09eca1a0484f9fc2a31a4b5f24ba33da54649e6a3261c0bee52d91576246bb54698c1535"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc893f9de119ec83fe37b178b5671d63448e9b5cde4de9a88cace3f52c2591194"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np188",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x871cb66f77db23f8e70541a647329c5ca9b6d40afd3950d48df4915f300e664a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x522c1eb0c4d1332668a2e3676efd54899579d85fd4e7007fd228702d9c964baa",
+ "receiptsRoot": "0x90d4e326daf1e15e41687f281f8e638992c4cdfbe590eb4956fd943aa39f1bba",
+ "logsBloom": "0x48000040000000000000000000004000000000000000000000400000000000002000000000000000000000000000000018000000000000000000002000000000000000000000100000002000000800000000000000000000000000002000000000000000000000000000000000000000040000020000040000000000000000000000000101000000000000000000010000000000040000000000000000000000008000000000000000000000800000000000201008000000000000001000000000000010000000000000100000000000000000000000040100000000000000000008000000000000000000000000000000000000004000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x758",
+ "extraData": "0x",
+ "baseFeePerGas": "0x16",
+ "blockHash": "0x174a8681a0d28b9a3d49afb279714acb2bfe4a3abfe490522bb3d899d3c71c8d",
+ "transactions": [
+ "0xf87981971783011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0870548904b9e901c294fd1c04a6cff92fbb40491e00a1ffcbc551c6c5eba2db3a0524ff53000a94b71aef3a2c516354bc5d7fdb3f236d4647020762a56d9bd2fbf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x39c96a6461782ac2efbcb5aaac2e133079b86fb29cb5ea69b0101bdad684ef0d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np189",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x174a8681a0d28b9a3d49afb279714acb2bfe4a3abfe490522bb3d899d3c71c8d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfb0eecb29a002997c00e0f67a77d21dd4fa07f2db85e3e362af4bbfcb69b6c12",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x762",
+ "extraData": "0x",
+ "baseFeePerGas": "0x14",
+ "blockHash": "0x1b56a73d407c9a5e222c2097149c2f2cbb480a70437ee41779974b8ab968a8e1",
+ "transactions": [
+ "0xf8648198158302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0111d3d32f82c89fc830943a4aa0b20e013886491e06acede59ea4252b3366c05a07b9f9199ecdb210151db8a50c74fa1488b198db4e5dda3ad1fa003b70d9bd03a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x72a2724cdf77138638a109f691465e55d32759d3c044a6cb41ab091c574e3bdb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np190",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1b56a73d407c9a5e222c2097149c2f2cbb480a70437ee41779974b8ab968a8e1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x36fce9409ec76cfda58bd4145be0289d761c81131ed0102347b96127fd0888e2",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbe",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x76c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x12",
+ "blockHash": "0x07d1571c1d0fbaf6cd5c2fa18e868d6dfc2aa56f7ee3bd5aaf61fa816d775ee9",
+ "transactions": [
+ "0xf86781991382520894478508483cbb05defd7dcdac355dadf06282a6f201808718e5bb3abd109fa0910304dbb7d545a9c528785d26bf9e4c06d4c84fdb1b8d38bc6ee28f3db06178a02ffc39c46a66af7b3af96e1e016a62ca92fc5e7e6b9dbe631acbdc325b7230a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x178ba15f24f0a8c33eed561d7927979c1215ddec20e1aef318db697ccfad0e03"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np191",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x07d1571c1d0fbaf6cd5c2fa18e868d6dfc2aa56f7ee3bd5aaf61fa816d775ee9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd5d1fc871c3a4694da0e9a9f453c0e6f4c8f38fbef45db36c67cd354e22eb303",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xbf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x776",
+ "extraData": "0x",
+ "baseFeePerGas": "0x10",
+ "blockHash": "0xda1708aede1e87f052ee6e9637f879462b613e4cbddacb18aa49907b55094ce4",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x16",
+ "validatorIndex": "0x5",
+ "address": "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf7b2c01b7c625588c9596972fdebae61db89f0d0f2b21286d4c0fa76683ff946"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np192",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xda1708aede1e87f052ee6e9637f879462b613e4cbddacb18aa49907b55094ce4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4d19a2ce0d61642b6420c9f23ea32bb72ebe24384ed110394d7e5ca98589f055",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x780",
+ "extraData": "0x",
+ "baseFeePerGas": "0xe",
+ "blockHash": "0x082079039cffbdf78a5cc86fddb47d96c888e0e90b092f9e0591e0099086cc45",
+ "transactions": [
+ "0xf882819a0f830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02356373d8d8ca7c15e547e717f7327ab0d803867cfabedf8d75e4d1cb264862ca011a3879ae15ab356e9558926382b7fa68b5c5a5c5b127b6f5176523dfe0ae986"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x16e43284b041a4086ad1cbab9283d4ad3e8cc7c3a162f60b3df5538344ecdf54"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np193",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x082079039cffbdf78a5cc86fddb47d96c888e0e90b092f9e0591e0099086cc45",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd67263b379522c5059bb0a7164b9cd3fa70697e4012b3b5c519ecf888dbc5700",
+ "receiptsRoot": "0xc1c820ad9bde8ce9524a7fa712d4849dc2f9f9553e8c00f1fe6c41323e31fbf7",
+ "logsBloom": "0x00000000000000000000000000000000000000000080000000000200000040000000000000000000000000000000000000000000000000000000001000000000000000000000000000001002000004020000000000000000000011000000000000000080000082000082080000000404000000080010000000000000000000000000100000010000000000000400000000000000000000000000000000400402000000000000000000000000000000000000000000200000000000002000000004000000400000002000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000800000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x78a",
+ "extraData": "0x",
+ "baseFeePerGas": "0xd",
+ "blockHash": "0xe1207296a903bee61a02dd94d685640d76ab57ea96dd5789819583e35f2d7eb3",
+ "transactions": [
+ "0xf879819b0e83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa03423551e59962468cb263c416cb4025c462624b8c8c687177571976c345a8d20a0190d3ab5979e300998fc96429a75c50e1c195115cada83e01fb14a28f2e294de"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0a98ea7f737e17706432eba283d50dde10891b49c3424d46918ed2b6af8ecf90"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np194",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe1207296a903bee61a02dd94d685640d76ab57ea96dd5789819583e35f2d7eb3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2111d275b4901e864fcded894a9d9a046f9077d8f6c5af65a72c2243a32dbeaa",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x794",
+ "extraData": "0x",
+ "baseFeePerGas": "0xc",
+ "blockHash": "0x8fd42cbdbbe1b8de72a5bb13684131e04572585077e0d61a0dfbb38d72ef309f",
+ "transactions": [
+ "0xf864819c0d8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0b4dac384ec258b1a752856b3fcda42244c3e648577bf52d74f25313b3327bf1ca02f7b54b9475768335aab1778fd7ec882f3adbc9e78d4d04a0b78e93e4d41a76b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7637225dd61f90c3cb05fae157272985993b34d6c369bfe8372720339fe4ffd2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np195",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8fd42cbdbbe1b8de72a5bb13684131e04572585077e0d61a0dfbb38d72ef309f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2efd726637cb91156021ac4ae337a87f9a1f28efd620de55b77faef0d3b84b22",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x79e",
+ "extraData": "0x",
+ "baseFeePerGas": "0xb",
+ "blockHash": "0x326484b702b3c743f907227c8aad8733b1a6b7fda510512fe4fec0380bfbc0f1",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e819d010c82520894ae3f4619b0413d70d3004b9131c3752153074e450180c001a07cb73f8bf18eacc2c753098683a80208ac92089492d43bc0349e3ca458765c54a03bf3eb6da85497e7865d119fde3718cdac76e73109384a997000c0b153401677"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6a7d064bc053c0f437707df7c36b820cca4a2e9653dd1761941af4070f5273b6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np196",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x326484b702b3c743f907227c8aad8733b1a6b7fda510512fe4fec0380bfbc0f1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xeba72457992e05a38b43a77a78ba648857cec13beb5412b632f6623521fe248d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x7a8",
+ "extraData": "0x",
+ "baseFeePerGas": "0xa",
+ "blockHash": "0x6a40d1d491a8624685fa20d913a684f691f1281da37059d527241526c965874d",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x17",
+ "validatorIndex": "0x5",
+ "address": "0xd1211001882d2ce16a8553e449b6c8b7f71e6183",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x91c1e6eec8f7944fd6aafdce5477f45d4f6e29298c9ef628a59e441a5e071fae"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np197",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6a40d1d491a8624685fa20d913a684f691f1281da37059d527241526c965874d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8713a1c42af83625ae9515312298d02425330b20a14b7040ec38f0655cb65317",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x7b2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x9",
+ "blockHash": "0x25702b83ea77e2ad219178c026a506fa7a9c3f625b023963bc9c13c0d5cfeb14",
+ "transactions": [
+ "0xf882819e0a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02ed567eed3a763f56fe05c1e44575993df5b6cf67e093e0e9b5ec069ecaf76a2a04891e566e0d136b24d62ffe17f2bfaa0736a68f97b91e298b31897c790b2ed28"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa1c227db9bbd2e49934bef01cbb506dd1e1c0671a81aabb1f90a90025980a3c3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np198",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x25702b83ea77e2ad219178c026a506fa7a9c3f625b023963bc9c13c0d5cfeb14",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2250f011d079600d76d5905dca93324f2fceb110390e8a7e7177569bd8ec73fd",
+ "receiptsRoot": "0x8027ec2e573bf62c00695cb9a0f67e28e4cce8dc44dc641d7388e4864d8ff78a",
+ "logsBloom": "0x00080000100000000000100000000840000000000000000000000000000000000000000000000000000000000000000000000000080080000080000000000000000000004000000000000000000000000000000000000000000000000000000200000000000000100100000000008001000000000000000000800000000000020010000000000000000000000000001000800000200000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000012000000000000000000040800000040004000000040000800001000000000000000000000000000000010000100000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x7bc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8",
+ "blockHash": "0xa752bd3886362e9e5e57dba077628fedbfbca6b2a657df205ad20d739b035c22",
+ "transactions": [
+ "0xf879819f0983011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0c362dc6d498fcbd0eab0518a012a348d87fe4f2e53f7843f350662c43258609ba026d83d49fd9654704da7435b3400713ed7909a7203d6c55b8d43dd1e9fe67226"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8fcfc1af10f3e8671505afadfd459287ae98be634083b5a35a400cc9186694cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np199",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa752bd3886362e9e5e57dba077628fedbfbca6b2a657df205ad20d739b035c22",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa8faa1ccb44b8d8d3ad926bdcb75a9e9fd18fa77728ef12aa9c4ba7be1906d3f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x7c6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8",
+ "blockHash": "0x5d80c24a7a87ae0ab200b864029fbfe7bb750ba0a01c07191b7f52330d2c79ad",
+ "transactions": [
+ "0xf86481a0098302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a08683c22fc25a5413b758a32c5a6515b1b055541ad523ae4159c4d04c3f864260a06c8f2e1e929e9df95158a161e793ae162e1e4297f8042bf9358dcc119f5545e5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcc1ea9c015bd3a6470669f85c5c13e42c1161fc79704143df347c4a621dff44f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np200",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5d80c24a7a87ae0ab200b864029fbfe7bb750ba0a01c07191b7f52330d2c79ad",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe4f7f192080fd853f053608561854cdb68eb8de9eda499fd7ad840ca729487d3",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x7d0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8",
+ "blockHash": "0x0fd7e67081119b73ebe7ae0483ce2154a2dfb8c503545d231e2af1f8942406ae",
+ "transactions": [
+ "0xf86781a109825208947c5bd2d144fdde498406edcb9fe60ce65b0dfa5f01808718e5bb3abd109fa015f510b05236b83a9370eb084e66272f93b4b646e225bdef016b01b3ac406391a03b4a2b683af1cb3ecae367c8a8e59c76c259ce2c5c5ffd1dc81de5066879e4b8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb0a22c625dd0c6534e29bccc9ebf94a550736e2c68140b9afe3ddc7216f797de"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np201",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0fd7e67081119b73ebe7ae0483ce2154a2dfb8c503545d231e2af1f8942406ae",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5188152524460d35f0c837dab28ac48f6aac93a75ecbb0bcb4af6a9c95e18a67",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xc9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x7da",
+ "extraData": "0x",
+ "baseFeePerGas": "0x8",
+ "blockHash": "0x3043a03ed3369ba0dfdddac07cae4ca805dbbb0b411b3f5dd5e66198928a715b",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x18",
+ "validatorIndex": "0x5",
+ "address": "0x4fb733bedb74fec8d65bedf056b935189a289e92",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x92b8e6ca20622e5fd91a8f58d0d4faaf7be48a53ea262e963bcf26a1698f9df3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np202",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3043a03ed3369ba0dfdddac07cae4ca805dbbb0b411b3f5dd5e66198928a715b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x09f47830b792bc39aa6b0c12b7024fa34d561ff9e0d32c27eab5127239799bb0",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xca",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x7e4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9178b45b38e39c3e3f4bc590a301254543eedb5b146bed0900465b194aaf94e8",
+ "transactions": [
+ "0xf88281a208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03b50dfd68a93199762b4b47c08ca4c9f67d99e772f3fec9843a4e1c3ae4d6963a070a7b2cc31e53de9d1fa14f55f28b212979bd83bbd9e9097e65845e05a9ee40f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf6253b8e2f31df6ca7a97086c3b4d49d9cbbbdfc5be731b0c3040a4381161c53"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np203",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9178b45b38e39c3e3f4bc590a301254543eedb5b146bed0900465b194aaf94e8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6a0d6e0a749247b4271d54ddfd2732ceb5b377c1db1ac40aa1d2339d3a143aaa",
+ "receiptsRoot": "0x189141497b4062bfbe61a7fb2f96cc8a95543e38c077c9150b740f8d01a313a8",
+ "logsBloom": "0x00000000000000000000040040000000000000000000080000000000004000000000000000004000000000008000000000000000000080000002008001000000000000000010000000000080000000000000000000200000002000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000020000000000000000000000800040000000000000000400000000000000000400001000000004000001000000000020000000000010000000000000000000000000000000000000000008000000000010000100000000000000001000000010000000000000800000000000000202000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xcb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x7ee",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9a575aa75a5f08a27533140141ffc7ed7d6e981da97316baf296dd1f8d1007d7",
+ "transactions": [
+ "0xf87881a30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109f9f3c7a9aedd154caa41f602593b4bc78db1101336a81095174d4487dd8338878a0458e45144a4d1a634950ae79ac251065204776baa96a3f94c6d71a00323fe9b4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xea8d762903bd24b80037d7ffe80019a086398608ead66208c18f0a5778620e67"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np204",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9a575aa75a5f08a27533140141ffc7ed7d6e981da97316baf296dd1f8d1007d7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda96365c5a33f358ed732463139254c4f186e899ad00b05d9a30ff39d4d1a27d",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xcc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x7f8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb35f9d9c454a03adc1eeeaa9fef20caeb8f9445663a4768d18bc0bc1790650b1",
+ "transactions": [
+ "0xf86481a4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0a82c39f1be580d16334c133165d5ceb8d9942b184ecccea09e73ff45120ac523a04432d6958bb18882f9f07e851abe454039a5b38d61fd975c7da486a834107204"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x543382975e955588ba19809cfe126ea15dc43c0bfe6a43d861d7ad40eac2c2f4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np205",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb35f9d9c454a03adc1eeeaa9fef20caeb8f9445663a4768d18bc0bc1790650b1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2258c0e37e5bedab21f7ea2f65190d1d51f781743653168d02181c8f16246c71",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xcd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x802",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x97f4a4e64ede52b5dfd694236e783d130206d111cf6a5eb83a3bb9a230dfd952",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81a50108825208949a7b7b3a5d50781b4f4768cd7ce223168f6b449b0180c080a04f3e818870a240e585d8990561b00ad3538cf64a189d0f5703a9431bc8fd5f25a0312f64dd9ab223877e94c71d83cb3e7fe359b96250d6a3c7253238979dd2f32a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x095294f7fe3eb90cf23b3127d40842f61b85da2f48f71234fb94d957d865a8a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np206",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x97f4a4e64ede52b5dfd694236e783d130206d111cf6a5eb83a3bb9a230dfd952",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda2ecb481078839fd39c044b3fceae6468338266d9572da0f2281e58b9596914",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xce",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x80c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb3c2c9a5de90f0637203e60288b50ecb21d17a2437cccf553d2424321fa112d4",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x19",
+ "validatorIndex": "0x5",
+ "address": "0xc337ded6f56c07205fb7b391654d7d463c9e0c72",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x144c2dd25fd12003ccd2678d69d30245b0222ce2d2bfead687931a7f6688482f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np207",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb3c2c9a5de90f0637203e60288b50ecb21d17a2437cccf553d2424321fa112d4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf0f20309e2cec2fb6af448c58c40e206b788241bb88e62a8e7479aadc6bfa94e",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xcf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x816",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9e63e1a7df1b726901e3139cfb429592ef8d2107aa566bcae5f3b8e21f99f0da",
+ "transactions": [
+ "0xf88281a608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa079aa26a33abe2e9504cfc6552c6b39434478b081f5cbbb613269d64980edaf93a079ffe44aec63b05644681b948ea0e5a996e106f3e074a90991c963ff3e7a8aa6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7295f7d57a3547b191f55951f548479cbb9a60b47ba38beb8d85c4ccf0e4ae4c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np208",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9e63e1a7df1b726901e3139cfb429592ef8d2107aa566bcae5f3b8e21f99f0da",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x177fc88f477d3dd466f7cac43b50d4b2b77fd468ef479177ed562d2401acd6c0",
+ "receiptsRoot": "0xd1458a51a7ca8d2c87390d85d986956f392bdd634ffbe4d5a7e2b09a142ce514",
+ "logsBloom": "0x00200000000000000000000000000000000000000400000000400000000000000000100400000000000000000010108000000000000000000000200800000000000004000000000000000002000000000000000000000000000000020002000408000021000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000002000000000000000000000400000000000000000000020000000000000000000000800000000000080000000000000000000000800000810002000000000400000000000000000000000000000000000000000000020000000000000000000000010080000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x820",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4e8e6e31a8922b68a96992288e49ab9716dd37f1da1ae5b22391bc62d61ac75a",
+ "transactions": [
+ "0xf87981a70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0969f6d3d90ca6b62cbda31ed28b7522b297d847e9aa41e0eae0b9f70c9de1e01a0274e038abf0b9f2fba70485f52e4566901af94c9645b22a46b19aebb53b4c25d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9e8e241e13f76a4e6d777a2dc64072de4737ac39272bb4987bcecbf60739ccf4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np209",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4e8e6e31a8922b68a96992288e49ab9716dd37f1da1ae5b22391bc62d61ac75a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x55980d8ac0e8bfd779b40795a6d125a712db70daa937ace1f22a5fcd5fd2dfa6",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x82a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xaf3e413fc388e1a5508f683df5806fe31d29f5df4552ccf2d6c6662816fae5fd",
+ "transactions": [
+ "0xf86481a8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa04973c2a9d2fcff13428e8a3b3f0979185222cad34366777db8dfc6438cdac357a0128ad521391c000e18211ad8ffa45b41962fca43be83a50ce299d3bd4407f44b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfc753bcea3e720490efded4853ef1a1924665883de46c21039ec43e371e96bb9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np210",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaf3e413fc388e1a5508f683df5806fe31d29f5df4552ccf2d6c6662816fae5fd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x522d0f5f8de1ef5b02ad61a3bff28c2bd0ce74abca03116e21f8af6e564d7fd2",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x834",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa5b31d7aaa42b7be0c35a0fa375718d25441f90296550c10325a3e0f4d63217c",
+ "transactions": [
+ "0xf86781a9088252089485f97e04d754c81dac21f0ce857adc81170d08c601808718e5bb3abd109fa0547e9550b5c687a2eb89c66ea85e7cd06aa776edd3b6e3e696676e22a90382b0a028cb3ab4ef2761a5b530f4e05ef50e5fc957cfbc0342f98b04aa2882eec906b2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5f5204c264b5967682836ed773aee0ea209840fe628fd1c8d61702c416b427ca"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np211",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa5b31d7aaa42b7be0c35a0fa375718d25441f90296550c10325a3e0f4d63217c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda7dd7f5babcf1b3c407e141b4ea76932922489f13265a468fb6ab88891ff588",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x83e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa1ffa80abb4f7f92b3932aa0ca90de5bb4a2908866b3d6727b05d5d41139e003",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1a",
+ "validatorIndex": "0x5",
+ "address": "0x28969cdfa74a12c82f3bad960b0b000aca2ac329",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5ba9a0326069e000b65b759236f46e54a0e052f379a876d242740c24f6c47aed"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np212",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa1ffa80abb4f7f92b3932aa0ca90de5bb4a2908866b3d6727b05d5d41139e003",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb6724f1d73bee909624707836e66ffbb21b568dd5bd697668ce18a4ae31818a4",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x848",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9a77bcf7bf0d7e6cebeb8c60b4c36538b4fab0e633b9683ba589981c293a009c",
+ "transactions": [
+ "0xf88281aa08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e582e9d64ed6f95da074eaeb70ca1e47e8627bb7cd4e34d5aab01ff49ee6dd90a022cc32cc7c3030b0b47f1f69911311acd2ae3e95f19f766b69ebb67804676262"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb40e9621d5634cd21f70274c345704af2e060c5befaeb2df109a78c7638167c2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np213",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9a77bcf7bf0d7e6cebeb8c60b4c36538b4fab0e633b9683ba589981c293a009c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6a1c08c9dfcc48c37e349407f37f9c10d9d4c4b1d6c28d30af2630679c74ea96",
+ "receiptsRoot": "0x730ab6f592da8dfc7815bcba110f6de8dd0343aa932f55b589ff99d83b9ec358",
+ "logsBloom": "0x00000000000000000000000000000000000000200000000400000000000000002008008000100100000800000000000020000000000000000000000000000000800001000000002000000000000000800000010000000000000000420008000004000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000004000000000000008000000000000000000000000000000000000000000000000000000400010000000000004000000000000008000000840000000000000000040000000000000000000000000000120000001000000100000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x852",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xecb42acc218101eb9c6d883a333d07c7736d7ed0b233f3730f5b9c9a75314cf5",
+ "transactions": [
+ "0xf87981ab0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a08747d48d3358eb47195c17f67f22af5eca1177fba591b82b8b626058a347b2e5a0420e02657efee51f73f95017b354b1bca2850269a5de7b307a280c63830f3333"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x70e26b74456e6fea452e04f8144be099b0af0e279febdff17dd4cdf9281e12a7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np214",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xecb42acc218101eb9c6d883a333d07c7736d7ed0b233f3730f5b9c9a75314cf5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x67ca707e9bd81330c2fb9060e88ce0b0905c85c9be26ae4779874f3892ebab0c",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x85c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1191fbb4f2692461fc0ae4aa7141a1743a345c101dc9db157bc7ad3072fe1e9d",
+ "transactions": [
+ "0xf86481ac088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a03752a40997c9b7b9c5dfd48f88990ddc727517540c403dadcb7476b8a4a9d4f6a0780178975646114017be4b06fae0689a979a45166f810604f76934239b0a2b9e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x43d7158f48fb1f124b2962dff613c5b4b8ea415967f2b528af6e7ae280d658e5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np215",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1191fbb4f2692461fc0ae4aa7141a1743a345c101dc9db157bc7ad3072fe1e9d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3b5ca86f1650f79fb42d74e523dc4e631989a3175023ced9a239e9bcc2c15a8e",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x866",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9b9e271d571b730c9e6acd133c99eba1ccd8b8174ffe080540fc3b1a5625943a",
+ "transactions": [
+ "0x02f869870c72dd9d5e883e81ad010882520894414a21e525a759e3ffeb22556be6348a92d5a13e0180c001a0047b3309af68dd86089494d30d3356a69a33aa30945e1f52a924298f3167ab669fb8b7bd6670a8bbcb89555528ff5719165363988aad1905a90a26c02633f8b9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb50b2b14efba477dddca9682df1eafc66a9811c9c5bd1ae796abbef27ba14eb4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np216",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9b9e271d571b730c9e6acd133c99eba1ccd8b8174ffe080540fc3b1a5625943a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc1ab95016db7b79d93ee0303af69ce00bdb090d39e20a739d280beb3e301c9d5",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x870",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4e27c497c83c3d06d4b209e7d5068920d7e22bb3c959daa4be5485d6ab0cce54",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1b",
+ "validatorIndex": "0x5",
+ "address": "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc14936902147e9a121121f424ecd4d90313ce7fc603f3922cebb7d628ab2c8dd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np217",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4e27c497c83c3d06d4b209e7d5068920d7e22bb3c959daa4be5485d6ab0cce54",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf8c17319b995ce543f9ace79aab7f7c928b36facae4e6e0dd50991f95bed1542",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xd9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x87a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdf05b4a3aff6236d0d3c1ee058b874309c37005a2bbb41a37432b470ed49e678",
+ "transactions": [
+ "0xf88281ae08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05a8e9e2a3556016a65d5b99849bd44cd6ab17cfb15d7850356c9b491357f0611a01f7d3c43fe1759b4ec768275e918e12dae75db56a5d2140d1403ef3df41f56df"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x86609ed192561602f181a9833573213eb7077ee69d65107fa94f657f33b144d2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np218",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdf05b4a3aff6236d0d3c1ee058b874309c37005a2bbb41a37432b470ed49e678",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x05bd7288ee80780a92b234fec2f8bb5bb4d0425721ddbf89d866c62b288f6bff",
+ "receiptsRoot": "0xbebbd614564d81a64e904001523ad2e17a94b946d6dfc779928ec9048cf9a3f7",
+ "logsBloom": "0x40000000000020000000000040000000000000000000001000000000000000021000000000004008000000000002000001000100000000000000002000000000000400000000000008002000000000000000100000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000100000400000000000000000000000000000000000000000000000000000020000000000010040000002000000000000000000000000000000000000000000000000020000000000200000000000200000000000000011000000000201400000000000001000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xda",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x884",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf9a9d8409219172c2a602cfb9eadffdeb13a68c55a48e048a19c3b17d85e3b46",
+ "transactions": [
+ "0xf87981af0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0b3a49ddc2fc9f12cb1dc0a67623d5a1a6a1b5bf59a8f1736c9f0ab3b564250d3a05fc1ca6dab6b9337827afb55342af8a51fae064157e9c78b76dacd66bbea55d1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0a71a6dbc360e176a0f665787ed3e092541c655024d0b136a04ceedf572c57c5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np219",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf9a9d8409219172c2a602cfb9eadffdeb13a68c55a48e048a19c3b17d85e3b46",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8236fb6bc66022c43d12c08612fd031d8b42852bef9a2dec04c1bc4b83cba489",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xdb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x88e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf69983460a4d977eceea022607df6db15b3d8103f78e58d73eeac3593053dbc6",
+ "transactions": [
+ "0xf86481b0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08a2bbd86fd1bb42e548fa4b4c4710f6c6ed03b4700f9e3a213bc70d17f016a3ca076d8bf736d722af615228680c31acd9815b9380a8bc5895cddb2361170274a7f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa4bcbab632ddd52cb85f039e48c111a521e8944b9bdbaf79dd7c80b20221e4d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np220",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf69983460a4d977eceea022607df6db15b3d8103f78e58d73eeac3593053dbc6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1d9d412ef451097aa53e4fc8f67393acfd520382a1c4cfa6c99e2fb180a661db",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xdc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x898",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xecea5d6aa092dc29520fcd6cd44102c571c415fd5d641e978af4933c476020a6",
+ "transactions": [
+ "0xf86781b10882520894fb95aa98d6e6c5827a57ec17b978d647fcc01d9801808718e5bb3abd10a0a0c71a69f756a2ef145f1fb1c9b009ff10af72ba0ee80ce59269708f917878bfb0a03bfe6a6c41b3fe72e8e12c2927ee5df6d3d37bd94346a2398d4fcf80e1028dde"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2bc468eab4fad397f9136f80179729b54caa2cb47c06b0695aab85cf9813620d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np221",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xecea5d6aa092dc29520fcd6cd44102c571c415fd5d641e978af4933c476020a6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x830dfc2fb9acb72d3c03a6181b026becbcdca1abf4ab584b2dd00c48fd2f6a62",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xdd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x8a2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbc664826810922530f7e9876cd57ef0185f2f5f9bbafb8ee9f6db2d6e67be311",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1c",
+ "validatorIndex": "0x5",
+ "address": "0x2795044ce0f83f718bc79c5f2add1e52521978df",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfc7f9a432e6fd69aaf025f64a326ab7221311147dd99d558633579a4d8a0667b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np222",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbc664826810922530f7e9876cd57ef0185f2f5f9bbafb8ee9f6db2d6e67be311",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7492f26a06f6b66d802f0ac93de1640ec7001652e4f9498afa5d279c1c405ccd",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xde",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x8ac",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb908ac3bd269a873b62219e78d5f36fdfd6fb7c9393ad50c624b4e8fd045b794",
+ "transactions": [
+ "0xf88281b208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa09765f880d3815c484a796d3fd4c1791ab32f501ba8167bfd55cde417b868e459a0310fdd4d8d953cf38b27fa32ad6e8922ef0d5bd7ba3e61539dd18942669187f1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x949613bd67fb0a68cf58a22e60e7b9b2ccbabb60d1d58c64c15e27a9dec2fb35"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np223",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb908ac3bd269a873b62219e78d5f36fdfd6fb7c9393ad50c624b4e8fd045b794",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1e515c524c17bcb3f8a1e8bd65c8403ae534c5c2c2fc0bddce2e69942c57028a",
+ "receiptsRoot": "0x336f567c728ef05cbd3f71c4a9e9195b8e9cd61f8f040fdd6583daf0580a0551",
+ "logsBloom": "0x00000000000000000000000000000000000000000000400000000000002000080000080000000000000000000000000000000000000000000000000000000000008000000040000030040000000000800000000006000000000008010001000000004000000000000020000000000000000000000000000000000000040000000400080000000000000000020000000000000040000020000000000000000000000020000001000000000000000000000000100000000000010000000000000001000000000000000000000002000000000000800000000000000200000000000000000000000000000000000020000000000000000000001000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xdf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x8b6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2e8980e0390ae8503a42316b0e8ceb3bbe99245131ab69115f2b5555d4ac1f4e",
+ "transactions": [
+ "0xf87981b30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0cdd0a69ca9a6c3977ae1734d40175aa0720a866ff9353ce4aadfd8a4cd762e53a0290a5ac57e2f318959aaadec811bf9f8017191594476415923ddafef9a25de7c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x289ddb1aee772ad60043ecf17a882c36a988101af91ac177954862e62012fc0e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np224",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2e8980e0390ae8503a42316b0e8ceb3bbe99245131ab69115f2b5555d4ac1f4e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa0a11d77a69e2c62b3cc952c07b650c8f13be0d6860ddf5ba26ef560cefd2000",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x8c0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcd2f03e81d096f1c361b6b0a1d28ae2c0ec1d42a90909026754f3759717a65db",
+ "transactions": [
+ "0xf86481b4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0e55768f282e2db5f2e48da696a07d1bff5687ca7fa5941800d02a1c49a4781b4a00eb30d56234ac991413000037e0f7fb87c8c08b88ae75aa33cb316714b638e1b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbfa48b05faa1a2ee14b3eaed0b75f0d265686b6ce3f2b7fa051b8dc98bc23d6a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np225",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcd2f03e81d096f1c361b6b0a1d28ae2c0ec1d42a90909026754f3759717a65db",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd8287e5675676595007edfbfff082b9f6f86f21bb0371e336ca22e12c6218f68",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x8ca",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2a2c4240cf6512959534cdaf586119243f718b4ff992ad851a61211a1ea744d8",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81b5010882520894f031efa58744e97a34555ca98621d4e8a52ceb5f0180c001a099b1b125ecb6df9a13deec5397266d4f19f7b87e067ef95a2bc8aba7b9822348a056e2ee0d8be47d342fe36c22d4a9be2f26136dba3bd79fa6fe47900e93e40bf3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7bf49590a866893dc77444d89717942e09acc299eea972e8a7908e9d694a1150"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np226",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2a2c4240cf6512959534cdaf586119243f718b4ff992ad851a61211a1ea744d8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1e3c75d8db0bd225181cc77b2ec19c7033a35ba033f036a97ba8b683d57d0909",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x8d4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1fb4e86909057635bfe8d130d4d606c1e9a32bd5e8da002df510861246633a96",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1d",
+ "validatorIndex": "0x5",
+ "address": "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x992f76aee242737eb21f14b65827f3ebc42524fb422b17f414f33c35a24092db"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np227",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1fb4e86909057635bfe8d130d4d606c1e9a32bd5e8da002df510861246633a96",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xacca3ad17c81310c870a9cf0df50479973bd92ade4a46b61a2012fa87c7b8a0f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x8de",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x6f03c5c20de46ba707f29a6219e4902bc719b5f9e700c9182d76345fa8b86177",
+ "transactions": [
+ "0xf88281b608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05147ab82c47d0c6f6298c21b54a83bc404088dcf119f5719034a1154f2c69acaa035070fffcba987b70efcfc6efbf5a43974de5e11331879bbfbfe7556915da7b2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xda6e4f935d966e90dffc6ac0f6d137d9e9c97d65396627e5486d0089b94076fa"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np228",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6f03c5c20de46ba707f29a6219e4902bc719b5f9e700c9182d76345fa8b86177",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0468ebde6657b86a2f1561ae8ef57c6cbe23b7dc08cc0ad823ea3831388e1691",
+ "receiptsRoot": "0x591e45121efd9a319ad048f68a35db27c69b829a65d0c7817224a1c5071ab327",
+ "logsBloom": "0x00000005000000000010000000080000000000000000000000000008200000004000002080000001000000000000000000010000000000080000000000000000000000000000800000000000000000000000000000000000000000000000000b00000200000000000000000000200000000000200001400000000000100000000000000000000400000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000020000000010000080000000000000114000000000000000000000040000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x8e8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8c7ac6681ed2a5020837149f8953a2762227b7bb41f2f46bc0c33508190c3e72",
+ "transactions": [
+ "0xf87981b70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04ccccf5fa7c7ed5b48d30bee3e8b61c99f8ff9ddecff89747e5685b059d70fa7a042982d8d2a54f9a055fd75df65488462a0ceae67b8a80966427c5d7ea1cf563b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x65467514ed80f25b299dcf74fb74e21e9bb929832a349711cf327c2f8b60b57f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np229",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8c7ac6681ed2a5020837149f8953a2762227b7bb41f2f46bc0c33508190c3e72",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9f5936ddc444db8ba3787be50038f195ddb86663f39b62d556f7700334f441d1",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x8f2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x01bb09f016e5dfda9ef7170f45fe4b648dd3761b26c83c18bb0eea828bbc8663",
+ "transactions": [
+ "0xf86481b8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07cc4f254afaef8c4953d8a30221c41a50b92629846448a90a62ebdc76de8b2eea073f46d5c867c718486a68dfdf1cd471d65caa8a2495faba0f0a19ca704201e1b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcc2ac03d7a26ff16c990c5f67fa03dabda95641a988deec72ed2fe38c0f289d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np230",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x01bb09f016e5dfda9ef7170f45fe4b648dd3761b26c83c18bb0eea828bbc8663",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x57dc2fdfe5e59055a9effb9660cfc7af5e87d25a03c9f90ce99ee320996a1991",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x8fc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x15d41d78de758ec47434a48dc695897705ad5990ac584d2a51d8b7a51419abe0",
+ "transactions": [
+ "0xf86781b908825208940a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a01808718e5bb3abd109fa0d2aa10777b7c398921921258eeecaff46668278fd6f814ea4edb06f2a1076353a0542ef4ed484a1403494238e418bb8d613012871710e72dde77bb1fa877f1fae3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x096dbe9a0190c6badf79de3747abfd4d5eda3ab95b439922cae7ec0cfcd79290"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np231",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x15d41d78de758ec47434a48dc695897705ad5990ac584d2a51d8b7a51419abe0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc6a8588f5fa71465604ccee5244d5c72a296994fb2bf1be478b664bc2aa77c39",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x906",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa3b4d9f55cfc3ed49c694fa2a634b73f397d5847b73b340d123b2111ba5adc71",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1e",
+ "validatorIndex": "0x5",
+ "address": "0xd0752b60adb148ca0b3b4d2591874e2dabd34637",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0c659c769744094f60332ec247799d7ed5ae311d5738daa5dcead3f47ca7a8a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np232",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa3b4d9f55cfc3ed49c694fa2a634b73f397d5847b73b340d123b2111ba5adc71",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x38cdb4e70eb9771bab194d9310b56dbfcba5d9912cd827406fff94bddf8549d3",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x910",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4ff6fbd3afcc33972501397c65fe211d7f0bf85a3bde8b31e4b6836375d09098",
+ "transactions": [
+ "0xf88281ba08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a06f8db09016d87e96d45d0835a60822fb305336ab1d792944f6f0aa909b73c9d7a01da7c6ba739bf780143672031e860f222149e1e6314171737fee23537a1e7f0c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9cb8a0d41ede6b951c29182422db215e22aedfa1a3549cd27b960a768f6ed522"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np233",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4ff6fbd3afcc33972501397c65fe211d7f0bf85a3bde8b31e4b6836375d09098",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbf1db5dc400fd491fad1abd61287f081ebd7398c76f20ecc0a6c9afb30ba5508",
+ "receiptsRoot": "0xed257fe243a1ffa922e5a62e40ffb504d403afc1d870fdcacd7f0aaf714e9ca1",
+ "logsBloom": "0x200000000000000000000000000000000000000000000000000009000000800000000000104010000000000000000000000000000000000000000100000000080008000000000000000000800000000000000000000000000008000000000000400000000000004040000000000000000000002000000000080004010000000000000000100000000000000000000040000000000000000000000080010000000000000002000000020c0000000000000000000000000000000000000000000000000000000000000000000000000000080000000080000000000000000000000000400080000000400000000000080000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xe9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x91a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf1364f41ffcf3f76e045b1634e4f62db38f5c053edfa7d0a13d87299896ddff9",
+ "transactions": [
+ "0xf87981bb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0ef0e59c1798c0a7645f75f893cf81eae4aff9f49159b7365b8d4e907367f91f6a0095a58cb4d8be1816acf8b4e11f9d9b2a03d3f392eee1f19bea70b50ed151584"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2510f8256a020f4735e2be224e3bc3e8c14e56f7588315f069630fe24ce2fa26"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np234",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf1364f41ffcf3f76e045b1634e4f62db38f5c053edfa7d0a13d87299896ddff9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5b75a7bfd5eb4c649cb36b69c5ccf86fecb002188d9e0f36c0fdbc8a160e4ac6",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xea",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x924",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa2474d57b356b865a29ccfb79623d9a34ed84db9f056da5dd4e963f816baa180",
+ "transactions": [
+ "0xf86481bc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a078dfab2121885d4181d63c7088757f7feb65131b155ad74541de35c055c31ec3a005cccd843ec8a535a567451c3b5034e05bac10f9328c63aa0b4893ee4f910ba2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2d3deb2385a2d230512707ece0bc6098ea788e3d5debb3911abe9a710dd332ea"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np235",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa2474d57b356b865a29ccfb79623d9a34ed84db9f056da5dd4e963f816baa180",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3f130c3409ad205204d14e6b5be4ccf2e65559d39cc98dfc265e1436990e5964",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xeb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x92e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9a195498e43997a5769957e54f0fa6f56d8442e54f8a26efafbf89130446fd4d",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81bd010882520894f8d20e598df20877e4d826246fc31ffb4615cbc00180c001a0c982933a25dd67a6d0b714f50be154f841a72970b3ed52d0d12c143e6a273350a07a9635960c75551def5d050beee4014e4fef2353c39d300e649c199eebc8fd5e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1cec4b230f3bccfff7ca197c4a35cb5b95ff7785d064be3628235971b7aff27c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np236",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9a195498e43997a5769957e54f0fa6f56d8442e54f8a26efafbf89130446fd4d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1ad56a036d6b544ee8f96f2d3e72dfdb360fa3c81edef33dd9e9fc1779d174a4",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xec",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x938",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xca48eaf8da077241a7938435cf1576b2628c65afea7b1aa2665c74573e352205",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x1f",
+ "validatorIndex": "0x5",
+ "address": "0x45f83d17e10b34fca01eb8f4454dac34a777d940",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x18e4a4238d43929180c7a626ae6f8c87a88d723b661549f2f76ff51726833598"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np237",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xca48eaf8da077241a7938435cf1576b2628c65afea7b1aa2665c74573e352205",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf43c19d64439e20deb920de4efbb248d44d4f43d0dfecd11350501bc1a4bf240",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xed",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x942",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd6a5ae0ebd55680da60432b756f7914f8fb8bbcead368348e3b7f07c8cfa501e",
+ "transactions": [
+ "0xf88281be08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06ba7d56fdfaf77a1a66bfef9529419b73d68fc1aa9edef961ac3a8898f04e5caa054635ee7b91858d97e66944311c81fd4f57d328ee4fbdf8ce730633909a75f01"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x700e1755641a437c8dc888df24a5d80f80f9eaa0d17ddab17db4eb364432a1f5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np238",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd6a5ae0ebd55680da60432b756f7914f8fb8bbcead368348e3b7f07c8cfa501e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x05a62e01803a967ff89e7e9febf8d50b1b3092aab5580c7f85f465e7d70fef3f",
+ "receiptsRoot": "0x294eca38bb21bd8afeb2e5f59d0d4625058d237e2109428dfb41b97138478318",
+ "logsBloom": "0x00000040000000001000000000008000000000000000200000000000000000000000008000000000000000020000000040000000000000000000000004000000000000000000800000000000000000000000000000000080000000000000001000000000400000000400000000000000000000000000000000000000000000000880000000000400002000000040000000000000000000000000000810000100000080000080000000000000080000000000000001000000000000000000000000000000080000002000000000000010000000000000000010000000000000002000000000800000000400000000000000000000080000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xee",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x94c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x06466f86e40c982578b247579fa1fa5773d6169e77a79a625950c4aa16ce88b1",
+ "transactions": [
+ "0xf87981bf0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0548377761079f73162f83bdc2cfb09dcde9e08c8db66d4d983f1856c5145fe6fa06b2bd1223fbb1b72016150f57bc7ae1f8cce5c0fd301bb9216bb804c89bf0a97"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcad29ceb73b2f3c90d864a2c27a464b36b980458e2d8c4c7f32f70afad707312"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np239",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x06466f86e40c982578b247579fa1fa5773d6169e77a79a625950c4aa16ce88b1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbca1fef6bcfcbb170b7b349f92a3b92fe03296dac1fd64ccda295c496a261a16",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xef",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x956",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x74b00e695ebf3210bda9ad8b3aa1523475d922fd556e551cfd606ebcf807d681",
+ "transactions": [
+ "0xf86481c0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08cfe044eb5748d538f72e560c45c7a01f94f4b7c6e9b1245bade89c0d97f9932a02b21fe651e5fb05d1f8de320dcf8cc037b2c0e989793f6b445f397c77f42a4f0"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa85e892063a7fd41d37142ae38037967eb047436c727fcf0bad813d316efe09f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np240",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x74b00e695ebf3210bda9ad8b3aa1523475d922fd556e551cfd606ebcf807d681",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x82a80ad266f2a1539a79b2dcf8827aabedcc1deeb6cfb4869a8ed2ea26923726",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x960",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd908ab400c351cee493619c9b0b56c6ae4d90bd6e995e59ac9302a7b20c13fc3",
+ "transactions": [
+ "0xf86781c10882520894fde502858306c235a3121e42326b53228b7ef46901808718e5bb3abd10a0a03d79397e88a64f6c2ca58b5ec7ba305012e619331946e60d6ab7c40e84bf1a34a04278773d2796a0944f6bedadea3794b7ad6a18ffd01496aabf597d4a7cf75e17"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x040100f17208bcbd9456c62d98846859f7a5efa0e45a5b3a6f0b763b9c700fec"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np241",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd908ab400c351cee493619c9b0b56c6ae4d90bd6e995e59ac9302a7b20c13fc3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x59b60dbf89d7c0e705c1e05f6d861bfb38bec347663df6063be9eb020e49972a",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x96a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x13fdff4106d52399ab52ee5d1e6a03097f6db6de8066597f88be7a797a183cb7",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x20",
+ "validatorIndex": "0x5",
+ "address": "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x49d54a5147de1f5208c509b194af6d64b509398e4f255c20315131e921f7bd04"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np242",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x13fdff4106d52399ab52ee5d1e6a03097f6db6de8066597f88be7a797a183cb7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1e5d7390e70d057c7dc29e173e338e7285e276a108eaecf3164dc734ce2fd9b5",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x974",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9cfff0339ca5c7928180f0d37f080f2c8cc4c00bfa2b6be3754b9d228219779f",
+ "transactions": [
+ "0xf88281c208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0057b9bf7b2b99c50cf16c0b995e2846ba833edc03f6efc1b97566022651cabeca0237b38f74a2a8c39a2c344ef2d7fe811c37cd20ed2f4d47bfc38d896f3c9db75"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x810ff6fcafb9373a4df3e91ab1ca64a2955c9e42ad8af964f829e38e0ea4ee20"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np243",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9cfff0339ca5c7928180f0d37f080f2c8cc4c00bfa2b6be3754b9d228219779f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8725e2687d45a52ad320e82b90e009b1aa5effe7ebfe994116afa25daa09468f",
+ "receiptsRoot": "0x2f9d61b38064fb9da0bb0f93ff73e1021c62ba761714e96a6674cd927bde4f9c",
+ "logsBloom": "0x00000000000800000000000000000000001000000000000000000000000000010000000000000000000000000000000000000000000000040000000000000000000000000010000000008000400000000000600000000000000000000800000140000000000080000000000000000000000200000000000000000000000000000000000000000180000000000000000000000000000000000000000000001000000000000000000100020000000000000001020000000000000080000000000000080000000000000000040000000000000000000000000000024080200000000000000000040000000208000000000000010000000000000000001000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x97e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0c71dc4665ac65f63a44434a3d55ffc285af6ec8b90b4ddfd4b4001add0e93c0",
+ "transactions": [
+ "0xf87981c30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa017b61104ac6d28f1262b3750475b328dfd50f8496e0772bf19047d9d1ee9e56da01aed9f9280926e68fb66065edcf80320cab6f6d7c7af4bc8d9d007e1ea6a168d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9b72096b8b672ac6ff5362c56f5d06446d1693c5d2daa94a30755aa636320e78"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np244",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0c71dc4665ac65f63a44434a3d55ffc285af6ec8b90b4ddfd4b4001add0e93c0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc5f9b1665244a32dc0885794d5aaf3ce0b464eed1208412ca14abcfe4b908f64",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x988",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1f7b85304f578a197b65ce6f6f9e0c90cf680cdb3f35a95d10ea0a32238df606",
+ "transactions": [
+ "0xf86481c4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0a93d446ef64bccf6c88d5285e78e7625fd5c9ac9c8aa11ad45db01b95b6694a5a0761620f10b11ee3cc1932adf95133349f5107aed7b8c150192fa89665ecd7552"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf68bff777db51db5f29afc4afe38bd1bf5cdec29caa0dc52535b529e6d99b742"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np245",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1f7b85304f578a197b65ce6f6f9e0c90cf680cdb3f35a95d10ea0a32238df606",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5bacfe50ff7f0200bc1a4ea28e3fbe1a269ea7cbdbe7fb5d83bde19774c92e7e",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x992",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8f3a666d3d090603513d1e31ac73c5b47a7fe8279c7359a3bad523a8fd414a96",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81c501088252089427abdeddfe8503496adeb623466caa47da5f63ab0180c001a0deade75f98612138653ca1c81d8cc74eeda3e46ecf43c1f8fde86428a990ae25a065f40f1aaf4d29268956348b7cc7fa054133ccb1522a045873cb43a9ffa25283"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9566690bde717eec59f828a2dba90988fa268a98ed224f8bc02b77bce10443c4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np246",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8f3a666d3d090603513d1e31ac73c5b47a7fe8279c7359a3bad523a8fd414a96",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1c407d215d7fa96b64c583107e028bcf1e789783c39c37482326b4d4dd522e05",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x99c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf1191b23680ae545b3ad4ffb3fd05209a7adefefc71e30970d1a4c72c383b5df",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x21",
+ "validatorIndex": "0x5",
+ "address": "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd0e821fbd57a4d382edd638b5c1e6deefb81352d41aa97da52db13f330e03097"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np247",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf1191b23680ae545b3ad4ffb3fd05209a7adefefc71e30970d1a4c72c383b5df",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x16a2c4f318277ea20b75f32c7c986673d92c14098e36dde553e451f131c21a66",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x9a6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2e34605bbfd5f548e1e9003c8d573e41a9286968bec837ba1f2b7780e3337288",
+ "transactions": [
+ "0xf88281c608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02648ce9c5825b33559225aada97c08de484ab8282549d90cfc1e086052c22be8a02054d7eeb1e8bf4ab25b2581ccb0b0a3500625cf7a0315860202eb2eaf094f9c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x43f9aa6fa63739abec56c4604874523ac6dabfcc08bb283195072aeb29d38dfe"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np248",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2e34605bbfd5f548e1e9003c8d573e41a9286968bec837ba1f2b7780e3337288",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x291c5ca9a114bdb7bf296b4ff4182b930dc869905eaa1219cbb5188e8feaa9ab",
+ "receiptsRoot": "0x9f35106348d01548df28e681773a27cffe40648e4d923974e4b87903f578da11",
+ "logsBloom": "0x00000001000000000000000800000000000000000000000000000000100000000000000200080000000000080001000000000000000000000000000001000000000202000000000000000000000000000002000002000000000000040000000000000000000000000200800000000000800002000000000000000000008000000000000000000000000400008000000000008000000000000000000002000000000000000000000010000000000000000000000000000000000000100000000000000000000000000000000181000000800000000000000000000000002000200000000000000000000000000280000000000000000000000000040000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x9b0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x22d7e31bcd496b70c0256f88d985be54cd46604897969a5edde95d8d75e2fc6a",
+ "transactions": [
+ "0xf87981c70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09f49a6018e3736ea3599def5663a57cfe19cb3f27bfdd80657503262a5bcfc87a02a26782058025cfe1205be964cc9ac31cdf510a8a9f867bff2317275b13ed02c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x54ebfa924e887a63d643a8277c3394317de0e02e63651b58b6eb0e90df8a20cd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np249",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x22d7e31bcd496b70c0256f88d985be54cd46604897969a5edde95d8d75e2fc6a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x359fe6cc7b7596b4455fdc075bc490d3697d4366c39c40dd6fc935da0ceac7e7",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xf9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x9ba",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1767170da9f173007588517f005241a12087642444518ce31bcf3ad27de4efcf",
+ "transactions": [
+ "0xf86481c8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa043e1ad9aa519d9a1e8a15918ee6bbc0fd98061db6058597bd984098600495f96a01d5edd1b3fc3b45ff2a17a9c7eee3ad4c75e24fc090a4a0e48f39da49e7ad263"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9e414c994ee35162d3b718c47f8435edc2c93394a378cb41037b671366791fc8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np250",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1767170da9f173007588517f005241a12087642444518ce31bcf3ad27de4efcf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc73008737d0cfdbec09b3074d48f44e406f0598003eab9a1f4c733de38512855",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfa",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x9c4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x163dc4f5b453d5fb626263184121f08cdb616a75e2f8ef978d38e91f5b995ee6",
+ "transactions": [
+ "0xf86781c90882520894aa7225e7d5b0a2552bbb58880b3ec00c286995b801808718e5bb3abd109fa00968ae76ffc10f7b50ca349156119aaf1d81a8772683d1c3ed005147f4682694a060f5f10a015e8685a3099140c2cc3ba0dc69026df97fb46748008c08978d162a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4356f072bb235238abefb3330465814821097327842b6e0dc4a0ef95680c4d34"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np251",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x163dc4f5b453d5fb626263184121f08cdb616a75e2f8ef978d38e91f5b995ee6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x693db83454936d0dacd29b34de3d2c49dc469bbe4337faec428b028e0d967642",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x9ce",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8f9b318e4cd81ddd537dff3fcfe099d3609b357f3a4f2aed390edc103a5aa7a6",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x22",
+ "validatorIndex": "0x5",
+ "address": "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x215df775ab368f17ed3f42058861768a3fba25e8d832a00b88559ca5078b8fbc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np252",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8f9b318e4cd81ddd537dff3fcfe099d3609b357f3a4f2aed390edc103a5aa7a6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd358fe0baedc04a81fdaf6cdfc71c2c874291e47d16dd51cc032f0678078a009",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x9d8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x23a585160ac1b5428ad1dea7e732b641ace396c4135dbf899ab2559f869bb5fb",
+ "transactions": [
+ "0xf88281ca08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0941941ac43420c855cda955414a23d3bad4d0f2bfbeda999250f2f87d228878da0357223781ec5d666a8d5e8088721e9952f00a762d5fc078133bea6bc657c947e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd17835a18d61605a04d2e50c4f023966a47036e5c59356a0463db90a76f06e3e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np253",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x23a585160ac1b5428ad1dea7e732b641ace396c4135dbf899ab2559f869bb5fb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcb19946b2b5a905882151fff9a12cce6e4c3be46f7da6b67263b0cc781fbe80a",
+ "receiptsRoot": "0x9b15dea2f021c6c74dc60deea77fd6a1ce29c9efc2596cbaaf73ef60370a03e3",
+ "logsBloom": "0x0000000000000100800000000000000000800000000000010000000000000000000000000000000000000000000080000000000000000000000000400000000000002000000000000000000000000000000000000000000000000000100008000000000000000000000000000000000020000000000000a004200000000000800000000000000000000000000000100000000000000000000000000440000000000000001001000010000000010000004000000000000000000000200000000000000000000000000000000000000000000400000000000000000000000200000000000000000440000000000120000c00000001000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x9e2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x706168d939a58a0dd048595d1c88fe1735dbeee42111dfbb2adee0ea9ef1d77b",
+ "transactions": [
+ "0xf87981cb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06fb97cf9fb9b8f7159a9dc549e412001ca969f0dafc3c9294b0e081741aa3d9aa003ed12873ddb354ccf7b0f8e511136ff335a8e4ff6bb7f93ce19e097970c9774"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x875032d74e62dbfd73d4617754d36cd88088d1e5a7c5354bf3e0906c749e6637"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np254",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x706168d939a58a0dd048595d1c88fe1735dbeee42111dfbb2adee0ea9ef1d77b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x907ae262cf7f9a93ecd0d1522c6a093ffe39594b65ec185c5059dfa7b3394371",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xfe",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x9ec",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xffd5337b506a04e2362e4a34847711bf688591ceb3ac4b7da257072ecef36a55",
+ "transactions": [
+ "0xf86481cc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a082f832d1212a980978d5716dca8820344200eb6967b24adb2bd112a896b4dda3a0393b965bcf272398cdd6de788c3aa929a67a42466883a472538fb1dad06c07ef"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6f22ae25f70f4b03a2a2b17f370ace1f2b15d17fc7c2457824348a8f2a1eff9f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np255",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xffd5337b506a04e2362e4a34847711bf688591ceb3ac4b7da257072ecef36a55",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc39a9999ffd22de07bcf6a6a16b5cf1da7675dcb135e3503111a1dd50913cf0c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0xff",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x9f6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcbf2f33d5616ea98f1b1cf12bdd145d35b4a928e4cb8b0fa41a6bd788ca3cbd2",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81cd010882520894a8100ae6aa1940d0b663bb31cd466142ebbdbd510180c080a054eafef27c71a73357c888f788f1936378929e1cdb226a205644dc1e2d68f32ba059af490b8ef4a4e98a282d9046655fc8818758e2af8ace2489927aaa3890fda3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf11fdf2cb985ce7472dc7c6b422c3a8bf2dfbbc6b86b15a1fa62cf9ebae8f6cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np256",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcbf2f33d5616ea98f1b1cf12bdd145d35b4a928e4cb8b0fa41a6bd788ca3cbd2",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x979018c4d3a004db4c94102d34d495dd3a4dc9c3c4bcd27d1a001f8095384208",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x100",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xa00",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x01b45ed6ccf0908b2e4b513eeea6aa86514677cb6d6d06d936e1871fc422daca",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x23",
+ "validatorIndex": "0x5",
+ "address": "0x47dc540c94ceb704a23875c11273e16bb0b8a87a",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbbc97696e588f80fbe0316ad430fd4146a29c19b926248febe757cd9408deddc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np257",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x01b45ed6ccf0908b2e4b513eeea6aa86514677cb6d6d06d936e1871fc422daca",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x55e1fa04203cc0edebab3501d9552eaf0ac3bba421bf3480a50e1549cd479dc5",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x101",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xa0a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x48f84c09e8d4bd8effd3865e8b3ac4202cb0dc0fb72299f35c8bad4558b895dc",
+ "transactions": [
+ "0xf88281ce08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08a7526f8f209ff44329b503a7d726f569b861894584401651a83668be3971cbfa040314bdfa618ead4fa21933ed3a8af7e814620e3befa914828b981b391096441"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x71dd15be02efd9f3d5d94d0ed9b5e60a205f439bb46abe6226879e857668881e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np258",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x48f84c09e8d4bd8effd3865e8b3ac4202cb0dc0fb72299f35c8bad4558b895dc",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8d05cad792af190bb84ad7a0bebd232c433cf16b90cffea9f4f824d562ec0eb5",
+ "receiptsRoot": "0x7b32e50058711e6aa1981f911bb5fb6bd05182c7e7850480874c3754788e5ee2",
+ "logsBloom": "0x000000000000000000000000000000000400000000000000000000000200000000000000000000000000000000002000000000000040000000000000000000800000000000000000000080080000000000040000000002002000002000008000000008000100000000000400000000000000000000000000000000000000200000000000002000000000002000000000004000000000000000000000000000020000000000000000010800000001000000000000000000000000000000000000000c0000010000000000000000000000000000000000000020000000000040000000000000000000000000300000000000000000000800008000000000400000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x102",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xa14",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xed832bf95db43a650d06fac15b9b6474b7d82d03b27bd43835eee199c95b64f1",
+ "transactions": [
+ "0xf87981cf0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0fa1c9705b3794f376d02943123846aaae435a6590ddb802e16e91f87ae13c910a0609129061ec7d065ea3c154152c452f76a7894f2459c42c33675af6a20c9ad3c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb90e98bd91f1f7cc5c4456bb7a8868a2bb2cd3dda4b5dd6463b88728526dceea"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np259",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xed832bf95db43a650d06fac15b9b6474b7d82d03b27bd43835eee199c95b64f1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x06ffd1eba12cda277819f77a9a89a4f78265f7aed5158dc51332218976856e82",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x103",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xa1e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x65f5a3780beee8d82281e7fe3e82b81dae2a14ef861e9df584590dd429b8d632",
+ "transactions": [
+ "0xf86481d0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07de64020fd82a08d2737ded6967d6a6095c02858161988f0626bad7dd2238057a00ad64af462ef2241d4e4c0da1dc108871126cf2aa2b82afd98d7069fc79d9085"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4e80fd3123fda9b404a737c9210ccb0bacc95ef93ac40e06ce9f7511012426c4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np260",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x65f5a3780beee8d82281e7fe3e82b81dae2a14ef861e9df584590dd429b8d632",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3d72e9a90b2dbfc909c697987538e4e9a8f2b127a783109fbb869bf3760bd7a0",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x104",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xa28",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcab55b4abc18bcf8e1b24ae34df180dc00edeadc072fa2e52ed54f2b09c6367f",
+ "transactions": [
+ "0xf86781d10882520894a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e01808718e5bb3abd109fa004c1d18013fb8b0554b8aaa549ee64a5a33c98edd5e51257447b4dd3b37f2adea05e3a37e5ddec2893b3fd38c4983b356c26dab5abb8b8ba6f56ac1ab9e747268b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xafb50d96b2543048dc93045b62357cc18b64d0e103756ce3ad0e04689dd88282"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np261",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcab55b4abc18bcf8e1b24ae34df180dc00edeadc072fa2e52ed54f2b09c6367f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c514217bbc30325a9d832e82e0f1816cff5d7fed0868f80269eb801957b22a0",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x105",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xa32",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x687b7f705112cf8d76b18d5ab3bc59fab146131c4b8efa05a38b42a14bcb251c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x24",
+ "validatorIndex": "0x5",
+ "address": "0xbc5959f43bc6e47175374b6716e53c9a7d72c594",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd73341a1c9edd04a890f949ede6cc1e942ad62b63b6a60177f0f692f141a7e95"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np262",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x687b7f705112cf8d76b18d5ab3bc59fab146131c4b8efa05a38b42a14bcb251c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x32fc9182d259ea7090be7140ec35dee534b5e755af25c3a41b2fe23452cd75ae",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x106",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xa3c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x59763420efabb84b6d4ae2b2a34f6db6108950debfe1feba4f706ad5227eca5f",
+ "transactions": [
+ "0xf88281d208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0010b2ab5421f3fe86f38332dd1c862ddcfc711b2255d8f2a677985d3858b643aa025f4fec49790d44c9b50ed1bea3c5700de165dc239173328e0d0c045f0dd4558"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc26601e9613493118999d9268b401707e42496944ccdbfa91d5d7b791a6d18f1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np263",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x59763420efabb84b6d4ae2b2a34f6db6108950debfe1feba4f706ad5227eca5f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdbed2b577f83fcb221ae85377d9c4f41b8ca95de085a3a697098ceaa937d23f8",
+ "receiptsRoot": "0xf4e79fec628d38bdc719707be2f797b74efbc9468ba5a3ae9415877e11c21db4",
+ "logsBloom": "0x00000000000008004000000000000000000000000000000010800000000000000040000000000000020000000000800410800000008000040000000000000000000000000000000000040000040000000000000000000000000000001000000000020000000000000400200000000100002000000000000000000000000000000008000010000000000000000020004400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000008000000000000080010000000000000000000000000000000200000000000020000000000000000000000000000020000800000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x107",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xa46",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf95bd5a6a4d1d51c8f00e6421bb1ecdb2a4b19222261aa412dcb4c371eea1af5",
+ "transactions": [
+ "0xf87981d30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0aa1f3a14b2bee05c15deffd1fcbad6d16deb140557251b04ddb61574fa8c70d8a0614a539b7fe8c276d26cabc1ff36c88c3f6b9cf3bc8836309a1d3f46626b5153"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfb4619fb12e1b9c4b508797833eef7df65fcf255488660d502def2a7ddceef6d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np264",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf95bd5a6a4d1d51c8f00e6421bb1ecdb2a4b19222261aa412dcb4c371eea1af5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2eb443ed50d07a6b1dbb2c154cc221cfb0475593b39ca2d3569224ea7a08030e",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x108",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xa50",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x68bd9ab4e0b622e480296f040ad58d1b7f048c712ad5b46c7a596265d5f8e9fc",
+ "transactions": [
+ "0xf86481d4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0533560fb23c458df00902dbacef307e98096d91f179c49458d99e2eecaeaf3d3a0314508cba155f195ff77eff1a25ed4f454a07b404ac82d3ea73796bd9af3128d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd08b7458cd9d52905403f6f4e9dac15ad18bea1f834858bf48ecae36bf854f98"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np265",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x68bd9ab4e0b622e480296f040ad58d1b7f048c712ad5b46c7a596265d5f8e9fc",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6e68dd5ff68bf8a325446716e5bc1629a4e77167c3b5c9249ac2e440b35dea9b",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x109",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xa5a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfd61bbebf4026ea51b90fafefc671dc4540e83436c83eb9bc51e6b2b15db5dc9",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81d5010882520894ac9e61d54eb6967e212c06aab15408292f8558c40180c001a0898d514a1f15103335e066d0625c4ec34a69a03480d67dcb3d3fe0f4f932100aa07e130fed862c1482467d112f64fb59e005068b52c291003c908b625b4993e20e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdf979da2784a3bb9e07c368094dc640aafc514502a62a58b464e50e5e50a34bd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np266",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfd61bbebf4026ea51b90fafefc671dc4540e83436c83eb9bc51e6b2b15db5dc9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4783eb369238bf2856e00bbc632735adf5ea404b766a0a70c27913314e170bac",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xa64",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xaa8b392a2333d1f8a498c60f1c9884705d0bff7dd5a524b5a119f547b0d6579c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x25",
+ "validatorIndex": "0x5",
+ "address": "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x15855037d4712ce0019f0169dcd58b58493be8373d29decfa80b8df046e3d6ba"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np267",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaa8b392a2333d1f8a498c60f1c9884705d0bff7dd5a524b5a119f547b0d6579c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd0b9db5bce164e65b476f578ff93039bad1be78c8d1f595ff8496c2f7a67fea4",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xa6e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa33f601ca31d93d804b269042c783f9a6f79857919289dbb935e81ba1fed86ea",
+ "transactions": [
+ "0xf88281d608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa03329c0816ba8af740dd07a393681abfd26c3f0a121cdfa2390607d0d1832e741a051d0d0b427004563def4552ee51b81a2ca1f41bb48e8b9ae20615381c353d9b3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfd1462a68630956a33e4b65c8e171a08a131097bc7faf5d7f90b5503ab30b69c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np268",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa33f601ca31d93d804b269042c783f9a6f79857919289dbb935e81ba1fed86ea",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcb8d1404a32030e577a2628884f57433fe91b36b838f8576471bc36d87784132",
+ "receiptsRoot": "0x65c1a0ac45edc227576188f00c72612cd6c4d27cdac8d997bc6c9f499d21565c",
+ "logsBloom": "0x00000000020000000000000000000001000000000000000000000000402000000000000001000010000000000000000000000000000000000000000000000000000000000800040080000100000006000000000000000000000008000000000000000000000000000001000000000000001000040000000000000000000000000000000000000000080000100000000000000100200000000000000000000000000000000000080000000000000000000040000000000000000000000001000000000040000000000000000000000000000000000100000000000000000100002000000000200000000000000000008000000000000000008010000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xa78",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x295de1a3c0821f092b15b4e51f02dd17ab7f1753f22f97c88a2081f9a19ffa01",
+ "transactions": [
+ "0xf87981d70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0310faf1dfcbc5597e207ab627226d2deeea1eedec7ffd8e68740fb76545586d1a01919f4683f202d4ccb3ab524d89d11119e7115645707333703d70f6fbe3c610d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xedad57fee633c4b696e519f84ad1765afbef5d2781b382acd9b8dfcf6cd6d572"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np269",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x295de1a3c0821f092b15b4e51f02dd17ab7f1753f22f97c88a2081f9a19ffa01",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0199e03e7400c428fb1bba7126f4eb3a12becd96c4458bff54952e5535b4a3d0",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xa82",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x494693083463dc335450802ab50c97022e63c21e326ff7cebd7870802411db3e",
+ "transactions": [
+ "0xf86481d8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0ea5ad6553fb67639cec694e6697ac7b718bd7044fcdf5608fa64f6058e67db93a03953b5792d7d9ef7fc602fbe260e7a290760e8adc634f99ab1896e2c0d55afcb"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc2641ba296c2daa6edf09b63d0f1cfcefd51451fbbc283b6802cbd5392fb145c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np270",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x494693083463dc335450802ab50c97022e63c21e326ff7cebd7870802411db3e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xad6e3dc4bf8e680448a8a6292fc7b9f69129c16eb7d853992c13ce0c91e7d1ce",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xa8c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc54e865454d4ba4a092904e151d7afdc9b7b7ef9723dee0325ee075eb6a9a5c0",
+ "transactions": [
+ "0xf86781d90882520894653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c01808718e5bb3abd109fa0f1c5d5e335842170288da2c7c7af6856ea0b566d2b4ab4b00a19cb94144d466ca02043677d1c397a96a2f8a355431a59a0d5c40fc053e9c45b6872464f3c77c5dc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5615d64e1d3a10972cdea4e4b106b4b6e832bc261129f9ab1d10a670383ae446"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np271",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc54e865454d4ba4a092904e151d7afdc9b7b7ef9723dee0325ee075eb6a9a5c0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4347088d10fe319fb00e8eee17f1b872f2e044cbe1cb797657294404bf370e30",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x10f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xa96",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc33055476392adfe03f3bd812f9bb09b7184dc8d58beefab62db84ee34860bed",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x26",
+ "validatorIndex": "0x5",
+ "address": "0x24255ef5d941493b9978f3aabb0ed07d084ade19",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0757c6141fad938002092ff251a64190b060d0e31c31b08fb56b0f993cc4ef0d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np272",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc33055476392adfe03f3bd812f9bb09b7184dc8d58beefab62db84ee34860bed",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa9c73e0cd551b43953f3b13ee9c65436102e647a83bfefa9443ad27733d0371c",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x110",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xaa0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x39f74e3f7d2c3f4ab7e89f3b597535ffebd200abe4b1aa67f721ffaa13cbc2b4",
+ "transactions": [
+ "0xf88281da08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0972f048bcd4f8e2678a209e354570de7452fa342744fab1e44b7af67b2484d9ea0076f82074ff9697256d2661ad9f9a7321ff54fa3100ecc479166286a9a22ada5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x14ddc31bc9f9c877ae92ca1958e6f3affca7cc3064537d0bbe8ba4d2072c0961"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np273",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x39f74e3f7d2c3f4ab7e89f3b597535ffebd200abe4b1aa67f721ffaa13cbc2b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf003762d896629dcd3a92a67ee13b96b080f4a3e71402a1dcbf9f444377329b5",
+ "receiptsRoot": "0x4d68fb9bfae6768b9578f5a63f455867ea5993ec2261fad2a25b45794d092f7c",
+ "logsBloom": "0x00000000000000000001000000000000000000000000000000000000000000000000000080000000000000100000008000000000000000800000000000000000000000000000000000000000000000400000000040000000240001100000000000000000000000000800000000000000000000000000000000060000000000000000000000000000040000000000002000000000000000080000000200000000000000000000000800000040000000040000000000000000000000000000100800000000000800100000000000000000000000000000002000800000000000000000000800000000014000040000000800000000000400000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x111",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xaaa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x23408e1ac73e1dd9c3a735776a73b4c79249e5a9eb62ec9f9012f7f6c11ba7d0",
+ "transactions": [
+ "0xf87981db0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a08883be3af4b0a273883412ad320e6dcace1f505d9b20194e8f9e2e092c8d5ce4a03da92647d3d92d2868d5b9c479d98faf263e78eb67f259101a65ff56ee1eccbf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x490b0f08777ad4364f523f94dccb3f56f4aacb2fb4db1bb042a786ecfd248c79"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np274",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x23408e1ac73e1dd9c3a735776a73b4c79249e5a9eb62ec9f9012f7f6c11ba7d0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x741d337861f144fc811cfac1db596e3bedb837b0fb090a3d013e5492bf02b233",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x112",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xab4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc7578d8b738ac9f5ab97605ce1c8101160faa615feeb8fc43282d8bd6ae450ac",
+ "transactions": [
+ "0xf86481dc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0bcd2b139343048e9174e86251017c9b7c4da9fc36e4a84cf98eaf3855561f8e3a01c25a7b3ff3ebd7d9cbed5aa65515f8ba06fb8860d0764a98591da24e7d1c842"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4a37c0e55f539f2ecafa0ce71ee3d80bc9fe33fb841583073c9f524cc5a2615a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np275",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc7578d8b738ac9f5ab97605ce1c8101160faa615feeb8fc43282d8bd6ae450ac",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe1ce5b13d3189869321889bb12feb5da33a621bf0dbc4612b370a4b6973201f7",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x113",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xabe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0bd8ca5ecbf0c960433cbe52bec31810c325088860cd911a1df20174fd30243a",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81dd010882520894d8c50d6282a1ba47f0a23430d177bbfbb72e2b840180c001a04330fe20e8b84e751616253b9bccc5ff2d896e00593bfbef92e81e72b4d98a85a07977b87c7eca1f6a8e4a535cb26860e32487c6b4b826623a7390df521b21eac7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x133295fdf94e5e4570e27125807a77272f24622750bcf408be0360ba0dcc89f2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np276",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0bd8ca5ecbf0c960433cbe52bec31810c325088860cd911a1df20174fd30243a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x76aa5a1d0fc7c2f7e01a8c515f018e30afb794badc14b5d8e3651096458947a0",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x114",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xac8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x604c3b8dbc400712146239b5b6e70426361e47c118c6fff4c1761554c3ad2e47",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x27",
+ "validatorIndex": "0x5",
+ "address": "0xdbe726e81a7221a385e007ef9e834a975a4b528c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa73eb87c45c96b121f9ab081c095bff9a49cfe5a374f316e9a6a66096f532972"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np277",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x604c3b8dbc400712146239b5b6e70426361e47c118c6fff4c1761554c3ad2e47",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaad6081261920a2bddee7ad943a54ceebdb32edf169b206bd185bd957c029389",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x115",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xad2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3dbceccc7aefcec187b98fc34ab00c1be2753676f6201a1e5e1356b5ce09c309",
+ "transactions": [
+ "0xf88281de08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a092ec956d91708337ef4625bb87caed7a2bab63e40c8e65e8c9ee79a89b525b53a02bfff0c6dadfbf70dbd9fb2d75a12414d808ee6cce90826132d63f8ef2ce96b5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9040bc28f6e830ca50f459fc3dac39a6cd261ccc8cd1cca5429d59230c10f34c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np278",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3dbceccc7aefcec187b98fc34ab00c1be2753676f6201a1e5e1356b5ce09c309",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xac5c584edba5f948690abb0f1c0f9bef685dec896c8f6c5c66ef8dd65810d53e",
+ "receiptsRoot": "0xdd1d7486ff21ad1c1e17b4d06cf0af6b4a32f650ac495deff2aae6cb73338de3",
+ "logsBloom": "0x00000000000000000000002000000200400000000082000000000000020100000000000000000000000000000000000000000000000000088000000000000010000000000000000000000800000800000000000000000000000000000000000000000000100000000004001004880000000000000000000000000000000000480000000000000000002000000000801000000000000000000000000000000080000010000000800000000000000000000000000000000000000000000000000040000000000000000000000000008010000100000000000100000000000000000000000000000000000000000000000000000000000000200000000010000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x116",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xadc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe69bddf40ecef2219c3ce0f27015125fb42d2339c75675f8e0dc587246cf617c",
+ "transactions": [
+ "0xf87981df0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa099b6473bcd99e0f32d82c046bad2e1824a8468bae8347768d907768e2fe64a2ba051f3f8b7323eab23d5543c8e372e4e184bc3ee108eab5455b89d40d9cbc23008"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xec1d134c49cde6046ee295672a8f11663b6403fb71338181a89dc6bc92f7dea8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np279",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe69bddf40ecef2219c3ce0f27015125fb42d2339c75675f8e0dc587246cf617c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x909007de8369b2fd9597dd7b84ab31e36b949026383fa8957befdba94703689b",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x117",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xae6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3f0eb43bfa229f0449d1b975632be01a69ed6c63eda12fb61bf83a2f8cde3c87",
+ "transactions": [
+ "0xf86481e0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0d8414a9d94412185c316893b53c874ae28ad6c0d67910ec66b39051f7842408ea05329ebb7080c9a6ae9372e8004706b78f7465746c3492816b6255fcba4d84979"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3130a4c80497c65a7ee6ac20f6888a95bd5b05636d6b4bd13d616dcb01591e16"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np280",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3f0eb43bfa229f0449d1b975632be01a69ed6c63eda12fb61bf83a2f8cde3c87",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4dcb18dbea7ec4b9dc13b208172da29eb275e2095a6f8c6aeee59d62d5c9dd76",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x118",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xaf0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x12c3c44447da5af2e83d37224a825c26890db2483d5732e4bac08b87fe3ce5fa",
+ "transactions": [
+ "0xf86781e10882520894b519be874447e0f0a38ee8ec84ecd2198a9fac7701808718e5bb3abd109fa0cfbd9ff7eeb9aef477970dcba479f89c7573e6167d16d0882ead77b20aaee690a01e34175b1b1758a581ca13f2ca021698933b1e8269c70fcb94c5e4aa39ee9b8e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xccdfd5b42f2cbd29ab125769380fc1b18a9d272ac5d3508a6bbe4c82360ebcca"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np281",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x12c3c44447da5af2e83d37224a825c26890db2483d5732e4bac08b87fe3ce5fa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcbbdc9e51f0cde277f8f0ba02544d4d2be87cb7a5853a501524d760b00ec5e57",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x119",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xafa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2ca033d3c29586c8a38da6008d4a446814d845565ed5955418b125fdbe4602e0",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x28",
+ "validatorIndex": "0x5",
+ "address": "0xae58b7e08e266680e93e46639a2a7e89fde78a6f",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x74342c7f25ee7dd1ae6eb9cf4e5ce5bcab56c798aea36b554ccb31a660e123af"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np282",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2ca033d3c29586c8a38da6008d4a446814d845565ed5955418b125fdbe4602e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa5f40d100045883afd309122196cd37e687124adc5ec4c609e9d4ea9e8050be1",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xb04",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x38ae7bdbc3e96e43871baeea0577a4a6e40dd3b4d2c6fea0b50d63e24dd24382",
+ "transactions": [
+ "0xf88281e208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a02a4dd1a40886d389cecff4ca095a57e2f1e924b8d0e80e95c67961bec5af4b34a00adc6e41c4fe22eb93c7bc6ac529c405a8beb3b75d3f82a24029c560d293bee1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf6f75f51a452481c30509e5de96edae82892a61f8c02c88d710dc782b5f01fc7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np283",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x38ae7bdbc3e96e43871baeea0577a4a6e40dd3b4d2c6fea0b50d63e24dd24382",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7a69e46d9beb12acb2476f649cf7fa7d31624c8b521351b533e302290b7ce166",
+ "receiptsRoot": "0x8f6545857c380d6f9aefa3a76d16cc79ce6d3e8d951a9041f19d57cbde82f55f",
+ "logsBloom": "0x00000800000000000004000000000001000000000040000000000800025000000000000000000000000000020000000000000000000080000008000000000000000000000000000000000000000041000000000008000000000000800000000000000000000000000080000000000000000080000000000000000000000000000000000000000000000000000010000000000000000000000000040000000000000040000000200000000081000400000000800000000010000000000000000000800000000000001000000000000000000000200000000000000000000008000000000000000000000000000000000000000080000004010000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xb0e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbf711951f526479f4c5a6a945594daacff51aacb288122fc4eea157e7f26c46b",
+ "transactions": [
+ "0xf87981e30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0ac71118aff6dbdfd117ed52c41169a3c1eec7c7b137fed7ec058a48916198f2da05b684d53b4cc1cdafdba987f894eb9c42da47785983593ee1318f8a79f83eff7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7ce6539cc82db9730b8c21b12d6773925ff7d1a46c9e8f6c986ada96351f36e9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np284",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbf711951f526479f4c5a6a945594daacff51aacb288122fc4eea157e7f26c46b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2d7b3e2f3ea5d7c34423a2461c1f17a4639b72a0a2f4715757ca44018b416be0",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xb18",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf5882e396311b698818e2e02c699c77a0865ea6320dc69499197aaf8fd8e6daa",
+ "transactions": [
+ "0xf86481e4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa088575e3574fdfafb5c288b553973607350d846bd81b304beddaa6ef3dd349eada03cacc2455d5296189c0fc6890380a3c405b96cecfc45dc04a7f7dafe76be64c9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1983684da5e48936b761c5e5882bbeb5e42c3a7efe92989281367fa5ab25e918"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np285",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf5882e396311b698818e2e02c699c77a0865ea6320dc69499197aaf8fd8e6daa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdc0d40e96eaa22025544b17cc122fab8f236a1a5d0bfa1a07a6ea680fc31661c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xb22",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0fabca07111b96e64ef425173cb375ed75f3e1b8ee34eed7593fe8930c9f487d",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81e5010882520894af2c6f1512d1cabedeaf129e0643863c574197320180c001a0c23170a740ba640770aca9fb699a2799d072b2466c97f126a834d86bdb22f516a03f242217b60ab672f352ae51249a8876a034ee51b6b4ad4a41b4d300c48e79f4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc564aa993f2b446325ee674146307601dd87eb7409266a97e695e4bb09dd8bf5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np286",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0fabca07111b96e64ef425173cb375ed75f3e1b8ee34eed7593fe8930c9f487d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6d0b749b8735df89c9d0bd4fff2d180d87a7ff86301fc157573ff0e774a942fc",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xb2c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x29d8373309b28aa3b206208c60bf6be454db83f0d5c4140604ec288251b4c5aa",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x29",
+ "validatorIndex": "0x5",
+ "address": "0x5df7504bc193ee4c3deadede1459eccca172e87c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9ca2ff57d59decb7670d5f49bcca68fdaf494ba7dc06214d8e838bfcf7a2824e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np287",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x29d8373309b28aa3b206208c60bf6be454db83f0d5c4140604ec288251b4c5aa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x06f453054ff02cd966887e3e22bf509aacb23ee18ca302b612f10d2fb473cfa3",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x11f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xb36",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x84b99bc78800f925e5ba4da02f58581a21a3ae711a6306147ff4379435e655ee",
+ "transactions": [
+ "0xf88281e608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bac48741d1f314ffaab63f07d4e7a0bc34c68dde478b439f4bca7dcf0b0a1493a036448a9a4150cad5f24411e8a9bbe89096d555ad08818e90d524bbad8b380b7a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6d7b7476cecc036d470a691755f9988409059bd104579c0a2ded58f144236045"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np288",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x84b99bc78800f925e5ba4da02f58581a21a3ae711a6306147ff4379435e655ee",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb45e7c8ace763c55943f9c73da1319566234dad9d29651d6b08227eb88c9c4fe",
+ "receiptsRoot": "0x490106e6f82f2847cc9eb542a9836943df09d8a6b2e4a4fafba322228449195a",
+ "logsBloom": "0x40000000000000000000100000000000000000000002000000000000000000000008000000000100000000400000000000000000000040000000000000040000000000000000004000002000000000000200000000000000000204000000000000000000000100000000000000000008000000000000000002000000200000000000000000000000000000000000000000000000008000000000000000010800000000000000004200000000000040008000000100000000000000000000000000000000000010000000000000000000000000000000080000400000000000000000000000000000000000000000000000000000040000200000000004800000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x120",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xb40",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc7104befaf82feba7ad56db858cc6743e8ac2af4b6a1a0949c9c1ba51c0fe869",
+ "transactions": [
+ "0xf87981e70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa017d70f5a57065bf0973a62206ec4a9b7f1f329904de722faf30fff8e2dca5719a006d0438164dd0ff38d669ebaa44dd53cec0b81d8cfe855a9aedee94b3b1f724d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x417504d79d00b85a29f58473a7ad643f88e9cdfe5da2ed25a5965411390fda4a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np289",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc7104befaf82feba7ad56db858cc6743e8ac2af4b6a1a0949c9c1ba51c0fe869",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4c863fc026d042a28f4ee149361f77c9dae309e18ea2497255ae91f8c41e0055",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x121",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xb4a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x38c868f4adbaf9c38505eee26eb316eb5065c194df8aeed5c605f8c309d4b68a",
+ "transactions": [
+ "0xf86481e8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0428b809dd6147da7fc27a9520ae39b6a361b8f646b4eae45b3b32e3e406d766ea00c794c60066a8d4e435ba368662d9a6c0ffdd57ec6c49fdb0c2d4c07a69875cf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe910eb040bf32e56e9447d63497799419957ed7df2572e89768b9139c6fa6a23"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np290",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x38c868f4adbaf9c38505eee26eb316eb5065c194df8aeed5c605f8c309d4b68a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4849e0698f5f4b970db7b185d122842a6f842611058a838fe4c48bf3c63b89b6",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x122",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xb54",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x962c229b0020efff007766682c8af73f38bc87fa2a83cf4a520b1e6706ced05e",
+ "transactions": [
+ "0xf86781e90882520894b70654fead634e1ede4518ef34872c9d4f083a5301808718e5bb3abd10a0a0953d5aa69077225dba6a0333ea4d69a05f652e0d2abb8df492a7e6a9d0cdbe3da004e41cb847aa131b9bb1e19cb3dd5f7a6cc2ac8b7f459ab8c3061380d41721ff"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8e462d3d5b17f0157bc100e785e1b8d2ad3262e6f27238fa7e9c62ba29e9c692"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np291",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x962c229b0020efff007766682c8af73f38bc87fa2a83cf4a520b1e6706ced05e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6334127515360bcab6eb39030e54b05d61d464576fb4f99fbece693ffa600610",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x123",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xb5e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd8f175dd35dd4a5d97e51309a5fdeb6e713aef85c25c9e2d661075535cf8d8c1",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2a",
+ "validatorIndex": "0x5",
+ "address": "0xb71de80778f2783383f5d5a3028af84eab2f18a4",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3e6f040dc96b2e05961c4e28df076fa654761f4b0e2e30f5e36b06f65d1893c1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np292",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd8f175dd35dd4a5d97e51309a5fdeb6e713aef85c25c9e2d661075535cf8d8c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6a53dd10b53014df9fed6a4ae0fee8fc21111c58421916e9c770906b7676cbaf",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x124",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xb68",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x56a449bf5c7dba876a8f68b55d9dbbb06c0dddd3c5f586ec4a95317a0f00c79d",
+ "transactions": [
+ "0xf88281ea08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a04efd756d15757c98077f04c9f50a22f7e74b1f28f970614a6824b4a406c11d0ba01c4bc3461a415a9c4dbfd4406c3c684a5427ce1490c93d7a9f5e43891dedc709"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x07e71d03691704a4bd83c728529642884fc1b1a8cfeb1ddcbf659c9b71367637"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np293",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x56a449bf5c7dba876a8f68b55d9dbbb06c0dddd3c5f586ec4a95317a0f00c79d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x82f613ee711de05f2cc6a4a107500bdd5045f1ba99ce2738222f343f6081efe6",
+ "receiptsRoot": "0x2c3a6865afbff0ff9319c72cb9974b085dfe9a34eb9b34e0f4bc267272a883ca",
+ "logsBloom": "0x00000800000000000000004000010000000000000000000000000000000000000180000000000000800000400000000000001000000000000000100000000000000000000000000008000400008000000000000000000000001000000004000001000000000000000008000000000000000000000000000000000000000000000000000000000000090800000000000000004000000000000100000000002400000000000800000000000000000000000000000000000000000000000000000000000000000000000000200001000000000000000000000000000000000000002000000000000000000200000040000000000008008000000000000000022000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x125",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xb72",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x45a502a5a428913c585b13dbdd0857fbf4ffc3e928b942b5e96c98aced1a1736",
+ "transactions": [
+ "0xf87981eb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03cbaa69de647fe3ea352a6e71bab2ee53555fb8ab88c5e68efe28f2e5d687b9ea063c88d4e12b282eb4075d28f2fc6f36c7017ed0d91e36dbfd9d63a358e96abac"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf4d05f5986e4b92a845467d2ae6209ca9b7c6c63ff9cdef3df180660158163ef"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np294",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x45a502a5a428913c585b13dbdd0857fbf4ffc3e928b942b5e96c98aced1a1736",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x291d2f7ab3a39d6c34a1b1c66e69262273221f6a8b2bac448e37e64da2330694",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x126",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xb7c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x00f4447478e16a0e4dbe26e2398381d77367268754921e89d20bb152c1648910",
+ "transactions": [
+ "0xf86481ec088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0aa81d6aa3b28238a33a52a3e3b5f00fa2300402a222f10c0e7451318b3f81e25a0223f13ffcec992f0ed7592df411b58352aad6d277dd16e7d0a55e5ab5702a18a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5ca251408392b25af49419f1ecd9338d1f4b5afa536dc579ab54e1e3ee6914d4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np295",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x00f4447478e16a0e4dbe26e2398381d77367268754921e89d20bb152c1648910",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe3e06a047edd89fc5a4f9ee475d8e10ace0a0bae37ad4df6613a6077870fcae4",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x127",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xb86",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1480b67138d2eb8359bf102ee31219dea9776af6c7fed33e8f4847ce943365c4",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81ed010882520894be3eea9a483308cb3134ce068e77b56e7c25af190180c080a0190737acd3a2a298d5a6f96a60ced561e536dd9d676c8494bc6d71e8b8a90b60a02c407a67004643eba03f80965fea491c4a6c25d90d5a9fd53c6a61b62971e7c5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe98b64599520cf62e68ce0e2cdf03a21d3712c81fa74b5ade4885b7d8aec531b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np296",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1480b67138d2eb8359bf102ee31219dea9776af6c7fed33e8f4847ce943365c4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8d04702ac0333be2a1e6ae46e4aa31fe4fe23f5458c6899a7fd8800d24162bc5",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x128",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xb90",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5b6e5684623ac4835ad30948dca710bb10d4bf48695089a4eca9e472300f37d7",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2b",
+ "validatorIndex": "0x5",
+ "address": "0x1c972398125398a3665f212930758ae9518a8c94",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd62ec5a2650450e26aac71a21d45ef795e57c231d28a18d077a01f761bc648fe"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np297",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5b6e5684623ac4835ad30948dca710bb10d4bf48695089a4eca9e472300f37d7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb59802d3b42a67087c2362fe27807e97ea95f8894d734e3711d61768b0779cc5",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x129",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xb9a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5903dfb3ecee5d8bc0e0cc0208b17dfc9a0dc86de2eaaee48da23ea0877b6c87",
+ "transactions": [
+ "0xf88281ee08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a01a3bb1f736220feefc5706b013d9cd88f2e5d5c1ee3398b15ba14e84ed6a12c9a078068efcdcd82d92408e849bb10f551cc406e796ff1d2e7d20e06a273d27dfdf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4d3fb38cf24faf44f5b37f248553713af2aa9c3d99ddad4a534e49cd06bb8098"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np298",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5903dfb3ecee5d8bc0e0cc0208b17dfc9a0dc86de2eaaee48da23ea0877b6c87",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x18be7053419eb1d23d487c6a3df27d208a2f8973d17b6b3e78417df0d3ab1644",
+ "receiptsRoot": "0xa7318d908cd687d0e6d982ec99a33a54b0cb9d1bbe3782f31ae731231e79039f",
+ "logsBloom": "0x00000000000000000000000400000000000000000000000000000000000000000000000000000008000000000000000000000000040000000000800000000000000000000000000800000010000000110000000000000000000020000000000200000000000000000000000004000000001000000000000000000000000000040100000000000000000000000000200000000800040000080040000000004000000000000000200000000000000204000000000000000000000100000000400008008000080000000100000000000000000000000000000000000000000001000000000000000000000000000000001000000000000000000100000000800000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xba4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x19f2a0716399f123d47e625de34fb2d6fbeadc26b2993e89504e73db85248052",
+ "transactions": [
+ "0xf87981ef0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0dc80fe6320cc01dd2ab63a42dd099e2fa5e0a640e6ccdf8ed634ca0c7382bd9fa04b356107e6a61d8852e7dc24f02691a9bd203564fed22da46bc9d9cd560c3dd4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x36e90abacae8fbe712658e705ac28fa9d00118ef55fe56ea893633680147148a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np299",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x19f2a0716399f123d47e625de34fb2d6fbeadc26b2993e89504e73db85248052",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf704271ace032c151b512221e777247a677847e2588ffb6fdea3de9af775b059",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xbae",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2d68907fbe46b2958a1e07b483359dd1e1ac8a6fa0b13e0a9c012cb5de4bf458",
+ "transactions": [
+ "0xf86481f0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa06074cb58acfc1417684962272c546809696c6d2110b75735b19852066839a38ea03bd4f9b9b32c074215420391000ce0358e01e65745d7a6aa5513c4f857dd6579"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x164177f08412f7e294fae37457d238c4dd76775263e2c7c9f39e8a7ceca9028a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np300",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2d68907fbe46b2958a1e07b483359dd1e1ac8a6fa0b13e0a9c012cb5de4bf458",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0d6f0609afeda40249aad175bb482c3560b6f0e2fb612addd06c6f3953662531",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xbb8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe7554d8e76e3ae2d92eceade591334e211020b97e176762c99573ba526c7fdc6",
+ "transactions": [
+ "0xf86781f1088252089408037e79bb41c0f1eda6751f0dabb5293ca2d5bf01808718e5bb3abd109fa0e3edf14f32e7cacb36fd116b5381fac6b12325a5908dcec2b8e2c6b5517f5ec5a051429c4c1e479fa018b7907e7e3b02a448e968368a5ce9e2ea807525d363f85e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xaa5a5586bf2f68df5c206dbe45a9498de0a9b5a2ee92235b740971819838a010"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np301",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe7554d8e76e3ae2d92eceade591334e211020b97e176762c99573ba526c7fdc6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4ebd469b936b8d119664429fa99c55d75c007d4d12b7eb4db058248fa52b7f46",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xbc2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x20cae70a3b0dbe466c0cb52294f4a0fcc2fdae8e8e23a070cfa0ebe6a9fabab9",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2c",
+ "validatorIndex": "0x5",
+ "address": "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x99d001850f513efdc613fb7c8ede12a943ff543c578a54bebbb16daecc56cec5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np302",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x20cae70a3b0dbe466c0cb52294f4a0fcc2fdae8e8e23a070cfa0ebe6a9fabab9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4e0e374db1e769d72af232e15f83b61024ab42a410b4088ad54ae31fb7ab24c2",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xbcc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8088940507cc523f7c12bcec9729eed01e631ccef6faa8a6413a89d77f109c0b",
+ "transactions": [
+ "0xf88281f208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03f816a6f00b46ffee7ae7dc0a8472c822003d7f175c03fc883435b5303662e29a053e91a9fcfb952b9d2ee2d3017e3d02c8988bb4abcb9c343b66d90094e9b9817"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x30a4501d58b23fc7eee5310f5262783b2dd36a94922d11e5e173ec763be8accb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np303",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8088940507cc523f7c12bcec9729eed01e631ccef6faa8a6413a89d77f109c0b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5cd39242444b2f075de43272eb00a7435191e5d07d4da17022f05f91167f8a71",
+ "receiptsRoot": "0x8c5ae4043b8c3ac3c3faf57678b01a0a80043b682d0a8ae2681dc5c892d7a562",
+ "logsBloom": "0x00000000000000008000808000000040000000000008000000010000000100000000000040000000000000000000001000000000000000000000000000000000100004000000000000800000000000000008008000000008000000000000000020000000000000000000000000000000000000040000000400000000000000000002000000000000000000000000000000000060000000000000000010000000000000000000001020000000080000400000000000000000000000000000000000000400100000000000000000000000200000400000000000000000800000000000000000000000000000000000000010000000004000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x12f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xbd6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3cfeeb3c000dbf1a34a7d601bacf17a26ab0618b14a821b61f847d10d41dd47d",
+ "transactions": [
+ "0xf87981f30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0cdff6973fabfb503b56e50264fa9d542805c351a2cf282d14e9a7e3f90df3bcea03fc2b2ef3d6e5c8d141f20dab6ea64a6ad2f7c5ab3da95c98cff7a73429036a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa804188a0434260c0825a988483de064ae01d3e50cb111642c4cfb65bfc2dfb7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np304",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3cfeeb3c000dbf1a34a7d601bacf17a26ab0618b14a821b61f847d10d41dd47d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb8480fa4b2321e09e390c660f11ec0d4466411bae4a7016975b2b4fd843260dd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x130",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xbe0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcb128d5be67707747d086abaf2a724879f3a54b7ca2bda6844678eb52a2d225f",
+ "transactions": [
+ "0xf86481f4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ceb79cfa45773ae766de6daf76c67f63fbf14c7cd3853b6cd9ba8cd7cd1608baa019c783f138465d2c59039c902cc9b90cbff0e71a09672939e2373390b1f8c4c5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc554c79292c950bce95e9ef57136684fffb847188607705454909aa5790edc64"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np305",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcb128d5be67707747d086abaf2a724879f3a54b7ca2bda6844678eb52a2d225f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x022e2901949be09d1a92be5055ced3cd0770b41c850daf830834dc7da22c9af3",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x131",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xbea",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x36ddc7075c24073ea0b9b997ebf4a82596f13b41a831293600aaf876d5d1e0e0",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81f5010882520894f16ba6fa61da3398815be2a6c0f7cb1351982dbc0180c001a08dac03d829e6f8eab08661cd070c8a58eed41467ad9e526bb3b9c939e3fd4482a02ac7208f150195c44c455ddeea0bbe104b9121fef5cba865311940f4de428eec"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc89e3673025beff5031d48a885098da23d716b743449fd5533a04f25bd2cd203"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np306",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x36ddc7075c24073ea0b9b997ebf4a82596f13b41a831293600aaf876d5d1e0e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xec2a36c595c95a6b095a795e22415b66f5875f243697e72c945361b4f440c3bc",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x132",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xbf4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x90eae29a9b788583ec3624dac546f4372b97d2b1b58edbcca1b9f82e62b0d3c6",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2d",
+ "validatorIndex": "0x5",
+ "address": "0x7f774bb46e7e342a2d9d0514b27cee622012f741",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x44c310142a326a3822abeb9161413f91010858432d27c9185c800c9c2d92aea6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np307",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x90eae29a9b788583ec3624dac546f4372b97d2b1b58edbcca1b9f82e62b0d3c6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x427bbc009fe03135af46fb83f7cdcf27c022159be37615c8caceff14061d2f1f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x133",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xbfe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdce2eeeafbf4e8ff4dbfa786434262fe7881254d7abcea2eabca03f5af5aa250",
+ "transactions": [
+ "0xf88281f608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa07b4f78cff0cb04bb8cb3d81e0aabef7b54c34db7438322bc8c1554448a37b027a00b760535ea891c9b4af5c70ac5726b3829418f5b21632aa8dda9ed2a91a7e30f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xae3f497ee4bd619d651097d3e04f50caac1f6af55b31b4cbde4faf1c5ddc21e8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np308",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdce2eeeafbf4e8ff4dbfa786434262fe7881254d7abcea2eabca03f5af5aa250",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4b11a079f7e911f563ce2c7a0bcda57feaea847b827bfceb4b0f0a1fde490e41",
+ "receiptsRoot": "0x2cea15106bcab9c8122ea9fc8d7b5ace9f0650a79134ad9732b933221eb0c440",
+ "logsBloom": "0x000000020000080000000000000000000000000000000000800000000000040000000001000000000000000000000001010000000010000000000000800000000000000000020008000080000000000000000000000000000000000080080000000000000000000000000200000100000000000000000000000002001000000000000000000800200000000000000000000000000000002000000000020020000008000000000000000000000000000000000000000000000000000000000100000000000004c0000000000000000000000010000000000000200000000000000000000000000010000000000004000200000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x134",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xc08",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd619d2e9c151c94d9610527d55ab721a092f2566b79a92821e4c7c8a106cce4f",
+ "transactions": [
+ "0xf87981f70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03d6fef2d466b342db8155272b9e676d55fdc0fedab7d1fce3b3be54459203a44a016b740412be1021d3f480fbf75fa6733d5a233489a0e1cf72bf56c8b37a0ef80"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3287d70a7b87db98964e828d5c45a4fa4cd7907be3538a5e990d7a3573ccb9c1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np309",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd619d2e9c151c94d9610527d55ab721a092f2566b79a92821e4c7c8a106cce4f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0d7fe7c7c5e17180dd3c5d11953d20c0df05569d83f29789680311e835d44c92",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x135",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xc12",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x722090df82f4d2bf93cc1d092239e427a1ed045284bc56b5aa142b02d2cb3955",
+ "transactions": [
+ "0xf86481f8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0b82807e311788292f679bc187111f494eb67171b03e417afdfb54e17f53b9ecfa05d9e1261b6bd95693c5e7859fa6e9ac0f380083750f46dec3f5058026c00aa54"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb52bb578e25d833410fcca7aa6f35f79844537361a43192dce8dcbc72d15e09b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np310",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x722090df82f4d2bf93cc1d092239e427a1ed045284bc56b5aa142b02d2cb3955",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x97742ddf818bf71e18497c37e9532561f45ff6f209555d67e694ec0cec856e7e",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x136",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xc1c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x81f5ce1e85499179e132dbe7b9eb21403c7f3df276820c668ed86a018065dbfa",
+ "transactions": [
+ "0xf86781f9088252089417333b15b4a5afd16cac55a104b554fc63cc873101808718e5bb3abd109fa0f2179ec11444804bb595a6a2f569ea474b66e654ff8d6d162ec6ed565f83c1aaa0657ed11774d5d4bb0ed0eb1206d1d254735434a0c267912713099336c2dc147a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xff8f6f17c0f6d208d27dd8b9147586037086b70baf4f70c3629e73f8f053d34f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np311",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x81f5ce1e85499179e132dbe7b9eb21403c7f3df276820c668ed86a018065dbfa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5feed3f1d6bc9de7faac7b8c1d3cfe80d29fbf205455bc25ac4c94ff5f514ca3",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x137",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xc26",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x685678cda85d28dbe24cd7ef896866decc88be80af44933953112194baeb70df",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2e",
+ "validatorIndex": "0x5",
+ "address": "0x06f647b157b8557a12979ba04cf5ba222b9747cf",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x70bccc358ad584aacb115076c8aded45961f41920ffedf69ffa0483e0e91fa52"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np312",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x685678cda85d28dbe24cd7ef896866decc88be80af44933953112194baeb70df",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xde4840156998638689e0d07c0c706d3f79031636ae0d810638ecdd66c85516f4",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x138",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xc30",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xabbd38fb9a670e62ceca6b3f5cb525834dc1208cd8bc51b3a855932951e34ee3",
+ "transactions": [
+ "0xf88281fa08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06193bab90c2a0e05f830df90babae78be711ea74e7fa7da80fb57bf1eac7b01ba007568dc41c59c9a3e9f4c46ad8bac850ecee5fdbe8add1a840db65266062453c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe3881eba45a97335a6d450cc37e7f82b81d297c111569e38b6ba0c5fb0ae5d71"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np313",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xabbd38fb9a670e62ceca6b3f5cb525834dc1208cd8bc51b3a855932951e34ee3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6fc93047d0ff562c8abee419aecf2b174b1c382f506dedcbb5ba04955cd985c7",
+ "receiptsRoot": "0xcd59afd93dd989872aa9f89197f533f1c6a90364b872e145f50ff782af2b758b",
+ "logsBloom": "0x00000000000000000000000001000000000000000000000010000000000000000000000800000000000000000000000004011000000000400000001000000000004000000000000000080000000080000000000000004000800000000400001000000000000000000008000000800004000000000000000000000000080008000000000040000000000000000000000000000020000001000000000000000000000400000000000000000300000000000000000000000000000000400000000000000000000000000000000000000000000400000000000000000000000000000010000000000000001000000000000000010000000000000000400000000040",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x139",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xc3a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x323e57df6d8869c18eac5a0746e2e3fa96645813704b4af06659dfea08d2473c",
+ "transactions": [
+ "0xf87981fb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0465ab07ff3930a9a8f24c5108701be4a0475480d72147e12305f9d67017af925a07b3dd5fbeae129ce4ea30381c15b2afd9be701e4969422415e07ecea3df82db1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2217beb48c71769d8bf9caaac2858237552fd68cd4ddefb66d04551e7beaa176"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np314",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x323e57df6d8869c18eac5a0746e2e3fa96645813704b4af06659dfea08d2473c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcae6ffdf3092bcb2ebdc66df86177bce69bf2f5921e5c4d482d94f2fd5f6649b",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xc44",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x36c686b156ca6fb1280730a2f86acfd8bcee71bb9666a473d00f0c7813fe5a2c",
+ "transactions": [
+ "0xf86481fc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0d92908e16f6965c17390bafa5649b05b9150b6db7cb63fccfa3d8ccc1f18ec7fa04082aba5936ac8d14c3f78d12f12d9437b575cebd82337c4499f2176afb74cba"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x06b56638d2545a02757e7f268b25a0cd3bce792fcb1e88da21b0cc21883b9720"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np315",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x36c686b156ca6fb1280730a2f86acfd8bcee71bb9666a473d00f0c7813fe5a2c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x1220b41d89a79f31d67f2373ea8563b54fb61661818e9aab06059361fc1412ca",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xc4e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe5456434219d6d602162c56859d7a24895a28aac0958bd46bef986d7d8cab2e0",
+ "transactions": [
+ "0x02f86a870c72dd9d5e883e81fd010882520894d20b702303d7d7c8afe50344d66a8a711bae14250180c001a067bed94b25c4f3ab70b3aae5cd44c648c9807cdf086299e77cf2977b9bce8244a076661b80df9b49579fce2e2201a51b08ecc4eb503d5f5517ecb20156fde7ec5a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xebdc8c9e2a85a1fb6582ca30616a685ec8ec25e9c020a65a85671e8b9dacc6eb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np316",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe5456434219d6d602162c56859d7a24895a28aac0958bd46bef986d7d8cab2e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x65c692f846c2dc380a912a71c1387fec7221a2b0fffae2451370c30ed15350d1",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xc58",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa0f3387ab2dd15ebc6dc9522d5d0ee33f01548722c7fde856fb0f4f00fc6a7a1",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x2f",
+ "validatorIndex": "0x5",
+ "address": "0xcccc369c5141675a9e9b1925164f30cdd60992dc",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x738f3edb9d8d273aac79f95f3877fd885e1db732e86115fa3d0da18e6c89e9cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np317",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa0f3387ab2dd15ebc6dc9522d5d0ee33f01548722c7fde856fb0f4f00fc6a7a1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3dc5f82b5983ab440abc575ac26ea2f4962c8c31f7e8721b537ea53d385827d5",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xc62",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf0da8bf67d04b148efa37b1c72f83bad458c873c35390e45853916d2a6011efa",
+ "transactions": [
+ "0xf88281fe08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f5f035f73b86709cffa1134edc422e41e8ec49f3455943045c8571f4f12e8f6fa0659c80c0802ca16b9c71c90a8c1d7c32580b8dc2e33eb246d05e9c4920314a31"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xae5ccfc8201288b0c5981cdb60e16bc832ac92edc51149bfe40ff4a935a0c13a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np318",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf0da8bf67d04b148efa37b1c72f83bad458c873c35390e45853916d2a6011efa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb0a0edf94f736c11dfd920d0d386b5857441067979baff670d45380f5ce9c2b2",
+ "receiptsRoot": "0xbe0275e0c21d0b23665e6d0b34bbb1669b585dfb6ef89c0903dcf8586ec86d00",
+ "logsBloom": "0x00000020000000000000000000000000000100000000000000000000000040000000001000000000000040000000001000000000000000000000000000000000000000000000000000000000000001000000000000000400000000000002000000000000000000000000000000000000004800000000000000000000000000000000000020000000001004000000000004000000000000000100000800000401008000000000000000000800000000000100000000200000000000002000000000000000020002000000000000000000000000000000000000000200004002000004000000000000000000080200000000000000000000000000010000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xc6c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9b47d293dedc13b8b02e999ebaf1bf25c233229acf97e7ff9e9491ffbdbcf859",
+ "transactions": [
+ "0xf87981ff0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03b9f00d5731e51c973193cb6169cb8024b864d02e5347f287f8de4807e343922a04763ef63ac8ddc3fab7ccc70a4890b69fc944f330f5dd92f1b0266aaa6730eb6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x69a7a19c159c0534e50a98e460707c6c280e7e355fb97cf2b5e0fd56c45a0a97"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np319",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9b47d293dedc13b8b02e999ebaf1bf25c233229acf97e7ff9e9491ffbdbcf859",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe7a75428fc4aadb70c1e0ac2ae59a54df93458845525804742ae02a83d4f235e",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x13f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xc76",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa2c25b920f18b7c73332a155d3ab99a4a88b6454f70c1bdfddfcbfe50311c702",
+ "transactions": [
+ "0xf865820100088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08c4b5e491ee67e169155453cdfc9f7ee6f122aeda5d73caf8337d6c29be1be3ca06b9a4038e45c6b5e858787dda6d1fe8d3c502a42996b4fe1abd2de1b834cf5fe"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4d2a1e9207a1466593e5903c5481a579e38e247afe5e80bd41d629ac3342e6a4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np320",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa2c25b920f18b7c73332a155d3ab99a4a88b6454f70c1bdfddfcbfe50311c702",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda3147e8c80cfa63013d1700016a432d64c00213231ac510ab15f7011eea14e8",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x140",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xc80",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xde65dcf316b36cd1d205e6df4a905df46ceedb163133ebffbab07fb6225d246d",
+ "transactions": [
+ "0xf8688201010882520894dd1e2826c0124a6d4f7397a5a71f633928926c0601808718e5bb3abd109fa01f5208621cee9149c99848d808ee0fa8d57b358afbd39dc594f383b7f525f4c6a01960c6254e869f06cfa3263972aa8e7cc79aec12caa728515c420d35b1336c0e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd3e7d679c0d232629818cbb94251c24797ce36dd2a45dbe8c77a6a345231c3b3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np321",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xde65dcf316b36cd1d205e6df4a905df46ceedb163133ebffbab07fb6225d246d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x05dcc2c2d7e87e4e1d836888d7158131800d123c6b2de255ba83054dfa109b02",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x141",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xc8a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf2fb525ebc86939eeafb51c320f9793182f89f7bc58ad12900362db56d9d4322",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x30",
+ "validatorIndex": "0x5",
+ "address": "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd1835b94166e1856dddb6eaa1cfdcc6979193f2ff4541ab274738bd48072899c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np322",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf2fb525ebc86939eeafb51c320f9793182f89f7bc58ad12900362db56d9d4322",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5efe08d743bbae45240fc20d02ab6e38e923dedc1027cf7bc3caff52a138dc06",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x142",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xc94",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x815a67d4526461c4d40a205f5e8cbd11964bd0ed1079edc334250475a0efe1f2",
+ "transactions": [
+ "0xf88382010208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f8cf692109b242d13af60f7def7e34fc16e4589de28a3fc445e83fece028b046a07ab0d98800bffd516adf4a56b048f67b4d5ffcf438c8463d82a0fe41509f51e6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1f12c89436a94d427a69bca5a080edc328bd2424896f3f37223186b440deb45e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np323",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x815a67d4526461c4d40a205f5e8cbd11964bd0ed1079edc334250475a0efe1f2",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe6408a88797a6a4177fdb082766f6f35cd304745d96ceec7ba85908cf887ba77",
+ "receiptsRoot": "0xf0fa46b5337f820bd96b8bf1a50706c91cf6e2d8a9bb0fd9859f0f80d60009e3",
+ "logsBloom": "0x00400000000000080000000060000000000000020000000000100000100000040000040000000004000010000000000400000000000001020400000000000000000000000000000000000000000000000000000000000100000000000000400000000000020000800000100000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000014000000008000000000000000000000000800000000004000000000000000000000000000000020000000000010000800000000000000000000000000000000800000000000000000000000000000000000000000000400000000010000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x143",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xc9e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc80438a37c405d0d3748ca7c92fb89f010ba9b06bd2136b919b563978f1ae6c1",
+ "transactions": [
+ "0xf87a8201030883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04d42d5415cbd9d939ef53ef60dbdffb80d016dc6e0704059b94ea4c1d398a2c6a06276655ceed05dd6ed9d6adcb9bb38bf699ae5f7ad1d8e47871404cd3ca98a00"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xccb765890b7107fd98056a257381b6b1d10a83474bbf1bdf8e6b0b8eb9cef2a9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np324",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc80438a37c405d0d3748ca7c92fb89f010ba9b06bd2136b919b563978f1ae6c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x38475f9f9a763356a2e995dd7ff0e2b3376078bd3048aa3d25bfec5257e1cf3f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x144",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xca8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1efad9b7aa7d15c849d6055ea15823066111fed8860177b6b0be3ed187a22664",
+ "transactions": [
+ "0xf865820104088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0654811f90e5259072ba79ea3e5a6ca7bfe8659e198ded895d149d1fc2bfe0167a052842cb4b3a0b0f2d722ec25a5c948bb2b78c3cd2d750303a5869a8812f17eed"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8bbf4e534dbf4580edc5a973194a725b7283f7b9fbb7d7d8deb386aaceebfa84"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np325",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1efad9b7aa7d15c849d6055ea15823066111fed8860177b6b0be3ed187a22664",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xda41e628e9aa8c362284b556f48a4e3f9e3e0daec75c7950cd5d4ea75b9f8223",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x145",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xcb2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8cfb3cab3103d0431ed161ebec0a29ffce5b82e8fa5b00520169a8be360b9054",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e8201050108825208941219c38638722b91f3a909f930d3acc16e3098040180c001a063adb9abb5014935b3dbf8c31059d6f1d9e12068a3f13bd3465db2b5a7f27f98a056f0f5bed39985d0921989b132e9638472405a2b1ba757e22df3276ca9b527fa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x85a0516088f78d837352dcf12547ee3c598dda398e78a9f4d95acfbef19f5e19"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np326",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8cfb3cab3103d0431ed161ebec0a29ffce5b82e8fa5b00520169a8be360b9054",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbcdb535ac430393001427eab3b9ff8330ae1c997c2631196da62db6c3c5a5a08",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x146",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xcbc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xacef7ee8af09f4b94fc20d862eb2426993ad2e2807e22be468143ea8cb585d0f",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x31",
+ "validatorIndex": "0x5",
+ "address": "0x6a632187a3abf9bebb66d43368fccd612f631cbc",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0f669bc7780e2e5719f9c05872a112f6511e7f189a8649cda5d8dda88d6b8ac3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np327",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xacef7ee8af09f4b94fc20d862eb2426993ad2e2807e22be468143ea8cb585d0f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf54751e3cc778e70000823cc9800dbecaf86c60afe48ddd4f942c9c26f606d6f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x147",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xcc6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x61642769719bcfbed733fd6b7c2cd51038dc1404f0e77f50c330ac8c9629b8c4",
+ "transactions": [
+ "0xf88382010608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0af7d5214c1fa8aff20cfd3e89d0db2ff361cf5c23dae0823c6719d9bd3c3a996a0581c85fafb49fa0753c67f65e6ad04871fab4a72a9bf5d9ab3bd7aa33b230225"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa7816288f9712fcab6a2b6fbd0b941b8f48c2acb635580ed80c27bed7e840a57"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np328",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x61642769719bcfbed733fd6b7c2cd51038dc1404f0e77f50c330ac8c9629b8c4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaf3502d0a6862e2cde40bbf084cba5e582a0ba3b3bc0beec6791a712c3d171e3",
+ "receiptsRoot": "0x52236ae99e7647366a3e31ba24153828332656ea5d242e422ffca1dbf576701d",
+ "logsBloom": "0x00000000000000004000000000000000000000001010000000000000000008000040000000000000000000000000000000020000200000000080000000000000000000200000000000000021000000000000400000000020000000000000000000000000000080000200000102000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000088000000800000000000000000000000000000000000020200004000000004000000000000000000002000000000000000000000020000002000080000000000000000000000402000000000000000000000000000000000000000000000000000000008",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x148",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xcd0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3acbeee2cb8786a166d6caf512afc82b72ed1ccbfbe39dd32dd53f842046866a",
+ "transactions": [
+ "0xf87a8201070883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a015a81314b3c04efc725ff998badcf9278fb668561e5f9cdd42336845be60ec6ea04c593cfd5526eaf42203a3e6b5020e612ddd4053fa3123f51ae02bf8dde98eb3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xda5168c8c83ac67dfc2772af49d689f11974e960dee4c4351bac637db1a39e82"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np329",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3acbeee2cb8786a166d6caf512afc82b72ed1ccbfbe39dd32dd53f842046866a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2a4691469da94625b4626e0a10273a2854e342a71b0711acebc46c8553eb8f0e",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x149",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xcda",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1c012e1db133493333b09aff51ca8a110b148221aaf1f28c3d21b41382b0d058",
+ "transactions": [
+ "0xf865820108088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0f9f0dcc20f1b62b8c567ac92dc1fbf50908f8bcd504fff3a342de336052e66bea00d38043fb1b141dc3fa2b97eaf09bc490be62e1cf7c40b670503ce0fbd8f6dce"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3f720ecec02446f1af948de4eb0f54775562f2d615726375c377114515ac545b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np330",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1c012e1db133493333b09aff51ca8a110b148221aaf1f28c3d21b41382b0d058",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x44248f33cb76fe58bf53afa7a07e7b3d1d1efb1dcde8379ba1719d987a4cb83e",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xce4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4e325a3f368a7235db02d7e604501ef2b416494a13136c23026e9dd3a3f38547",
+ "transactions": [
+ "0xf86882010908825208941f5746736c7741ae3e8fa0c6e947cade81559a8601808718e5bb3abd109fa0edd3402a6c7a96114e4c8520d7bf3f06c00d9f24ee08de4c8afdbf05b4487b7da068cd4cf2242a8df916b3594055ee05551b77021bbea9b9eb9740f9a8e6466d80"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x273830a0087f6cef0fdb42179aa1c6c8c19f7bc83c3dc7aa1a56e4e05ca473ea"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np331",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4e325a3f368a7235db02d7e604501ef2b416494a13136c23026e9dd3a3f38547",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x30f652c6dbb2b9b0f66b7031f6fd0a8c163866de7b7f33c3e8a0d1f9b37a6d20",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xcee",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb1a056033a59f165c7df49320a7a67b1fdf266039f12ca8cd2ca8b904425dadf",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x32",
+ "validatorIndex": "0x5",
+ "address": "0x984c16459ded76438d98ce9b608f175c28a910a0",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7044f700543fd542e87e7cdb94f0126b0f6ad9488d0874a8ac903a72bade34e9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np332",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb1a056033a59f165c7df49320a7a67b1fdf266039f12ca8cd2ca8b904425dadf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7ef2bb0e7090f0d465ded8b1064d0aafb5da43bc603b3ae8e39b678616f22f04",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xcf8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x961da5e8745e0e4ae8287d73382c5b0d651110a7c7f900abf5f04b3e114b4776",
+ "transactions": [
+ "0xf88382010a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0b67083c09c180ffba5ddc095999eaacd6d2cec077395c58d882c7a0706954896a02aaa853bfdbcdac9eefd90ff627107b5ca67b0c3969f3a770a4545a3b9d01514"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf63a7ff76bb9713bea8d47831a1510d2c8971accd22a403d5bbfaaa3dc310616"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np333",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x961da5e8745e0e4ae8287d73382c5b0d651110a7c7f900abf5f04b3e114b4776",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xff5f5d4ea4c9cb2944bea27f92a309b59ac66d45d231125258186ad3fcd58b61",
+ "receiptsRoot": "0xd5a4c662356c2fb912cf7df7798aabe0c8598dd3918c2c7e05db6619b76d855e",
+ "logsBloom": "0x00000000044004000000000000000100000000000000001000000000800000000000000000000000000000001000000000000002000101000002000000000000080000100000000000000000000000000000000000000200000000000000000010000000000000000000000100000800800000000000000000004000000800000000020000001000000002000000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000200200080000000000000000000000000000002000000200000000080000000000008000000000000000000400000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xd02",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa966ce90648fa40427896d7206976e783f96979437cbb3aed9cc9b050675763c",
+ "transactions": [
+ "0xf87a82010b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0e65e3fb877a256ecdcf4de6dc51df2bd755e14acad6b24c68e7168dbdfcf77b5a017ffeb5a31596ad459195610c5c5e3f348468dab79d930d49cddc0601cd5a965"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa68dbd9898dd1589501ca3220784c44d41852ad997a270e215539d461ec090f8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np334",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa966ce90648fa40427896d7206976e783f96979437cbb3aed9cc9b050675763c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc8b1d4c2863741606d2cb870ed951e27495def1661f5192eef61cea97b8cd79d",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xd0c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x266c92734d3a74137a12e4f6af6fe2cc401992b473d8af9121edbf3a78e4cf8a",
+ "transactions": [
+ "0xf86582010c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa041e92995e25443285655d748126496dbe98874a5cee8a1f0e58ea9f6a650f862a07feb73712a079a889322fcb61999780dab187d69eef21757af3eb0c9825f64c1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x59e501ae3ba9e0c3adafdf0f696d2e6a358e1bec43cbe9b0258c2335dd8d764f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np335",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x266c92734d3a74137a12e4f6af6fe2cc401992b473d8af9121edbf3a78e4cf8a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x53e02e88b716b3d80f9cac4ea6e30497d8a5e0f2dc4df131a20a9ffb78fe8cda",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x14f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xd16",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xebbfb2910659e643ff415b200900100e8e116b6d84a3e8e17b87d3e93dcdf3be",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82010d0108825208949ae62b6d840756c238b5ce936b910bb99d5650470180c080a0025cc19f12be3ff2a51342412dc152953e8e8b61c9c3858c9d476cc214be4e30a0193960b0d01b790ef99b9a39b7475d18e83499f1635fc0a3868fc67c4da5b2c3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4f19cff0003bdc03c2fee20db950f0efb323be170f0b09c491a20abcf26ecf43"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np336",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xebbfb2910659e643ff415b200900100e8e116b6d84a3e8e17b87d3e93dcdf3be",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6be6c01d240a951a6adb298d9cb4e7c9e5e8960540de958b4b458fcfa489bf36",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x150",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xd20",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1f86807324e8cce9f4294076c96c4b2007acb0d2aba5c9ad2695e68aad468f8c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x33",
+ "validatorIndex": "0x5",
+ "address": "0x2847213288f0988543a76512fab09684131809d9",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x52b1b89795a8fabd3c8594bd571b44fd72279979aaa1d49ea7105c787f8f5fa6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np337",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1f86807324e8cce9f4294076c96c4b2007acb0d2aba5c9ad2695e68aad468f8c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd2cd6e558f19ab03db7ee9677a850741b4f1f763c3de94539a16d54c27f6cac0",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x151",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xd2a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x7cec5c4064e153c1c3adeda621a8764ebd7a693aa70891ef0bc7b6f95e64ae7b",
+ "transactions": [
+ "0xf88382010e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a057a97e1fae6dc03c4a29ad01b4d2ebea7069f1bef844b28b92875346d4454c46a01f5821fcf724aa6b0a3b082a6462e5f191a3c5659ba1b66b82cd42cf3175ba59"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7c1416bd4838b93bc87990c9dcca108675bafab950dd0faf111d9eddc4e54327"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np338",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7cec5c4064e153c1c3adeda621a8764ebd7a693aa70891ef0bc7b6f95e64ae7b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe1531cb938cfb7009f343d7ce9de03c63fe99878807b1ec8954b3a29a2d630f1",
+ "receiptsRoot": "0xa8c44170e431c7d7adf58109a7dbb58eeb38a19244c8a866311ef3a45fd13dfd",
+ "logsBloom": "0x00000000000000000000000000002000000000000000000000000000000080000000002000000000000000000000000000000000008000010000000000000000000000000000000000000000000000000800000040000420000400000000000000000000000000000000000000000000000000000000004000000000000000000200000018000000040000008400000000000000000000000000000001000000201000000010000001000400000000000000000000000000000002002000000000000400000000000000000000000000000000001000000000000000000000000000000000000080000000000004100000101000001000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x152",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xd34",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x11bd9e6153d072615b7e129ce56e720c40c048dd37afb5fdbfff09f994ae4a13",
+ "transactions": [
+ "0xf87a82010f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0de79b818723588fa8952e0d007ef1e1db2240b355f4f0f69f2af9df6b3408407a00962c062cd7fc4b8bf627bab2c0a00349d7b1bfc6f7875ca3a18967ad30ff219"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xef87a35bb6e56e7d5a1f804c63c978bbd1c1516c4eb70edad2b8143169262c9f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np339",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x11bd9e6153d072615b7e129ce56e720c40c048dd37afb5fdbfff09f994ae4a13",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd35f874d00597dfb19f0363bbab78f3356e12ec8b4ee89f2883285139d7a3c29",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x153",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xd3e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf7122487788d84678b120512a25b1393417a66e19db5b507d471dd17628a84ea",
+ "transactions": [
+ "0xf865820110088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa083a20e0b736688ba1f10440def989495ff253a281368f0ca21154d327c0468b8a0119312bdfeff761612ef529e4066bd28b4ed46895e5b67593fb0a3a897d3aa16"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe978f25d16f468c0a0b585994d1e912837f55e1cd8849e140f484a2702385ef2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np340",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf7122487788d84678b120512a25b1393417a66e19db5b507d471dd17628a84ea",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfa5b72ef0354b0b53f973b5285234c441e1bbf86d26374dd3856b36627d5caa3",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x154",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xd48",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb1d88e8bd186bb264de8def507f6a5876ec6f3af27be936763dfd39213ab07e8",
+ "transactions": [
+ "0xf8688201110882520894b55a3d332d267493105927b892545d2cd4c83bd601808718e5bb3abd10a0a073cc84153b8891468325ac12743faf7e373b78dbf8b9f856cb2622c7b4fd10e1a0388714fe9d2f85a88b962e213cbe1fa3c4a9823cea051cf91c607ecbd90093d8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc3e85e9260b6fad139e3c42587cc2df7a9da07fadaacaf2381ca0d4a0c91c819"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np341",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb1d88e8bd186bb264de8def507f6a5876ec6f3af27be936763dfd39213ab07e8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xac6b9759a537d44a1629532184219d1f658f68745491b27e81c87361e72ad602",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x155",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xd52",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x70dad5a0db225381e8f841db9d8adf9a350051128cc22c0e5a00ad990c592b0d",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x34",
+ "validatorIndex": "0x5",
+ "address": "0x1037044fabf0421617c47c74681d7cc9c59f136c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbd2647c989abfd1d340fd05add92800064ad742cd82be8c2ec5cc7df20eb0351"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np342",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x70dad5a0db225381e8f841db9d8adf9a350051128cc22c0e5a00ad990c592b0d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe579eb979cbfd580c19ef8583f73a0fda902ee0895903a767d544ade95c50baa",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x156",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xd5c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb9b47ee8f7c38e7e1f69148756182d3da3a7d0c123948d2c56e5268357fced99",
+ "transactions": [
+ "0xf88382011208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0874d69f306b86e76465f6f0ad314cadee41f0f0d1844d35408201c3b2f690de0a0698f29877cb7dec8ee91a42a74f0f5270cbb391836fdaeda1e0876d3c16177b9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x99ac5ad7b62dd843abca85e485a6d4331e006ef9d391b0e89fb2eeccef1d29a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np343",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb9b47ee8f7c38e7e1f69148756182d3da3a7d0c123948d2c56e5268357fced99",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf9106c3c4fcc77588a382ba0c2f605f6e07fcc418edac1cdd7de3b0e70f81b9f",
+ "receiptsRoot": "0x07a001dcc7eec5d1e8aa3508d61fcf5d511b4f9b766801b63319aa423ef08c3f",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000010000800000000000000000000840000004000000000080000010000000000000000000000000000000000000000000000020000000000000000008000010000000000000000000000000000000100000000108000000000000210000000000100000000000000000000002000000408000000000030000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200008800008000008000000000000000400000100000000000000008000000000000000000000080000000000000000000001010000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x157",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xd66",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xde78022135caa19aa76718718d5de70d69e3f2488ff6769aee87c1d765237214",
+ "transactions": [
+ "0xf87a8201130883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa084f91b21758f4c28d386fa99e8b7e126d27a1f9e293e5df2683057e09a9c6a2fa051772044b702ac375f615dc0d6aaa8c1d38c3ac2a830539d2ab62935c5132921"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x02a4349c3ee7403fe2f23cad9cf2fb6933b1ae37e34c9d414dc4f64516ea9f97"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np344",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xde78022135caa19aa76718718d5de70d69e3f2488ff6769aee87c1d765237214",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x19268b0f7992afe0cf1f3c0ac73b371ed7d9e79dddf0435b72bc45e1682a9c74",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x158",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xd70",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8123c0650f836341cace6e65f0826a678974333748bc91a93d569224d63f832a",
+ "transactions": [
+ "0xf865820114088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0904e2a23972254826c8f3f5efa2d39122f980811cb9dd3e5d2869618d458856aa00fd104e760443aa8abcbdfbf2263d45a32a7aec32e59548b3e73575bc21f0243"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x627b41fdbdf4a95381da5e5186123bf808c119b849dfdd3f515fa8d54c19c771"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np345",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8123c0650f836341cace6e65f0826a678974333748bc91a93d569224d63f832a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3ef70ee0614b3ae112271af4be70033c61a89f337aa527b8657df19422d94913",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x159",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xd7a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc74bc2976b5c5cbcfd64757534333c98d56bcac3109fc4504e3c324801f27530",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820115010882520894b68176634dde4d9402ecb148265db047d17cb4ab0180c080a09f3175e9aa2fe2332600b71de0b0977c7c60ccbeee66ea360226326817f2d59ba06a870e0876002f789b3203f4a33d5e621ac67051704e1f2260b80d816260b3e6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc087b16d7caa58e1361a7b158159469975f55582a4ef760465703a40123226d7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np346",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc74bc2976b5c5cbcfd64757534333c98d56bcac3109fc4504e3c324801f27530",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbbec06f293095304adb3f03ba055fd08a691c89d5de1ade4c1ed31b9c6672989",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xd84",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x60a82197fb6b3b7d9a4912ec6ac783460863e449f48c28d68a45b4d4bf0a99f4",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x35",
+ "validatorIndex": "0x5",
+ "address": "0x8cf42eb93b1426f22a30bd22539503bdf838830c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf7a477c0c27d4890e3fb56eb2dc0386e7409d1c59cab6c7f22b84de45b4c6867"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np347",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x60a82197fb6b3b7d9a4912ec6ac783460863e449f48c28d68a45b4d4bf0a99f4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x169c28a15311ed314bc0a4529aaddacc79d5fd6becdaaae69276079408d57eda",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xd8e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xefbb190d45953f5e6292e14fc50b51539bca514890f94eda3e3ba2553417303a",
+ "transactions": [
+ "0xf88382011608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a065a20271c4b6acc45c7e172465adcdc218b164c0936999de9bdd37c4a4c63fd0a003792daae8ab2be81df0df962c26697830d30af560c8a85a0fba05e5cfc82d66"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1cb440b7d88e98ceb953bc46b003fde2150860be05e11b9a5abae2c814a71571"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np348",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xefbb190d45953f5e6292e14fc50b51539bca514890f94eda3e3ba2553417303a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x704fde0fccaf5957d60018e958bfb8cc7bb7e77eed37cee3bdcdcca280b3b1fb",
+ "receiptsRoot": "0x0016ae7d40181cb711af89f17dc40dfb53384c5ef535847ae4982b1d58bfadd1",
+ "logsBloom": "0x00000000000000000000000004800000000000000000000000000000000200000000000000000000000000008000000020000000000200000000000000000000000000000000000000000000000000000000000000004000000000000008000000000008010000000000100008000000000020000000000400000080000000080000000000040000000080000000000002000000000000000000000000001000000000200000000000800100000000000000000040000008000000000000000000000040200000000000000000000000000000000000000000000000020000000000200000020000001008000001000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xd98",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xac7efb8f8fa8949755e520c30b52d9c292eb7e46eb8cac907f1267f72de81237",
+ "transactions": [
+ "0xf87a8201170883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0a7fe70291d9f18d3daffb9c6845116569c9be21f8b04c47235999ad35c20a079a03ad45b41a4993ea744bb28012bae4998ad6e97da464162d4ce51810e442e3ccc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x72613e3e30445e37af38976f6bb3e3bf7debbcf70156eb37c5ac4e41834f9dd2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np349",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xac7efb8f8fa8949755e520c30b52d9c292eb7e46eb8cac907f1267f72de81237",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x898ac18f3ec544e0908e3a1c5434515aa421b796a41501b0474375f49fba30c8",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xda2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x498a0d50858ecbfd2fe317843b04c02a00dfa8c2ee6a0e3641947439f0eb7dba",
+ "transactions": [
+ "0xf865820118088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0027208b707b49c8686502030a1029e738d91a7c0bf9dff86bb90ccda2e5fc158a04b1d06ac6269fc336d1e6d0bac45e82b7d47ca4c271c7fed3bd1c6599b4bd0c6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe69e7568b9e70ee7e71ebad9548fc8afad5ff4435df5d55624b39df9e8826c91"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np350",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x498a0d50858ecbfd2fe317843b04c02a00dfa8c2ee6a0e3641947439f0eb7dba",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3a29d14904f05f088f4aede9ab588a53f6a54db4f43cd77f0227445a0d7c8386",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xdac",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xac94cbd2aa423a9fc3dd35e9918a288b31a6b6127f829ef08b3d106212d5c005",
+ "transactions": [
+ "0xf8688201190882520894dfe052578c96df94fa617102199e66110181ed2c01808718e5bb3abd109fa0020ee6a1ada31c18eac485e0281a56fc6d8c4152213d0629e6d8dd325adb60b1a00f72e01c463b98817219db62e689416c510866450efc878a6035e9346a70795f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc3f1682f65ee45ce7019ee7059d65f8f1b0c0a8f68f94383410f7e6f46f26577"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np351",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xac94cbd2aa423a9fc3dd35e9918a288b31a6b6127f829ef08b3d106212d5c005",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x693ec0330efa3e07b25a9a758d30a43389876e03846885dda5cdb009ff0e2674",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x15f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xdb6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5c72e42631163c4ff7bb5a0e0051317b4b432609769052e2efe6043155ead48c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x36",
+ "validatorIndex": "0x5",
+ "address": "0x6b2884fef44bd4288621a2cda9f88ca07b480861",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x93ee1e4480ed7935097467737e54c595a2a6424cf8eaed5eacc2bf23ce368192"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np352",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5c72e42631163c4ff7bb5a0e0051317b4b432609769052e2efe6043155ead48c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc25a9e84540d654be4abb3e8581cd2cc7cf97e54895e7a62d08eb78431d3f244",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x160",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xdc0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf3760efebd2ee1fbbda6bfff5aded8bb4ac38928857a4b22edab12bda293a2d7",
+ "transactions": [
+ "0xf88382011a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00df7ffb1778e645f4fc3b0e2236b34c038c43aacbbc43abc8d710c3fc33901e5a00d7d3d9cbc790b2e206b30639a4b55c1d2f3c2ea18c058a5085f16d72b50455b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb07f8855348b496166d3906437b8b76fdf7918f2e87858d8a78b1deece6e2558"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np353",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf3760efebd2ee1fbbda6bfff5aded8bb4ac38928857a4b22edab12bda293a2d7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x911acb703f25c08267716b25fc43b19bf4ce43a053393e6f1dce78c1cba8c485",
+ "receiptsRoot": "0x758b6a000deb6b7275c48ea96b2cbf580372445f0bc5b285eb764ed1800e8747",
+ "logsBloom": "0x00000000000005001000000000000000000000000000908000000200420000000000020000000000000000004000800010000000000000000200000000000000004000000002000000000000000080000000000000000000040000000000000000000000100400000000400000000000000000000000010000000400000000000000010000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000200000000000000000000000020000820000800000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x161",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xdca",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9584dd2f0e20e3b4c274103aa168c495888b69ef8de7fe40cf413b6964c8393d",
+ "transactions": [
+ "0xf87a82011b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0c6d3e03aa8b0625a3225e077addb3cf47c9d061148da25021b22a0746083cc11a06176a93c704e6c5088e9d18cbaca7eab1de348207c2ba50083934c4e215a079d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xec60e51de32061c531b80d2c515bfa8f81600b9b50fc02beaf4dc01dd6e0c9ca"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np354",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9584dd2f0e20e3b4c274103aa168c495888b69ef8de7fe40cf413b6964c8393d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaca595525f5aa4f17314e44a3fdc0dae0f4037a1ee0a12bfb1bec7b9219f8d6c",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x162",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xdd4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x55a29172dc5a0a9d27b1778bec1c1591c0c8ec114d322fe60f5a39258e1783a0",
+ "transactions": [
+ "0xf86582011c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ad6f8d4d86d80157b67311edc959413ac3f525a5ec6334cc826125dfb1908b05a02e91a1d46e2df7c7eb4dc92224252298c66dbbf321fbb6c827a6e2d348277298"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2fc9f34b3ed6b3cabd7b2b65b4a21381ad4419670eed745007f9efa8dd365ef1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np355",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x55a29172dc5a0a9d27b1778bec1c1591c0c8ec114d322fe60f5a39258e1783a0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa307681299c7c385c512cbf83195ee62d35d29487665eb57cf2698c1b3e82066",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x163",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xdde",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb99cdd27bfb2535b0247fef5fe8097fc4e60f2a1c54a9adb3243192dafe1e657",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82011d01088252089433fc6e8ad066231eb5527d1a39214c1eb390985d0180c001a0167190e2e0fed95ab5c7265a53f25a92d659e1d46eb9ecbac193e7151b82ec1ca0269353e9c5ef331135563e2983279669220687652e7f231725303ccf7d2a8ebd"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf4af3b701f9b088d23f93bb6d5868370ed1cdcb19532ddd164ed3f411f3e5a95"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np356",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb99cdd27bfb2535b0247fef5fe8097fc4e60f2a1c54a9adb3243192dafe1e657",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb36926502e2ee904451fa5970a453aebe89f5bc25cd8c1dcae196810968617c1",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x164",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xde8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbdd33f47e688a8c88c0bb8514d3eff12f6f1ca570d3ae31aab000689d8dd4af3",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x37",
+ "validatorIndex": "0x5",
+ "address": "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8272e509366a028b8d6bbae2a411eb3818b5be7dac69104a4e72317e55a9e697"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np357",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbdd33f47e688a8c88c0bb8514d3eff12f6f1ca570d3ae31aab000689d8dd4af3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x67558b87a732daed74e1b9ed7aef6326aabe984df466494d2fc59d9ea951c6c6",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x165",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xdf2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x60fbbf44b7687b97e348c42a24637f027125b00a39e5e63995405da84de95ce0",
+ "transactions": [
+ "0xf88382011e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0b20886ab8d36222d79bf9dad933333062a51e71dbd6de720f872874edb727276a05f68ff1bcbb8019f43e4e37a481075cc5565512eb56d34ccb707e8aec00a4204"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa194d76f417dafe27d02a6044a913c0b494fe893840b5b745386ae6078a44e9c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np358",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x60fbbf44b7687b97e348c42a24637f027125b00a39e5e63995405da84de95ce0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x15bdc9a6fcc0d4d133bc86adbda378e2110d51fc60304207240f24f60d4fc99d",
+ "receiptsRoot": "0xf9f06ad2e1bbf826b5cbeabfd01d508c4d7bc0781b946c5afc105a2e20d9155a",
+ "logsBloom": "0x0020000200000000000004000000000000000000010000001000000000000400000000000000008000000000000400000000a820000000000000000004000001001000000800000000000000000000000000000000000000100020000002000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000040000000000000000000002000000000000000000000000008000000000000000000000000000000000000000000004000000000000000000000000000000000140000000000000800000000000010000000000000000000000004000000000010000000000004401000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x166",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xdfc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb32a72eff6c1fed26a63381d9de7254e9a85e9c459fad22c037e8a11eb95d04f",
+ "transactions": [
+ "0xf87a82011f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0c35e2924126964cdf4a8847f4cb4a870f24a4654de527a3dc9fad248d338aab6a00d9292c8e92050bebef84a83b3deacddf95a33015a3d284b578cb0f1621c5a70"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa255e59e9a27c16430219b18984594fc1edaf88fe47dd427911020fbc0d92507"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np359",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb32a72eff6c1fed26a63381d9de7254e9a85e9c459fad22c037e8a11eb95d04f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x21d7cc2931eed33ddb03977b7d99c97ac378c41ed2ac25331478cd1fbd583e7a",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x167",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xe06",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x31483924290768786929b9836507966e24a775f86f3724200851b2eaa262ac36",
+ "transactions": [
+ "0xf865820120088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0aab9710502eb45f06f5470674b88b22c30fdc865a22c86a7095f355629fb6d11a01d905abe10e39ed037ad29a46a81d0af6d52d9de2d7bef20e7b02db8c1cf13a0"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7996946b8891ebd0623c7887dd09f50a939f6f29dea4ca3c3630f50ec3c575cb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np360",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x31483924290768786929b9836507966e24a775f86f3724200851b2eaa262ac36",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x128ac2d4c23be8773c460ed383defee0e767a4fe0a55e9f600a60e0fe051735b",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x168",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xe10",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdfabceebb90036f92ea3e859b9fcadd8642f00dcdf45278c09d93fb56d320b04",
+ "transactions": [
+ "0xf8688201210882520894662fb906c0fb671022f9914d6bba12250ea6adfb01808718e5bb3abd10a0a0d3a858be3712102b61ec73c8317d1e557043f308869f4a04e3a4578e2d9aa7e7a0202a5f044cc84da719ec69b7985345b2ef82cf6b0357976e99e46b38c77fe613"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb04cbab069405f18839e6c6cf85cc19beeb9ee98c159510fcb67cb84652b7db9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np361",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdfabceebb90036f92ea3e859b9fcadd8642f00dcdf45278c09d93fb56d320b04",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa8f8fd676089911db9824cafe64222a854d4767d0cc5fded3fa1643f735afd80",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x169",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xe1a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa7dab2cd20b59a5961ff34f49d421a579c939d6898b084ae4db8971604df1380",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x38",
+ "validatorIndex": "0x5",
+ "address": "0x8fa24283a8c1cc8a0f76ac69362139a173592567",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6f241a5e530d1e261ef0f5800d7ff252c33ce148865926e6231d4718f0b9eded"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np362",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa7dab2cd20b59a5961ff34f49d421a579c939d6898b084ae4db8971604df1380",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb19cdea25a29e5ba5bf0a69180560c2bcf35823b81d82d8b97499ad1cc22873b",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xe24",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0f9c87bb2b9d07ca411420399c22658ea7be36c5bd1fbbf1c759592959cc3a94",
+ "transactions": [
+ "0xf88382012208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa034e8481ee12e75836d1e4cc88aef813a6bc8247b73aeb7a466a1ce95bca6e5fea07585402e69f5856a5724a9e83a9bf9cf77bc92cc619489f9903f09b8c3530f24"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfcfa9f1759f8db6a7e452af747a972cf3b1b493a216dbd32db21f7c2ce279cce"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np363",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0f9c87bb2b9d07ca411420399c22658ea7be36c5bd1fbbf1c759592959cc3a94",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x09f1a8d40ad941a3c47fd34c32682a0058f79387d467a7ebb5d957455aab9fb6",
+ "receiptsRoot": "0xde87ab5715c2af5f977bcf679cd4e771796d49365c3111487aba12fdb69483a2",
+ "logsBloom": "0x00800000000000000000000040000000000000000000000000000000000000000000000000080000000000000000000000000000008000000000000000000000000000002000000000000000000000000001020000000000000000000104000004000000000000000000000000000000000000000000800001000000040000000000000002000000000000000001000000000008400000000000000100000000000000000000001000000000000000040000000000000000010200000000000000000000000000080000000000000000000020002000000020000100400000000000000000000040000000000000100000010000000000000001000040000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xe2e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xcdbbd78682fb1c3e75c9821acce03f6fd048226147e7041d84952c6aa3c18b5e",
+ "transactions": [
+ "0xf87a8201230883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0317931eb522b3488621079d412251962cc5a02794939e3a3b0c94c92df0b4da5a001348209aa47bc1a55590243d5168b2beb06c929b46104d144ba526070b2e5ea"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdf880227742710ac4f31c0466a6da7c56ec54caccfdb8f58e5d3f72e40e800f3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np364",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xcdbbd78682fb1c3e75c9821acce03f6fd048226147e7041d84952c6aa3c18b5e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x96f076c6c4d61d649b8f9c4290ff81fad55bfebe6e171f2d2bedb4b941977873",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xe38",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xab15226c228033c1118398e475d860a1ea7534e4d620ae9ceb2893fa3a73ff7a",
+ "transactions": [
+ "0xf865820124088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0886d94140ef16f0079167a92ea5577d300a4e87982588af41676d8d9a7a7f043a0388a734d4f7a8eb510a5e7aba3141505773bd329a70ff438be40d7b378fdafa6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xadfe28a0f8afc89c371dc7b724c78c2e3677904d03580c7141d32ba32f0ed46f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np365",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xab15226c228033c1118398e475d860a1ea7534e4d620ae9ceb2893fa3a73ff7a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x208cc1a739ecf1c8aed87a70e4f580b28d06f7dba19ef679a4b809870c0e66a4",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xe42",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe3c3b2311857f76f1031d8384102288970bf25ab710e5e8ca3e7fee19ea3fcde",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820125010882520894f1fc98c0060f0d12ae263986be65770e2ae42eae0180c080a06563737b6bfddfb8bc5ec084651a8e51e3b95fe6ed4361065c988acaf764f210a00a96a1747559028cd02304adb52867678419ebef0f66012733fea03ee4eae43b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb264d19d2daf7d5fcf8d2214eba0aacf72cabbc7a2617219e535242258d43a31"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np366",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe3c3b2311857f76f1031d8384102288970bf25ab710e5e8ca3e7fee19ea3fcde",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf4a7f460684eacde84218991911d63333e89a5a8fe5293e43b2b283209bb7297",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xe4c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf1f80c035c0860545aeb848923615c5bb8cbd15305ddc6a87b9d9a4d509a8d5c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x39",
+ "validatorIndex": "0x5",
+ "address": "0x19041ad672875015bc4041c24b581eafc0869aab",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf2207420648dccc4f01992831e219c717076ff3c74fb88a96676bbcfe1e63f38"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np367",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf1f80c035c0860545aeb848923615c5bb8cbd15305ddc6a87b9d9a4d509a8d5c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x44f6e5c8fd3452b71ade752a742ca9f61626aeeaa20e89d47fe414d1df414745",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x16f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xe56",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xaa0d0fadd5774766ac1a78447bd5ef9f5a816c9068d28097c78d02737ce7f05a",
+ "transactions": [
+ "0xf88382012608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00d5ce478373461565e41764365499cc4a43519643829503796c5453e1bc7ff0ea03ef00a5fe608838a9156d394317734b358ac026af08b33c2aabfea8e9d485dfa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x41e8fae73b31870db8546eea6e11b792e0c9daf74d2fbb6471f4f6c6aaead362"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np368",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xaa0d0fadd5774766ac1a78447bd5ef9f5a816c9068d28097c78d02737ce7f05a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7fd199408596db163d237e6d25f64b90ac2bc04158524e8baac5d55f881bb52b",
+ "receiptsRoot": "0x8d3f058248d263db5e6d6d78ddf91fd2ec0183f2bdf3e9e142af87a53388e526",
+ "logsBloom": "0x00000000000000000000000000000100000200008000000000000000000000000000400000000000000000000000000000000000010008000000000000000000000020000600000000000020000002000010000000000000000000000000000000000000080000000020200000000000000000000000000000000001000000000000000000800000002000000800000000000000010000000000000000000000000000000000000000000000004000000000008000000000000000000000000000000000040000000000000000000000200000000000000000000000401000000009800000000010000000000000000000000000000000000000808000000800",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x170",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xe60",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4b263e57c931fa090da8bc6890c9d6fc2ad2dd5a66bb3a5563cc477735893a96",
+ "transactions": [
+ "0xf87a8201270883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a008faafda0a060040eca56f846ecbd6a399914482c31359f1ec04c98cc476ce82a04d2b02adc2c947898fa00cbedb4532f471cb5eb92ee19a30697ddd0c713132e3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4e7a5876c1ee2f1833267b5bd85ac35744a258cc3d7171a8a8cd5c87811078a2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np369",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4b263e57c931fa090da8bc6890c9d6fc2ad2dd5a66bb3a5563cc477735893a96",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2a2360860a67f9187f50f56201c50d2309c961a2b408072e7c3d069c8c1216cd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x171",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xe6a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x0adc9e078ab6f0799b5cbc8e46e53a0d96d4fe4ba0b6ff75088445c304000226",
+ "transactions": [
+ "0xf865820128088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0da49c9575be5d906d247a5f4f0574e76d1edb1368dbdda1b4a5b58fba3fca82da00fa1c561fc766acefeeabf085384962f2599b3ca6b02996962095eed297df611"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8d4a424d1a0ee910ccdfc38c7e7f421780c337232d061e3528e025d74b362315"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np370",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x0adc9e078ab6f0799b5cbc8e46e53a0d96d4fe4ba0b6ff75088445c304000226",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x971bbdee0e408ff826563636c5eccce30540c1cba590880849a72ac21f74a4e4",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x172",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xe74",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1636ca42281a5e77303d2d1095d71b2c59f0b175c98a3adb9630cd6463d2be04",
+ "transactions": [
+ "0xf8688201290882520894a92bb60b61e305ddd888015189d6591b0eab023301808718e5bb3abd109fa0626bd8978288bcf1d7719926fba91597d6aa8ead945c89044693d780523a05dda0074494ccf5362aa73db798940296b77b80a7ec6037f5ed2c946094b9df8a2347"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfa65829d54aba84896370599f041413d50f1acdc8a178211b2960827c1f85cbf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np371",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1636ca42281a5e77303d2d1095d71b2c59f0b175c98a3adb9630cd6463d2be04",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2a239ffb7957e73c3eebeb33b01444599ddcd5861f1dfb4bbe31584061f11389",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x173",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xe7e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbf62c63fdcd8b0648bfec616e9270243233b47c513a9519932cb82d70ed5c2be",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3a",
+ "validatorIndex": "0x5",
+ "address": "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xda5dfc12da14eafad2ac2a1456c241c4683c6e7e40a7c3569bc618cfc9d6dca3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np372",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbf62c63fdcd8b0648bfec616e9270243233b47c513a9519932cb82d70ed5c2be",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xadbba859a71886f49ccd216fbc6c51a42a7a6eff927970b298d4e0f6e2a9597d",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x174",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xe88",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x349a0919fb81864d824dd7345c583a9fb5c99ef0bd9c549be68b10e72e7c8c2a",
+ "transactions": [
+ "0xf88382012a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa085c885407da43158c33afe4c9d10a846d4cf5bb820c70f019ff8b6ee9dfb027ba077c0e90a4a029bea55eadf3b0d39261b6204a5c1b8e5e80838ebeef5c9fd456c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x16243e7995312ffa3983c5858c6560b2abc637c481746003b6c2b58c62e9a547"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np373",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x349a0919fb81864d824dd7345c583a9fb5c99ef0bd9c549be68b10e72e7c8c2a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe5a5661f0d0f149de13c6a68eadbb59e31cb30cf6e18629346fe80789b1f3fbc",
+ "receiptsRoot": "0x97965a7b5cca18575c284022cd83e7efb8af6fcf19595c26001b159771ffb0ce",
+ "logsBloom": "0x80000000000000000000000100000000000000000000000000000010000008100180000000000000200040000000000002000000000000000000000040000000000000000000000000000000000100000000000000000000000000400000020020000000000000000000000000000000000008000000000000000000000000000000000000002000000000000000000000000000000000048200000000000000000000000000000000000000000000000000000000000000000000000100000800000000000000000000000000000000000000000000000000000000440000000000000000121400000000000000000000040001000020000000000040000200",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x175",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xe92",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x90c6119a5ecf366ff337473422f9872fddac4e2b193a2e0a065cf7de60644992",
+ "transactions": [
+ "0xf87a82012b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa03e8b18cd5d8c796e69f450a4c00e75d7e2d38cf9d25dd19e2033fbd56fbf4b84a0175ca19057500b32a52b668251a0aec6c8f3e1e92dec9c6741a13ffe3fb214cc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb75f0189b31abbbd88cd32c47ed311c93ec429f1253ee715a1b00d1ca6a1e094"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np374",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x90c6119a5ecf366ff337473422f9872fddac4e2b193a2e0a065cf7de60644992",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0a82334be200ef303c1c3b95b92b6f397df138b7e6eb23d830fb306996f1c79b",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x176",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xe9c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb023fb820fb7f3cc5b8c8ffec71401eae32858e7f5e69ffbdbdd71751bf1c23d",
+ "transactions": [
+ "0xf86582012c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0519fcc6ae02e4901d4ccfcd2b0560f06bf13478b459310ddaae39f44b7ed1394a03b529b53be6c0451a4b644f5031746cb1db62cfbe43b962da26aff507d4293ef"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd087eb94d6347da9322e3904add7ff7dd0fd72b924b917a8e10dae208251b49d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np375",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb023fb820fb7f3cc5b8c8ffec71401eae32858e7f5e69ffbdbdd71751bf1c23d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8e7778cdef2ec78802c7431cdd44768e4a4f6d9c6cc494ae02dc20c10bc6eead",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x177",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xea6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xafe3e6ffafc8cd84d8aa5f81d7b622b3e18df979dbffb44601eb239bc22132bf",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82012d010882520894469542b3ece7ae501372a11c673d7627294a85ca0180c080a09add65921c40226ee4a686b9fa70c7582eba8c033ccc9c27775c6bc33c9232fba021a6e73ccb2f16e540594b4acbba2c852a3e853742359fcbc772880879fe1197"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xbc17244b8519292d8fbb455f6253e57ecc16b5803bd58f62b0d94da7f8b2a1d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np376",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xafe3e6ffafc8cd84d8aa5f81d7b622b3e18df979dbffb44601eb239bc22132bf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0b7ff239a80d7ca996fe534cf3d36898e55e3b4dbd6c130cc433dfb10d83c2dd",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x178",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xeb0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2b7573e48bca65c866e82401d2160b5bcaec5f8cd92fba6354d2fa8c50128e2c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3b",
+ "validatorIndex": "0x5",
+ "address": "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3ff8b39a3c6de6646124497b27e8d4e657d103c72f2001bdd4c554208a0566e3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np377",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2b7573e48bca65c866e82401d2160b5bcaec5f8cd92fba6354d2fa8c50128e2c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5cac010e2605b327b97a4ef6f78d4c65554588283336081d8ef497a3860fdbde",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x179",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xeba",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x77b6c58098c59ec84605e8f12c7fbe8a358d52adf77948577ce7396ae18aaac3",
+ "transactions": [
+ "0xf88382012e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a015118995d271e570428c3c349d49390af0fd81d3217f90159fc25b9d0791d6efa018c1a844d5d3523ce37308f0cd2e46e8d6ef99a9eb750e7325ca2c67d59aaf85"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4d0f765d2b6a01f0c787bbb13b1360c1624704883e2fd420ea36037fa7e3a563"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np378",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x77b6c58098c59ec84605e8f12c7fbe8a358d52adf77948577ce7396ae18aaac3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe908771dea594628e0f4d2b5d3354bbc6f9cfa04a97249657a74b792c3254b77",
+ "receiptsRoot": "0x8dc461a171023c5f8e3f5d78e0842291fbe7b0a502495a334a1bc98337a8a1b4",
+ "logsBloom": "0x00000004000000000000000000002000000000000000000000000100080000000000000020000000000020000000000000200100000000000000000010000000000000000000000008001000000000000000040200000000000000000000020000000000080000000000000000000000000000000000000100000000000000000000000000010000000000000000200000000400000000010000120000000010000008000000000000000000100000000000000000080000000200000000000000000800000000000400010000000000000000000000000000000000000000000004000000000000004000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xec4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x891853e3e9dd73b513556fa241d000aa63fecc5452cf39b3cc756619e9cea7b4",
+ "transactions": [
+ "0xf87a82012f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0d0666f18210bb986b7239269bfbd56336376ed77bb97b56e15df7647c1f06fe3a0718dc6abdefe863e76f0c3c356364d456d34d399b20ed93b61ed93a77bccbe80"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf6f1dc891258163196785ce9516a14056cbe823b17eb9b90eeee7a299c1ce0e0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np379",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x891853e3e9dd73b513556fa241d000aa63fecc5452cf39b3cc756619e9cea7b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x197f321622808ee71925004345aaf99ac87a833c97ee852265b6d8be5c0656fe",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xece",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8d3b2038418a6d5e44a3f5aef149d7d76a20f3ebd5aa3c9d4565ddaa94d00c07",
+ "transactions": [
+ "0xf865820130088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa02f7e9b19c96e60b8bd18eaadf71b049e0f204d42e826667e5b741041663c1963a01ff9a63ae688fc0c05047b819d1b8326c55f60b62f84658814bf35c63b3e5c65"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1dbf19b70c0298507d20fb338cc167d9b07b8747351785047e1a736b42d999d1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np380",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8d3b2038418a6d5e44a3f5aef149d7d76a20f3ebd5aa3c9d4565ddaa94d00c07",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x19c0d6f1bcdcb2c419bb69ed7f176bd58c4833c057faede354566c4e6d6e9f20",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xed8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa63604362866798edab2056c5ddadc63dc1490c6f13bf5dd54008e1e0f64ecd1",
+ "transactions": [
+ "0xf86882013108825208947f2dce06acdeea2633ff324e5cb502ee2a42d97901808718e5bb3abd109fa0fd195ea41804b21ffffdbca38fd49a9874371e51e81642917d001d201a943e24a0542bca46a2dc92fddb9abffcf2b3e78dc491d6e95040692e6d1446a6b487a42a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc3b71007b20abbe908fdb7ea11e3a3f0abff3b7c1ced865f82b07f100167de57"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np381",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa63604362866798edab2056c5ddadc63dc1490c6f13bf5dd54008e1e0f64ecd1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6c634927494436f7c4daaee4ea5c99813ec3066af379315b031f40fdf12c74d8",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xee2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x2187bb0b54e92e3bc6f0da1665631a818ac120ad68aa9674277d542f1e542f44",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3c",
+ "validatorIndex": "0x5",
+ "address": "0x96a1cabb97e1434a6e23e684dd4572e044c243ea",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3f45edc424499d0d4bbc0fd5837d1790cb41c08f0269273fdf66d682429c25cc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np382",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x2187bb0b54e92e3bc6f0da1665631a818ac120ad68aa9674277d542f1e542f44",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x04f641173e82bbe7455a3acd37242315859a80d9b4a19a56997645e31a1d1097",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xeec",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdd46cd98c3f0f31bf7b060263fa47e9b0aa1c4e4c7206af16ad3a01dac3bff5f",
+ "transactions": [
+ "0xf88382013208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08bc9a47ee84ed9389b94c57e8c7014515fefd3e891eff0e1deac8cb1266cfb05a06612fac81c3e0a0b905873bb3f9137f9f8ae952344a174e4d425564b31851350"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xcb8f5db9446c485eaae7edbc03e3afed72892fa7f11ad8eb7fa9dffbe3c220eb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np383",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdd46cd98c3f0f31bf7b060263fa47e9b0aa1c4e4c7206af16ad3a01dac3bff5f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2cc62d5cb6ca1b74dd31ced44a51655d15f0c67d9e8b4560584124ea91649145",
+ "receiptsRoot": "0x7288150e98b9056465e864af6976d5ec6de80da74cee77596b9a67de235177ac",
+ "logsBloom": "0x000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000040000000000008200000000000000000000000000000000000000000000000041000000000000000000000010000000800c0000000000000000400001000000000000001610000000080000200080000000000008000000001000000800000000000200000000008000000000000000000000000040000000002000000000080000000000000000000000000000000000000000000000000000000000000000000000000008000000000200000000040000800080",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x17f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xef6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x808dd663054b022868554929395cf380b27661a0ae7333a92d69160769afbbbe",
+ "transactions": [
+ "0xf87a8201330883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0f1dbbd841499d2a51db61a05cf4a7a5650fd83eafe8516d0ad49e99db40c0d13a0542104414214add483f5e7397e9b98e95d336d60ff2b661eabfc8125548df848"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3d151527b5ba165352a450bee69f0afc78cf2ea9645bb5d8f36fb04435f0b67c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np384",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x808dd663054b022868554929395cf380b27661a0ae7333a92d69160769afbbbe",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf88d2d5d961b54872a1475e17a9107724ba2cd0ca28cb7320aad2f903dc74deb",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x180",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xf00",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x86bca890ff8f5be8c986745f38ef4a87ce167fcaacc0de928f4c8db469bba94a",
+ "transactions": [
+ "0xf865820134088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0922834adc69ced79913745b4a53a63ff0b0d73552c658f63c35b74fe831f1990a072af738962b2108e1e3e534c88145aa55764f2908bdbce0a4433ef88e3fbfb0c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdd96b35b4ffabce80d377420a0b00b7fbf0eff6a910210155d22d9bd981be5d3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np385",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x86bca890ff8f5be8c986745f38ef4a87ce167fcaacc0de928f4c8db469bba94a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x248cbc35df3f48575474369a9105962a22bff30f3e973711545bb9cae1e06dff",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x181",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xf0a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x83132e862eb410579a38d85bbec7fdd5b890647bc9ccc2ad881361a9389cd3fa",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e8201350108825208943bcc2d6d48ffeade5ac5af3ee7acd7875082e50a0180c080a03931e5e7d02ed045834da39a409083c260fbc96dc256c1d927f1704147eeaeb6a0215269010bb3e7dd8f03d71db3e617985b447c2e0dd6fc0939c125db43039d0f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xace0c30b543d3f92f37eaac45d6f8730fb15fcaaaad4097ea42218abe57cb9f4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np386",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x83132e862eb410579a38d85bbec7fdd5b890647bc9ccc2ad881361a9389cd3fa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x899d1787e12b4ee7d5e497ac1b07d460146316edd86d589dd357e4e39e6e50a5",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x182",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xf14",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb2b948b9139c380319a045813000f17a02153426ae3db02065a7bc6fb1b3d41e",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3d",
+ "validatorIndex": "0x5",
+ "address": "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf6342dd31867c9bef6ffa06b6cf192db23d0891ed8fe610eb8d1aaa79726da01"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np387",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb2b948b9139c380319a045813000f17a02153426ae3db02065a7bc6fb1b3d41e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6fd59459f6805b1c3f35cd672f058d3f4215b8ba06217056195a249529106097",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x183",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xf1e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xec59612429465042cb5bfe00c2720e2b06608cc0befdf12185f61213dede36a3",
+ "transactions": [
+ "0xf88382013608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02f68ef0be353bceb12bd978567947ea2ade48f275f8488d4d9089a6a5df54ecaa01ea605cad7ded16c6744be5446342cef46c0f802938d30db72ee4e35eb0ee726"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa6589e823979c2c2ac55e034d547b0c63aa02109133575d9f159e8a7677f03cb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np388",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xec59612429465042cb5bfe00c2720e2b06608cc0befdf12185f61213dede36a3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x87aa8da72c4f54683d4ddfe7592b17518075332583bf40a0af34b072e1b8d5ca",
+ "receiptsRoot": "0x6b2a7f9df51def8b942a27f69021bd8954a4d01182bc78fe20171ec738d6a1cd",
+ "logsBloom": "0x00010000004000000000000000000000000000040000000020000000000000000000000100208000000000000004000000000000000000000000000000000000000000000000000020000000000002000000000000000000020000000000000048000000000000000000004810000000201000000000000000000000000000000000000000000008000000000000010000000000000000000000000080004000000000000000040000000000020000000000000010000000000000000000040000000080001000000400000000000000000000000000000000000000000000000000000000000000000000080000000000000020000200004000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x184",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xf28",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x18a50573c6144ce2d2c185b146827fbde1568f647d6bcc2c2556df64a00d3462",
+ "transactions": [
+ "0xf87a8201370883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a036602b451fdd27281014a28c261ac59feabe8c6730619162c51ccd6452e0efcfa01dbbc3cb987dd50dbb59072a156ce01b7825d252e5855249afbda11fd763436e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9ce48bc641cc1d54ffdb409aab7da1304d5ee08042596b3542ca9737bb2b79a8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np389",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x18a50573c6144ce2d2c185b146827fbde1568f647d6bcc2c2556df64a00d3462",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4970ca728c597509e3afb689227e843d5da3be74aea9719a756d65db2694b152",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x185",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xf32",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3ad7ba10baedb1b98556cd20670c57f2f3a4aa0ddfbf76c9a2cbbcec188dada5",
+ "transactions": [
+ "0xf865820138088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a09a9bf09cafb07d6a97b972a3b405a1dd30dcd6945d9adda6cf921c211bc046e1a03c97b3b08d67e3ccfcb8408e39d2e0971761c1905fbd7028fb52a1f163fb92f3"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa44be801bd978629775c00d70df6d70b76d0ba918595e81415a27d1e3d6fdee9"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np390",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3ad7ba10baedb1b98556cd20670c57f2f3a4aa0ddfbf76c9a2cbbcec188dada5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc5da7efe2ca6d0468002914ea2c334be08121fb5450b4a1b74baf08e65115192",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x186",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xf3c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa2deafade520007dd7d127c439290f2bac7a2027b80ff616ccf8ce62eeba6506",
+ "transactions": [
+ "0xf8688201390882520894f83af0ceb5f72a5725ffb7e5a6963647be7d884701808718e5bb3abd109fa0a38cf9766454bd02d4f06f5bd214f5fe9e53b7a299eda5c7523060704fcdb751a067c33351f6f7bbd9de5b5435f6cadc10ba5e94f3cbcc40ee53496c782f99d71f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xce17f1e7af9f7ea8a99b2780d87b15d8b80a68fb29ea52f962b00fecfc6634e0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np391",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa2deafade520007dd7d127c439290f2bac7a2027b80ff616ccf8ce62eeba6506",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7f1f4d793182771fbacb9ef07a0736edbe4aa2417bf775c7b499b35ad791575a",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x187",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xf46",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfce102ce6fa4701cfa7ca7c4aae937b79190e29b55a453e67f31adece99c4f92",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3e",
+ "validatorIndex": "0x5",
+ "address": "0xf997ed224012b1323eb2a6a0c0044a956c6b8070",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4bd91febab8df3770c957560e6185e8af59d2a42078756c525cd7769eb943894"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np392",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfce102ce6fa4701cfa7ca7c4aae937b79190e29b55a453e67f31adece99c4f92",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x58f87e8c7ffa26035df5258225c492a17f353b2d33420e0ac5b5413f0c29be1a",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x188",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xf50",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5aff5c82ef6756d97e6caaf6bc6084f4091ed2503b88083a0c4b0484f6e9525d",
+ "transactions": [
+ "0xf88382013a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e60cd99574bb50b626cf0b20d73ece21858aba52609136e6e2dc420a9fdc00eea00aeff0a4419c24268d9784a1ae211927004d8dbbbda3c47c0d0e2d32178ce8f4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x414c2a52de31de93a3c69531247b016ac578435243073acc516d4ea673c8dd80"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np393",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5aff5c82ef6756d97e6caaf6bc6084f4091ed2503b88083a0c4b0484f6e9525d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x14a7327b3cff203afe17f16aca0470fbe12cfac971c79ef9bd5b3ef71bce5591",
+ "receiptsRoot": "0x3b0559fd9e27f69f8a378d27e3b5a82f18881f307f49ec63f89ad4bae18a1ee6",
+ "logsBloom": "0x00001000800000000000400040000000000010002000000000004000000000000000000000000000000000000000000000000000000000040000000020000000000000000000000000000000000001800000000200000000000000000000000021000000000000000000000000000000000000000000000000002000000000020000000008000002000000000000000000000000000000000000000000080100000000000000000000000000000020000000000040000000000000000000000000000000000000000020000000000000000001000000000000000200000000000000000000004000000000000000000004000080000000020000001000a00008",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x189",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xf5a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb22e30af8a7f23e2b73275e505b5c6f482357576c82e3d718b0c4c33914d97e6",
+ "transactions": [
+ "0xf87a82013b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa061705b5163977bf95976fb0d2f44c1c581d19de8f68084001ed516813a7f5785a07daeb176a18749f11e1cec56a72e988c8362c2e15b86a9c5ae3e2cb2ddde0ce2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x647fb60bdf2683bd46b63d6884745782364a5522282ed1dc67d9e17c4aaab17d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np394",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb22e30af8a7f23e2b73275e505b5c6f482357576c82e3d718b0c4c33914d97e6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x02eb8f611a78bed4123c7b1ec6ca3148dee547538828183756744882a58b6993",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xf64",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9a348ddcb5d7c63d344358308acfd52c1be4432de1bdd02a4c1483521b95d7e0",
+ "transactions": [
+ "0xf86582013c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0463d74275ffee97deea0603bdab389823c88c03997f176d4c349514d78d4dbc4a06b9796eed221b40094ded3ec3fa9bdbf097561ac3f8a142fef5e2c894a8296de"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfa681ffd0b0dd6f6775e99a681241b86a3a24446bc8a69cdae915701243e3855"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np395",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9a348ddcb5d7c63d344358308acfd52c1be4432de1bdd02a4c1483521b95d7e0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe5d836ff1dc0a199a799bdb1aa945580acf9e06c96bd6b88cbc60903e5904b9c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xf6e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x584b00c97139674af12f17a4a4828e59951c7f7d0c4fae83d5711ce5e582fdca",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82013d010882520894469dacecdef1d68cb354c4a5c015df7cb6d655bf0180c001a06faf4090490862eba3c27dfe0a030a442ccc89d4478eca3ed09039386554f07ba0656f741b64c54808ac5a6956540d3f7aaec811bf4efa7239a0ca0c7fb410b4d6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x106ca692777b30cb2aa23ca59f5591514b28196ee8e9b06aa2b4deaea30d9ef6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np396",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x584b00c97139674af12f17a4a4828e59951c7f7d0c4fae83d5711ce5e582fdca",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8fc7b0893f25c43c0dd53f57c7f98653e86d2570923f1831840c09c7c728efab",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xf78",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8e2b4e77e4fd7ab14ffaca65bc3a0868f14ce792ffe5f26cc0cc4abf8ebc5cd4",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x3f",
+ "validatorIndex": "0x5",
+ "address": "0x6d09a879576c0d941bea7833fb2285051b10d511",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x494ac6d09377eb6a07ff759df61c2508e65e5671373d756c82e648bd9086d91a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np397",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8e2b4e77e4fd7ab14ffaca65bc3a0868f14ce792ffe5f26cc0cc4abf8ebc5cd4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb87cec8c84db91856e9ae32af116b449b8cb1d61cae190a182aebfb85d691e8f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xf82",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x657f16f62e12433129b4b3f80e92eee4a65d1cb6e8b847ce632d32cb79ba5abe",
+ "transactions": [
+ "0xf88382013e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0065cd2e05815fd9bf6e9aced9947d0c43feed03d4bd010ce93828c5e45a9b483a019449b8fc18e639f9c1d7b0adbd3941622d1f2e8127b82993e0f8bb9cdc2999f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0ae4ccd2bffa603714cc453bfd92f769dce6c9731c03ac3e2083f35388e6c795"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np398",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x657f16f62e12433129b4b3f80e92eee4a65d1cb6e8b847ce632d32cb79ba5abe",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe154fbe6ca3c192310dea977b202b7e57523be45dfb36cf46816f7b1b86c910b",
+ "receiptsRoot": "0x09e88b070a05aab53918792ba761837b32e299692e1ee33a27d3b654a45ea25f",
+ "logsBloom": "0x00000001000000000400000000001000000008120000000220000000000400000000008000000000000000002000000000000000000000000000000000000000020000008000000000000000000004000000000000000000000000000000000080000000000000000000000000010000000000000200000000000000004004000000000010000000000001000008000000000000000000000000000000000008000000100000000000000000000000000010000000000000000000000000001000000000000000000000000000000010200000000004000010040000100000000000000000000000000000000000000000000000000000000000020000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xf8c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x677cd475087726e83d09edba4d2e6cdcaa5f1b9f5e7c26260ff6ebf4dd86a6aa",
+ "transactions": [
+ "0xf87a82013f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a017bd3457b4b843b788bd719c6e49a5efad177ca349fa23ee93130c68a6c123a6a0595becbedbd04d964a7e8ca826f50061e1b1f16bea32c966670f7dbcc63dbbff"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd860c999490d9836cc00326207393c78445b7fb90b12aa1d3607e3662b3d32cd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np399",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x677cd475087726e83d09edba4d2e6cdcaa5f1b9f5e7c26260ff6ebf4dd86a6aa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x771db9f41d228f8d3e1a33889cc04468bb9691860cbdbf28203d90713eed1fb1",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x18f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xf96",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf60f85724891ffc25eb8c5c596e55846df4032b2edb35d0fc6ac64870db6b42f",
+ "transactions": [
+ "0xf865820140088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0db06597d4b08ca3fef9b08c69896cef6505785b448bfd0e051ebc7616a2f5a1aa07ca5051c69a0dcb5fae23ba89cb806d860072426d2e450eda056e9e9d8ee360c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9587384f876dfec24da857c0bcdb3ded17f3328f28a4d59aa35ca7c25c8102cf"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np400",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf60f85724891ffc25eb8c5c596e55846df4032b2edb35d0fc6ac64870db6b42f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd210aa806d0d5c95200a88fcc329357fb03782cc236bdc5f184c80246391162f",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x190",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xfa0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe7a757335322c1008ee83083154c9a787ea3d93efce41c1b32882c8a6ea3a14f",
+ "transactions": [
+ "0xf8688201410882520894f14d90dc2815f1fc7536fc66ca8f73562feeedd101808718e5bb3abd109fa04a18131d30b0344910cae7c41ee5c1c23171c40292d34e9a82c9c7cef3d3836aa0598a3835ad1903c3d7ad158c57ff0db10e12d8acbef318ddd0514f671a08ce94"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4df8093d29bc0ec4e2a82be427771e77a206566194734a73c23477e1a9e451f8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np401",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe7a757335322c1008ee83083154c9a787ea3d93efce41c1b32882c8a6ea3a14f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf77d84bb9077b7805492805f09aaeac8fdd72dadaba54464256d1b9633d7313d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x191",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xfaa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x32976c704b12fd1ec0e6a409b89c8d3d5d0802f676bfd1848ae07cbb612f0289",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x40",
+ "validatorIndex": "0x5",
+ "address": "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc56640f78acbd1da07701c365369766f09a19800ba70276f1f1d3cd1cf6e0686"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np402",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x32976c704b12fd1ec0e6a409b89c8d3d5d0802f676bfd1848ae07cbb612f0289",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c45d111367d1e2766e18c8ef100cb4cbdd1db4171d269d0dee91b7789bf302e",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x192",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xfb4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4cbab31c513775bdd5b7f91a153fff77cf1602430cedcebec80bedf0b6533658",
+ "transactions": [
+ "0xf88382014208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0bab2abc49f4f65119331667d5bd95daefb8eec437cb7950b46f1b9a890efd4b7a065396085f5f690d669006b05bab15614816e44cf88bf49fcdf0a5857f364e6a1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7173d4210aa525eece6b4b19b16bab23686ff9ac71bb9d16008bb114365e79f2"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np403",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4cbab31c513775bdd5b7f91a153fff77cf1602430cedcebec80bedf0b6533658",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xade6dd841f231dcce74ab564f55972731c7eb4a0b5c3ec1a64bb979f754b786c",
+ "receiptsRoot": "0x424252c901f76c684b72e2637c97666a35b4020fe9fd8add1bd00fc83cf57512",
+ "logsBloom": "0x08000000000000000010000000000010002000000000000000000000040000200000000000000000001000000000020000000000000000000000000000000400010000000000000000000000000000000000000000000000000000000000000020400000000008100000040000000000000014000000028000000000000001000008000000000000000000000000000100000000001000000000000000000000000000020000000000000000000000000000000000000000000000000000800000000000080000000000000000000000000000000000000080000000000000001000000200800002000000000000000040000000000000000000000400000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x193",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xfbe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x64bfcedbb6b431f370027c5e2414fa70536e4cadaedca69d960d815570b1a514",
+ "transactions": [
+ "0xf87a8201430883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0097f470d08b374cc1ea0e0ecfb841f22e6f105c4989a6a41f23619320011f4dba06c843174399416f4a98ee5b5170a4330fbc487cc1bdc4e67f8eb3ca279fa8415"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x89698b41d7ac70e767976a9f72ae6a46701456bc5ad8d146c248548409c90015"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np404",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x64bfcedbb6b431f370027c5e2414fa70536e4cadaedca69d960d815570b1a514",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x96e966680b69cd6f8f3c95b0bfcaa337959db055f2b4329813dd02f9e5350742",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x194",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xfc8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4a13ab52191afd567f4587bee39174c54ca458576730a03854abfad2aca2e0da",
+ "transactions": [
+ "0xf865820144088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a09fd0702bca1c10269dcf83862a9f07981858a8a1579f3ed68642fdc8b77478cda027b1f49755229583c844b747c040251c2671dcfe83fa26df37d4bbfb54635864"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5b605ab5048d9e4a51ca181ac3fa7001ef5d415cb20335b095c54a40c621dbff"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np405",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4a13ab52191afd567f4587bee39174c54ca458576730a03854abfad2aca2e0da",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7fa007461e28a3bd63c35eb625b4c122197ed1d63a00b0a0959652cb745c034d",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x195",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0xfd2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3c7adb6035b88d99e1113b076cd7ee852294e0f651e87e779f93b9625f50f173",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820145010882520894360671abc40afd33ae0091e87e589fc320bf9e3d0180c080a09b0a44741dc7e6cb0f88199ca38f15034fab4164d9055788834e8123b7264c87a02c38a3ecda52aebc3725c65ee1cd0461a8d706ddfc9ed27d156cf50b61ef5069"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9129a84b729e7f69a5522a7020db57e27bf8cbb6042e030106c0cbd185bf0ab8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np406",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3c7adb6035b88d99e1113b076cd7ee852294e0f651e87e779f93b9625f50f173",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3d03d9ffcd17834d8b99988eb8c1c9f36b8e627f50e2d850a6538d7610ba8457",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x196",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0xfdc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xda2511fe0f2d0c7384fdfaa42ba9d93127690645ed7f3bb5b48ab3bf31550561",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x41",
+ "validatorIndex": "0x5",
+ "address": "0x6510225e743d73828aa4f73a3133818490bd8820",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x31a63d6d54153ab35fc57068db205a3e68908be238658ca82d8bee9873f82159"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np407",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xda2511fe0f2d0c7384fdfaa42ba9d93127690645ed7f3bb5b48ab3bf31550561",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xeb5feebaa9bd10619704d66efc97f95338c3e02dcebc2710be462faa47ddfc63",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x197",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0xfe6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x32704763870e0504f0386bb2e87511ccb2d033c83e9ef57a72327f5d23fd3996",
+ "transactions": [
+ "0xf88382014608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e767d5dbf82d8857bccd947a04354b0023b0e283098f75e4d7d79348c24dca95a00a4d04094359f0817637570cf1ed12dcd2614da2e845751734d67175839a3903"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x828641bcea1bc6ee1329bc39dca0afddc11e6867f3da13d4bb5170c54158860d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np408",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x32704763870e0504f0386bb2e87511ccb2d033c83e9ef57a72327f5d23fd3996",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xaadc011ce89c8dd628f56494b7f19d8cf66c1555b3cb6b38fd6e31c908e83804",
+ "receiptsRoot": "0x0c78f3779ab455eed4ce5e60071fff80a3d289a33fd656e17017d53978fada5d",
+ "logsBloom": "0x00000000000000020000000040000000000080010000000000000000000000010000000000000000000000000000000000000000000000000000000004000000000000000000000000000001000000000000008001000000000000000000000000000000000000001000000000002000000000000000000000000000002000000000000000000000000000000810001000000004000000000000000000000000000000000040008000200000000000400000000000000000000800000000001000000000000000000000040100000000000000001000000000000000108000000000000000020000800000002000000100000000000000002000000000004000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x198",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0xff0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x16f96f705d6378a460f67690c9df7ba0b0130dfb7bda8d79ac2ffe9fdee84606",
+ "transactions": [
+ "0xf87a8201470883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a00eab4059563c228f12cd79cdc77c5594af5bb5f9778dab439aead79a99c7da9aa010476536728e9bf977ad4c2cc25fb7d5587869148789e9fd6bf40d65b9e94bbb"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7e0752ddd86339f512ec1b647d3bf4b9b50c45e309ab9e70911da7716454b053"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np409",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x16f96f705d6378a460f67690c9df7ba0b0130dfb7bda8d79ac2ffe9fdee84606",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0ed00985c27ccb9453093f70f7cae8594259e64c8962ee22121019210fe01824",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x199",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0xffa",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x70c71163387d8226f299ed02fd7f266f79d708f11ea9133d28a6b13ee751e259",
+ "transactions": [
+ "0xf865820148088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0310416be8b0e49ec34116f9c8eb4dd4d4dc6e39e5c97ccb94ac96e8cd21a7333a029b7a950def860ab8bfd4e49e5f34bc731344ab60770ea27f656e64e6b2f90de"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x31d973051189456d5998e05b500da6552138644f8cdbe4ec63f96f21173cb6a1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np410",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x70c71163387d8226f299ed02fd7f266f79d708f11ea9133d28a6b13ee751e259",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7ff6b18a2c62836e16cad9956e08422a430c268cda51f219422b628491066c6e",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19a",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1004",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x67c274a189945d313dccd5b9cb4b7fd47614b59c716a4ed0944d8a1429781e78",
+ "transactions": [
+ "0xf8688201490882520894579ab019e6b461188300c7fb202448d34669e5ff01808718e5bb3abd10a0a0de600e017080351550412ac87f184ec2c3f672e08f1c362ab58b94631e8864dca047d41b8691a1f7f8818e59ad473451a0edfc88826a6b808f84f56baed90d5634"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe33e65b3d29c3b55b2d7b584c5d0540eb5c00c9f157287863b0b619339c302f0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np411",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x67c274a189945d313dccd5b9cb4b7fd47614b59c716a4ed0944d8a1429781e78",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x95d1e2783fcf975ce0a79a05166ad33628065812d76f1f92f88d8f77f5a49e88",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19b",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x100e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x7ae0486d0457d3261e308c1074c7a206e11f3a41a8b3b49ff379d0998a62278c",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x42",
+ "validatorIndex": "0x5",
+ "address": "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x78d55514bcef24b40c7eb0fbe55f922d4468c194f313898f28ba85d8534df82c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np412",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7ae0486d0457d3261e308c1074c7a206e11f3a41a8b3b49ff379d0998a62278c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa1e185a2970fcd9903cadff06453ace3bff731a5295334d332c3fafd1d50033a",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19c",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1018",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb075a9e715b341d481dfad3f02ff0a123aa8043d4ae24d5f0574a7249cc00bcf",
+ "transactions": [
+ "0xf88382014a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06222a14090e09278dc92b9002ee33b54e5bbbecd9afe56fa18d00dfe761ce8a1a06e8ec220dc8219ae16f46f3a4696fc8b4046fd33fa41efb473222fc058d65ed4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2e0f4be4d8adf8690fd64deddbc543f35c5b4f3c3a27b10a77b1fdb8d590f1ee"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np413",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb075a9e715b341d481dfad3f02ff0a123aa8043d4ae24d5f0574a7249cc00bcf",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x19a70ab3d8102a74b87887d95a29fe82ce4d4ab36fe3f57f336ded8bd0a7b3d6",
+ "receiptsRoot": "0x2ac314ac40ad6f04e3ec1fc2b315d4ce6eb64537ae9bf3fad670a0a1df1e5e3a",
+ "logsBloom": "0x00000001008000000040000000000000000000000000000000000000000002000000000000000000000000200000000000001000000000002000000000000000001008000000002000000000000000000000000000000000000000000000000000000080000000000000008000080000002100000000000000000200000000000100000000000002040000000000000000000000000000000000200003000000000000004000000000000000000000020000000000000000000000000000000000040000000002000000002200000000000000000000000000000001000000004000000000000000000000000000000200000000100000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19d",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1022",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x936ce32cab37d0a985a937a8d3c7191ec7f48a10d524d04289d59efa4ca4e581",
+ "transactions": [
+ "0xf87a82014b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a07af33005afb5f1b38c17ed2bb2b83a0c1d0d6ecd30ab4e32091582d5a3eceb28a008bfc076226d8ebf0a2c86c5ea5f65ea1f1d0cb7b7036b2049444c2fcfb55031"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe1b83ea8c4329f421296387826c89100d82bdc2263ffd8eb9368806a55d9b83b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np414",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x936ce32cab37d0a985a937a8d3c7191ec7f48a10d524d04289d59efa4ca4e581",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0e4a2aebaaa31e943227335fd579582b6ed68abaa2706294b038ccb00ceae64f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19e",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x102c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd352dfead0be49f8a1f2f7954f90df4b3e4383f8adb54062abd8041b0a0878fd",
+ "transactions": [
+ "0xf86582014c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa05e26cfc612b47c55ae5a521eca26d4adbeaefe893bf1b0226cd121cbd7cdb45aa00be4c1040e89e1db4b10b4f36b38ef682de4f3308fd65d4f39346ffcf016cfdb"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4ddad36d7262dd9201c5bdd58523f4724e3b740fddbed2185e32687fecacdf6b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np415",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd352dfead0be49f8a1f2f7954f90df4b3e4383f8adb54062abd8041b0a0878fd",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc149cc44783e5dc5c6be9d4facfc2e9d3d31dff27f8495ea3fc2acfc22310516",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x19f",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1036",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xddf15ae692657c7be84b2e663acd7d669dc84a83622c9bbca07aba3a8461d8a6",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82014d01088252089488654f0e7be1751967bba901ed70257a3cb799400180c001a0a79b0ff9846673061d1b90a17cd8bd9e7c7f62b99b39fbe4749777d3ed4544e0a0750ecfe9895402861ebea87e9b483b2c116bc2d4920329aa1c29efb9dcdf47e6"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x156c0674e46cdec70505443c5269d42c7bb14ee6c00f86a23962f08906cbb846"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np416",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xddf15ae692657c7be84b2e663acd7d669dc84a83622c9bbca07aba3a8461d8a6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x39d41e6a842119b876ef50fcce4e677b2760950f191f0b17ac11bb61f5d271b0",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1040",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5647e4a4349ab2ed23ddc1f61244c94f194735701ad4041ea62bc578654fecdb",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x43",
+ "validatorIndex": "0x5",
+ "address": "0xa179dbdd51c56d0988551f92535797bcf47ca0e7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdfc56ec6c218a08b471d757e0e7de8dddec9e82f401cb7d77df1f2a9ca54c607"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np417",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5647e4a4349ab2ed23ddc1f61244c94f194735701ad4041ea62bc578654fecdb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6f8f7979fade5692d7fd5e0f6253e0e3082614421af4bcfbd63c12f2df06876f",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x104a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb50098d59b2351e10448f5560aff3f933bb24fed7101cda025bcdd5308fb4631",
+ "transactions": [
+ "0xf88382014e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0fea6631902fceb5662ca53076387bbbb0e0fd9bcac1df121172fd29bd6700434a0632755563256841b198d853ee1861224df35abe91c6d15ca60cb3f660ce05e2d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x395d660f77c4360705cdc0be895907ec183097f749fac18b6eaa0245c1009074"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np418",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb50098d59b2351e10448f5560aff3f933bb24fed7101cda025bcdd5308fb4631",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x26b3aa514e4bfed98a760b1cc6d5c7c855232ecac4f00826049369385376458b",
+ "receiptsRoot": "0xa3ea729352d4252acd6b48dcc940d3acfe0d657ca5d3091eda1ae882c7c14776",
+ "logsBloom": "0x00000080200000000000000000030000000000000000000008000000000000002000000400000400000000000080802000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000800000000000002000000080000000000000000000000000010000000800000000000000000000000000000200000000000000000080000000000000001000000000000000000000004000080000100100000000000000000200000000000040040000000000000000000040000000000100010080000000000000000000000000010000000000000000000000000000000000000000000000000040000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1054",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd87426372101b44c6fb40defa47f5e64ced815cf6bcbe830367d328e52fa3bd5",
+ "transactions": [
+ "0xf87a82014f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa08ded8700920cf761c49ef0831076f10597be8fe624b891585941b1a1d145a18fa05640b1e1c59257bc6b6352be6bb6a7862a541b3fca52da28912b08b8072b57e5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x84c0060087da2c95dbd517d0f2dd4dfba70691a5952fe4048c310e88e9c06e4f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np419",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd87426372101b44c6fb40defa47f5e64ced815cf6bcbe830367d328e52fa3bd5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x730477c9b8be2e32598ff45ddf03837963e5d2fcd5c8c07d23b47b385c22d4b7",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x105e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xac9d6592b309e9e3ec0d899eda9ccd7d508e846553ac4a87da8b420c99173211",
+ "transactions": [
+ "0xf865820150088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0bb5b1c9e4a9e86b6381ce83f476e3efb45b847315ec3e27e1536539ba2290f42a07eee4b7b9b0d0dc1b873baf519a668f4605ccbb82ad619acb74598535a35bdd1"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf4df943c52b1d5fb9c1f73294ca743577d83914ec26d6e339b272cdeb62de586"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np420",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xac9d6592b309e9e3ec0d899eda9ccd7d508e846553ac4a87da8b420c99173211",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xef5088187720800d3dec63e4e25560c839cad852b7a795fd9e9876ee2a02b16a",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1068",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x834b28c2883caaa276a3a0f2603da1bb8171001967787b96071588f296b7671b",
+ "transactions": [
+ "0xf868820151088252089447e642c9a2f80499964cfda089e0b1f52ed0f57d01808718e5bb3abd109fa0c37c23a91d6abced211855a2d6d5e383f54aa6ff40c26abc5f27a22cdafa5618a0190f82ff101eabad8b9c7041006dcb3e3a9a85c814938bef8ec7d1aa63fa5892"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0bb47661741695863ef89d5c2b56666772f871be1cc1dccf695bd357e4bb26d6"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np421",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x834b28c2883caaa276a3a0f2603da1bb8171001967787b96071588f296b7671b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8fa327b5c3e6a5036585a3b751910d613c3d2b6b56b0a5c1da7727ce50d4cb57",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1072",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1232a401598e285a5e94aaa0644787458ac9e410b4b50cbc103523f2d2d4c198",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x44",
+ "validatorIndex": "0x5",
+ "address": "0x494d799e953876ac6022c3f7da5e0f3c04b549be",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4a1f7691f29900287c6931545884881143ecae44cb26fdd644892844fde65dac"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np422",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1232a401598e285a5e94aaa0644787458ac9e410b4b50cbc103523f2d2d4c198",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa5eef4d5746f0409111e198bb292fd06bf9ac9a14dc734ca636005246e713e5c",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x107c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x271fd072d8e81da656b1f06548d486ce23f9fd399e070d3a01a3bd28c2d4eb7c",
+ "transactions": [
+ "0xf88382015208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0435a46c3720f21ff83b01b3d6e88f602e45dee024e69f7df083e47ee400fa063a020b2e545bea301a0322157c61d6f8bdee62066305c627c1c10fb9eb1fbdf0fed"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9b133cc50cbc46d55ce2910eebaf8a09ab6d4e606062c94aac906da1646bc33f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np423",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x271fd072d8e81da656b1f06548d486ce23f9fd399e070d3a01a3bd28c2d4eb7c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5486d8d4c4159eb6389774b47a76d5e347e3b31ecf92c08eda9e261e3106f0cc",
+ "receiptsRoot": "0xc0c07d0984b850e6ccc2e081d26ec135c42d526e9bb51a6c1987784d659c07d5",
+ "logsBloom": "0x00000000000000000000000000000200000000000020000000400000000000000000000000000000000000100000000000000000000400000000000000200010000000000a00000008000000000200000000000000000200000000000000000000000000000000000000000000000001000000000000000000000000000000000000000806000000000000000048000000000000002000000040000500001000000002000000000000000000000000000000000000000000000000000000000000000000000000000000800000000800002008000000000000000000000000000000020000100010000000000000000000000000000000000000000010000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1086",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x966f75efe4cd3d4171d4dd7dbe65453d3fae561f5af4d67142cc15ad53dae212",
+ "transactions": [
+ "0xf87a8201530883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a015ae0fac40a467ff5ad10fe01c838c564f0d30707c8b02be656345842959fedda07a3d9842f721d8cb4494a2df6ff689c4c19e44c8c81f013d1f969624d49850b2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x473b076b542da72798f9de31c282cb1dcd76cba2a22adc7391670ffdbc910766"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np424",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x966f75efe4cd3d4171d4dd7dbe65453d3fae561f5af4d67142cc15ad53dae212",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa9339a9c149937412b8c9d01a85c7af270578af9eebb80ad2cf208764c40e608",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1090",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x92a740edd1bceefb2f497e906a5f53bc10928c909069ba76b34663dabfc01f91",
+ "transactions": [
+ "0xf865820154088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0c14791fa1c6907f6279226a31c5f287c93702ba72f19fb9999b93b8ad612b36fa0371a0819796295976ab02fcafbe818a711cf6485a21d038dcb72b5000f04d63d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x225dd472ef6b36a51de5c322a31a9f71c80f0f350432884526d9844bb2e676d3"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np425",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x92a740edd1bceefb2f497e906a5f53bc10928c909069ba76b34663dabfc01f91",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xac3cc175fd0ba02252342155b4d9dd7fb790eb49b667058912b43f5bd6e939d5",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1a9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x109a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5a7a3b8f0d389c13d810588336964f1a94b29184e3d9bc751eb64ef4635ad0f5",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820155010882520894d854d6dd2b74dc45c9b883677584c3ac7854e01a0180c080a07a17de801de3309b57dd86df30b61553d5c04071581d243f33f43c4d64930e09a075f7e820212e8f96d7583c66548719db621537fe20f7568d5ee62176881b70e8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x31df97b2c9fc65b5520b89540a42050212e487f46fac67685868f1c3e652a9aa"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np426",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5a7a3b8f0d389c13d810588336964f1a94b29184e3d9bc751eb64ef4635ad0f5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe677d652ba3a8822155791a1d1491ee57497ebfa49e3e38c909752dd8067a9e8",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1aa",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x10a4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf963480776054d809830c23d97833cfbf2971fc0fa04a6fe4974ea25a761f8c9",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x45",
+ "validatorIndex": "0x5",
+ "address": "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4416d885f34ad479409bb9e05e8846456a9be7e74655b9a4d7568a8d710aa06a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np427",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf963480776054d809830c23d97833cfbf2971fc0fa04a6fe4974ea25a761f8c9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x08414161950ff53f6f053f2886c473a22eb595a0052de01fd24c7af1bc27a5ac",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ab",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x10ae",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe8c8baed11565acb9d54e46ed79327292e07686ada5cd14fb02558ac39c518ec",
+ "transactions": [
+ "0xf88382015608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02f6b9a47dcc55d9130085e0dfd615fee0acea46517280eea07dff8ee6afd40e3a01fc33c02a467db6d30ccf56ad8b5bb32fd49ad9a7866db580e7a581987518921"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xae627f8802a46c1357fa42a8290fd1366ea21b8ccec1cc624e42022647c53802"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np428",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe8c8baed11565acb9d54e46ed79327292e07686ada5cd14fb02558ac39c518ec",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5afe7e66edc543cc377a33069ba58d5788801f1ef0f370d69ff71db5f63b6b88",
+ "receiptsRoot": "0xb278e6670351b21cd1c267f24972d7868327ae82ef7a3b377af968b4c6659925",
+ "logsBloom": "0xc0000000000000000020000000000000000000001000000001000000000020000000000000000004000008000000000000000000000000000000000000000000000000001000000000000000800010000000000000000001000000000000000000000000008000000000000000000201000001800000000000000000000000000000000001000840080000000000040000100000000000000000000000000000000000000000000000000000000800000000000000000000000000020000000000002000000000000000000000000040000000000000001000000400000000010000000000000000008000000000000000000000000000100000020000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ac",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x10b8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xedf9debf0ac1be313a1f9e6f0121d36c284e2c7962acac1fa5c8aae207c07b34",
+ "transactions": [
+ "0xf87a8201570883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06cbb3f84663bf7369864941fe566b1beb8d5db0095cbd49ebfdee89c164031e6a0461b62f4b01d15206e95e6c7bfe9364456d8b7edd446d1b488a2688c47b83775"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8961e8b83d91487fc32b3d6af26b1d5e7b4010dd8d028fe165187cdfb04e151c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np429",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xedf9debf0ac1be313a1f9e6f0121d36c284e2c7962acac1fa5c8aae207c07b34",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf1c25b007a4c84577aa49389214e8b8b63f81cb20b61095db784cd8e781fbdcc",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ad",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x10c2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x94a14e5fafedb96bffc4624affb9a20762f447e5abb90865c4418a539743932e",
+ "transactions": [
+ "0xf865820158088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0a285aa615fe480c778997ca57059b8ddec5cee0e5a94ec05cd028a03d04aadaba07549f0c6ded9fe03eb40b413803b8f02d9dc51591e29977d12a204518648008e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc22e39f021605c6f3d967aef37f0bf40b09d776bac3edb4264d0dc07389b9845"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np430",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x94a14e5fafedb96bffc4624affb9a20762f447e5abb90865c4418a539743932e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x401f1feec84dc7c894bb9f03dd52b5af121262ab2f6bd29e6de4e96c1ed67870",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ae",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x10cc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x855b2ccb1c00d717f49ec7074cee1f781edfc072eeef44012e18613a9172fc9d",
+ "transactions": [
+ "0xf8688201590882520894c305dd6cfc073cfe5e194fc817536c419410a27d01808718e5bb3abd109fa0163f29bc7be2e8fe3c6347fe4de06fa7330e3a3049c0e9dcded1795ff1c1e810a04ea7492a5e457fd21252166f5a5d5d9d5e5c7a19da2c7fd4a822bf60156b91a9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x7cfa4c7066c690c12b9e8727551bef5fe05b750ac6637a5af632fce4ceb4e2ce"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np431",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x855b2ccb1c00d717f49ec7074cee1f781edfc072eeef44012e18613a9172fc9d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc97f5e63e102992e2a849afad97481ea818d213707de515acd9c2bc246cdf65f",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1af",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x10d6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4155e12dee1bb9ed17527871568425b8eb672004a2e2c19cb1947004fc5f0b0e",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x46",
+ "validatorIndex": "0x5",
+ "address": "0x368b766f1e4d7bf437d2a709577a5210a99002b6",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x943d79e4329b86f8e53e8058961955f2b0a205fc3edeea2aae54ba0c22b40c31"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np432",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4155e12dee1bb9ed17527871568425b8eb672004a2e2c19cb1947004fc5f0b0e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9c177f669a297c904a6a6ad51765a5916a0e0a3d9858b289e70bf054b370d685",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x10e0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd660a48f06384f7ee4402d24193c76d2f4a00b85ca53ae9883b4ee3c07260586",
+ "transactions": [
+ "0xf88382015a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa078d6fdbc4224106e1f59483aff597485ed0eebf922317913522a0693727b5ee8a035876b3170b9a88dc391f83dcac8088aeb65233613c74d8f50f1d1d3b1ce842f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x66598070dab784e48a153bf9c6c3e57d8ca92bed6592f0b9e9abe308a17aedf0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np433",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd660a48f06384f7ee4402d24193c76d2f4a00b85ca53ae9883b4ee3c07260586",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x98d101f68f7aa5bb170cfdd60281d7a5c3ae335ab03c0f87bdb5e72cc022d55f",
+ "receiptsRoot": "0x1919995eb19582a49f7b79b55e7ec75fae399916006f29e4177543d99cc2a5e3",
+ "logsBloom": "0x00000000000040000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000080000040004000001000000008000000000000000000000000000000000000000000000000000000000800000000000000080000001000000000000080000000000400020000400000000000000000000000000000000000000000000001000000000000000000000000000000000000000000012000400000000000002000000000000000200000000100000000000000000000000000000000000000000000000000000000004004000000000000002000000000000002010000004000014000000000000080810000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x10ea",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x73404b62b42dbc6a6604152b87426e852cc3b34847f45f27c0fca1f3a619f84a",
+ "transactions": [
+ "0xf87a82015b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09fb0d3ddf1fce9562d227b3cd6c35ac2e89f39141823d94cda0e6efb4519c715a06925af0950104623efa7954872196fe6d539eb269263a17db3740652382d100f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xac8fe4eb91577288510a9bdae0d5a8c40b8225172379cd70988465d8b98cfa70"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np434",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x73404b62b42dbc6a6604152b87426e852cc3b34847f45f27c0fca1f3a619f84a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7d06044c1009a2320b83bdfe22ffe7b8ffa6fa1f65d5e42f7c1588417a8ff421",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x10f4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x9832bc48443f86a5809f75ad91caa04101363a43b300cef39918deaae8594e08",
+ "transactions": [
+ "0xf86582015c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0aa24c6fb2c99f1ce21f7ffd84e87fb6f81ff76cebe06fb5c0871294a353210dfa0350602877ed48896e8b4124b35c0c47da66c17fc0d553d9248ca1de942114306"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2b0018a8548e5ce2a6b6b879f56e3236cc69d2efff80f48add54efd53681dfce"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np435",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x9832bc48443f86a5809f75ad91caa04101363a43b300cef39918deaae8594e08",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x03d23380eb6a02b52fcfeb82c0fefd180c014e72a7f48f2627237e7bda6d5610",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x10fe",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe5e23a0fd4a2515c0e1292823b094a1aeec3ed64db400675b591fc077bf34c3f",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82015d0108825208942143e52a9d8ad4c55c8fdda755f4889e3e3e77210180c001a0673c5473955d0d26d49b25b82af905ee33ba365178f44dc4ac39221efec23c88a017f46fc9b15ba0c1ea78d4d9f773582d94f61f6471f2918cb0598f33eb9bc89b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x823445936237e14452e253a6692290c1be2e1be529ddbeecc35c9f54f7ea9887"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np436",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe5e23a0fd4a2515c0e1292823b094a1aeec3ed64db400675b591fc077bf34c3f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf8829f712e0ea692e266ae3c78400816c5f5bc1d75a3bff3816f7fef71b2044c",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1108",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x6e26197c94723ba471d049f6082abd0a6e684225b2ee9d8fa675b18ef11492c1",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x47",
+ "validatorIndex": "0x5",
+ "address": "0x5123198d8a827fe0c788c409e7d2068afde64339",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x3051a0d0701d233836b2c802060d6ee629816c856a25a62dc73bb2f2fc93b918"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np437",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6e26197c94723ba471d049f6082abd0a6e684225b2ee9d8fa675b18ef11492c1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc66ecc1bdb4fa4b85c0b383d4db20fdaa2cba32973260dc444abb43e8536e93a",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1112",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb5f0ca3b4503c50b8eab9c63a95b209426af616a5b0d8468e63246c3f590caac",
+ "transactions": [
+ "0xf88382015e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0179370023b242bccf25d4899c2f29936353b5f1c37a8f7c665e55b75f80bf297a018a66d1d2ef7072f7fc54af07d15edc14ecf5a71f510be740c090f0815178ff2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x44a50fda08d2f7ca96034186475a285a8a570f42891f72d256a52849cb188c85"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np438",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb5f0ca3b4503c50b8eab9c63a95b209426af616a5b0d8468e63246c3f590caac",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa9b50e298c6a4bbd23a659ab24a3a7426b1087497561c39de2f1bf27da019b83",
+ "receiptsRoot": "0x8f45041560ebf83ec428723c6d69db271346e4c5a1b234b56efe318d549187cb",
+ "logsBloom": "0x00000000000400400000000000041000000000000004000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000202000000000000000000000000000080000000000000000000000010000000040000000004000004800000000000000400000000020000400000000000000000008000020400000000000000000000000000000000000000000000000000000000000000000000000000000000000800002000000001000000000000800002000000100000000000000000000000000000000004000009000000000008000000080000000000000000000000000000000900",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x111c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfe8e1ceca43818cb8f2e4fc94ead6cea53a8fd515af2bc67a39a15584ec3cd86",
+ "transactions": [
+ "0xf87a82015f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0354b9d4a470abdae9da30183321b96b5fd09bc96c1ebd3137b3c6350c21e8de2a026877262b14edc851e17cba052b022dd1038fd51ef65ecbaff09dd07186f035a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6e60069a12990ef960c0ac825fd0d9eb44aec9eb419d0df0c25d7a1d16c282e7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np439",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfe8e1ceca43818cb8f2e4fc94ead6cea53a8fd515af2bc67a39a15584ec3cd86",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xad6a72de336a98aec47ed431bf7d39d537741125313255629633cba91b0097bd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1126",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfd02d6b4d954d36af8829bf98464c0cc410de1e28216e45ac5e90fc1fc5780d3",
+ "transactions": [
+ "0xf865820160088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa09c6b3542e181028aad33517584cd16e92836f975955abdcbf1205b6250c921d4a040816d88e011c2d3073502523867b94987fa0781793a7857ff2453ec2d121444"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x581ddf7753c91af00c894f8d5ab22b4733cfeb4e75c763725ebf46fb889fa76a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np440",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfd02d6b4d954d36af8829bf98464c0cc410de1e28216e45ac5e90fc1fc5780d3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x863de67ea016127a436ee6670f8642bd5ab997ce75361c3cce667abbe90b7283",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1130",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe0c31051877e8d3f6f625498659eff12247ded622d4155f6fd4a498852e46192",
+ "transactions": [
+ "0xf86882016108825208940fe037febcc3adf9185b4e2ad4ea43c125f0504901808718e5bb3abd10a0a0654dc39f93a879b9aec58ace2fdbd5c47e383cae2d14f1a49f6ec93d539be892a070505a0ef2e83f057e9844dbd56eda0949197f0c4a2b6d0f2979db1710fca4ed"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9a1dfba8b68440fcc9e89b86e2e290367c5e5fb0833b34612d1f4cfc53189526"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np441",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe0c31051877e8d3f6f625498659eff12247ded622d4155f6fd4a498852e46192",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x66989995258d8db8bd3b8eac83c7762c50323b8f21f1aaddf3ad0208afc6318d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1b9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x113a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe9da2b3df6fbc520bf3a80b36bd3437210880763ea7acbf422076049724a14ac",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x48",
+ "validatorIndex": "0x5",
+ "address": "0xd39b94587711196640659ec81855bcf397e419ff",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x54a623060b74d56f3c0d6793e40a9269c56f90bcd19898855113e5f9e42abc2d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np442",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe9da2b3df6fbc520bf3a80b36bd3437210880763ea7acbf422076049724a14ac",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf37b2d059d8764938039410fc2581f4793fb4f9c66abf4f8a32276dd60334f4d",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ba",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1144",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xeafce24dfb100daa2a1ee55da0030d8e057fc943b96b6e7f321af98b47e8107e",
+ "transactions": [
+ "0xf88382016208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bf7859d7e53ab582f4189f50f06832f2fa9763498350b739d7a677b34df97861a03ab21050f73bda7c737cef08e6a77edc9766aa0ef14dfdfc22fbcfdb6771825e"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1cfeb8cd5d56e1d202b4ec2851f22e99d6ad89af8a4e001eb014b724d2d64924"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np443",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xeafce24dfb100daa2a1ee55da0030d8e057fc943b96b6e7f321af98b47e8107e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x23eacf2b963df64726e41314251669bf12f3925de3933e0b713863d1a7a6fc6b",
+ "receiptsRoot": "0xc97de406788b669a824183dab763b8caa8988371aea1f18b96e6b1f9abdee729",
+ "logsBloom": "0x04000000200100000000002000000204000000000000000000000000000008000800000000000000000000000000000001000080000000400000000000000000000000000000000000000000000000000000400000100000000000004000040000000000000000001000000000000000080000000000000000200000000000000000000000000000000000008000000000000000000000000000040000000000000000040100000000000000000000000000000000010000080000000000000000001000002000000000000400000100000000000004000040020000000000000000000000000000000000000000000010000010000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1bb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x114e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa53dc7dc3ac37fdd69bedd119e5113397594ab4171b7c010913864890dbd7f96",
+ "transactions": [
+ "0xf87a8201630883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0332397d6a00a7d2a3453bf053c8d158774d82d6ea252c2d564bbd48f9e882418a01187aef824b2759cba8c1574666919b77889353a9905720170518b03b38cc71d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xad223cbf591f71ffd29e2f1c676428643313e3a8e8a7d0b0e623181b3047be92"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np444",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa53dc7dc3ac37fdd69bedd119e5113397594ab4171b7c010913864890dbd7f96",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x71e7debe9374beede2414966d6eb2c2eadf548c293ba65821869bc274709badb",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1bc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1158",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x48640726ce7b39f951f82d46cfd4f8d71c93534109a0f93810c41289f6c97d2e",
+ "transactions": [
+ "0xf865820164088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0b7296876d0713a392d440d71244cda1a3ecb09009a2f4d0ae5d26a398a8bee92a04dd844c3b7cbf88f10b080a3a0fd8a0e21e8d3041450c69786efe9ee7af18dcc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe13f31f026d42cad54958ad2941f133d8bd85ee159f364a633a79472f7843b67"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np445",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x48640726ce7b39f951f82d46cfd4f8d71c93534109a0f93810c41289f6c97d2e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x58a574089cbd9986bf63c3ee8e0e8d400e9b97b8d1280166f7505de051f4c661",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1bd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1162",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x40fa37188938bd349b17c8738f79a071533e0c0f6eaf4b1d6d6614fcae9925d6",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820165010882520894046dc70a4eba21473beb6d9460d880b8cfd666130180c080a09a954eff1b0e590a3a78b724b687c6ab944181990998780d56cc3593c704996ea0418db96b5dc1057f6acb018244f82ed6ece03d88c07f6ae767eaebe3b7ac9387"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb45099ae3bbe17f4417d7d42951bd4425bce65f1db69a354a64fead61b56306d"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np446",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x40fa37188938bd349b17c8738f79a071533e0c0f6eaf4b1d6d6614fcae9925d6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbd0820c57ebb5be91343940d7197af10c1d95a23a1b99bc5fa1a77997849273c",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1be",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x116c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xeebf24886684542e08624e438bfad2c52eded1a4924aef3fd58d60ed6eaa1d19",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x49",
+ "validatorIndex": "0x5",
+ "address": "0x6ca60a92cbf88c7f527978dc183a22e774755551",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9d2b65379c5561a607df4dae8b36eca78818acec4455eb47cfa437a0b1941707"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np447",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xeebf24886684542e08624e438bfad2c52eded1a4924aef3fd58d60ed6eaa1d19",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbc2acbe23d81c5bec8c73c20cfbb12be681cc92fa399ed4a44e7a91fb433c577",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1bf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1176",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x837fc89a9611fa0b6a0d2f5a7dec3e06eda2ea3ee84bc6ce214c432b243c256f",
+ "transactions": [
+ "0xf88382016608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0daffe9dd6ca6d33e1a44ce5725c7e795639c4bd4a36cfb18d520c9fc892b7ca5a01286dcff57cb583238854ca89346c969387d982ca7e14cbd82413855fdda282a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5855b3546d3becda6d5dd78c6440f879340a5734a18b06340576a3ce6a48d9a0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np448",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x837fc89a9611fa0b6a0d2f5a7dec3e06eda2ea3ee84bc6ce214c432b243c256f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x95fea999be7fc8cfa0e1c8a9a10dc33d073417bf87ff698edab332c6e18ecc60",
+ "receiptsRoot": "0xcf29f818a1be0922fc0576d2500603f4e9ab8a9e251986d891170f993f0c8f0a",
+ "logsBloom": "0x00000000000000000000000004010001000020000000000000040000000000000000000000000000000000000001000000000080001000000000000000000400000000000800000000000000000000000000400004000000000000008000000000000000000000000000000000000000000010000000000000000040000008000000000000000000000000000000000020000004020000000000000000000002000208200000000000080000000000000000000000000000000080000020000000000001200000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000010018000100000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1180",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x05505959a8095b30ab40f55294926448248b48b0430ce33332c7b748e956aafa",
+ "transactions": [
+ "0xf87a8201670883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0745918999757459ef7ab7145b734444d0437fa7b3939a6ca2a07652a727d1ef9a0074b0898accddb3ac54941b1fce130c31edd3d838dfefd506668cd989f4c5389"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xd6a61c76ae029bb5bca86d68422c55e8241d9fd9b616556b375c91fb7224b79e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np449",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x05505959a8095b30ab40f55294926448248b48b0430ce33332c7b748e956aafa",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa4269875f0bd6dc1360830e3e07eae0956700e8c3aa69cd61b423abf51bfce54",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x118a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x57095cf08428bbd1fff32a14f1a811750ff2de206ee3ea1d6f6f18f7a2606d30",
+ "transactions": [
+ "0xf865820168088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa01f0e57c3b6f3908a7afb46717ef32caf9b73c4a4b2f48b09e0fcbea02ae716e1a017c79cab83300efab682d0c0438b23b49136a17e22560e75d32014c5951b4fd4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x96ac5006561083735919ae3cc8d0762a9cba2bdefd4a73b8e69f447f689fba31"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np450",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x57095cf08428bbd1fff32a14f1a811750ff2de206ee3ea1d6f6f18f7a2606d30",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd315f1048882fde9bc00a0bae351ab3229cec00efa7ef4b61fd5c1be40619f81",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1194",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe6d3cb3da9e188604d0e8bc2f03a0df4fefa836f9bf4b679e54e97138f72dd08",
+ "transactions": [
+ "0xf8688201690882520894104eb07eb9517a895828ab01a3595d3b94c766d501808718e5bb3abd10a0a0597dbb3f69603be721ae0f2a63eeee9f008829ff273b54243673f9ea192ddc0aa01f7dd04defb45af840d46a950b8bede0b3ce8a718004c1ca2f3bbd4efcbd7563"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4ced18f55676b924d39aa7bcd7170bac6ff4fbf00f6a800d1489924c2a091412"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np451",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe6d3cb3da9e188604d0e8bc2f03a0df4fefa836f9bf4b679e54e97138f72dd08",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3222feed7d40d321811eb16ac78aaa0561580b176e0605bfecc30427a7702996",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x119e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x465bd8f010df142744fc22da07b631a4e2d11ae75bca1608f7592548c420178b",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4a",
+ "validatorIndex": "0x5",
+ "address": "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc95a6a7efdbefa710a525085bcb57ea2bf2d4ae9ebfcee4be3777cfcc3e534ea"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np452",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x465bd8f010df142744fc22da07b631a4e2d11ae75bca1608f7592548c420178b",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x96bcc6f26c5f94c33c57d1614edd2b385e36d9972250c79758eeaeb09927c0a8",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x11a8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc7131bb27a6e1395d028d543cfd6f9e71ec4f2d2ecbc44cef53b5b626e01cad9",
+ "transactions": [
+ "0xf88382016a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03fc929c6e9476221ddd5f2f5093981cc13f4b8206ee3454720f06c0bd5c95caba038f23a2c21ba59155127a15502ddd731f30d6f94c6aafde8e73fbe39237766a2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x2b2917b5b755eb6af226e16781382bd22a907c9c7411c34a248af2b5a0439079"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np453",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc7131bb27a6e1395d028d543cfd6f9e71ec4f2d2ecbc44cef53b5b626e01cad9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x168c847144cfea8b88e6ec4f673ebddbf18331bde8002e044b1d1df7408edf04",
+ "receiptsRoot": "0x4ff26b781abcaf6d8a14f4f5283feeee87038dbcb46b9987d6042a01b1b07f9a",
+ "logsBloom": "0x00000000000400000000000000800000000000002000008000200000020000000000000000000000000040000000000000000000000000000000000000800000000000000020000000000000000000000000000000000000400000000000000000000000000000000000000000800400000000000000000000000400020000000000000000800000000010000000000000004000000000000000800000000000000000001000000000000000800000000000000004010000000000000004000000000000000000000000008000000000000000000000000004000020010000000008000000000000000000000000000000100100000010000020000004000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x11b2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x6d6eba2abd0851251651f038c9bcd8b21c56e6cefc95adb259a2b0c3ae4f158d",
+ "transactions": [
+ "0xf87a82016b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa07061a8a3f917f765ec8aef5e4ad237d377c0131f63f31da7bdc6af9942a1bc4aa051bf3e7c6676f2fbde507834995f4e269113adf35b98bc71cd22d9c168692f5c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x18d5804f2e9ad3f891ecf05e0bfc2142c2a9f7b4de03aebd1cf18067a1ec6490"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np454",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x6d6eba2abd0851251651f038c9bcd8b21c56e6cefc95adb259a2b0c3ae4f158d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7e75fe29c17414bea5febf41c577c117b57c1a731aa7a18b6c5d2ba9e3bc27dd",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x11bc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5cfbc66c760f871b8cf6d87140887788db0622a0f54274737f9cd043b156f50c",
+ "transactions": [
+ "0xf86582016c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ec3fe55b96a9d14e22fc0a8aa5991138ba954245754c0e0dda2b5b7dbb6711caa0296a6b87da18224fac7c922e2a7f0ec41330a6f510934a1e0e3c6a65dd72dfcb"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb47682f0ce3783700cbe5ffbb95d22c943cc74af12b9c79908c5a43f10677478"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np455",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5cfbc66c760f871b8cf6d87140887788db0622a0f54274737f9cd043b156f50c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdf26695268f674fc809ad21c323bcab53727af440302b923eec2d46ee3cd7aa3",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x11c6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x8f4a24fc6a150744744d03371d34758cf69d4216538804395397ed081692c7fb",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82016d01088252089446b61db0aac95a332cecadad86e52531e578cf1f0180c080a0774ced5c8674413b351ae8ac3b96705d1d3db10deae39134572be985f16c008ba06f3e4b250f84fcf95ae85946da8a1c79f922a211dbe516fcfcff0180911429b8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe4b60e5cfb31d238ec412b0d0e3ad9e1eb00e029c2ded4fea89288f900f7db0e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np456",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x8f4a24fc6a150744744d03371d34758cf69d4216538804395397ed081692c7fb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x358b2d72362d209f8c7131a484e49caff1dda8f550fe6103be80ac369cfe49fc",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x11d0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xafcf58746fc811dd74a0e4a66d91efbb00b2ab2c96680e132234a947798abf7a",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4b",
+ "validatorIndex": "0x5",
+ "address": "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfc0ea3604298899c10287bba84c02b9ec5d6289c1493e9fc8d58920e4eaef659"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np457",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xafcf58746fc811dd74a0e4a66d91efbb00b2ab2c96680e132234a947798abf7a",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x2dd7146f049ba679aae26c42d1da7f6660ea964a7b227509e5296a9d0170e93e",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1c9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x11da",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5346eb38677572982317e96be00144f1600800e5a738c875522183ad74f408d4",
+ "transactions": [
+ "0xf88382016e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa038214a2cc756a0ffe043200d5e12183223f81912c0156df732c3b1d85bc2a237a0744a52bf9fca64223bc279e589d21b9fda190325bf3b576f41a792ccbec5bc08"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4c3301a70611b34e423cf713bda7f6f75bd2070f909681d3e54e3a9a6d202e5a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np458",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5346eb38677572982317e96be00144f1600800e5a738c875522183ad74f408d4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x62b1bdf3b4a63f480b24af9f3b55dc6ad6e52bb81caa13b286960694b3b600b0",
+ "receiptsRoot": "0x25a0fc424c07569fb4229958de04f1d6497b3d8b6a78757f42963f95c354e2b1",
+ "logsBloom": "0x10001020000000000000000000000000000000000000000100000100000000000000000000000000000000800000000000000000000000000000000040000000000000000000000000000000020000080000000000000000400000000000000000001400000000010006000000000000000000800200800000000000000000000000000000002000000000000000000080000000000000000000000001000000000000000000000000800000000000000000000000000000000000000000000000080000000008004000000080000000000000000000000000000000000000000200000000020000000000000000400080000008004000000400000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ca",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x11e4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x83f464b150683ab5ce359179f4f9d6e960049959d2ec46a4ae7a07af2de41a6c",
+ "transactions": [
+ "0xf87a82016f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa05e304ec406ec4c83644417e1e58b49757d3ac78da5c5280fbda19b1f149137daa035b73caa8da3b6ce0e5f1b014c127f93f7be595f104cd933b5ff07549fd1812b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x84a5b4e32a62bf3298d846e64b3896dffbbcc1fafb236df3a047b5223577d07b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np459",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x83f464b150683ab5ce359179f4f9d6e960049959d2ec46a4ae7a07af2de41a6c",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5614ae860626ff1e044740a53f3cb5126f72002928c034aecbdfe4291ce73b91",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1cb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x11ee",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3c1ccfa2b5f88830245f76a22fa29ce22fb5b284de5937ff66adc67a445bf5c5",
+ "transactions": [
+ "0xf865820170088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a05d0d172a5fb9787aa2ee5205e5986de935984adf6030d5668be0e31332f7b145a022c4c7a89391e8f4508095fc5c1ed16aa0c08da6790be108240dc64763d42dae"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xff70b97d34af8e2ae984ada7bc6f21ed294d9b392a903ad8bbb1be8b44083612"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np460",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3c1ccfa2b5f88830245f76a22fa29ce22fb5b284de5937ff66adc67a445bf5c5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x715b0d1e4306032fa54c79f84599828d98bc84ed9cdb52a407e58730b4c112db",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1cc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x11f8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xfc7412d30ba5b6f5b319b07e51296906a42fdae50a88c1f90016d487b1df41f6",
+ "transactions": [
+ "0xf86882017108825208948a817bc42b2e2146dc4ca4dc686db0a4051d294401808718e5bb3abd10a0a0a755d1c641b8965ea140ad348135496fc412ffa43a72bbd2c7c0e26b814a75f1a067d81cca370b6ea40ccd2ad3662d16fa36bd380845bee04c55c6531455d0687d"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x73e186de72ef30e4be4aeebe3eaec84222f8a325d2d07cd0bd1a49f3939915ce"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np461",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xfc7412d30ba5b6f5b319b07e51296906a42fdae50a88c1f90016d487b1df41f6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c6710fa12f6392a52eaa92d776fe1c24245dd52883ff2276547e65c34952eeb",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1cd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1202",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xdad167dfa9bb65a470a36a3996f0587d645b3fbfe9e3522a1436f1dd6a3a37f3",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4c",
+ "validatorIndex": "0x5",
+ "address": "0x48701721ec0115f04bc7404058f6c0f386946e09",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xed185ec518c0459392b274a3d10554e452577d33ecb72910f613941873e61215"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np462",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xdad167dfa9bb65a470a36a3996f0587d645b3fbfe9e3522a1436f1dd6a3a37f3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x8c73a23f75ee594dacc63d24a5d5655a1ccbeead972dba58ad86787c44442c6c",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ce",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x120c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc50795e72a34041bdabf74a87f77d78f3a07f2005396dcf9925b08a8a686bd61",
+ "transactions": [
+ "0xf88382017208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0567311948632a5f4d53e0491aa8e7f939a3e0da38be1db4b6c757422de3f8bf6a01134e092948e423c7f8867c02822c95f3ce21b6d4e8d3666e2cf47ca88ad7499"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5cfbad3e509733bce64e0f6492b3886300758c47a38e9edec4b279074c7966d4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np463",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc50795e72a34041bdabf74a87f77d78f3a07f2005396dcf9925b08a8a686bd61",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb6a995ce6f848e4f2f2ad8ced5491859a5d0a3b6767108f3ce5cfcb33303349f",
+ "receiptsRoot": "0x5bb341cd099f8898164b032e64db73752f528a10e8d9c60c9b4fff08af32dcf5",
+ "logsBloom": "0x000002040000000000000000000000000000000000000000200000000000000000000000000000000000000000000300000000000000000000010020000000080000000000000000000000000000000000000000000200000000000000201000000000000000080000000000000000000000000000000040100000000010000080100000002000000000000000004000000008a0000000100000000000400000000000000000200000000000200400000000000000000000000000000000000000000000000000200000000000000002000000000000000000000000000000000000000000000000030000000000000200000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1cf",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1216",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x69a26219f28581c8898c2790cf785e3f2b0081a416d51722d85b5ac313d5f36d",
+ "transactions": [
+ "0xf87a8201730883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a06092eab6a3d9e41841ad4b9c97154ac35269c852606da6dd04940a1a055fa979a052a6e3e769e27310acdef840cb1182f4a2b6b08583b01cb8325c98253feaf7aa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x867a7ab4c504e836dd175bd6a00e8489f36edaeda95db9ce4acbf9fb8df28926"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np464",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x69a26219f28581c8898c2790cf785e3f2b0081a416d51722d85b5ac313d5f36d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf54cc52e78b0ea88b082230970d262fc78070bff347c000f60c53400d111a59c",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1220",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3ed11b20d6eced6314897749d304a677d345ce9343fe964143548980ea71615e",
+ "transactions": [
+ "0xf865820174088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0342c58642563f78afdb5cf7b9fbc935268a8fd81a5bd7997c33f61cdff8fb9c2a07466870d997603b5dd7755f151b76f056d4948ae82372b05babc01b9addaad19"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x0d01993fd605f101c950c68b4cc2b8096ef7d0009395dec6129f86f195eb2217"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np465",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3ed11b20d6eced6314897749d304a677d345ce9343fe964143548980ea71615e",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5b583ecaeffb409a488709df2c592c932e93a9b954bb5b62c36739324ae7d89c",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x122a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x20ca98d23c09a37aa1805c3989ca7a7bfff9ade344de4575f5063a10c60510ca",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82017501088252089423e6931c964e77b02506b08ebf115bad0e1eca660180c080a06263b1d5b9028231af73bfa386be8fc770e11f60137428378137c34f12c2c242a02b340f5b45217d9b914921a191ce5f7ba67af038e3b3c2c72aaca471412b02f7"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x8e14fd675e72f78bca934e1ffad52b46fd26913063e7e937bce3fa11aed29075"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np466",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x20ca98d23c09a37aa1805c3989ca7a7bfff9ade344de4575f5063a10c60510ca",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xdaf72de0a7092d2a2a6d31336c138ab45852ca65398578fbc435b3c591fa7c3a",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1234",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd1c6165f74a48fb1da29dde0ec4588f1b5708d1b810696ab128a6db9ce08a1eb",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4d",
+ "validatorIndex": "0x5",
+ "address": "0x706be462488699e89b722822dcec9822ad7d05a7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4ec1847e4361c22cdecc67633e244b9e6d04ec103f4019137f9ba1ecc90198f4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np467",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd1c6165f74a48fb1da29dde0ec4588f1b5708d1b810696ab128a6db9ce08a1eb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb9f6529424870d0fbfe7d70438762f3ccf9d2f212d3e42c837f6e9218d72451a",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x123e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xee2b973ebc00c239bf4fd6c382cc78890065370286476ae02a9b1bd76788f810",
+ "transactions": [
+ "0xf88382017608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e42b1ec38a455f867d421d170e634c86f8a84a2cb00ec5024f343667042f303ea067797c75de08e6eafd819d4c408324fba318e16b378b7dedbc0708056aebb696"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xec69e9bbb0184bf0889df50ec7579fa4029651658d639af456a1f6a7543930ef"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np468",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xee2b973ebc00c239bf4fd6c382cc78890065370286476ae02a9b1bd76788f810",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3017b68d781fb29ccbca4c6ff597a9e18d6cee4f02974dbb32f04b5a7f519271",
+ "receiptsRoot": "0x00fbb0bcdb236cd79dbbefe84d42f31ee3274cc5e9116ffb0d70301b983dbd52",
+ "logsBloom": "0x00000000010008200000000000000000200400000000000000000000022000000000000000000000000000000000000000000000000800000000000000000000000000200080000002000000000000000000000000008000000000000000000000000800080000000004004000000000000000001000000000000000000000000010000000000200000002000000000000010000000000000004000000000000000000000400000000000000000000000040000000000000000000000080000000000200000000000000000000000108000000000000000000000020010000000000000000000000000000000000000000000000000000000040000040000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1248",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x66a71dd383d4ead0e00787a06fcfb3c75c36fa72b5d98f39dc37ca129315b8d9",
+ "transactions": [
+ "0xf87a8201770883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa01975b5adb5e05e7dbaf63d31d34e5dfb802c4ca28127176811ada2b0a9411be6a02b9cd65ba817631163e95275ec2bd5319edeef4f74eb6efb32150a523282db16"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xefdd626048ad0aa6fcf806c7c2ad7b9ae138136f10a3c2001dc5b6c920db1554"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np469",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x66a71dd383d4ead0e00787a06fcfb3c75c36fa72b5d98f39dc37ca129315b8d9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7da79133a491b6c2566dc329ed006ee0010fe59b515fbce5589eda0f31dd091b",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1252",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x7f166dd54e16fcd0e302579768e0bb090b06f4e35cba5b48b0b5c42e367c0832",
+ "transactions": [
+ "0xf865820178088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa02a73665ddc16b8e231ef04b5f0ad8afa56248db6f43222848032c72e97a807b8a00a17dda1a1d0ba616354fda9e86c836bcb002c7e54153be4cc95776446c6b2a5"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x551de1e4cafd706535d77625558f8d3898173273b4353143e5e1c7e859848d6b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np470",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x7f166dd54e16fcd0e302579768e0bb090b06f4e35cba5b48b0b5c42e367c0832",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xcbeab9491879fdd48e387106f31e983546cff3f4795ff5190722d2ac1f3792b6",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x125c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xeedbf487ab11603d1a8e08d672886d16cd318bc421a358d199df281a473ac7b0",
+ "transactions": [
+ "0xf8688201790882520894878dedd9474cfa24d91bccc8b771e180cf01ac4001808718e5bb3abd109fa0515a62775619f55c366d080a7c397ea42dcfd2fdcce1862ef98dab875077f367a023756d4f3bd644dde1c25f8cde45fbea557dacf0492bbecb409f6b2cdacbb9b8"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x137efe559a31d9c5468259102cd8634bba72b0d7a0c7d5bcfc449c5f4bdb997a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np471",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xeedbf487ab11603d1a8e08d672886d16cd318bc421a358d199df281a473ac7b0",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x60452d4fa157207a12986fb9c810855fe19a2492ad046335ec9b4fe41e48de19",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1266",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe2cefda7c9752d4706e180cf9228524bd767f36f6380f0c6255498abedc66ce7",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4e",
+ "validatorIndex": "0x5",
+ "address": "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xfb0a1b66acf5f6bc2393564580d74637945891687e61535aae345dca0b0f5e78"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np472",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe2cefda7c9752d4706e180cf9228524bd767f36f6380f0c6255498abedc66ce7",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x0b580cdca4b5a562a85801f2e45bd99e764124b9715915fd4bfc6f6eb483ef96",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1270",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x35f103c6c3cfc385bf9f512f7b4d7903e314b60cb715df196cf574391b8506df",
+ "transactions": [
+ "0xf88382017a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05c8cad8eec0edc7394b3bace08088ee19b7eacb754b0a5695fc52a0cd17c19f6a0033d27e9eeb87fa5ae4868a14d0b66d941f0ffa3a3781e60cbb751bab7b507da"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x96eea2615f9111ee8386319943898f15c50c0120b8f3263fab029123c5fff80c"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np473",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x35f103c6c3cfc385bf9f512f7b4d7903e314b60cb715df196cf574391b8506df",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd08b438590148463c602be8f8899fd6c2cb42972fe2df0e71cb42ebefea3f404",
+ "receiptsRoot": "0x307ca5ba4dfd34e9f362cea8e1f54ff58f9318a35cf7e1ae24823d41572d7742",
+ "logsBloom": "0x00000000000000000000000000000000800000000000000000008000000000000000000000040000000000000000100000000000000000000000000000000001000000000000000000000400000000000000000000000000300000000001000000002040000000000000008000000000000000000000000000000000000100000010000000000000000401000000000000000000000000000000000000000080000000000058400000000400000800000000000000000000000000000000000001000000000000000000000000004000000000000100100000000000000000000000000000000200400000000000100000000000002000040000000000100000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1d9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x127a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x1f50e2662ba03c36242e9717f767077fd0d1659ed1a5e2e5024bf1a9de6303f1",
+ "transactions": [
+ "0xf87a82017b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06cfb2ecb740895c1bdd352c502898651d83d35cb17ec4a0b30b04fe190a05758a02606cabbaa5b1d57ff9da73837cff8cbd03f242b83880f8cf3ba6f0ee907d538"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x68725bebed18cd052386fd6af9b398438c01356223c5cc15f49093b92b673eff"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np474",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x1f50e2662ba03c36242e9717f767077fd0d1659ed1a5e2e5024bf1a9de6303f1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6d86e3351111e6c2d4eafc36553273c03636a22fae54a9e076be2e7cb0cdf9d7",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1da",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x1284",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa3baf412ffd440d9baceb4d19fc213652de91fee569633fb5f8f77b737dd23f3",
+ "transactions": [
+ "0xf86582017c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a044380da66c7033fceaa15191e7549bd08fed4c16f96cf1282b2f39bccaad1ff0a00d036ed4649f8300b82a534b03a19b4547784997b61328ba41dd7fa5380de99b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe2f1e4557ed105cf3bd8bc51ebaa4446f554dcb38c005619bd9f203f4494f5dd"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np475",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa3baf412ffd440d9baceb4d19fc213652de91fee569633fb5f8f77b737dd23f3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4e2eff0a0a0cfaa9726ffd557089d4a85855fabe4b81334326bd400289f5ed12",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1db",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x128e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa63c5dedb28356376c60a58b8b766be086203e9b8d9c016e0863fd4e8cf42a06",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82017d01088252089445dcb3e20af2d8ba583d774404ee8fedcd97672b0180c001a0d3b69c226bf73db84babb6185a83b0dd491467adfc01d279df4c09d5d2d3fba4a0368ddb772caa32963df97961cf8ef0db33e0df5945000f0e39d9a288bd73ee30"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x48ef06d84d5ad34fe56ce62e095a34ea4a903bf597a8640868706af7b4de7288"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np476",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa63c5dedb28356376c60a58b8b766be086203e9b8d9c016e0863fd4e8cf42a06",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x3de8e5ff6961615b029591cbe9ea51723c809d965421da4f3f8ae26ffe59d69d",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1dc",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1298",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xbcf5e09e90541f9a8e36eca4ce43a64e1e05e93f4aba193be8e2da860b5ba0bc",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x4f",
+ "validatorIndex": "0x5",
+ "address": "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5c57714b2a85d0d9331ce1ee539a231b33406ec19adcf1d8f4c88ab8c1f4fbae"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np477",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xbcf5e09e90541f9a8e36eca4ce43a64e1e05e93f4aba193be8e2da860b5ba0bc",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x6eb0d2ff3e3dd2cdaad61b121b06afcf7863f34152ecbdf8b8773604630a56b3",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1dd",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x12a2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd5c167589a4663ae0585e5fff8fe256f35baaa26843df17dedcf6040709d6257",
+ "transactions": [
+ "0xf88382017e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0939d9f6f260f24b45073aeabe00660f617f1dbfcf522cd6c90ef189dfc9dbfa0a02dfd90c6f1a6822039b8fbd5bff435e939882da970ed1b58a4639eddcb79b23b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x204299e7aa8dfe5328a0b863b20b6b4cea53a469d6dc8d4b31c7873848a93f33"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np478",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd5c167589a4663ae0585e5fff8fe256f35baaa26843df17dedcf6040709d6257",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xfadd61dbce8d90cae8144c1b2297209079517cb13f3a4e60a6c8f2ea7b4d3770",
+ "receiptsRoot": "0x3ec27c047700a74288e3ee48062fed9fbba71b1704febedea9f4e9e3a92faabf",
+ "logsBloom": "0x00100000000000000000000040004000000000000800008080000000000000100000000000000001000000000000000000000000000004000008000008200000002000004000000400000000000000000000000008000000000000000000004000000000000000000000000040000000800004000000000000400000000000000000001000000000000000000410010000000000000000000400000000020000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010080000000000000000100000000000800000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1de",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x12ac",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xb061affdd716a0d4c5d081a1c3659d0201dce5c698ae942440565ca789e55b00",
+ "transactions": [
+ "0xf87a82017f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0dffee1543462b1d024b5d54728f2e3284d90d8fd24b94fd96bd027b4ca51e768a02ed5ddd2050f1b7bcbc123e31fb0536fbf1661a8f7541c7a10729e8a505cc080"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb74eea6df3ce54ee9f069bebb188f4023673f8230081811ab78ce1c9719879e5"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np479",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xb061affdd716a0d4c5d081a1c3659d0201dce5c698ae942440565ca789e55b00",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x931dde8f1566d5b88162261e5f8c8fede3f14bfab1c11934aae8f2a38aca7b36",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1df",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x12b6",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xd8fd694b37ff2f40373350baa6cbf326e675330a7d070dedf57065b72304aece",
+ "transactions": [
+ "0xf865820180088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0c2e07d6867be2220a74a18404d2b9b9adb2f6b1764907aaec954f46e0b9fd18aa01504fbbb49a910d6469e64741d99ea5031c14d4721e488998ef2f594022f34e2"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xaf5624a3927117b6f1055893330bdf07a64e96041241d3731b9315b5cd6d14d7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np480",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xd8fd694b37ff2f40373350baa6cbf326e675330a7d070dedf57065b72304aece",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x452e515470ad9f96543d5a469c85e77c4f675f70a56662537491b01528898b99",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x12c0",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xee3a60bb251ec04e27e020f297aa6f159dad08673e76b280e67114583478aec9",
+ "transactions": [
+ "0xf868820181088252089450996999ff63a9a1a07da880af8f8c745a7fe72c01808718e5bb3abd109fa0f06ad492cdd04b44f321abe9cb98e5977f03909173e4b6361f50d44c080f9d6aa07fdc23c04fab8e0a576e6896b13a661b2dcb256cf8ca42fa21f0f370097a53a4"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc657b0e79c166b6fdb87c67c7fe2b085f52d12c6843b7d6090e8f230d8306cda"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np481",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xee3a60bb251ec04e27e020f297aa6f159dad08673e76b280e67114583478aec9",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa424a562451b0728dc1451b83451fb65f9cad240a6e12ae45314a3c0fc49c4bd",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x12ca",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe261b4fbd07d32f5f19564c572258acbe4be1a6b2ea03a57ccbb94e254f37cd5",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x50",
+ "validatorIndex": "0x5",
+ "address": "0xc57aa6a4279377063b17c554d3e33a3490e67a9a",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa0e08ceff3f3c426ab2c30881eff2c2fc1edf04b28e1fb38e622648224ffbc6b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np482",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe261b4fbd07d32f5f19564c572258acbe4be1a6b2ea03a57ccbb94e254f37cd5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x5a1ad989a90bb48e30208fafcd5131d4dec171928eb27a8ab446df6086df0f94",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x12d4",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe8f039d9e217e95c5622ac64609dcaaa54abbf24376fe6c65a29d2b50060cff1",
+ "transactions": [
+ "0xf88382018208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a085873eb64b12c743e5652beb56056bd656368a87247a72b159667d4755d7a714a0134397c5062d25029e41def2275efe8c56e466e3a1547d3525533e29641d203f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc9792da588df98731dfcbf54a6264082e791540265acc2b3ccca5cbd5c0c16de"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np483",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe8f039d9e217e95c5622ac64609dcaaa54abbf24376fe6c65a29d2b50060cff1",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x54928b5673094b4ce9833ecf8c1490381f0317ac2e9d51f47673e386b82ae93d",
+ "receiptsRoot": "0xeda5fd4b20fab5a0732205bfe235b5b212cfa5eb525752ae8b9bb0ca224262ec",
+ "logsBloom": "0x04000000000420002000000000000000020000000000000000000000000000000000000000000000000000100000000040000102000000000000000080000000008000000000000000000000900000000000000000000000040000000000000000000000000000000000100000100000000000001000010000000000000000010000000000000001000040000000000000000000000000000100000000000000000000000020010000000008000000000002000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000080000000400000000000010000000000000000000000000000000002020000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x12de",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x4b31828b7c27c371fdbc62a7b0b6807d1050d15ad53736f73c4063b391aa8b91",
+ "transactions": [
+ "0xf87a8201830883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a05c87beb281558e43744b39a1d0b62e75dfb5ea245fd2d66c657ff053fa5c45e1a077a1c629133272d7fef83436c8f67f327fc77bedea95009b3d569a5f03485b50"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc74f4bb0f324f42c06e7aeacb9446cd5ea500c3b014d5888d467610eafb69297"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np484",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x4b31828b7c27c371fdbc62a7b0b6807d1050d15ad53736f73c4063b391aa8b91",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf92302c8ac6987ab39ddc9a7413f552337da61d611a086900a5e47b9b3c1422f",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x12e8",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x56c5997ee01e4a2bad320a6af0120843f01908c525450d04458eca33799e7958",
+ "transactions": [
+ "0xf865820184088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ef66b5859d5e5be7e02ce0b7d103b957ceba18d69047aec94746e87945b7230ba071c5785cce709e44dd94db5684b4e552e343a44862fba233c49a3fa99b0d63f9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1acd960a8e1dc68da5b1db467e80301438300e720a450ab371483252529a409b"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np485",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x56c5997ee01e4a2bad320a6af0120843f01908c525450d04458eca33799e7958",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x89822c6bc267d77690ae905ebc8dbe9426f9a83764224d4bc9624104881db28e",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e5",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x12f2",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xa5d5571bc983cefbe29844e1914f948256b70833f1e99d8dcb0282e1f9dbbfef",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e820185010882520894913f841dfc8703ae76a4e1b8b84cd67aab15f17a0180c080a0d4b8d15fc05f29b58f0459b336dc48b142e8d14572edad06e346aa7728491ce8a064c8078691ba1c4bb110f6dff74e26d3c0df2505940558746a1c617091ddc61a"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x6cef279ba63cbac953676e889e4fe1b040994f044078196a6ec4e6d868b79aa1"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np486",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xa5d5571bc983cefbe29844e1914f948256b70833f1e99d8dcb0282e1f9dbbfef",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xe88ebfc2a7990356801a2e5a308418fa8fe4445548fafe8227f4382f64ad8597",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e6",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x12fc",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x686566b93e0b0c5d08d2de9e0547a5639e6878d15c59baab066c48365ce7e350",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x51",
+ "validatorIndex": "0x5",
+ "address": "0x311df588ca5f412f970891e4cc3ac23648968ca2",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x60eb986cb497a0642b684852f009a1da143adb3128764b772daf51f6efaae90a"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np487",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x686566b93e0b0c5d08d2de9e0547a5639e6878d15c59baab066c48365ce7e350",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xb852ee14e385a383f894d49c4dabd2d0704216e924283102b9b281ae5306a291",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e7",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1306",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xc005c46cb9de70c37edd02e3ae623bb8b6e4160674fafbbd34a802f85d2725b6",
+ "transactions": [
+ "0xf88382018608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0ddc578e5c190613c2dc0ce34585e98c512fc9b4ae877b0b3f9b85e01a36b90b5a044c7152f99374ce61bb3b9ebb9ec9e5c4f623faa9b8972cf80f891fd45be9bbf"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xc50024557485d98123c9d0e728db4fc392091f366e1639e752dd677901681acc"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np488",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xc005c46cb9de70c37edd02e3ae623bb8b6e4160674fafbbd34a802f85d2725b6",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa3f2cdabc9ec81196b1930e223115ab39e3aa82a3267c2eab58dfcd4ac28879d",
+ "receiptsRoot": "0xa98965822a3cbebe261b9e53038a23e30a7a9ea1878b91ee19c2b9ae55907433",
+ "logsBloom": "0x0000000000000000000000000000000c000000000000000000000000000000000000000000002000000000800000000008000000000000000000000000000000000000000000200200000000002004000000000000000000000000000000000000000000000000000000020000040000000000080000000000004000000000000000000000000000000000000000100000000200000000000000200000000800040000000000000000000000441000000000000000000000000000000000004020400000000000000000000800000000000000002000000000040000000000000000000000000000000000000000000100000000000000400100000200000010",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e8",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1310",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xabe558d433bc22296ae2fc7412d05672f2ec66c7940ef6a76f9bb22aa09b219d",
+ "transactions": [
+ "0xf87a8201870883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09d84bd49c461dee138a01ba1116ba5a0866c4d398db99b3b6e8ec5119ddaf31da046d87610c10b340e616174c09a5addfb8ef7f1b64dcadf4edd14af37ec74a55c"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xb860632e22f3e4feb0fdf969b4241442eae0ccf08f345a1cc4bb62076a92d93f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np489",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xabe558d433bc22296ae2fc7412d05672f2ec66c7940ef6a76f9bb22aa09b219d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x39ebb75595ae4b664d792fdf4b702a8a4cec3fb1fa62debd297075d3543e05af",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1e9",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x131a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5591e9a74a56e9765790e3088a82c8e6e39ef0d75071afe13fa51c9b130413db",
+ "transactions": [
+ "0xf865820188088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a06ffd1874ec840566ae82b8a15038ee44b5241705bdb421b459c17100d1300d1aa0121f314d9f41658c831f52b82d4a13b333413d68809cea260e790de9283a434b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x21085bf2d264529bd68f206abc87ac741a2b796919eeee6292ed043e36d23edb"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np490",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5591e9a74a56e9765790e3088a82c8e6e39ef0d75071afe13fa51c9b130413db",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xa3d5920be7fa102b7b35c191800c65c8b8806bd7c8c04cdc0342a3d28aeafa3c",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ea",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1324",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x38cee342db6a91998dd73c4d25bca6d8730977aaa19f0a092d47c00ff10c4edb",
+ "transactions": [
+ "0xf8688201890882520894b47f70b774d780c3ec5ac411f2f9198293b9df7a01808718e5bb3abd10a0a0d33c0cd7f521603ea8deaa363ab591627f5af193759f0aeb8cd9fe4f22a4dd5ca0667bb0ee041403cba2e562882bb9afc43bd560af3c95136c7bf4f1e361355316"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x80052afb1f39f11c67be59aef7fe6551a74f6b7d155a73e3d91b3a18392120a7"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np491",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x38cee342db6a91998dd73c4d25bca6d8730977aaa19f0a092d47c00ff10c4edb",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xf1034fb8a7585c73d7df19cae6b0581d6836278bd57d05fa19f18c6501eace46",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1eb",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x132e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x669efe3cceb25caf14b93a424eaa152070686561e028d50b8adbf87d45f4d18f",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x52",
+ "validatorIndex": "0x5",
+ "address": "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xa3b0793132ed37459f24d6376ecfa8827c4b1d42afcd0a8c60f9066f230d7675"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np492",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x669efe3cceb25caf14b93a424eaa152070686561e028d50b8adbf87d45f4d18f",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9b830dad01831671e183f743996cc400135e0b324f1270468af08b37e83b8b17",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ec",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x1338",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x92932a0312ff65482174399e2cd29656c7051fa3747e47a906b54207c4fd1a92",
+ "transactions": [
+ "0xf88382018a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e94663b4e19d1c2f86adde879e4cb965b7eda513a542ba26136b7010aae11681a03e7d58f3bef3bba01e70b75c70bc0d070f95bba8994c9f12705f2a5281160f47"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xe69d353f4bc38681b4be8cd5bbce5eb4e819399688b0b6225b95384b08dcc8b0"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np493",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x92932a0312ff65482174399e2cd29656c7051fa3747e47a906b54207c4fd1a92",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xc616c572be45daa3d7eae2481876e5d8f753631f976d4da110a6ad29bdfad30f",
+ "receiptsRoot": "0x78902fbbd0a8ab65f6b731f1145a5f6f467f9fdae375707236cff65e050bbfeb",
+ "logsBloom": "0x00000000002000000000080000000000800000000000000000800000000100000000000000000000000000000000000000000000000004000000000010000000000040000000000010000000000400000000000000000000000000080000000000020000000000000000000000000000000000000000000010000000000000000000000000008000000000000000000000000000000000400000000001000040000000000000000000000000000000000000000040000000040000000880000000008020000000800000008000000000000040020180000000000000000000400800000000000000000000000080000200000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ed",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1342",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x52b55abe0e252ea389cc21f01782fd70ca4e4ef6031883f6b79c097de33964d4",
+ "transactions": [
+ "0xf87a82018b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0fbd0141af6d135ce0949d33ba4beba57e9b7f388c37e9725b762cb61e8db17dea05ecd43ff335efc34b06551202c4223fc39e1c842d4edfad8e46f19bc7a93f57f"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x221e784d42a121cd1d13d111128fcae99330408511609ca8b987cc6eecafefc4"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np494",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x52b55abe0e252ea389cc21f01782fd70ca4e4ef6031883f6b79c097de33964d4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x7e626fcfe3b1ca7a31dc26a08fbc503c7a85876a64a22a270ec99ef534566c45",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ee",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x134c",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x5370ce9fa467f03411f240030b4a0b9fcbb05c5b97b09356d071ade6548767e8",
+ "transactions": [
+ "0xf86582018c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a05a02d5d03439ebbdf2c3b2d98305dda7adbed1ce5549c474b4b9e4f7200d4beaa016d123a1de79c4a654c1d1ab2169ee672c66922fa036e951c60fec9fe4643ee9"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xdcd669ebef3fb5bebc952ce1c87ae4033b13f37d99cf887022428d024f3a3d2e"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np495",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x5370ce9fa467f03411f240030b4a0b9fcbb05c5b97b09356d071ade6548767e8",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x9d90c0fd0677204966d6fdbcafcfacc7fe93a465748d2ce8afbc76b6d9b9bbe1",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1ef",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1356",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x58488c77f4726356a586e999547ffa283a73f17058064f3f56eeb02a5f67b4b4",
+ "transactions": [
+ "0x02f86b870c72dd9d5e883e82018d0108825208946e3d512a9328fa42c7ca1e20064071f88958ed930180c080a0990aa3c805c666109799583317176d55a73d96137ff886be719a36537d577e3da05d1244d8c33e85b49e2061112549e616b166a1860b07f00ff963a0b37c29bcaa"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4dd1eb9319d86a31fd56007317e059808f7a76eead67aecc1f80597344975f46"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np496",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x58488c77f4726356a586e999547ffa283a73f17058064f3f56eeb02a5f67b4b4",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x32f6d8bc2270e39de3a25c3d8d7b31595eef7d3eb5122eece96edf18a7b8290f",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f0",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x0",
+ "timestamp": "0x1360",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xe521dace14e46c9d8491f262d38c1741f6fa385466a68c7ceadd08c1515600d3",
+ "transactions": [],
+ "withdrawals": [
+ {
+ "index": "0x53",
+ "validatorIndex": "0x5",
+ "address": "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7",
+ "amount": "0x64"
+ }
+ ],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x5e1834c653d853d146db4ab6d17509579497c5f4c2f9004598bcd83172f07a5f"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np497",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xe521dace14e46c9d8491f262d38c1741f6fa385466a68c7ceadd08c1515600d3",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0x4e1202b318372f0cacbc989e0aa420c4280dcb8ecd7c3bb05c645bf9fb27d54e",
+ "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f1",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x146ec",
+ "timestamp": "0x136a",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x3464afae6c8c9839a124b8dba3d363e646b61c9160a61b1c231c67a6a72daff5",
+ "transactions": [
+ "0xf88382018e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0d9866a4e71a4efbccc717617f5c712557608513ce8b49f6e24fc06e0d717b7b6a056d3c051f6dbe09a1c94e23499ba8014f74e123caa3252068ee67e8f25e1e323"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x9f78a30e124d21168645b9196d752a63166a1cf7bbbb9342d0b8fee3363ca8de"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np498",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x3464afae6c8c9839a124b8dba3d363e646b61c9160a61b1c231c67a6a72daff5",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xd04a20f359c38d0cb7a31e5e7b002251c15e0242b864964ddbe9642d1c8f7e30",
+ "receiptsRoot": "0xe40714733f96bc282c17b688a91dfb6d070114fc7bc3f095887afa3567af588c",
+ "logsBloom": "0x00400000000001400400000000000000020000000000000000000000400000000000000000400000000000000000000000040100000000800000000000000000000000000000010000000000000000080000000000000000008100000000000000000000000000000000000000200000300000008000000000000010002000000000000000008000000000000000000000000000000000000000100000000000000000000000000000000004000000000000100001000000480000000000000000000000000000000000000000000000000000440000000000000000000010000000000100000000000000000000000000000000000000000000000000800000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f2",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0xfc65",
+ "timestamp": "0x1374",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0xf7ad3df877f1a7ac6d94087db3f3e01a80264b0909e681bf9c7d21879df0df5d",
+ "transactions": [
+ "0xf87a82018f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0dd12539d461aa41247581166cecdf2eb60a75ac780929c9e6b982d9625aadc1fa06b813ce4e36c5147759f90672f6e239fab2851a63ac3b998ead89c0ead85589b"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x1f7c1081e4c48cef7d3cb5fd64b05135775f533ae4dabb934ed198c7e97e7dd8"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np499",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0xf7ad3df877f1a7ac6d94087db3f3e01a80264b0909e681bf9c7d21879df0df5d",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xbd38c27a1fad5fb839aad98a9c6719652d1714351f24d786b23bf23076b31ba6",
+ "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f3",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x1d36e",
+ "timestamp": "0x137e",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39",
+ "transactions": [
+ "0xf865820190088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a012969b1c46cb1b69a3fdf15b8bbccc1574572b79b38bf81803c91b0384309545a06d1c09143ad2bfeccbb04d63441058c83b60a5cbfdad87db36421dfcf008cd16"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0x4d40a7ec354a68cf405cc57404d76de768ad71446e8951da553c91b06c7c2d51"
+ ]
+ },
+ {
+ "jsonrpc": "2.0",
+ "id": "np500",
+ "method": "engine_newPayloadV3",
+ "params": [
+ {
+ "parentHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39",
+ "feeRecipient": "0x0000000000000000000000000000000000000000",
+ "stateRoot": "0xea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1f4",
+ "gasLimit": "0x47e7c40",
+ "gasUsed": "0x5208",
+ "timestamp": "0x1388",
+ "extraData": "0x",
+ "baseFeePerGas": "0x7",
+ "blockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7",
+ "transactions": [
+ "0xf868820191088252089415af6900147a8730b5ce3e1db6333f33f64ebb2c01808718e5bb3abd109fa085b3c275e830c2034a4666e3a57c8640a8e5e7b7c8d0687467e205c037b4c5d7a052e2aa8b60be142eee26f197b1e0a983f8df844c770881d820dfc4d1bb3d9adc"
+ ],
+ "withdrawals": [],
+ "blobGasUsed": "0x0",
+ "excessBlobGas": "0x0"
+ },
+ [],
+ "0xf653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c"
+ ]
+ }
+]
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/testdata/txinfo.json b/cmd/devp2p/internal/ethtest/testdata/txinfo.json
new file mode 100644
index 0000000000..8e1d917fb7
--- /dev/null
+++ b/cmd/devp2p/internal/ethtest/testdata/txinfo.json
@@ -0,0 +1,3018 @@
+{
+ "deploy-callenv": {
+ "contract": "0x9344b07175800259691961298ca11c824e65032d",
+ "block": "0x1"
+ },
+ "deploy-callme": {
+ "contract": "0x17e7eedce4ac02ef114a7ed9fe6e2f33feba1667",
+ "block": "0x2"
+ },
+ "randomcode": null,
+ "randomlogs": null,
+ "randomstorage": null,
+ "uncles": {
+ "11": {
+ "hashes": [
+ "0x900edfd7e6de8a4a4ae18d2e7df829de69427e06eb9a381c3fe1e3002a750d75"
+ ]
+ },
+ "16": {
+ "hashes": [
+ "0x750eda0129037fbbcfcbfd6362a60ffbbc53a3f14ba9259cf2ac7f02da2a827c"
+ ]
+ },
+ "21": {
+ "hashes": [
+ "0x763d1a545e23079b4796461f2146cd3b24cc45ceab6e932db010bd2736e45403"
+ ]
+ },
+ "26": {
+ "hashes": [
+ "0x98180f6103a7e303444de4e152e81539ad614d0cd755e0e655715ab676d11e32"
+ ]
+ },
+ "31": {
+ "hashes": [
+ "0x04a8c9b6d23b2ada25bff618036c08bf6428fb35b89bce694607fac697f470e3"
+ ]
+ },
+ "36": {
+ "hashes": [
+ "0x9225da0395e14243f1e626b330ea8fe6afde356e50e8448936a29e1c203d661d"
+ ]
+ },
+ "41": {
+ "hashes": [
+ "0x74a80b9b13a264aff16e9156de67474c916de966327e9e1666fc2027e1bf63ad"
+ ]
+ },
+ "46": {
+ "hashes": [
+ "0xcf2bddf3649c7af6e9c8592aa5fad693f39f46369749e1c7127848d4ae9ff1ec"
+ ]
+ },
+ "51": {
+ "hashes": [
+ "0xeb31c29a94de8cf2fc3d0b80023b716fb5d31cc24d695d606eef2389705ade45"
+ ]
+ },
+ "56": {
+ "hashes": [
+ "0xb3a6af7632306e2dbd56b3bbf0e77d7b5c199053f348c74ce938afae615cd4fe"
+ ]
+ },
+ "6": {
+ "hashes": [
+ "0x97186bc5df663e72934212ab5a7b4449f07f12f44b267e119817791fe0ed66c5"
+ ]
+ },
+ "61": {
+ "hashes": [
+ "0x3a2cf075f456fcf264293a32d41f72506ad8cf9697d6b6d8ab3d8258cdaa90bd"
+ ]
+ },
+ "66": {
+ "hashes": [
+ "0x94d338db2e75740d17df19b0d8a111d5d68b2dfa38819b88929190b4b08b5993"
+ ]
+ },
+ "71": {
+ "hashes": [
+ "0xe9938f6ac90bc4dfdea315ed630b03ad9392b264d362ee1e1b2703fb3db5047a"
+ ]
+ }
+ },
+ "valuetransfer": [
+ {
+ "block": "0x7",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "nonce": "0x5",
+ "to": "0xca358758f6d27e6cf45272937977a748fd88391d",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x1c",
+ "r": "0x7252efaed5a8dbefd451c8e39a3940dc5c6a1e81899e0252e892af3060fd90ed",
+ "s": "0x30b6bd9550c9685a1175cece7f680732ac7d3d5445160f8d9309ec1ddba414be",
+ "hash": "0xd04f2bb15db6c40aaf1dcb5babc47914b5f6033b2925cb9daa3c0e0dab493fcb"
+ }
+ },
+ {
+ "block": "0xc",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x9",
+ "to": "0xef6cbd2161eaea7943ce8693b9824d23d1793ffb",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x1160803ff1253dead1d84d68a06cb92fcbb265ddb0edb9a5200b28b8c834ce6b",
+ "s": "0x4f1f42c91a7b177f696fc1890de6936097c205f9dcd1d17a4a83ac4d93d84d9c",
+ "hash": "0x778450f223b07f789e343c18207a3388c01070c2f6a89506f2db4c656bc1a37f"
+ }
+ },
+ {
+ "block": "0x11",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xd",
+ "to": "0x4a64a107f0cb32536e5bce6c98c393db21cca7f4",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xea20f9d952a58697ffb40cefcab9627f552c9658b3181498fd706418f89a3360",
+ "s": "0x4988596c88fe69f7d032df8e6f515a618a2c2e30f330febb3b548eb4fc1e8ca2",
+ "hash": "0xc2cffc70d847fbe50a53d618de21a24629b97e8dd4c1bcbf73979b2a48ee16df"
+ }
+ },
+ {
+ "block": "0x16",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x11",
+ "to": "0x7cb7c4547cf2653590d7a9ace60cc623d25148ad",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x5f315b1989161bf29054e9e030a05b05b3d7efb4c60e39531b96af1690913f91",
+ "s": "0x6f1d8de5adad6f76ed0d2b4c6885d3a5502c12dae1d124b310e8c8856bd22099",
+ "hash": "0xfa9cd1e12446cd8c23fc76b0ae9beba0ebdc021aa87726b6febcd5ba4a504f01"
+ }
+ },
+ {
+ "block": "0x1b",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x15",
+ "to": "0x77adfc95029e73b173f60e556f915b0cd8850848",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x148500c79a2f0d59158458da4e3b2a5ace441bf314942243c9e05da3457d394e",
+ "s": "0x2a83c5f921ffddd3c0b2a05999f820d1d03bce9ac9810941bb286c4db4ce9939",
+ "hash": "0xbfeeb9406545ede112801fe48aeaf30c8e2384739e8e585f1c0e726689abc4b8"
+ }
+ },
+ {
+ "block": "0x20",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x19",
+ "to": "0x36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a43",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x14346079d6d3690f923625efde8933b2ad99c2bfda9310983a21b60e3c261d3c",
+ "s": "0x501ae278f370f3c0283fb04f966b6c501cbee0ad4c784f4187e38fcc38a9ccbb",
+ "hash": "0x792614188c26e2f348ac3223813794c60de97b83a298e84f4bae51dda6de140c"
+ }
+ },
+ {
+ "block": "0x25",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x1d",
+ "to": "0xbbf3f11cb5b43e700273a78d12de55e4a7eab741",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x86bc86521cc6091198253d75caf394a8e23fd4fb82b48236d29f81a95aeebec5",
+ "s": "0xae9de4ac4265e3f415514905d8f8c747c959771080fa031dc5fd9b7333ffc28",
+ "hash": "0xc44716fcd212d538b2d143ddec3003b209667bfc977e209e7da1e8bf3c5223b8"
+ }
+ },
+ {
+ "block": "0x2a",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x21",
+ "to": "0x684888c0ebb17f374298b65ee2807526c066094c",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x88fa9d9bbc92e44b8edcda67ee23aca611deac4cec336b215fb72547a1d0e07e",
+ "s": "0x297c4d7054cb545bee5221a70454b6270e098f39f91bf25c0526aa8c0a0a441c",
+ "hash": "0xc97ceb5b227ade5363592a68c39dcf1788abbf67b2440934b1ae11cf4b19417c"
+ }
+ },
+ {
+ "block": "0x2f",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x25",
+ "to": "0x8a5edab282632443219e051e4ade2d1d5bbc671c",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x649b4ad4dcf07bcfba3dd7afd2ce220d0ae463c1bcc891ab1fcae84eca6fcc69",
+ "s": "0x5c69b0ad46c90eee811e4b71ce0aed22f479c207bee813dac8cce07e5a65adae",
+ "hash": "0xaf340a1b347c756a11e331e771d37d9205eada520f4f0d8d27f725d7c196aed1"
+ }
+ },
+ {
+ "block": "0x34",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x29",
+ "to": "0x4b227777d4dd1fc61c6f884f48641d02b4d121d3",
+ "gas": "0x5208",
+ "gasPrice": "0x1",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x7d015036540013eb6aa141a2475fa1dd88d3bee57a67beaf6ef5de8f40969601",
+ "s": "0x4dc750a08f793ff3105479e7919508d14abe56748698375046b995d86267b18c",
+ "hash": "0x07a2a98ac904bcf4c17a773426b34d2b3120af65b12f9bfd437d48c175f364eb"
+ }
+ },
+ {
+ "block": "0x39",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x2d",
+ "to": "0x19581e27de7ced00ff1ce50b2047e7a567c76b1c",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x27f555e9",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xde8b08caa214d0087ffd11206d485cb5cde6a6b6a76b390f53d94a8c16691593",
+ "s": "0x14dfe16ec3e37b8c6d3257deaf987b70b0776b97e4213c1f912c367e7d558370",
+ "yParity": "0x1",
+ "hash": "0xa883c918fb6e392a2448ef21051482bfcbeb5d26b7ebfad2a010a40e188cb43b"
+ }
+ },
+ {
+ "block": "0x3e",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x31",
+ "to": "0x62b67e1f685b7fef51102005dddd27774be3fee3",
+ "gas": "0x5208",
+ "gasPrice": "0x14847701",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x6797c616a0fe0fad65b6020fc658541fd25577a3f0e7de47a65690ab81c7a34b",
+ "s": "0x115e6d138f23c97d35422f53aa98d666877d513dbe5d4d8c4654500ead1f4f8f",
+ "hash": "0xb2203865a1a1eace5b82c5154f369d86de851d8c5cd6a19e187f437a1ae28e94"
+ }
+ },
+ {
+ "block": "0x43",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x35",
+ "to": "0x6b23c0d5f35d1b11f9b683f0b0a617355deb1127",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0xa88fcba",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0xdc3f3d86de44ee4dd795ff8ab480f4f5273c8ca61edb4c7561a369c80fbbb983",
+ "s": "0x43a90e087a6f5ba014e17316ec63b97a5a9ada19ab78177c87cb39ded9b37b0d",
+ "yParity": "0x0",
+ "hash": "0x647d637e54f1de1216cdfd83477a067308365c837c6c317febc9d3593907c7cc"
+ }
+ },
+ {
+ "block": "0x48",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x39",
+ "to": "0x44bd7ae60f478fae1061e11a7739f4b94d1daf91",
+ "gas": "0x5208",
+ "gasPrice": "0x568d2fa",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x50fc2310f542cf90b3376f54d296158f5be7ad852db200f9956e3210c0f8125c",
+ "s": "0x4f880fe872915a7843c37147a69758eff0a93cfaf8ce54f36502190e54b6e5c7",
+ "hash": "0x77050c3fb6b1212cf2f739f781b024b210177b3bcbd5b62e2b3c00f1d41764d1"
+ }
+ },
+ {
+ "block": "0x4c",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x3d",
+ "to": "0x72dfcfb0c470ac255cde83fb8fe38de8a128188e",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x32ca5d0",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x116da1fc19daf120ddc2cc3fa0a834f9c176028e65d5f5d4c86834a0b4fe2a36",
+ "s": "0x17001c3ad456650dd1b28c12f41c94f50b4571da5b62e9f2a95dff4c8c3f61fd",
+ "yParity": "0x0",
+ "hash": "0x3e4639389b6a41ff157523860ffc77eb3e66a31aee867eb4148dcc5ee8b3c66f"
+ }
+ },
+ {
+ "block": "0x50",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x41",
+ "to": "0x5c62e091b8c0565f1bafad0dad5934276143ae2c",
+ "gas": "0x5208",
+ "gasPrice": "0x1dce189",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xb82a5be85322581d1e611c5871123983563adb99e97980574d63257ab98807d5",
+ "s": "0xdd49901bf0b0077d71c9922c4bd8449a78e2918c6d183a6653be9aaa334148",
+ "hash": "0x9c9de14ea0ce069a4df1c658e70e48aa7baaf64fddd4ab31bf4cb6d5550a4691"
+ }
+ },
+ {
+ "block": "0x55",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x45",
+ "to": "0xa25513c7e0f6eaa80a3337ee18081b9e2ed09e00",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0xf4dd50",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0xe8ac7cb5028b3e20e8fc1ec90520dab2be89c8f50f4a14e315f6aa2229d33ce8",
+ "s": "0x7c2504ac2e5b2fe4d430db81a923f6cc2d73b8fd71281d9f4e75ee9fc18759b9",
+ "yParity": "0x0",
+ "hash": "0xff5e3c25f68d57ee002b3b39229ffba0879390475a00fa67a679b707997df530"
+ }
+ },
+ {
+ "block": "0x5a",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x49",
+ "to": "0xbbeebd879e1dff6918546dc0c179fdde505f2a21",
+ "gas": "0x5208",
+ "gasPrice": "0x7dbb16",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x2f0119acaae03520f87748a1a855d0ef7ac4d5d1961d8f72f42734b5316a849",
+ "s": "0x182ad3a9efddba6be75007e91afe800869a18a36a11feee4743dde2ab6cc54d9",
+ "hash": "0xd696adb31daca7c3121e65d11dc00e5d5fdb72c227c701a2925dc19a46fbd43e"
+ }
+ },
+ {
+ "block": "0x5f",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x4d",
+ "to": "0xd2e2adf7177b7a8afddbc12d1634cf23ea1a7102",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x408f23",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x8556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6",
+ "s": "0x1cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4",
+ "yParity": "0x1",
+ "hash": "0x385b9f1ba5dbbe419dcbbbbf0840b76b941f3c216d383ec9deb9b1a323ee0cea"
+ }
+ },
+ {
+ "block": "0x64",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x51",
+ "to": "0x18ac3e7343f016890c510e93f935261169d9e3f5",
+ "gas": "0x5208",
+ "gasPrice": "0x212636",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x99aba91f70df4d53679a578ed17e955f944dc96c7c449506b577ac1288dac6d4",
+ "s": "0x582c7577f2343dd5a7c7892e723e98122227fca8486debd9a43cd86f65d4448a",
+ "hash": "0xd622bf64af8b9bd305e0c86152721b0711b6d24abe3748e2a8cd3a3245f6f878"
+ }
+ },
+ {
+ "block": "0x69",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x55",
+ "to": "0xde7d1b721a1e0632b7cf04edf5032c8ecffa9f9a",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x11056e",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x2a6c70afb68bff0d4e452f17042700e1ea43c10fc75e55d842344c1eb55e2e97",
+ "s": "0x27c64f6f48cfa60dc47bfb2063f9f742a0a4f284d6b65cb394871caca2928cde",
+ "yParity": "0x0",
+ "hash": "0x47efc21f94ef1ef4e9a7d76d9370713acdf8c2b822ad35409566b9251fb0bf5c"
+ }
+ },
+ {
+ "block": "0x6e",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x59",
+ "to": "0x1b16b1df538ba12dc3f97edbb85caa7050d46c14",
+ "gas": "0x5208",
+ "gasPrice": "0x8bd6d",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xabbde17fddcc6495e854f86ae50052db04671ae3b6f502d45ba1363ae68ee62c",
+ "s": "0x3aa20e294b56797a930e48eda73a4b036b0d9389893806f65af26b05f303100f",
+ "hash": "0xcf4a0a2b8229fa2f772a90fdef00d073c821c8f56d93bce703007fc5eb528e71"
+ }
+ },
+ {
+ "block": "0x73",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x5d",
+ "to": "0x043a718774c572bd8a25adbeb1bfcd5c0256ae11",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x47cdd",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x2ae4b3f6fa0e08145814f9e8da8305b9ca422e0da5508a7ae82e21f17d8c1196",
+ "s": "0x77a6ea7a39bbfe93f6b43a48be83fa6f9363775a5bdb956c8d36d567216ea648",
+ "yParity": "0x1",
+ "hash": "0xded7c87461fb84ffd49426b474741c2eace8982edf07af918bf8794415742384"
+ }
+ },
+ {
+ "block": "0x78",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x61",
+ "to": "0x2d711642b726b04401627ca9fbac32f5c8530fb1",
+ "gas": "0x5208",
+ "gasPrice": "0x24deb",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xb4d70622cd8182ff705beb3dfa5ffa4b8c9e4b6ad5ad00a14613e28b076443f6",
+ "s": "0x676eb97410d3d70cfa78513f5ac156b9797abbecc7a8c69df814135947dc7d42",
+ "hash": "0x9e2b47fc494a2285f98c89949878e11f7c6d47d24ae95bdab2801333ea8d11a7"
+ }
+ },
+ {
+ "block": "0x7d",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x65",
+ "to": "0xd10b36aa74a59bcf4a88185837f658afaf3646ef",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x12eea",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x882e961b849dc71672ce1014a55792da7aa8a43b07175d2b7452302c5b3cac2a",
+ "s": "0x41356d00a158aa670c1a280b28b3bc8bb9d194a159c05812fa0a545f5b4bc57b",
+ "yParity": "0x0",
+ "hash": "0x240efcc882536fad14fcd34be50b508cb4c39b39f1493b8d64682760505b6cf7"
+ }
+ },
+ {
+ "block": "0x82",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x69",
+ "to": "0xa5ab782c805e8bfbe34cb65742a0471cf5a53a97",
+ "gas": "0x5208",
+ "gasPrice": "0x9b8c",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x78e180a6afd88ae67d063c032ffa7e1ee629ec053306ce2c0eb305b2fb98245e",
+ "s": "0x7563e1d27126c9294391a71da19044cb964fd6c093e8bc2a606b6cb5a0a604ac",
+ "hash": "0xa28d808cbc5ef9e82cd5023ea542fab4052895618b8627c000bb8cc8ccc2e693"
+ }
+ },
+ {
+ "block": "0x87",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x6d",
+ "to": "0x4bfa260a661d68110a7a0a45264d2d43af9727de",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x4fe1",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xbb105cab879992d2769014717857e3c9f036abf31aa59aed2c2da524d938ff8",
+ "s": "0x3b5386a238de98973ff1a9cafa80c90cdcbdfdb4ca0e59ff2f48c925f0ea872e",
+ "yParity": "0x1",
+ "hash": "0x83adc66f82e98155384ae9ef0e5be253eba9be959a50bcb48a7a3e6df97d6996"
+ }
+ },
+ {
+ "block": "0x8c",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x71",
+ "to": "0x9defb0a9e163278be0e05aa01b312ec78cfa3726",
+ "gas": "0x5208",
+ "gasPrice": "0x2907",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x4adf7509b10551a97f2cb6262c331096d354c6c8742aca384e63986006b8ac93",
+ "s": "0x581250d189e9e1557ccc88190cff66de404c99754b4eb3c94bb3c6ce89157281",
+ "hash": "0x8e285b12f0ec16977055c8bc17008411883af1b5b33883a8128e50ed3e585685"
+ }
+ },
+ {
+ "block": "0x91",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x75",
+ "to": "0x7da59d0dfbe21f43e842e8afb43e12a6445bbac0",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x1513",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x6ca026ba6084e875f3ae5220bc6beb1cdb34e8415b4082a23dd2a0f7c13f81ec",
+ "s": "0x568da83b9f5855b786ac46fb241eee56b6165c3cc350d604e155aca72b0e0eb1",
+ "yParity": "0x0",
+ "hash": "0x41ca48c0312c6d3fc433f9fd363281dae924885f73ab7466f9e8c97d6ea3b993"
+ }
+ },
+ {
+ "block": "0x96",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x79",
+ "to": "0x84873854dba02cf6a765a6277a311301b2656a7f",
+ "gas": "0x5208",
+ "gasPrice": "0xad4",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xab3202c9ba5532322b9d4eb7f4bdf19369f04c97f008cf407a2668f5353e8a1f",
+ "s": "0x5affa251c8d29f1741d26b42a8720c416f7832593cd3b64dff1311a337799e8f",
+ "hash": "0x7527f1a2c9cad727c70ca0d2117fc52dbfff87962411d0b821e7418a42abd273"
+ }
+ },
+ {
+ "block": "0x9b",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x7d",
+ "to": "0x8d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f2",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x592",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xf9075613b9069dab277505c54e8381b0bb91032f688a6fe036ef83f016771897",
+ "s": "0x4cb4fc2e695439af564635863f0855e1f40865997663d900bc2ab572e78a70a2",
+ "yParity": "0x1",
+ "hash": "0xab2e87692b96ba3083b497227a9a17671bc5eee7ff12d50b850f442a4cdcd8b5"
+ }
+ },
+ {
+ "block": "0xa0",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x81",
+ "to": "0xc19a797fa1fd590cd2e5b42d1cf5f246e29b9168",
+ "gas": "0x5208",
+ "gasPrice": "0x2de",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x857754afc3330f54a3e6400f502ad4a850a968671b641e271dcb9f68aacea291",
+ "s": "0x7d8f3fb2f3062c39d4271535a7d02960be9cb5a0a8de0baef2211604576369bf",
+ "hash": "0x64f8f0ad9c6526cb33e626626a25b8660a546aefa002692e46cd4d0331cd26ed"
+ }
+ },
+ {
+ "block": "0xa5",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x85",
+ "to": "0x6922e93e3827642ce4b883c756b31abf80036649",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x17b",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x89e6d36baf81743f164397205ded9e5b3c807e943610d5b9adb9cfeb71b90299",
+ "s": "0x3d56c57f842a92a5eb71c8f9f394fe106d993960421c711498013806957fdcaf",
+ "yParity": "0x0",
+ "hash": "0x33b886e4c1c43507a08f0da97d083aa507cf905a90c17ffe20a2a24296f2db31"
+ }
+ },
+ {
+ "block": "0xaa",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x89",
+ "to": "0xbceef655b5a034911f1c3718ce056531b45ef03b",
+ "gas": "0x5208",
+ "gasPrice": "0xc5",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x626dfd18ca500eedb8b439667d9b8d965da2f2d8ffcd36a5c5b60b9a05a52d9f",
+ "s": "0x7271175e4b74032edeb9b678ffb5e460edb2986652e45ff9123aece5f6c66838",
+ "hash": "0xe92638806137815555a0ffe5cc4c2b63b29171fd6f2473736201d8c3c3dbb748"
+ }
+ },
+ {
+ "block": "0xaf",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x8d",
+ "to": "0x5a6e7a4754af8e7f47fc9493040d853e7b01e39d",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x68",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x8c62285d8318f84e669d3a135f99bbfe054422c48e44c5b9ce95891f87a37122",
+ "s": "0x28e75a73707ee665c58ff54791b62bd43a79de1522918f4f13f00ed4bd82b71b",
+ "yParity": "0x1",
+ "hash": "0x3f9133ad0b7430b124cc4b1213bc3fa72be41a58584ca05e8d863ec728890873"
+ }
+ },
+ {
+ "block": "0xb4",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x91",
+ "to": "0x27952171c7fcdf0ddc765ab4f4e1c537cb29e5e5",
+ "gas": "0x5208",
+ "gasPrice": "0x39",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x76a045602a7de6b1414bdc881a321db0ce5255e878a65513bad6ac3b7f473aa7",
+ "s": "0x1a33017b5bcf6e059de612293db8e62b4c4a3414a7ba057c08dd6172fb78a86c",
+ "hash": "0x201f5041569d4dd9e5cc533867f1864daf1a7ee1a424d703d7aa8a43b07b491d"
+ }
+ },
+ {
+ "block": "0xb9",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x95",
+ "to": "0x04d6c0c946716aac894fc1653383543a91faab60",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x20",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x39c18634a9f085ba0cd63685a54ef8f5c5b648856382896c7b0812ee603cd8a",
+ "s": "0x5ecfde61ea3757f59f0d8f0c77df00c0e68392eea1d8b76e726cb94fb5052b8a",
+ "yParity": "0x0",
+ "hash": "0xf83394fd19018fd54a5004121bc780995f99cb47832ddb11f7c50bf507606202"
+ }
+ },
+ {
+ "block": "0xbe",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x99",
+ "to": "0x478508483cbb05defd7dcdac355dadf06282a6f2",
+ "gas": "0x5208",
+ "gasPrice": "0x13",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x910304dbb7d545a9c528785d26bf9e4c06d4c84fdb1b8d38bc6ee28f3db06178",
+ "s": "0x2ffc39c46a66af7b3af96e1e016a62ca92fc5e7e6b9dbe631acbdc325b7230a1",
+ "hash": "0x586f6726554ffef84726c93123de9fb1f0194dfd55ed7ca3ceae67e27b1f4fef"
+ }
+ },
+ {
+ "block": "0xc3",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x9d",
+ "to": "0xae3f4619b0413d70d3004b9131c3752153074e45",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0xc",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x7cb73f8bf18eacc2c753098683a80208ac92089492d43bc0349e3ca458765c54",
+ "s": "0x3bf3eb6da85497e7865d119fde3718cdac76e73109384a997000c0b153401677",
+ "yParity": "0x1",
+ "hash": "0xadfacbcb99b52f33c74cbd7c45d1f0d31efc4a3f025f9832cf28e666c79c8e4c"
+ }
+ },
+ {
+ "block": "0xc8",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xa1",
+ "to": "0x7c5bd2d144fdde498406edcb9fe60ce65b0dfa5f",
+ "gas": "0x5208",
+ "gasPrice": "0x9",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x15f510b05236b83a9370eb084e66272f93b4b646e225bdef016b01b3ac406391",
+ "s": "0x3b4a2b683af1cb3ecae367c8a8e59c76c259ce2c5c5ffd1dc81de5066879e4b8",
+ "hash": "0xed00ce6bd533009ddfb39d7735f1e2c468a231cf4c5badb59d1e1234c5fe3794"
+ }
+ },
+ {
+ "block": "0xcd",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xa5",
+ "to": "0x9a7b7b3a5d50781b4f4768cd7ce223168f6b449b",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x4f3e818870a240e585d8990561b00ad3538cf64a189d0f5703a9431bc8fd5f25",
+ "s": "0x312f64dd9ab223877e94c71d83cb3e7fe359b96250d6a3c7253238979dd2f32a",
+ "yParity": "0x0",
+ "hash": "0x883c915c1ef312df1e499ef78d09767a374706d8ec89af9c65c46acd675bf817"
+ }
+ },
+ {
+ "block": "0xd2",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xa9",
+ "to": "0x85f97e04d754c81dac21f0ce857adc81170d08c6",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x547e9550b5c687a2eb89c66ea85e7cd06aa776edd3b6e3e696676e22a90382b0",
+ "s": "0x28cb3ab4ef2761a5b530f4e05ef50e5fc957cfbc0342f98b04aa2882eec906b2",
+ "hash": "0x27d83955c23134e42c9beaa88332f770d09e589354c1047870328b7a2f8612c9"
+ }
+ },
+ {
+ "block": "0xd7",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xad",
+ "to": "0x414a21e525a759e3ffeb22556be6348a92d5a13e",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x47b3309af68dd86089494d30d3356a69a33aa30945e1f52a924298f3167ab66",
+ "s": "0xb8b7bd6670a8bbcb89555528ff5719165363988aad1905a90a26c02633f8b9",
+ "yParity": "0x1",
+ "hash": "0xb75adb0bd26a8060f67c947b699471d71a66c61f2b8c6903a776c3eca7ad731e"
+ }
+ },
+ {
+ "block": "0xdc",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xb1",
+ "to": "0xfb95aa98d6e6c5827a57ec17b978d647fcc01d98",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xc71a69f756a2ef145f1fb1c9b009ff10af72ba0ee80ce59269708f917878bfb0",
+ "s": "0x3bfe6a6c41b3fe72e8e12c2927ee5df6d3d37bd94346a2398d4fcf80e1028dde",
+ "hash": "0x0301d78cc4bc0330c468026de4671377a07560c2356293c2af44334e6424361a"
+ }
+ },
+ {
+ "block": "0xe1",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xb5",
+ "to": "0xf031efa58744e97a34555ca98621d4e8a52ceb5f",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x99b1b125ecb6df9a13deec5397266d4f19f7b87e067ef95a2bc8aba7b9822348",
+ "s": "0x56e2ee0d8be47d342fe36c22d4a9be2f26136dba3bd79fa6fe47900e93e40bf3",
+ "yParity": "0x1",
+ "hash": "0x6e07cf26de1881f062629d9efa026c55b9e8084082086e974ddeb66654cd9530"
+ }
+ },
+ {
+ "block": "0xe6",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xb9",
+ "to": "0x0a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xd2aa10777b7c398921921258eeecaff46668278fd6f814ea4edb06f2a1076353",
+ "s": "0x542ef4ed484a1403494238e418bb8d613012871710e72dde77bb1fa877f1fae3",
+ "hash": "0xd77aeb22fbd8f99b75c970995d226b6985f2dcac6f22d65aa5d492d66e90f53f"
+ }
+ },
+ {
+ "block": "0xeb",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xbd",
+ "to": "0xf8d20e598df20877e4d826246fc31ffb4615cbc0",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xc982933a25dd67a6d0b714f50be154f841a72970b3ed52d0d12c143e6a273350",
+ "s": "0x7a9635960c75551def5d050beee4014e4fef2353c39d300e649c199eebc8fd5e",
+ "yParity": "0x1",
+ "hash": "0x597bc815e8b0c315e692257aabe4ecfce7055fa3659f02dd8444c7d58c9055f3"
+ }
+ },
+ {
+ "block": "0xf0",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xc1",
+ "to": "0xfde502858306c235a3121e42326b53228b7ef469",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x3d79397e88a64f6c2ca58b5ec7ba305012e619331946e60d6ab7c40e84bf1a34",
+ "s": "0x4278773d2796a0944f6bedadea3794b7ad6a18ffd01496aabf597d4a7cf75e17",
+ "hash": "0xe9c1c01813ee52f2a9b8aa63e200714c7527315caf55d054890c10acc73c6cec"
+ }
+ },
+ {
+ "block": "0xf5",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xc5",
+ "to": "0x27abdeddfe8503496adeb623466caa47da5f63ab",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xdeade75f98612138653ca1c81d8cc74eeda3e46ecf43c1f8fde86428a990ae25",
+ "s": "0x65f40f1aaf4d29268956348b7cc7fa054133ccb1522a045873cb43a9ffa25283",
+ "yParity": "0x1",
+ "hash": "0x2beff883cd58f8d155069d608dfc47f730a07f1ed361987b008c17a4b8b84a4b"
+ }
+ },
+ {
+ "block": "0xfa",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xc9",
+ "to": "0xaa7225e7d5b0a2552bbb58880b3ec00c286995b8",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x968ae76ffc10f7b50ca349156119aaf1d81a8772683d1c3ed005147f4682694",
+ "s": "0x60f5f10a015e8685a3099140c2cc3ba0dc69026df97fb46748008c08978d162a",
+ "hash": "0x084d5438c574a2332976d95cfae552edb797001b5af69eacf4486538ab4bdbd2"
+ }
+ },
+ {
+ "block": "0xff",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xcd",
+ "to": "0xa8100ae6aa1940d0b663bb31cd466142ebbdbd51",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x54eafef27c71a73357c888f788f1936378929e1cdb226a205644dc1e2d68f32b",
+ "s": "0x59af490b8ef4a4e98a282d9046655fc8818758e2af8ace2489927aaa3890fda3",
+ "yParity": "0x0",
+ "hash": "0xecce661913425dbe38e2d30e7ec20ead32185d76f516525148d2647ee94aac8e"
+ }
+ },
+ {
+ "block": "0x104",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xd1",
+ "to": "0xa8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x4c1d18013fb8b0554b8aaa549ee64a5a33c98edd5e51257447b4dd3b37f2ade",
+ "s": "0x5e3a37e5ddec2893b3fd38c4983b356c26dab5abb8b8ba6f56ac1ab9e747268b",
+ "hash": "0x0d903532e3740a8fb644943befee0187e6180eb31a327afc73e042ec314c02cc"
+ }
+ },
+ {
+ "block": "0x109",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xd5",
+ "to": "0xac9e61d54eb6967e212c06aab15408292f8558c4",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x898d514a1f15103335e066d0625c4ec34a69a03480d67dcb3d3fe0f4f932100a",
+ "s": "0x7e130fed862c1482467d112f64fb59e005068b52c291003c908b625b4993e20e",
+ "yParity": "0x1",
+ "hash": "0xdd62d8c48dd14b156b3ea74d123fe3ddd7bc7700d0f189df3761ec7a8d65d1e9"
+ }
+ },
+ {
+ "block": "0x10e",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xd9",
+ "to": "0x653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xf1c5d5e335842170288da2c7c7af6856ea0b566d2b4ab4b00a19cb94144d466c",
+ "s": "0x2043677d1c397a96a2f8a355431a59a0d5c40fc053e9c45b6872464f3c77c5dc",
+ "hash": "0x284452da997f42dbe0e511078f5005514fdeda8d0905439fe2f3a5ecc3aec1ac"
+ }
+ },
+ {
+ "block": "0x113",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xdd",
+ "to": "0xd8c50d6282a1ba47f0a23430d177bbfbb72e2b84",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x4330fe20e8b84e751616253b9bccc5ff2d896e00593bfbef92e81e72b4d98a85",
+ "s": "0x7977b87c7eca1f6a8e4a535cb26860e32487c6b4b826623a7390df521b21eac7",
+ "yParity": "0x1",
+ "hash": "0xd667f29e2cccf282a82791cb46f9181ad04c8179bc11af957c499b3627907a6f"
+ }
+ },
+ {
+ "block": "0x118",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xe1",
+ "to": "0xb519be874447e0f0a38ee8ec84ecd2198a9fac77",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xcfbd9ff7eeb9aef477970dcba479f89c7573e6167d16d0882ead77b20aaee690",
+ "s": "0x1e34175b1b1758a581ca13f2ca021698933b1e8269c70fcb94c5e4aa39ee9b8e",
+ "hash": "0x935596bc447ea87dca90e3bac15f679129af2c813abe1657811f70dcafe660c2"
+ }
+ },
+ {
+ "block": "0x11d",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xe5",
+ "to": "0xaf2c6f1512d1cabedeaf129e0643863c57419732",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xc23170a740ba640770aca9fb699a2799d072b2466c97f126a834d86bdb22f516",
+ "s": "0x3f242217b60ab672f352ae51249a8876a034ee51b6b4ad4a41b4d300c48e79f4",
+ "yParity": "0x1",
+ "hash": "0xc659a1be386492afe2ca97cbbe9d1645763b502030c17e3acf9d539e22b74093"
+ }
+ },
+ {
+ "block": "0x122",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xe9",
+ "to": "0xb70654fead634e1ede4518ef34872c9d4f083a53",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x953d5aa69077225dba6a0333ea4d69a05f652e0d2abb8df492a7e6a9d0cdbe3d",
+ "s": "0x4e41cb847aa131b9bb1e19cb3dd5f7a6cc2ac8b7f459ab8c3061380d41721ff",
+ "hash": "0x6f7f93620049c80ba6429e3c2f7563f7048f725f245c22bcc6de438fd394bb7e"
+ }
+ },
+ {
+ "block": "0x127",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xed",
+ "to": "0xbe3eea9a483308cb3134ce068e77b56e7c25af19",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x190737acd3a2a298d5a6f96a60ced561e536dd9d676c8494bc6d71e8b8a90b60",
+ "s": "0x2c407a67004643eba03f80965fea491c4a6c25d90d5a9fd53c6a61b62971e7c5",
+ "yParity": "0x0",
+ "hash": "0xe48311c620199dfc77bc280caa0a1bcbbd00457b079a7154a6f8bc229beb41f1"
+ }
+ },
+ {
+ "block": "0x12c",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xf1",
+ "to": "0x08037e79bb41c0f1eda6751f0dabb5293ca2d5bf",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xe3edf14f32e7cacb36fd116b5381fac6b12325a5908dcec2b8e2c6b5517f5ec5",
+ "s": "0x51429c4c1e479fa018b7907e7e3b02a448e968368a5ce9e2ea807525d363f85e",
+ "hash": "0xa960e3583c41a164dc743eac939626f891f20f7dfdf71f204c2f84ca1087ae90"
+ }
+ },
+ {
+ "block": "0x131",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xf5",
+ "to": "0xf16ba6fa61da3398815be2a6c0f7cb1351982dbc",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x8dac03d829e6f8eab08661cd070c8a58eed41467ad9e526bb3b9c939e3fd4482",
+ "s": "0x2ac7208f150195c44c455ddeea0bbe104b9121fef5cba865311940f4de428eec",
+ "yParity": "0x1",
+ "hash": "0xc7ccef252840e9fc1821f2c2eb0ca8c9508ff3f4c23f85322e09dd9313849694"
+ }
+ },
+ {
+ "block": "0x136",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xf9",
+ "to": "0x17333b15b4a5afd16cac55a104b554fc63cc8731",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xf2179ec11444804bb595a6a2f569ea474b66e654ff8d6d162ec6ed565f83c1aa",
+ "s": "0x657ed11774d5d4bb0ed0eb1206d1d254735434a0c267912713099336c2dc147a",
+ "hash": "0x45ed5258df6ecd5ba8b99db384e39d22c193662830e79f972547d81e3857cc70"
+ }
+ },
+ {
+ "block": "0x13b",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0xfd",
+ "to": "0xd20b702303d7d7c8afe50344d66a8a711bae1425",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x67bed94b25c4f3ab70b3aae5cd44c648c9807cdf086299e77cf2977b9bce8244",
+ "s": "0x76661b80df9b49579fce2e2201a51b08ecc4eb503d5f5517ecb20156fde7ec5a",
+ "yParity": "0x1",
+ "hash": "0xa3b085cc524be64d822be105f3bb92c05c773cb93bffc774ba9aac21f9603ce6"
+ }
+ },
+ {
+ "block": "0x140",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x101",
+ "to": "0xdd1e2826c0124a6d4f7397a5a71f633928926c06",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x1f5208621cee9149c99848d808ee0fa8d57b358afbd39dc594f383b7f525f4c6",
+ "s": "0x1960c6254e869f06cfa3263972aa8e7cc79aec12caa728515c420d35b1336c0e",
+ "hash": "0x34671329e36adeee3261ea7313388804f481e6a0e2f77cce6961aed112498803"
+ }
+ },
+ {
+ "block": "0x145",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x105",
+ "to": "0x1219c38638722b91f3a909f930d3acc16e309804",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x63adb9abb5014935b3dbf8c31059d6f1d9e12068a3f13bd3465db2b5a7f27f98",
+ "s": "0x56f0f5bed39985d0921989b132e9638472405a2b1ba757e22df3276ca9b527fa",
+ "yParity": "0x1",
+ "hash": "0x7bfa3e961b16291e9ee2f4dc0b6489bb0b12ff7a6ed6491c100dd1041472ff9e"
+ }
+ },
+ {
+ "block": "0x14a",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x109",
+ "to": "0x1f5746736c7741ae3e8fa0c6e947cade81559a86",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xedd3402a6c7a96114e4c8520d7bf3f06c00d9f24ee08de4c8afdbf05b4487b7d",
+ "s": "0x68cd4cf2242a8df916b3594055ee05551b77021bbea9b9eb9740f9a8e6466d80",
+ "hash": "0x90ea391ff615d345ad4e35e53af26e283fc2fd9ecb3221a9610fb2a376c38caf"
+ }
+ },
+ {
+ "block": "0x14f",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x10d",
+ "to": "0x9ae62b6d840756c238b5ce936b910bb99d565047",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x25cc19f12be3ff2a51342412dc152953e8e8b61c9c3858c9d476cc214be4e30",
+ "s": "0x193960b0d01b790ef99b9a39b7475d18e83499f1635fc0a3868fc67c4da5b2c3",
+ "yParity": "0x0",
+ "hash": "0xa1ea0831d6727a0e7316822d3cc3815f1e2ba71e124fcd8b886610d5d42fd5ff"
+ }
+ },
+ {
+ "block": "0x154",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x111",
+ "to": "0xb55a3d332d267493105927b892545d2cd4c83bd6",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x73cc84153b8891468325ac12743faf7e373b78dbf8b9f856cb2622c7b4fd10e1",
+ "s": "0x388714fe9d2f85a88b962e213cbe1fa3c4a9823cea051cf91c607ecbd90093d8",
+ "hash": "0xd30ff6e59e0e1278dab8083cb01e1e66900adc72cc4263cbdffc98e08a728b89"
+ }
+ },
+ {
+ "block": "0x159",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x115",
+ "to": "0xb68176634dde4d9402ecb148265db047d17cb4ab",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x9f3175e9aa2fe2332600b71de0b0977c7c60ccbeee66ea360226326817f2d59b",
+ "s": "0x6a870e0876002f789b3203f4a33d5e621ac67051704e1f2260b80d816260b3e6",
+ "yParity": "0x0",
+ "hash": "0x5565d4f07ad007f4bfe27837904f2ce365cff6c036aa5169df651f217944b1f4"
+ }
+ },
+ {
+ "block": "0x15e",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x119",
+ "to": "0xdfe052578c96df94fa617102199e66110181ed2c",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x20ee6a1ada31c18eac485e0281a56fc6d8c4152213d0629e6d8dd325adb60b1",
+ "s": "0xf72e01c463b98817219db62e689416c510866450efc878a6035e9346a70795f",
+ "hash": "0x9055a34f1c764ce297f1bce6c94680a0e8d532debeb6af642c956122f4c7d079"
+ }
+ },
+ {
+ "block": "0x163",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x11d",
+ "to": "0x33fc6e8ad066231eb5527d1a39214c1eb390985d",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x167190e2e0fed95ab5c7265a53f25a92d659e1d46eb9ecbac193e7151b82ec1c",
+ "s": "0x269353e9c5ef331135563e2983279669220687652e7f231725303ccf7d2a8ebd",
+ "yParity": "0x1",
+ "hash": "0x0aa77f1fa0e9ab541616fb3104788109f84010d4b410508e5779f052ee49c5b9"
+ }
+ },
+ {
+ "block": "0x168",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x121",
+ "to": "0x662fb906c0fb671022f9914d6bba12250ea6adfb",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xd3a858be3712102b61ec73c8317d1e557043f308869f4a04e3a4578e2d9aa7e7",
+ "s": "0x202a5f044cc84da719ec69b7985345b2ef82cf6b0357976e99e46b38c77fe613",
+ "hash": "0x01bdc2fb7f53293c98e430dc42b1ef18773493f0f1bd03460eb45e438168048d"
+ }
+ },
+ {
+ "block": "0x16d",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x125",
+ "to": "0xf1fc98c0060f0d12ae263986be65770e2ae42eae",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x6563737b6bfddfb8bc5ec084651a8e51e3b95fe6ed4361065c988acaf764f210",
+ "s": "0xa96a1747559028cd02304adb52867678419ebef0f66012733fea03ee4eae43b",
+ "yParity": "0x0",
+ "hash": "0x36cf0f21e046b484333889a22e4880ad05807f2922340e6e822591cfa5138815"
+ }
+ },
+ {
+ "block": "0x172",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x129",
+ "to": "0xa92bb60b61e305ddd888015189d6591b0eab0233",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x626bd8978288bcf1d7719926fba91597d6aa8ead945c89044693d780523a05dd",
+ "s": "0x74494ccf5362aa73db798940296b77b80a7ec6037f5ed2c946094b9df8a2347",
+ "hash": "0x8cb5e311a3e79a31c06afaecbbf9c814759f039f55b06ead4e8a1c2933766c8c"
+ }
+ },
+ {
+ "block": "0x177",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x12d",
+ "to": "0x469542b3ece7ae501372a11c673d7627294a85ca",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x9add65921c40226ee4a686b9fa70c7582eba8c033ccc9c27775c6bc33c9232fb",
+ "s": "0x21a6e73ccb2f16e540594b4acbba2c852a3e853742359fcbc772880879fe1197",
+ "yParity": "0x0",
+ "hash": "0x55c8ee8da8d54305ca22c9d7b4226539a60741ed599327d33013f8d0385c61bd"
+ }
+ },
+ {
+ "block": "0x17c",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x131",
+ "to": "0x7f2dce06acdeea2633ff324e5cb502ee2a42d979",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xfd195ea41804b21ffffdbca38fd49a9874371e51e81642917d001d201a943e24",
+ "s": "0x542bca46a2dc92fddb9abffcf2b3e78dc491d6e95040692e6d1446a6b487a42a",
+ "hash": "0x3964c50008f0dce6974ef2c088a84207191eb56ab4ac86cbf5d149a661ecb479"
+ }
+ },
+ {
+ "block": "0x181",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x135",
+ "to": "0x3bcc2d6d48ffeade5ac5af3ee7acd7875082e50a",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x3931e5e7d02ed045834da39a409083c260fbc96dc256c1d927f1704147eeaeb6",
+ "s": "0x215269010bb3e7dd8f03d71db3e617985b447c2e0dd6fc0939c125db43039d0f",
+ "yParity": "0x0",
+ "hash": "0x23583194a4443b0144115327770bf71f645283515ca26fc775dd23244a876e83"
+ }
+ },
+ {
+ "block": "0x186",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x139",
+ "to": "0xf83af0ceb5f72a5725ffb7e5a6963647be7d8847",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xa38cf9766454bd02d4f06f5bd214f5fe9e53b7a299eda5c7523060704fcdb751",
+ "s": "0x67c33351f6f7bbd9de5b5435f6cadc10ba5e94f3cbcc40ee53496c782f99d71f",
+ "hash": "0x41019c72018f2f499368e96aed89293b24873f611018c3787eeb81a0a01b667b"
+ }
+ },
+ {
+ "block": "0x18b",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x13d",
+ "to": "0x469dacecdef1d68cb354c4a5c015df7cb6d655bf",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x6faf4090490862eba3c27dfe0a030a442ccc89d4478eca3ed09039386554f07b",
+ "s": "0x656f741b64c54808ac5a6956540d3f7aaec811bf4efa7239a0ca0c7fb410b4d6",
+ "yParity": "0x1",
+ "hash": "0x054500013715ec41cb39492f2856925c7f22f80fd22365f19de8124b14e77e90"
+ }
+ },
+ {
+ "block": "0x190",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x141",
+ "to": "0xf14d90dc2815f1fc7536fc66ca8f73562feeedd1",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x4a18131d30b0344910cae7c41ee5c1c23171c40292d34e9a82c9c7cef3d3836a",
+ "s": "0x598a3835ad1903c3d7ad158c57ff0db10e12d8acbef318ddd0514f671a08ce94",
+ "hash": "0x1b562d975247f54df92dc775c61ef8fb004714fd57d0c804dd64e44be2f10cb5"
+ }
+ },
+ {
+ "block": "0x195",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x145",
+ "to": "0x360671abc40afd33ae0091e87e589fc320bf9e3d",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x9b0a44741dc7e6cb0f88199ca38f15034fab4164d9055788834e8123b7264c87",
+ "s": "0x2c38a3ecda52aebc3725c65ee1cd0461a8d706ddfc9ed27d156cf50b61ef5069",
+ "yParity": "0x0",
+ "hash": "0x3e3bec1253082bf314cb1155ef241912bc842b8ced86b70e5e3b24585a130d66"
+ }
+ },
+ {
+ "block": "0x19a",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x149",
+ "to": "0x579ab019e6b461188300c7fb202448d34669e5ff",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xde600e017080351550412ac87f184ec2c3f672e08f1c362ab58b94631e8864dc",
+ "s": "0x47d41b8691a1f7f8818e59ad473451a0edfc88826a6b808f84f56baed90d5634",
+ "hash": "0x519fbf530d16289510ebb27b099ad16ad03e72227497db7a62e6c0e89d3a708a"
+ }
+ },
+ {
+ "block": "0x19f",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x14d",
+ "to": "0x88654f0e7be1751967bba901ed70257a3cb79940",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xa79b0ff9846673061d1b90a17cd8bd9e7c7f62b99b39fbe4749777d3ed4544e0",
+ "s": "0x750ecfe9895402861ebea87e9b483b2c116bc2d4920329aa1c29efb9dcdf47e6",
+ "yParity": "0x1",
+ "hash": "0x6364bf260fee1aea143ec4a4c596d64e15252f8fa4c7ab7ae69d51ff4cbd343b"
+ }
+ },
+ {
+ "block": "0x1a4",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x151",
+ "to": "0x47e642c9a2f80499964cfda089e0b1f52ed0f57d",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xc37c23a91d6abced211855a2d6d5e383f54aa6ff40c26abc5f27a22cdafa5618",
+ "s": "0x190f82ff101eabad8b9c7041006dcb3e3a9a85c814938bef8ec7d1aa63fa5892",
+ "hash": "0x2ee70986d957daba62588ac40c9bf75f6707a34dc5ef5897ae7cd3998f2e05bc"
+ }
+ },
+ {
+ "block": "0x1a9",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x155",
+ "to": "0xd854d6dd2b74dc45c9b883677584c3ac7854e01a",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x7a17de801de3309b57dd86df30b61553d5c04071581d243f33f43c4d64930e09",
+ "s": "0x75f7e820212e8f96d7583c66548719db621537fe20f7568d5ee62176881b70e8",
+ "yParity": "0x0",
+ "hash": "0xbaf8e87ba94a0d70e37443c4475b2525806827b3ae964b30eb4dad7936b2eb6e"
+ }
+ },
+ {
+ "block": "0x1ae",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x159",
+ "to": "0xc305dd6cfc073cfe5e194fc817536c419410a27d",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x163f29bc7be2e8fe3c6347fe4de06fa7330e3a3049c0e9dcded1795ff1c1e810",
+ "s": "0x4ea7492a5e457fd21252166f5a5d5d9d5e5c7a19da2c7fd4a822bf60156b91a9",
+ "hash": "0x4a84eeb0addd194ae92631aa43ed4f4fece16258bcbbc91de6324e20bde0f914"
+ }
+ },
+ {
+ "block": "0x1b3",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x15d",
+ "to": "0x2143e52a9d8ad4c55c8fdda755f4889e3e3e7721",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0x673c5473955d0d26d49b25b82af905ee33ba365178f44dc4ac39221efec23c88",
+ "s": "0x17f46fc9b15ba0c1ea78d4d9f773582d94f61f6471f2918cb0598f33eb9bc89b",
+ "yParity": "0x1",
+ "hash": "0x01b1e85401ca88bc02c33956d0bfeea9ec0b6c916f1478d4eae39818e999cb74"
+ }
+ },
+ {
+ "block": "0x1b8",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x161",
+ "to": "0x0fe037febcc3adf9185b4e2ad4ea43c125f05049",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x654dc39f93a879b9aec58ace2fdbd5c47e383cae2d14f1a49f6ec93d539be892",
+ "s": "0x70505a0ef2e83f057e9844dbd56eda0949197f0c4a2b6d0f2979db1710fca4ed",
+ "hash": "0xf8c7948d4418ad9948d7352c6c21dcb5b7f72664dfcfe553dfc444df7afc9c0b"
+ }
+ },
+ {
+ "block": "0x1bd",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x165",
+ "to": "0x046dc70a4eba21473beb6d9460d880b8cfd66613",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x9a954eff1b0e590a3a78b724b687c6ab944181990998780d56cc3593c704996e",
+ "s": "0x418db96b5dc1057f6acb018244f82ed6ece03d88c07f6ae767eaebe3b7ac9387",
+ "yParity": "0x0",
+ "hash": "0xf09a7e0da3b14049923d019fb5d457531ddaa4456cf84124a17479b0bfd6261b"
+ }
+ },
+ {
+ "block": "0x1c2",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x169",
+ "to": "0x104eb07eb9517a895828ab01a3595d3b94c766d5",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0x597dbb3f69603be721ae0f2a63eeee9f008829ff273b54243673f9ea192ddc0a",
+ "s": "0x1f7dd04defb45af840d46a950b8bede0b3ce8a718004c1ca2f3bbd4efcbd7563",
+ "hash": "0x00c458459a2d2f501907a6a4122fba7ae70fb3ef632676e492912231022f80c8"
+ }
+ },
+ {
+ "block": "0x1c7",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x16d",
+ "to": "0x46b61db0aac95a332cecadad86e52531e578cf1f",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x774ced5c8674413b351ae8ac3b96705d1d3db10deae39134572be985f16c008b",
+ "s": "0x6f3e4b250f84fcf95ae85946da8a1c79f922a211dbe516fcfcff0180911429b8",
+ "yParity": "0x0",
+ "hash": "0x6603c100a34224ddb8aaeb9e234f0c611d40a5df807de68803b71e0ff0f3aea8"
+ }
+ },
+ {
+ "block": "0x1cc",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x171",
+ "to": "0x8a817bc42b2e2146dc4ca4dc686db0a4051d2944",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xa755d1c641b8965ea140ad348135496fc412ffa43a72bbd2c7c0e26b814a75f1",
+ "s": "0x67d81cca370b6ea40ccd2ad3662d16fa36bd380845bee04c55c6531455d0687d",
+ "hash": "0x46e00cb4ede9be515c8910a31881df229ebb2804722ad9d6723e1101a87f1889"
+ }
+ },
+ {
+ "block": "0x1d1",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x175",
+ "to": "0x23e6931c964e77b02506b08ebf115bad0e1eca66",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x6263b1d5b9028231af73bfa386be8fc770e11f60137428378137c34f12c2c242",
+ "s": "0x2b340f5b45217d9b914921a191ce5f7ba67af038e3b3c2c72aaca471412b02f7",
+ "yParity": "0x0",
+ "hash": "0xa5b751caaaff89a472fb427c17ac7637b4a9de7cda34beaaf891516278655479"
+ }
+ },
+ {
+ "block": "0x1d6",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x179",
+ "to": "0x878dedd9474cfa24d91bccc8b771e180cf01ac40",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x515a62775619f55c366d080a7c397ea42dcfd2fdcce1862ef98dab875077f367",
+ "s": "0x23756d4f3bd644dde1c25f8cde45fbea557dacf0492bbecb409f6b2cdacbb9b8",
+ "hash": "0x2e232fb6d73423c9dcaff38257d36fcad74a2c627a70030b43a0bed36d136625"
+ }
+ },
+ {
+ "block": "0x1db",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x17d",
+ "to": "0x45dcb3e20af2d8ba583d774404ee8fedcd97672b",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x1",
+ "r": "0xd3b69c226bf73db84babb6185a83b0dd491467adfc01d279df4c09d5d2d3fba4",
+ "s": "0x368ddb772caa32963df97961cf8ef0db33e0df5945000f0e39d9a288bd73ee30",
+ "yParity": "0x1",
+ "hash": "0xc80615944f9bfeb945b7416052667eec0a78b2f3beb7c2811ebb9e9210e45c4c"
+ }
+ },
+ {
+ "block": "0x1e0",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x181",
+ "to": "0x50996999ff63a9a1a07da880af8f8c745a7fe72c",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0xf06ad492cdd04b44f321abe9cb98e5977f03909173e4b6361f50d44c080f9d6a",
+ "s": "0x7fdc23c04fab8e0a576e6896b13a661b2dcb256cf8ca42fa21f0f370097a53a4",
+ "hash": "0x8c1f1466ce25a97e88ab37bc9b5362eaf95fb523fb80d176429fa41c2fa2d629"
+ }
+ },
+ {
+ "block": "0x1e5",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x185",
+ "to": "0x913f841dfc8703ae76a4e1b8b84cd67aab15f17a",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0xd4b8d15fc05f29b58f0459b336dc48b142e8d14572edad06e346aa7728491ce8",
+ "s": "0x64c8078691ba1c4bb110f6dff74e26d3c0df2505940558746a1c617091ddc61a",
+ "yParity": "0x0",
+ "hash": "0x969e178ea1a76626b96bf06e207edb6299c36c6a14e46462960832feb93f6d42"
+ }
+ },
+ {
+ "block": "0x1ea",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x189",
+ "to": "0xb47f70b774d780c3ec5ac411f2f9198293b9df7a",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd10a0",
+ "r": "0xd33c0cd7f521603ea8deaa363ab591627f5af193759f0aeb8cd9fe4f22a4dd5c",
+ "s": "0x667bb0ee041403cba2e562882bb9afc43bd560af3c95136c7bf4f1e361355316",
+ "hash": "0xa35c19e4e8154c35656544b92e88fb62c4210e38f09608248e2a99841ac99964"
+ }
+ },
+ {
+ "block": "0x1ef",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x2",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x18d",
+ "to": "0x6e3d512a9328fa42c7ca1e20064071f88958ed93",
+ "gas": "0x5208",
+ "gasPrice": null,
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerGas": "0x8",
+ "value": "0x1",
+ "input": "0x",
+ "accessList": [],
+ "v": "0x0",
+ "r": "0x990aa3c805c666109799583317176d55a73d96137ff886be719a36537d577e3d",
+ "s": "0x5d1244d8c33e85b49e2061112549e616b166a1860b07f00ff963a0b37c29bcaa",
+ "yParity": "0x0",
+ "hash": "0xeb282a48d309db881eead661ee7c64696b2699fa7c431d39a573ecaa0bc31052"
+ }
+ },
+ {
+ "block": "0x1f4",
+ "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f",
+ "tx": {
+ "type": "0x0",
+ "chainId": "0xc72dd9d5e883e",
+ "nonce": "0x191",
+ "to": "0x15af6900147a8730b5ce3e1db6333f33f64ebb2c",
+ "gas": "0x5208",
+ "gasPrice": "0x8",
+ "maxPriorityFeePerGas": null,
+ "maxFeePerGas": null,
+ "value": "0x1",
+ "input": "0x",
+ "v": "0x18e5bb3abd109f",
+ "r": "0x85b3c275e830c2034a4666e3a57c8640a8e5e7b7c8d0687467e205c037b4c5d7",
+ "s": "0x52e2aa8b60be142eee26f197b1e0a983f8df844c770881d820dfc4d1bb3d9adc",
+ "hash": "0x22e616c85493bcd23147d1c9f5dd081b32daf5c7b3e824f61b5fc1bd34a47e67"
+ }
+ }
+ ],
+ "withdrawals": {
+ "101": {
+ "withdrawals": [
+ {
+ "index": "0x4",
+ "validatorIndex": "0x5",
+ "address": "0x3f79bb7b435b05321651daefd374cdc681dc06fa",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "106": {
+ "withdrawals": [
+ {
+ "index": "0x5",
+ "validatorIndex": "0x5",
+ "address": "0x189f40034be7a199f1fa9891668ee3ab6049f82d",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "111": {
+ "withdrawals": [
+ {
+ "index": "0x6",
+ "validatorIndex": "0x5",
+ "address": "0x65c74c15a686187bb6bbf9958f494fc6b8006803",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "116": {
+ "withdrawals": [
+ {
+ "index": "0x7",
+ "validatorIndex": "0x5",
+ "address": "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "121": {
+ "withdrawals": [
+ {
+ "index": "0x8",
+ "validatorIndex": "0x5",
+ "address": "0xa1fce4363854ff888cff4b8e7875d600c2682390",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "126": {
+ "withdrawals": [
+ {
+ "index": "0x9",
+ "validatorIndex": "0x5",
+ "address": "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "131": {
+ "withdrawals": [
+ {
+ "index": "0xa",
+ "validatorIndex": "0x5",
+ "address": "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "136": {
+ "withdrawals": [
+ {
+ "index": "0xb",
+ "validatorIndex": "0x5",
+ "address": "0x4f362f9093bb8e7012f466224ff1237c0746d8c8",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "141": {
+ "withdrawals": [
+ {
+ "index": "0xc",
+ "validatorIndex": "0x5",
+ "address": "0x075198bfe61765d35f990debe90959d438a943ce",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "146": {
+ "withdrawals": [
+ {
+ "index": "0xd",
+ "validatorIndex": "0x5",
+ "address": "0x956062137518b270d730d4753000896de17c100a",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "151": {
+ "withdrawals": [
+ {
+ "index": "0xe",
+ "validatorIndex": "0x5",
+ "address": "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "156": {
+ "withdrawals": [
+ {
+ "index": "0xf",
+ "validatorIndex": "0x5",
+ "address": "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "161": {
+ "withdrawals": [
+ {
+ "index": "0x10",
+ "validatorIndex": "0x5",
+ "address": "0x8a8950f7623663222542c9469c73be3c4c81bbdf",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "166": {
+ "withdrawals": [
+ {
+ "index": "0x11",
+ "validatorIndex": "0x5",
+ "address": "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "171": {
+ "withdrawals": [
+ {
+ "index": "0x12",
+ "validatorIndex": "0x5",
+ "address": "0x087d80f7f182dd44f184aa86ca34488853ebcc04",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "176": {
+ "withdrawals": [
+ {
+ "index": "0x13",
+ "validatorIndex": "0x5",
+ "address": "0xf4f97c88c409dcf3789b5b518da3f7d266c48806",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "181": {
+ "withdrawals": [
+ {
+ "index": "0x14",
+ "validatorIndex": "0x5",
+ "address": "0x892f60b39450a0e770f00a836761c8e964fd7467",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "186": {
+ "withdrawals": [
+ {
+ "index": "0x15",
+ "validatorIndex": "0x5",
+ "address": "0x281c93990bac2c69cf372c9a3b66c406c86cca82",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "191": {
+ "withdrawals": [
+ {
+ "index": "0x16",
+ "validatorIndex": "0x5",
+ "address": "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "196": {
+ "withdrawals": [
+ {
+ "index": "0x17",
+ "validatorIndex": "0x5",
+ "address": "0xd1211001882d2ce16a8553e449b6c8b7f71e6183",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "201": {
+ "withdrawals": [
+ {
+ "index": "0x18",
+ "validatorIndex": "0x5",
+ "address": "0x4fb733bedb74fec8d65bedf056b935189a289e92",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "206": {
+ "withdrawals": [
+ {
+ "index": "0x19",
+ "validatorIndex": "0x5",
+ "address": "0xc337ded6f56c07205fb7b391654d7d463c9e0c72",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "211": {
+ "withdrawals": [
+ {
+ "index": "0x1a",
+ "validatorIndex": "0x5",
+ "address": "0x28969cdfa74a12c82f3bad960b0b000aca2ac329",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "216": {
+ "withdrawals": [
+ {
+ "index": "0x1b",
+ "validatorIndex": "0x5",
+ "address": "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "221": {
+ "withdrawals": [
+ {
+ "index": "0x1c",
+ "validatorIndex": "0x5",
+ "address": "0x2795044ce0f83f718bc79c5f2add1e52521978df",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "226": {
+ "withdrawals": [
+ {
+ "index": "0x1d",
+ "validatorIndex": "0x5",
+ "address": "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "231": {
+ "withdrawals": [
+ {
+ "index": "0x1e",
+ "validatorIndex": "0x5",
+ "address": "0xd0752b60adb148ca0b3b4d2591874e2dabd34637",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "236": {
+ "withdrawals": [
+ {
+ "index": "0x1f",
+ "validatorIndex": "0x5",
+ "address": "0x45f83d17e10b34fca01eb8f4454dac34a777d940",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "241": {
+ "withdrawals": [
+ {
+ "index": "0x20",
+ "validatorIndex": "0x5",
+ "address": "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "246": {
+ "withdrawals": [
+ {
+ "index": "0x21",
+ "validatorIndex": "0x5",
+ "address": "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "251": {
+ "withdrawals": [
+ {
+ "index": "0x22",
+ "validatorIndex": "0x5",
+ "address": "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "256": {
+ "withdrawals": [
+ {
+ "index": "0x23",
+ "validatorIndex": "0x5",
+ "address": "0x47dc540c94ceb704a23875c11273e16bb0b8a87a",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "261": {
+ "withdrawals": [
+ {
+ "index": "0x24",
+ "validatorIndex": "0x5",
+ "address": "0xbc5959f43bc6e47175374b6716e53c9a7d72c594",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "266": {
+ "withdrawals": [
+ {
+ "index": "0x25",
+ "validatorIndex": "0x5",
+ "address": "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "271": {
+ "withdrawals": [
+ {
+ "index": "0x26",
+ "validatorIndex": "0x5",
+ "address": "0x24255ef5d941493b9978f3aabb0ed07d084ade19",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "276": {
+ "withdrawals": [
+ {
+ "index": "0x27",
+ "validatorIndex": "0x5",
+ "address": "0xdbe726e81a7221a385e007ef9e834a975a4b528c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "281": {
+ "withdrawals": [
+ {
+ "index": "0x28",
+ "validatorIndex": "0x5",
+ "address": "0xae58b7e08e266680e93e46639a2a7e89fde78a6f",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "286": {
+ "withdrawals": [
+ {
+ "index": "0x29",
+ "validatorIndex": "0x5",
+ "address": "0x5df7504bc193ee4c3deadede1459eccca172e87c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "291": {
+ "withdrawals": [
+ {
+ "index": "0x2a",
+ "validatorIndex": "0x5",
+ "address": "0xb71de80778f2783383f5d5a3028af84eab2f18a4",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "296": {
+ "withdrawals": [
+ {
+ "index": "0x2b",
+ "validatorIndex": "0x5",
+ "address": "0x1c972398125398a3665f212930758ae9518a8c94",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "301": {
+ "withdrawals": [
+ {
+ "index": "0x2c",
+ "validatorIndex": "0x5",
+ "address": "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "306": {
+ "withdrawals": [
+ {
+ "index": "0x2d",
+ "validatorIndex": "0x5",
+ "address": "0x7f774bb46e7e342a2d9d0514b27cee622012f741",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "311": {
+ "withdrawals": [
+ {
+ "index": "0x2e",
+ "validatorIndex": "0x5",
+ "address": "0x06f647b157b8557a12979ba04cf5ba222b9747cf",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "316": {
+ "withdrawals": [
+ {
+ "index": "0x2f",
+ "validatorIndex": "0x5",
+ "address": "0xcccc369c5141675a9e9b1925164f30cdd60992dc",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "321": {
+ "withdrawals": [
+ {
+ "index": "0x30",
+ "validatorIndex": "0x5",
+ "address": "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "326": {
+ "withdrawals": [
+ {
+ "index": "0x31",
+ "validatorIndex": "0x5",
+ "address": "0x6a632187a3abf9bebb66d43368fccd612f631cbc",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "331": {
+ "withdrawals": [
+ {
+ "index": "0x32",
+ "validatorIndex": "0x5",
+ "address": "0x984c16459ded76438d98ce9b608f175c28a910a0",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "336": {
+ "withdrawals": [
+ {
+ "index": "0x33",
+ "validatorIndex": "0x5",
+ "address": "0x2847213288f0988543a76512fab09684131809d9",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "341": {
+ "withdrawals": [
+ {
+ "index": "0x34",
+ "validatorIndex": "0x5",
+ "address": "0x1037044fabf0421617c47c74681d7cc9c59f136c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "346": {
+ "withdrawals": [
+ {
+ "index": "0x35",
+ "validatorIndex": "0x5",
+ "address": "0x8cf42eb93b1426f22a30bd22539503bdf838830c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "351": {
+ "withdrawals": [
+ {
+ "index": "0x36",
+ "validatorIndex": "0x5",
+ "address": "0x6b2884fef44bd4288621a2cda9f88ca07b480861",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "356": {
+ "withdrawals": [
+ {
+ "index": "0x37",
+ "validatorIndex": "0x5",
+ "address": "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "361": {
+ "withdrawals": [
+ {
+ "index": "0x38",
+ "validatorIndex": "0x5",
+ "address": "0x8fa24283a8c1cc8a0f76ac69362139a173592567",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "366": {
+ "withdrawals": [
+ {
+ "index": "0x39",
+ "validatorIndex": "0x5",
+ "address": "0x19041ad672875015bc4041c24b581eafc0869aab",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "371": {
+ "withdrawals": [
+ {
+ "index": "0x3a",
+ "validatorIndex": "0x5",
+ "address": "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "376": {
+ "withdrawals": [
+ {
+ "index": "0x3b",
+ "validatorIndex": "0x5",
+ "address": "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "381": {
+ "withdrawals": [
+ {
+ "index": "0x3c",
+ "validatorIndex": "0x5",
+ "address": "0x96a1cabb97e1434a6e23e684dd4572e044c243ea",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "386": {
+ "withdrawals": [
+ {
+ "index": "0x3d",
+ "validatorIndex": "0x5",
+ "address": "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "391": {
+ "withdrawals": [
+ {
+ "index": "0x3e",
+ "validatorIndex": "0x5",
+ "address": "0xf997ed224012b1323eb2a6a0c0044a956c6b8070",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "396": {
+ "withdrawals": [
+ {
+ "index": "0x3f",
+ "validatorIndex": "0x5",
+ "address": "0x6d09a879576c0d941bea7833fb2285051b10d511",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "401": {
+ "withdrawals": [
+ {
+ "index": "0x40",
+ "validatorIndex": "0x5",
+ "address": "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "406": {
+ "withdrawals": [
+ {
+ "index": "0x41",
+ "validatorIndex": "0x5",
+ "address": "0x6510225e743d73828aa4f73a3133818490bd8820",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "411": {
+ "withdrawals": [
+ {
+ "index": "0x42",
+ "validatorIndex": "0x5",
+ "address": "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "416": {
+ "withdrawals": [
+ {
+ "index": "0x43",
+ "validatorIndex": "0x5",
+ "address": "0xa179dbdd51c56d0988551f92535797bcf47ca0e7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "421": {
+ "withdrawals": [
+ {
+ "index": "0x44",
+ "validatorIndex": "0x5",
+ "address": "0x494d799e953876ac6022c3f7da5e0f3c04b549be",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "426": {
+ "withdrawals": [
+ {
+ "index": "0x45",
+ "validatorIndex": "0x5",
+ "address": "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "431": {
+ "withdrawals": [
+ {
+ "index": "0x46",
+ "validatorIndex": "0x5",
+ "address": "0x368b766f1e4d7bf437d2a709577a5210a99002b6",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "436": {
+ "withdrawals": [
+ {
+ "index": "0x47",
+ "validatorIndex": "0x5",
+ "address": "0x5123198d8a827fe0c788c409e7d2068afde64339",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "441": {
+ "withdrawals": [
+ {
+ "index": "0x48",
+ "validatorIndex": "0x5",
+ "address": "0xd39b94587711196640659ec81855bcf397e419ff",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "446": {
+ "withdrawals": [
+ {
+ "index": "0x49",
+ "validatorIndex": "0x5",
+ "address": "0x6ca60a92cbf88c7f527978dc183a22e774755551",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "451": {
+ "withdrawals": [
+ {
+ "index": "0x4a",
+ "validatorIndex": "0x5",
+ "address": "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "456": {
+ "withdrawals": [
+ {
+ "index": "0x4b",
+ "validatorIndex": "0x5",
+ "address": "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "461": {
+ "withdrawals": [
+ {
+ "index": "0x4c",
+ "validatorIndex": "0x5",
+ "address": "0x48701721ec0115f04bc7404058f6c0f386946e09",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "466": {
+ "withdrawals": [
+ {
+ "index": "0x4d",
+ "validatorIndex": "0x5",
+ "address": "0x706be462488699e89b722822dcec9822ad7d05a7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "471": {
+ "withdrawals": [
+ {
+ "index": "0x4e",
+ "validatorIndex": "0x5",
+ "address": "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "476": {
+ "withdrawals": [
+ {
+ "index": "0x4f",
+ "validatorIndex": "0x5",
+ "address": "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "481": {
+ "withdrawals": [
+ {
+ "index": "0x50",
+ "validatorIndex": "0x5",
+ "address": "0xc57aa6a4279377063b17c554d3e33a3490e67a9a",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "486": {
+ "withdrawals": [
+ {
+ "index": "0x51",
+ "validatorIndex": "0x5",
+ "address": "0x311df588ca5f412f970891e4cc3ac23648968ca2",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "491": {
+ "withdrawals": [
+ {
+ "index": "0x52",
+ "validatorIndex": "0x5",
+ "address": "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "496": {
+ "withdrawals": [
+ {
+ "index": "0x53",
+ "validatorIndex": "0x5",
+ "address": "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "81": {
+ "withdrawals": [
+ {
+ "index": "0x0",
+ "validatorIndex": "0x5",
+ "address": "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "86": {
+ "withdrawals": [
+ {
+ "index": "0x1",
+ "validatorIndex": "0x5",
+ "address": "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "91": {
+ "withdrawals": [
+ {
+ "index": "0x2",
+ "validatorIndex": "0x5",
+ "address": "0x245843abef9e72e7efac30138a994bf6301e7e1d",
+ "amount": "0x64"
+ }
+ ]
+ },
+ "96": {
+ "withdrawals": [
+ {
+ "index": "0x3",
+ "validatorIndex": "0x5",
+ "address": "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c",
+ "amount": "0x64"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/cmd/devp2p/internal/ethtest/transaction.go b/cmd/devp2p/internal/ethtest/transaction.go
index db5199d334..0ea7c32752 100644
--- a/cmd/devp2p/internal/ethtest/transaction.go
+++ b/cmd/devp2p/internal/ethtest/transaction.go
@@ -19,429 +19,141 @@ package ethtest
import (
"errors"
"fmt"
- "math/big"
- "strings"
+ "os"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/internal/utesting"
- "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/eth/protocols/eth"
)
-// var faucetAddr = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
-var faucetKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
-
-func (s *Suite) sendSuccessfulTxs(t *utesting.T) error {
- tests := []*types.Transaction{
- getNextTxFromChain(s),
- unknownTx(s),
- }
- for i, tx := range tests {
- if tx == nil {
- return errors.New("could not find tx to send")
- }
- t.Logf("Testing tx propagation %d: sending tx %v %v %v\n", i, tx.Hash().String(), tx.GasPrice(), tx.Gas())
- // get previous tx if exists for reference in case of old tx propagation
- var prevTx *types.Transaction
- if i != 0 {
- prevTx = tests[i-1]
- }
- // write tx to connection
- if err := sendSuccessfulTx(s, tx, prevTx); err != nil {
- return fmt.Errorf("send successful tx test failed: %v", err)
- }
- }
- return nil
-}
-
-func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction) error {
- sendConn, recvConn, err := s.createSendAndRecvConns()
+// sendTxs sends the given transactions to the node and
+// expects the node to accept and propagate them.
+func (s *Suite) sendTxs(txs []*types.Transaction) error {
+ // Open sending conn.
+ sendConn, err := s.dial()
if err != nil {
return err
}
defer sendConn.Close()
- defer recvConn.Close()
if err = sendConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err)
}
- // Send the transaction
- if err = sendConn.Write(&Transactions{tx}); err != nil {
- return fmt.Errorf("failed to write to connection: %v", err)
- }
- // peer receiving connection to node
- if err = recvConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- // update last nonce seen
- nonce = tx.Nonce()
- // Wait for the transaction announcement
- for {
- switch msg := recvConn.readAndServe(s.chain, timeout).(type) {
- case *Transactions:
- recTxs := *msg
- // if you receive an old tx propagation, read from connection again
- if len(recTxs) == 1 && prevTx != nil {
- if recTxs[0] == prevTx {
- continue
- }
- }
- for _, gotTx := range recTxs {
- if gotTx.Hash() == tx.Hash() {
- // Ok
- return nil
- }
- }
- return fmt.Errorf("missing transaction: got %v missing %v", recTxs, tx.Hash())
- case *NewPooledTransactionHashes66:
- txHashes := *msg
- // if you receive an old tx propagation, read from connection again
- if len(txHashes) == 1 && prevTx != nil {
- if txHashes[0] == prevTx.Hash() {
- continue
- }
- }
- for _, gotHash := range txHashes {
- if gotHash == tx.Hash() {
- // Ok
- return nil
- }
- }
- return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash())
- case *NewPooledTransactionHashes:
- txHashes := msg.Hashes
- if len(txHashes) != len(msg.Sizes) {
- return fmt.Errorf("invalid msg size lengths: hashes: %v sizes: %v", len(txHashes), len(msg.Sizes))
- }
- if len(txHashes) != len(msg.Types) {
- return fmt.Errorf("invalid msg type lengths: hashes: %v types: %v", len(txHashes), len(msg.Types))
- }
- // if you receive an old tx propagation, read from connection again
- if len(txHashes) == 1 && prevTx != nil {
- if txHashes[0] == prevTx.Hash() {
- continue
- }
- }
- for index, gotHash := range txHashes {
- if gotHash == tx.Hash() {
- if msg.Sizes[index] != uint32(tx.Size()) {
- return fmt.Errorf("invalid tx size: got %v want %v", msg.Sizes[index], tx.Size())
- }
- if msg.Types[index] != tx.Type() {
- return fmt.Errorf("invalid tx type: got %v want %v", msg.Types[index], tx.Type())
- }
- // Ok
- return nil
- }
- }
- return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash())
-
- default:
- return fmt.Errorf("unexpected message in sendSuccessfulTx: %s", pretty.Sdump(msg))
- }
- }
-}
-
-func (s *Suite) sendMaliciousTxs(t *utesting.T) error {
- badTxs := []*types.Transaction{
- getOldTxFromChain(s),
- invalidNonceTx(s),
- hugeAmount(s),
- hugeGasPrice(s),
- hugeData(s),
- }
-
- // setup receiving connection before sending malicious txs
+ // Open receiving conn.
recvConn, err := s.dial()
- if err != nil {
- return fmt.Errorf("dial failed: %v", err)
- }
- defer recvConn.Close()
- if err = recvConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- for i, tx := range badTxs {
- t.Logf("Testing malicious tx propagation: %v\n", i)
- if err = sendMaliciousTx(s, tx); err != nil {
- return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err)
- }
- }
- // check to make sure bad txs aren't propagated
- return checkMaliciousTxPropagation(s, badTxs, recvConn)
-}
-
-func sendMaliciousTx(s *Suite, tx *types.Transaction) error {
- conn, err := s.dial()
- if err != nil {
- return fmt.Errorf("dial failed: %v", err)
- }
- defer conn.Close()
- if err = conn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
-
- // write malicious tx
- if err = conn.Write(&Transactions{tx}); err != nil {
- return fmt.Errorf("failed to write to connection: %v", err)
- }
- return nil
-}
-
-var nonce = uint64(99)
-
-// sendMultipleSuccessfulTxs sends the given transactions to the node and
-// expects the node to accept and propagate them.
-func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction) error {
- txMsg := Transactions(txs)
- t.Logf("sending %d txs\n", len(txs))
-
- sendConn, recvConn, err := s.createSendAndRecvConns()
if err != nil {
return err
}
- defer sendConn.Close()
defer recvConn.Close()
- if err = sendConn.peer(s.chain, nil); err != nil {
- return fmt.Errorf("peering failed: %v", err)
- }
if err = recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err)
}
- // Send the transactions
- if err = sendConn.Write(&txMsg); err != nil {
+ if err = sendConn.Write(ethProto, eth.TransactionsMsg, eth.TransactionsPacket(txs)); err != nil {
return fmt.Errorf("failed to write message to connection: %v", err)
}
- // update nonce
- nonce = txs[len(txs)-1].Nonce()
-
- // Wait for the transaction announcement(s) and make sure all sent txs are being propagated.
- // all txs should be announced within a couple announcements.
- recvHashes := make([]common.Hash, 0)
+ var (
+ got = make(map[common.Hash]bool)
+ end = time.Now().Add(timeout)
+ )
- for i := 0; i < 20; i++ {
- switch msg := recvConn.readAndServe(s.chain, timeout).(type) {
- case *Transactions:
+ // Wait for the transaction announcements, make sure all txs ar propagated.
+ for time.Now().Before(end) {
+ msg, err := recvConn.ReadEth()
+ if err != nil {
+ return fmt.Errorf("failed to read from connection: %w", err)
+ }
+ switch msg := msg.(type) {
+ case *eth.TransactionsPacket:
for _, tx := range *msg {
- recvHashes = append(recvHashes, tx.Hash())
+ got[tx.Hash()] = true
}
- case *NewPooledTransactionHashes66:
- recvHashes = append(recvHashes, *msg...)
- case *NewPooledTransactionHashes:
- recvHashes = append(recvHashes, msg.Hashes...)
- default:
- if !strings.Contains(pretty.Sdump(msg), "i/o timeout") {
- return fmt.Errorf("unexpected message while waiting to receive txs: %s", pretty.Sdump(msg))
+ case *eth.NewPooledTransactionHashesPacket68:
+ for _, hash := range msg.Hashes {
+ got[hash] = true
}
+ default:
+ return fmt.Errorf("unexpected eth wire msg: %s", pretty.Sdump(msg))
}
- // break once all 2000 txs have been received
- if len(recvHashes) == 2000 {
- break
- }
- if len(recvHashes) > 0 {
- _, missingTxs := compareReceivedTxs(recvHashes, txs)
- if len(missingTxs) > 0 {
- continue
- } else {
- t.Logf("successfully received all %d txs", len(txs))
- return nil
+
+ // Check if all txs received.
+ allReceived := func() bool {
+ for _, tx := range txs {
+ if !got[tx.Hash()] {
+ return false
+ }
}
+ return true
}
- }
- _, missingTxs := compareReceivedTxs(recvHashes, txs)
- if len(missingTxs) > 0 {
- for _, missing := range missingTxs {
- t.Logf("missing tx: %v", missing.Hash())
+ if allReceived() {
+ return nil
}
- return fmt.Errorf("missing %d txs", len(missingTxs))
}
- return nil
-}
-// checkMaliciousTxPropagation checks whether the given malicious transactions were
-// propagated by the node.
-func checkMaliciousTxPropagation(s *Suite, txs []*types.Transaction, conn *Conn) error {
- switch msg := conn.readAndServe(s.chain, time.Second*8).(type) {
- case *Transactions:
- // check to see if any of the failing txs were in the announcement
- recvTxs := make([]common.Hash, len(*msg))
- for i, recvTx := range *msg {
- recvTxs[i] = recvTx.Hash()
- }
- badTxs, _ := compareReceivedTxs(recvTxs, txs)
- if len(badTxs) > 0 {
- return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs)
- }
- case *NewPooledTransactionHashes66:
- badTxs, _ := compareReceivedTxs(*msg, txs)
- if len(badTxs) > 0 {
- return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs)
- }
- case *NewPooledTransactionHashes:
- badTxs, _ := compareReceivedTxs(msg.Hashes, txs)
- if len(badTxs) > 0 {
- return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs)
- }
- case *Error:
- // Transaction should not be announced -> wait for timeout
- return nil
- default:
- return fmt.Errorf("unexpected message in sendFailingTx: %s", pretty.Sdump(msg))
- }
- return nil
+ return fmt.Errorf("timed out waiting for txs")
}
-// compareReceivedTxs compares the received set of txs against the given set of txs,
-// returning both the set received txs that were present within the given txs, and
-// the set of txs that were missing from the set of received txs
-func compareReceivedTxs(recvTxs []common.Hash, txs []*types.Transaction) (present []*types.Transaction, missing []*types.Transaction) {
- // create a map of the hashes received from node
- recvHashes := make(map[common.Hash]common.Hash)
- for _, hash := range recvTxs {
- recvHashes[hash] = hash
+func (s *Suite) sendInvalidTxs(txs []*types.Transaction) error {
+ // Open sending conn.
+ sendConn, err := s.dial()
+ if err != nil {
+ return err
}
-
- // collect present txs and missing txs separately
- present = make([]*types.Transaction, 0)
- missing = make([]*types.Transaction, 0)
- for _, tx := range txs {
- if _, exists := recvHashes[tx.Hash()]; exists {
- present = append(present, tx)
- } else {
- missing = append(missing, tx)
- }
+ defer sendConn.Close()
+ if err = sendConn.peer(s.chain, nil); err != nil {
+ return fmt.Errorf("peering failed: %v", err)
}
- return present, missing
-}
+ sendConn.SetDeadline(time.Now().Add(timeout))
-func unknownTx(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
+ // Open receiving conn.
+ recvConn, err := s.dial()
+ if err != nil {
+ return err
}
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
+ defer recvConn.Close()
+ if err = recvConn.peer(s.chain, nil); err != nil {
+ return fmt.Errorf("peering failed: %v", err)
}
- txNew := types.NewTransaction(tx.Nonce()+1, to, tx.Value(), tx.Gas(), tx.GasPrice(), tx.Data())
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
+ recvConn.SetDeadline(time.Now().Add(timeout))
-func getNextTxFromChain(s *Suite) *types.Transaction {
- // Get a new transaction
- for _, blocks := range s.fullChain.blocks[s.chain.Len():] {
- txs := blocks.Transactions()
- if txs.Len() != 0 {
- return txs[0]
- }
+ if err = sendConn.Write(ethProto, eth.TransactionsMsg, txs); err != nil {
+ return fmt.Errorf("failed to write message to connection: %w", err)
}
- return nil
-}
-func generateTxs(s *Suite, numTxs int) (map[common.Hash]common.Hash, []*types.Transaction, error) {
- txHashMap := make(map[common.Hash]common.Hash, numTxs)
- txs := make([]*types.Transaction, numTxs)
-
- nextTx := getNextTxFromChain(s)
- if nextTx == nil {
- return nil, nil, errors.New("failed to get the next transaction")
- }
- gas := nextTx.Gas()
-
- nonce = nonce + 1
- // generate txs
- for i := 0; i < numTxs; i++ {
- tx := generateTx(s.chain.chainConfig, nonce, gas)
- if tx == nil {
- return nil, nil, errors.New("failed to get the next transaction")
- }
- txHashMap[tx.Hash()] = tx.Hash()
- txs[i] = tx
- nonce = nonce + 1
+ // Make map of invalid txs.
+ invalids := make(map[common.Hash]struct{})
+ for _, tx := range txs {
+ invalids[tx.Hash()] = struct{}{}
}
- return txHashMap, txs, nil
-}
-func generateTx(chainConfig *params.ChainConfig, nonce uint64, gas uint64) *types.Transaction {
- var to common.Address
- tx := types.NewTransaction(nonce, to, big.NewInt(1), gas, big.NewInt(1), []byte{})
- return signWithFaucet(chainConfig, tx)
-}
-
-func getOldTxFromChain(s *Suite) *types.Transaction {
- for _, blocks := range s.fullChain.blocks[:s.chain.Len()-1] {
- txs := blocks.Transactions()
- if txs.Len() != 0 {
- return txs[0]
+ // Get responses.
+ recvConn.SetReadDeadline(time.Now().Add(timeout))
+ for {
+ msg, err := recvConn.ReadEth()
+ if errors.Is(err, os.ErrDeadlineExceeded) {
+ // Successful if no invalid txs are propagated before timeout.
+ return nil
+ } else if err != nil {
+ return fmt.Errorf("failed to read from connection: %w", err)
+ }
+
+ switch msg := msg.(type) {
+ case *eth.TransactionsPacket:
+ for _, tx := range txs {
+ if _, ok := invalids[tx.Hash()]; ok {
+ return fmt.Errorf("received bad tx: %s", tx.Hash())
+ }
+ }
+ case *eth.NewPooledTransactionHashesPacket68:
+ for _, hash := range msg.Hashes {
+ if _, ok := invalids[hash]; ok {
+ return fmt.Errorf("received bad tx: %s", hash)
+ }
+ }
+ default:
+ return fmt.Errorf("unexpected eth message: %v", pretty.Sdump(msg))
}
}
- return nil
-}
-
-func invalidNonceTx(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
- txNew := types.NewTransaction(tx.Nonce()-2, to, tx.Value(), tx.Gas(), tx.GasPrice(), tx.Data())
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func hugeAmount(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
- amount := largeNumber(2)
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
- txNew := types.NewTransaction(tx.Nonce(), to, amount, tx.Gas(), tx.GasPrice(), tx.Data())
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func hugeGasPrice(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
- gasPrice := largeNumber(2)
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
- txNew := types.NewTransaction(tx.Nonce(), to, tx.Value(), tx.Gas(), gasPrice, tx.Data())
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func hugeData(s *Suite) *types.Transaction {
- tx := getNextTxFromChain(s)
- if tx == nil {
- return nil
- }
- var to common.Address
- if tx.To() != nil {
- to = *tx.To()
- }
- txNew := types.NewTransaction(tx.Nonce(), to, tx.Value(), tx.Gas(), tx.GasPrice(), largeBuffer(2))
- return signWithFaucet(s.chain.chainConfig, txNew)
-}
-
-func signWithFaucet(chainConfig *params.ChainConfig, tx *types.Transaction) *types.Transaction {
- signer := types.LatestSigner(chainConfig)
- signedTx, err := types.SignTx(tx, signer, faucetKey)
- if err != nil {
- return nil
- }
- return signedTx
}
diff --git a/cmd/devp2p/internal/ethtest/types.go b/cmd/devp2p/internal/ethtest/types.go
deleted file mode 100644
index 645e3bb9a5..0000000000
--- a/cmd/devp2p/internal/ethtest/types.go
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see .
-
-package ethtest
-
-import (
- "crypto/ecdsa"
- "errors"
- "fmt"
- "time"
-
- "github.com/ethereum/go-ethereum/eth/protocols/eth"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/p2p/rlpx"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-type Message interface {
- Code() int
- ReqID() uint64
-}
-
-type Error struct {
- err error
-}
-
-func (e *Error) Unwrap() error { return e.err }
-func (e *Error) Error() string { return e.err.Error() }
-func (e *Error) String() string { return e.Error() }
-
-func (e *Error) Code() int { return -1 }
-func (e *Error) ReqID() uint64 { return 0 }
-
-func errorf(format string, args ...interface{}) *Error {
- return &Error{fmt.Errorf(format, args...)}
-}
-
-// Hello is the RLP structure of the protocol handshake.
-type Hello struct {
- Version uint64
- Name string
- Caps []p2p.Cap
- ListenPort uint64
- ID []byte // secp256k1 public key
-
- // Ignore additional fields (for forward compatibility).
- Rest []rlp.RawValue `rlp:"tail"`
-}
-
-func (msg Hello) Code() int { return 0x00 }
-func (msg Hello) ReqID() uint64 { return 0 }
-
-// Disconnect is the RLP structure for a disconnect message.
-type Disconnect struct {
- Reason p2p.DiscReason
-}
-
-func (msg Disconnect) Code() int { return 0x01 }
-func (msg Disconnect) ReqID() uint64 { return 0 }
-
-type Ping struct{}
-
-func (msg Ping) Code() int { return 0x02 }
-func (msg Ping) ReqID() uint64 { return 0 }
-
-type Pong struct{}
-
-func (msg Pong) Code() int { return 0x03 }
-func (msg Pong) ReqID() uint64 { return 0 }
-
-// Status is the network packet for the status message for eth/64 and later.
-type Status eth.StatusPacket
-
-func (msg Status) Code() int { return 16 }
-func (msg Status) ReqID() uint64 { return 0 }
-
-type UpgradeStatus eth.UpgradeStatusPacket
-
-func (msg UpgradeStatus) Code() int { return 27 } // p2p.baseProtocolLength + eth.UpgradeStatusMsg
-func (msg UpgradeStatus) ReqID() uint64 { return 0 }
-
-// NewBlockHashes is the network packet for the block announcements.
-type NewBlockHashes eth.NewBlockHashesPacket
-
-func (msg NewBlockHashes) Code() int { return 17 }
-func (msg NewBlockHashes) ReqID() uint64 { return 0 }
-
-type Transactions eth.TransactionsPacket
-
-func (msg Transactions) Code() int { return 18 }
-func (msg Transactions) ReqID() uint64 { return 18 }
-
-// GetBlockHeaders represents a block header query.
-type GetBlockHeaders eth.GetBlockHeadersPacket66
-
-func (msg GetBlockHeaders) Code() int { return 19 }
-func (msg GetBlockHeaders) ReqID() uint64 { return msg.RequestId }
-
-type BlockHeaders eth.BlockHeadersPacket66
-
-func (msg BlockHeaders) Code() int { return 20 }
-func (msg BlockHeaders) ReqID() uint64 { return msg.RequestId }
-
-// GetBlockBodies represents a GetBlockBodies request
-type GetBlockBodies eth.GetBlockBodiesPacket66
-
-func (msg GetBlockBodies) Code() int { return 21 }
-func (msg GetBlockBodies) ReqID() uint64 { return msg.RequestId }
-
-// BlockBodies is the network packet for block content distribution.
-type BlockBodies eth.BlockBodiesPacket66
-
-func (msg BlockBodies) Code() int { return 22 }
-func (msg BlockBodies) ReqID() uint64 { return msg.RequestId }
-
-// NewBlock is the network packet for the block propagation message.
-type NewBlock eth.NewBlockPacket
-
-func (msg NewBlock) Code() int { return 23 }
-func (msg NewBlock) ReqID() uint64 { return 0 }
-
-// NewPooledTransactionHashes66 is the network packet for the tx hash propagation message.
-type NewPooledTransactionHashes66 eth.NewPooledTransactionHashesPacket66
-
-func (msg NewPooledTransactionHashes66) Code() int { return 24 }
-func (msg NewPooledTransactionHashes66) ReqID() uint64 { return 0 }
-
-// NewPooledTransactionHashes is the network packet for the tx hash propagation message.
-type NewPooledTransactionHashes eth.NewPooledTransactionHashesPacket68
-
-func (msg NewPooledTransactionHashes) Code() int { return 24 }
-func (msg NewPooledTransactionHashes) ReqID() uint64 { return 0 }
-
-type GetPooledTransactions eth.GetPooledTransactionsPacket66
-
-func (msg GetPooledTransactions) Code() int { return 25 }
-func (msg GetPooledTransactions) ReqID() uint64 { return msg.RequestId }
-
-type PooledTransactions eth.PooledTransactionsPacket66
-
-func (msg PooledTransactions) Code() int { return 26 }
-func (msg PooledTransactions) ReqID() uint64 { return msg.RequestId }
-
-// Conn represents an individual connection with a peer
-type Conn struct {
- *rlpx.Conn
- ourKey *ecdsa.PrivateKey
- negotiatedProtoVersion uint
- negotiatedSnapProtoVersion uint
- ourHighestProtoVersion uint
- ourHighestSnapProtoVersion uint
- caps []p2p.Cap
-}
-
-// Read reads an eth66 packet from the connection.
-func (c *Conn) Read() Message {
- code, rawData, _, err := c.Conn.Read()
- if err != nil {
- return errorf("could not read from connection: %v", err)
- }
-
- var msg Message
- switch int(code) {
- case (Hello{}).Code():
- msg = new(Hello)
- case (Ping{}).Code():
- msg = new(Ping)
- case (Pong{}).Code():
- msg = new(Pong)
- case (Disconnect{}).Code():
- msg = new(Disconnect)
- case (Status{}).Code():
- msg = new(Status)
- case (UpgradeStatus{}).Code():
- msg = new(UpgradeStatus)
- case (GetBlockHeaders{}).Code():
- ethMsg := new(eth.GetBlockHeadersPacket66)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
- return (*GetBlockHeaders)(ethMsg)
- case (BlockHeaders{}).Code():
- ethMsg := new(eth.BlockHeadersPacket66)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
- return (*BlockHeaders)(ethMsg)
- case (GetBlockBodies{}).Code():
- ethMsg := new(eth.GetBlockBodiesPacket66)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
- return (*GetBlockBodies)(ethMsg)
- case (BlockBodies{}).Code():
- ethMsg := new(eth.BlockBodiesPacket66)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
- return (*BlockBodies)(ethMsg)
- case (NewBlock{}).Code():
- msg = new(NewBlock)
- case (NewBlockHashes{}).Code():
- msg = new(NewBlockHashes)
- case (Transactions{}).Code():
- msg = new(Transactions)
- case (NewPooledTransactionHashes66{}).Code():
- // Try decoding to eth68
- ethMsg := new(NewPooledTransactionHashes)
- if err := rlp.DecodeBytes(rawData, ethMsg); err == nil {
- return ethMsg
- }
- msg = new(NewPooledTransactionHashes66)
- case (GetPooledTransactions{}.Code()):
- ethMsg := new(eth.GetPooledTransactionsPacket66)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
- return (*GetPooledTransactions)(ethMsg)
- case (PooledTransactions{}.Code()):
- ethMsg := new(eth.PooledTransactionsPacket66)
- if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
- return (*PooledTransactions)(ethMsg)
- default:
- msg = errorf("invalid message code: %d", code)
- }
-
- if msg != nil {
- if err := rlp.DecodeBytes(rawData, msg); err != nil {
- return errorf("could not rlp decode message: %v", err)
- }
- return msg
- }
- return errorf("invalid message: %s", string(rawData))
-}
-
-// Write writes a eth packet to the connection.
-func (c *Conn) Write(msg Message) error {
- payload, err := rlp.EncodeToBytes(msg)
- if err != nil {
- return err
- }
- _, err = c.Conn.Write(uint64(msg.Code()), payload)
- return err
-}
-
-// ReadSnap reads a snap/1 response with the given id from the connection.
-func (c *Conn) ReadSnap(id uint64) (Message, error) {
- respId := id + 1
- start := time.Now()
- for respId != id && time.Since(start) < timeout {
- code, rawData, _, err := c.Conn.Read()
- if err != nil {
- return nil, fmt.Errorf("could not read from connection: %v", err)
- }
- var snpMsg interface{}
- switch int(code) {
- case (GetAccountRange{}).Code():
- snpMsg = new(GetAccountRange)
- case (AccountRange{}).Code():
- snpMsg = new(AccountRange)
- case (GetStorageRanges{}).Code():
- snpMsg = new(GetStorageRanges)
- case (StorageRanges{}).Code():
- snpMsg = new(StorageRanges)
- case (GetByteCodes{}).Code():
- snpMsg = new(GetByteCodes)
- case (ByteCodes{}).Code():
- snpMsg = new(ByteCodes)
- case (GetTrieNodes{}).Code():
- snpMsg = new(GetTrieNodes)
- case (TrieNodes{}).Code():
- snpMsg = new(TrieNodes)
- default:
- //return nil, fmt.Errorf("invalid message code: %d", code)
- continue
- }
- if err := rlp.DecodeBytes(rawData, snpMsg); err != nil {
- return nil, fmt.Errorf("could not rlp decode message: %v", err)
- }
- return snpMsg.(Message), nil
- }
- return nil, errors.New("request timed out")
-}
diff --git a/cmd/devp2p/internal/v4test/discv4tests.go b/cmd/devp2p/internal/v4test/discv4tests.go
index 3afcfd0698..ca556851b4 100644
--- a/cmd/devp2p/internal/v4test/discv4tests.go
+++ b/cmd/devp2p/internal/v4test/discv4tests.go
@@ -497,7 +497,7 @@ func FindnodeAmplificationWrongIP(t *utesting.T) {
// If we receive a NEIGHBORS response, the attack worked and the test fails.
reply, _, _ := te.read(te.l2)
if reply != nil {
- t.Error("Got NEIGHORS response for FINDNODE from wrong IP")
+ t.Error("Got NEIGHBORS response for FINDNODE from wrong IP")
}
}
diff --git a/cmd/devp2p/nodesetcmd.go b/cmd/devp2p/nodesetcmd.go
index 4aa7ecd20a..d0ba0517ba 100644
--- a/cmd/devp2p/nodesetcmd.go
+++ b/cmd/devp2p/nodesetcmd.go
@@ -25,6 +25,7 @@ import (
"strings"
"time"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/params"
@@ -228,7 +229,7 @@ func ethFilter(args []string) (nodeFilter, error) {
var filter forkid.Filter
switch args[0] {
case "mainnet":
- filter = forkid.NewStaticFilter(params.MainnetChainConfig, params.MainnetGenesisHash)
+ filter = forkid.NewStaticFilter(params.MainnetChainConfig, core.DefaultGenesisBlock().ToBlock())
default:
return nil, fmt.Errorf("unknown network %q", args[0])
}
diff --git a/cmd/devp2p/rlpxcmd.go b/cmd/devp2p/rlpxcmd.go
index dccecf3c37..aa7d065818 100644
--- a/cmd/devp2p/rlpxcmd.go
+++ b/cmd/devp2p/rlpxcmd.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/rlpx"
"github.com/ethereum/go-ethereum/rlp"
"github.com/urfave/cli/v2"
@@ -46,22 +47,30 @@ var (
}
rlpxEthTestCommand = &cli.Command{
Name: "eth-test",
- Usage: "Runs tests against a node",
- ArgsUsage: " ",
+ Usage: "Runs eth protocol tests against a node",
+ ArgsUsage: "",
Action: rlpxEthTest,
Flags: []cli.Flag{
testPatternFlag,
testTAPFlag,
+ testChainDirFlag,
+ testNodeFlag,
+ testNodeJWTFlag,
+ testNodeEngineFlag,
},
}
rlpxSnapTestCommand = &cli.Command{
Name: "snap-test",
- Usage: "Runs tests against a node",
- ArgsUsage: " ",
+ Usage: "Runs snap protocol tests against a node",
+ ArgsUsage: "",
Action: rlpxSnapTest,
Flags: []cli.Flag{
testPatternFlag,
testTAPFlag,
+ testChainDirFlag,
+ testNodeFlag,
+ testNodeJWTFlag,
+ testNodeEngineFlag,
},
}
)
@@ -103,10 +112,8 @@ func rlpxPing(ctx *cli.Context) error {
// rlpxEthTest runs the eth protocol test suite.
func rlpxEthTest(ctx *cli.Context) error {
- if ctx.NArg() < 3 {
- exit("missing path to chain.rlp as command-line argument")
- }
- suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
+ p := cliTestParams(ctx)
+ suite, err := ethtest.NewSuite(p.node, p.chainDir, p.engineAPI, p.jwt)
if err != nil {
exit(err)
}
@@ -115,12 +122,44 @@ func rlpxEthTest(ctx *cli.Context) error {
// rlpxSnapTest runs the snap protocol test suite.
func rlpxSnapTest(ctx *cli.Context) error {
- if ctx.NArg() < 3 {
- exit("missing path to chain.rlp as command-line argument")
- }
- suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
+ p := cliTestParams(ctx)
+ suite, err := ethtest.NewSuite(p.node, p.chainDir, p.engineAPI, p.jwt)
if err != nil {
exit(err)
}
return runTests(ctx, suite.SnapTests())
}
+
+type testParams struct {
+ node *enode.Node
+ engineAPI string
+ jwt string
+ chainDir string
+}
+
+func cliTestParams(ctx *cli.Context) *testParams {
+ nodeStr := ctx.String(testNodeFlag.Name)
+ if nodeStr == "" {
+ exit(fmt.Errorf("missing -%s", testNodeFlag.Name))
+ }
+ node, err := parseNode(nodeStr)
+ if err != nil {
+ exit(err)
+ }
+ p := testParams{
+ node: node,
+ engineAPI: ctx.String(testNodeEngineFlag.Name),
+ jwt: ctx.String(testNodeJWTFlag.Name),
+ chainDir: ctx.String(testChainDirFlag.Name),
+ }
+ if p.engineAPI == "" {
+ exit(fmt.Errorf("missing -%s", testNodeEngineFlag.Name))
+ }
+ if p.jwt == "" {
+ exit(fmt.Errorf("missing -%s", testNodeJWTFlag.Name))
+ }
+ if p.chainDir == "" {
+ exit(fmt.Errorf("missing -%s", testChainDirFlag.Name))
+ }
+ return &p
+}
diff --git a/cmd/devp2p/runtest.go b/cmd/devp2p/runtest.go
index f72aa91119..7e3723c641 100644
--- a/cmd/devp2p/runtest.go
+++ b/cmd/devp2p/runtest.go
@@ -20,6 +20,7 @@ import (
"os"
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
+ "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/internal/utesting"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"
@@ -27,23 +28,51 @@ import (
var (
testPatternFlag = &cli.StringFlag{
- Name: "run",
- Usage: "Pattern of test suite(s) to run",
+ Name: "run",
+ Usage: "Pattern of test suite(s) to run",
+ Category: flags.TestingCategory,
}
testTAPFlag = &cli.BoolFlag{
- Name: "tap",
- Usage: "Output TAP",
+ Name: "tap",
+ Usage: "Output test results in TAP format",
+ Category: flags.TestingCategory,
}
+
+ // for eth/snap tests
+ testChainDirFlag = &cli.StringFlag{
+ Name: "chain",
+ Usage: "Test chain directory (required)",
+ Category: flags.TestingCategory,
+ }
+ testNodeFlag = &cli.StringFlag{
+ Name: "node",
+ Usage: "Peer-to-Peer endpoint (ENR) of the test node (required)",
+ Category: flags.TestingCategory,
+ }
+ testNodeJWTFlag = &cli.StringFlag{
+ Name: "jwtsecret",
+ Usage: "JWT secret for the engine API of the test node (required)",
+ Category: flags.TestingCategory,
+ Value: "0x7365637265747365637265747365637265747365637265747365637265747365",
+ }
+ testNodeEngineFlag = &cli.StringFlag{
+ Name: "engineapi",
+ Usage: "Engine API endpoint of the test node (required)",
+ Category: flags.TestingCategory,
+ }
+
// These two are specific to the discovery tests.
testListen1Flag = &cli.StringFlag{
- Name: "listen1",
- Usage: "IP address of the first tester",
- Value: v4test.Listen1,
+ Name: "listen1",
+ Usage: "IP address of the first tester",
+ Value: v4test.Listen1,
+ Category: flags.TestingCategory,
}
testListen2Flag = &cli.StringFlag{
- Name: "listen2",
- Usage: "IP address of the second tester",
- Value: v4test.Listen2,
+ Name: "listen2",
+ Usage: "IP address of the second tester",
+ Value: v4test.Listen2,
+ Category: flags.TestingCategory,
}
)
@@ -54,7 +83,7 @@ func runTests(ctx *cli.Context, tests []utesting.Test) error {
}
// Disable logging unless explicitly enabled.
if !ctx.IsSet("verbosity") && !ctx.IsSet("vmodule") {
- log.Root().SetHandler(log.DiscardHandler())
+ log.SetDefault(log.NewLogger(log.DiscardHandler()))
}
// Run the tests.
var run = utesting.RunTests
diff --git a/cmd/ethkey/message_test.go b/cmd/ethkey/message_test.go
index 544a494cfa..389bb8c8ea 100644
--- a/cmd/ethkey/message_test.go
+++ b/cmd/ethkey/message_test.go
@@ -22,6 +22,7 @@ import (
)
func TestMessageSignVerify(t *testing.T) {
+ t.Parallel()
tmpdir := t.TempDir()
keyfile := filepath.Join(tmpdir, "the-keyfile")
diff --git a/cmd/ethkey/run_test.go b/cmd/ethkey/run_test.go
index 6006f6b5bb..73506e5da1 100644
--- a/cmd/ethkey/run_test.go
+++ b/cmd/ethkey/run_test.go
@@ -21,8 +21,8 @@ import (
"os"
"testing"
- "github.com/docker/docker/pkg/reexec"
"github.com/ethereum/go-ethereum/internal/cmdtest"
+ "github.com/ethereum/go-ethereum/internal/reexec"
)
type testEthkey struct {
diff --git a/cmd/evm/README.md b/cmd/evm/README.md
index e6c6fe06ad..25647c18a9 100644
--- a/cmd/evm/README.md
+++ b/cmd/evm/README.md
@@ -88,7 +88,7 @@ type Env struct {
CurrentTimestamp uint64 `json:"currentTimestamp"`
Withdrawals []*Withdrawal `json:"withdrawals"`
// optional
- CurrentDifficulty *big.Int `json:"currentDifficuly"`
+ CurrentDifficulty *big.Int `json:"currentDifficulty"`
CurrentRandom *big.Int `json:"currentRandom"`
CurrentBaseFee *big.Int `json:"currentBaseFee"`
ParentDifficulty *big.Int `json:"parentDifficulty"`
@@ -214,7 +214,7 @@ exitcode:3 OK
The chain configuration to be used for a transition is specified via the
`--state.fork` CLI flag. A list of possible values and configurations can be
-found in [`tests/init.go`](tests/init.go).
+found in [`tests/init.go`](../../tests/init.go).
#### Examples
##### Basic usage
diff --git a/cmd/evm/blockrunner.go b/cmd/evm/blockrunner.go
index 0be5f69711..c5d836e0ea 100644
--- a/cmd/evm/blockrunner.go
+++ b/cmd/evm/blockrunner.go
@@ -21,30 +21,36 @@ import (
"errors"
"fmt"
"os"
+ "regexp"
+ "sort"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
- "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2"
)
+var RunFlag = &cli.StringFlag{
+ Name: "run",
+ Value: ".*",
+ Usage: "Run only those tests matching the regular expression.",
+}
+
var blockTestCommand = &cli.Command{
Action: blockTestCmd,
Name: "blocktest",
- Usage: "executes the given blockchain tests",
+ Usage: "Executes the given blockchain tests",
ArgsUsage: "",
+ Flags: []cli.Flag{RunFlag},
}
func blockTestCmd(ctx *cli.Context) error {
if len(ctx.Args().First()) == 0 {
return errors.New("path-to-test argument required")
}
- // Configure the go-ethereum logger
- glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
- glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
- log.Root().SetHandler(glogger)
+
var tracer vm.EVMLogger
// Configure the EVM logger
if ctx.Bool(MachineFlag.Name) {
@@ -64,9 +70,30 @@ func blockTestCmd(ctx *cli.Context) error {
if err = json.Unmarshal(src, &tests); err != nil {
return err
}
- for i, test := range tests {
- if err := test.Run(false, rawdb.HashScheme, tracer); err != nil {
- return fmt.Errorf("test %v: %w", i, err)
+ re, err := regexp.Compile(ctx.String(RunFlag.Name))
+ if err != nil {
+ return fmt.Errorf("invalid regex -%s: %v", RunFlag.Name, err)
+ }
+
+ // Run them in order
+ var keys []string
+ for key := range tests {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+ for _, name := range keys {
+ if !re.MatchString(name) {
+ continue
+ }
+ test := tests[name]
+ if err := test.Run(false, rawdb.HashScheme, tracer, func(res error, chain *core.BlockChain) {
+ if ctx.Bool(DumpFlag.Name) {
+ if state, _ := chain.State(); state != nil {
+ fmt.Println(string(state.Dump(nil)))
+ }
+ }
+ }); err != nil {
+ return fmt.Errorf("test %v: %w", name, err)
}
}
return nil
diff --git a/cmd/evm/compiler.go b/cmd/evm/compiler.go
index 699d434bb0..c071834b59 100644
--- a/cmd/evm/compiler.go
+++ b/cmd/evm/compiler.go
@@ -29,7 +29,7 @@ import (
var compileCommand = &cli.Command{
Action: compileCmd,
Name: "compile",
- Usage: "compiles easm source to evm binary",
+ Usage: "Compiles easm source to evm binary",
ArgsUsage: "",
}
diff --git a/cmd/evm/disasm.go b/cmd/evm/disasm.go
index a6a16fd13b..b1f35cbaf5 100644
--- a/cmd/evm/disasm.go
+++ b/cmd/evm/disasm.go
@@ -29,7 +29,7 @@ import (
var disasmCommand = &cli.Command{
Action: disasmCmd,
Name: "disasm",
- Usage: "disassembles evm binary",
+ Usage: "Disassembles evm binary",
ArgsUsage: "",
}
diff --git a/cmd/evm/internal/t8ntool/block.go b/cmd/evm/internal/t8ntool/block.go
index 09dca8984e..a2dc473437 100644
--- a/cmd/evm/internal/t8ntool/block.go
+++ b/cmd/evm/internal/t8ntool/block.go
@@ -30,40 +30,44 @@ import (
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/urfave/cli/v2"
)
//go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go
type header struct {
- ParentHash common.Hash `json:"parentHash"`
- OmmerHash *common.Hash `json:"sha3Uncles"`
- Coinbase *common.Address `json:"miner"`
- Root common.Hash `json:"stateRoot" gencodec:"required"`
- TxHash *common.Hash `json:"transactionsRoot"`
- ReceiptHash *common.Hash `json:"receiptsRoot"`
- Bloom types.Bloom `json:"logsBloom"`
- Difficulty *big.Int `json:"difficulty"`
- Number *big.Int `json:"number" gencodec:"required"`
- GasLimit uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed uint64 `json:"gasUsed"`
- Time uint64 `json:"timestamp" gencodec:"required"`
- Extra []byte `json:"extraData"`
- MixDigest common.Hash `json:"mixHash"`
- Nonce *types.BlockNonce `json:"nonce"`
- BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
- WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
+ ParentHash common.Hash `json:"parentHash"`
+ OmmerHash *common.Hash `json:"sha3Uncles"`
+ Coinbase *common.Address `json:"miner"`
+ Root common.Hash `json:"stateRoot" gencodec:"required"`
+ TxHash *common.Hash `json:"transactionsRoot"`
+ ReceiptHash *common.Hash `json:"receiptsRoot"`
+ Bloom types.Bloom `json:"logsBloom"`
+ Difficulty *big.Int `json:"difficulty"`
+ Number *big.Int `json:"number" gencodec:"required"`
+ GasLimit uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed uint64 `json:"gasUsed"`
+ Time uint64 `json:"timestamp" gencodec:"required"`
+ Extra []byte `json:"extraData"`
+ MixDigest common.Hash `json:"mixHash"`
+ Nonce *types.BlockNonce `json:"nonce"`
+ BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
+ WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
+ BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
+ ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
}
type headerMarshaling struct {
- Difficulty *math.HexOrDecimal256
- Number *math.HexOrDecimal256
- GasLimit math.HexOrDecimal64
- GasUsed math.HexOrDecimal64
- Time math.HexOrDecimal64
- Extra hexutil.Bytes
- BaseFee *math.HexOrDecimal256
+ Difficulty *math.HexOrDecimal256
+ Number *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
+ GasUsed math.HexOrDecimal64
+ Time math.HexOrDecimal64
+ Extra hexutil.Bytes
+ BaseFee *math.HexOrDecimal256
+ BlobGasUsed *math.HexOrDecimal64
+ ExcessBlobGas *math.HexOrDecimal64
}
type bbInput struct {
@@ -113,22 +117,25 @@ func (c *cliqueInput) UnmarshalJSON(input []byte) error {
// ToBlock converts i into a *types.Block
func (i *bbInput) ToBlock() *types.Block {
header := &types.Header{
- ParentHash: i.Header.ParentHash,
- UncleHash: types.EmptyUncleHash,
- Coinbase: common.Address{},
- Root: i.Header.Root,
- TxHash: types.EmptyTxsHash,
- ReceiptHash: types.EmptyReceiptsHash,
- Bloom: i.Header.Bloom,
- Difficulty: common.Big0,
- Number: i.Header.Number,
- GasLimit: i.Header.GasLimit,
- GasUsed: i.Header.GasUsed,
- Time: i.Header.Time,
- Extra: i.Header.Extra,
- MixDigest: i.Header.MixDigest,
- BaseFee: i.Header.BaseFee,
- WithdrawalsHash: i.Header.WithdrawalsHash,
+ ParentHash: i.Header.ParentHash,
+ UncleHash: types.EmptyUncleHash,
+ Coinbase: common.Address{},
+ Root: i.Header.Root,
+ TxHash: types.EmptyTxsHash,
+ ReceiptHash: types.EmptyReceiptsHash,
+ Bloom: i.Header.Bloom,
+ Difficulty: common.Big0,
+ Number: i.Header.Number,
+ GasLimit: i.Header.GasLimit,
+ GasUsed: i.Header.GasUsed,
+ Time: i.Header.Time,
+ Extra: i.Header.Extra,
+ MixDigest: i.Header.MixDigest,
+ BaseFee: i.Header.BaseFee,
+ WithdrawalsHash: i.Header.WithdrawalsHash,
+ BlobGasUsed: i.Header.BlobGasUsed,
+ ExcessBlobGas: i.Header.ExcessBlobGas,
+ ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
}
// Fill optional values.
@@ -150,7 +157,7 @@ func (i *bbInput) ToBlock() *types.Block {
if i.Header.Nonce != nil {
header.Nonce = *i.Header.Nonce
}
- if header.Difficulty != nil {
+ if i.Header.Difficulty != nil {
header.Difficulty = i.Header.Difficulty
}
return types.NewBlockWithHeader(header).WithBody(i.Txs, i.Ommers).WithWithdrawals(i.Withdrawals)
@@ -207,11 +214,6 @@ func (i *bbInput) sealClique(block *types.Block) (*types.Block, error) {
// BuildBlock constructs a block from the given inputs.
func BuildBlock(ctx *cli.Context) error {
- // Configure the go-ethereum logger
- glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
- glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
- log.Root().SetHandler(glogger)
-
baseDir, err := createBasedir(ctx)
if err != nil {
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go
index 982e7db8b0..ae0cb5e4ad 100644
--- a/cmd/evm/internal/t8ntool/execution.go
+++ b/cmd/evm/internal/t8ntool/execution.go
@@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
@@ -59,7 +60,7 @@ type ExecutionResult struct {
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
- CurrentBlobGasUsed *math.HexOrDecimal64 `json:"currentBlobGasUsed,omitempty"`
+ CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
}
type ommer struct {
@@ -69,25 +70,26 @@ type ommer struct {
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
type stEnv struct {
- Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
- Difficulty *big.Int `json:"currentDifficulty"`
- Random *big.Int `json:"currentRandom"`
- ParentDifficulty *big.Int `json:"parentDifficulty"`
- ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"`
- ParentGasUsed uint64 `json:"parentGasUsed,omitempty"`
- ParentGasLimit uint64 `json:"parentGasLimit,omitempty"`
- GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
- Number uint64 `json:"currentNumber" gencodec:"required"`
- Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
- ParentTimestamp uint64 `json:"parentTimestamp,omitempty"`
- BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
- Ommers []ommer `json:"ommers,omitempty"`
- Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
- BaseFee *big.Int `json:"currentBaseFee,omitempty"`
- ParentUncleHash common.Hash `json:"parentUncleHash"`
- ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"`
- ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
- ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
+ Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *big.Int `json:"currentDifficulty"`
+ Random *big.Int `json:"currentRandom"`
+ ParentDifficulty *big.Int `json:"parentDifficulty"`
+ ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"`
+ ParentGasUsed uint64 `json:"parentGasUsed,omitempty"`
+ ParentGasLimit uint64 `json:"parentGasLimit,omitempty"`
+ GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
+ Number uint64 `json:"currentNumber" gencodec:"required"`
+ Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
+ ParentTimestamp uint64 `json:"parentTimestamp,omitempty"`
+ BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
+ Ommers []ommer `json:"ommers,omitempty"`
+ Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
+ BaseFee *big.Int `json:"currentBaseFee,omitempty"`
+ ParentUncleHash common.Hash `json:"parentUncleHash"`
+ ExcessBlobGas *uint64 `json:"currentExcessBlobGas,omitempty"`
+ ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
+ ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
type stEnvMarshaling struct {
@@ -115,8 +117,8 @@ type rejectedTx struct {
// Apply applies a set of transactions to a pre-state
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
- txs types.Transactions, miningReward int64,
- getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) {
+ txIt txIterator, miningReward int64,
+ getTracerFn func(txIndex int, txHash common.Hash) (vm.EVMLogger, error)) (*state.StateDB, *ExecutionResult, []byte, error) {
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
// required blockhashes
var hashError error
@@ -139,6 +141,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
rejectedTxs []*rejectedTx
includedTxs types.Transactions
gasUsed = uint64(0)
+ blobGasUsed = uint64(0)
receipts = make(types.Receipts, 0)
txIndex = 0
)
@@ -162,17 +165,19 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
rnd := common.BigToHash(pre.Env.Random)
vmContext.Random = &rnd
}
- // If excessBlobGas is defined, add it to the vmContext.
+ // Calculate the BlobBaseFee
+ var excessBlobGas uint64
if pre.Env.ExcessBlobGas != nil {
- vmContext.ExcessBlobGas = pre.Env.ExcessBlobGas
+ excessBlobGas := *pre.Env.ExcessBlobGas
+ vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
} else {
// If it is not explicitly defined, but we have the parent values, we try
// to calculate it ourselves.
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
- excessBlobGas := eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
- vmContext.ExcessBlobGas = &excessBlobGas
+ excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
+ vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
}
}
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
@@ -182,9 +187,19 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
misc.ApplyDAOHardFork(statedb)
}
- var blobGasUsed uint64
- for i, tx := range txs {
- if tx.Type() == types.BlobTxType && vmContext.ExcessBlobGas == nil {
+ if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
+ evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
+ core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
+ }
+
+ for i := 0; txIt.Next(); i++ {
+ tx, err := txIt.Tx()
+ if err != nil {
+ log.Warn("rejected tx", "index", i, "error", err)
+ rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
+ continue
+ }
+ if tx.Type() == types.BlobTxType && vmContext.BlobBaseFee == nil {
errMsg := "blob tx used but field env.ExcessBlobGas missing"
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg})
@@ -196,9 +211,19 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
continue
}
+ txBlobGas := uint64(0)
+ if tx.Type() == types.BlobTxType {
+ txBlobGas = uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes()))
+ if used, max := blobGasUsed+txBlobGas, uint64(params.MaxBlobGasPerBlock); used > max {
+ err := fmt.Errorf("blob gas (%d) would exceed maximum allowance %d", used, max)
+ log.Warn("rejected tx", "index", i, "err", err)
+ rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
+ continue
+ }
+ }
tracer, err := getTracerFn(txIndex, tx.Hash())
if err != nil {
- return nil, nil, err
+ return nil, nil, nil, err
}
vmConfig.Tracer = tracer
statedb.SetTxContext(tx.Hash(), txIndex)
@@ -219,13 +244,11 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
gaspool.SetGas(prevGas)
continue
}
- if tx.Type() == types.BlobTxType {
- blobGasUsed += params.BlobTxBlobGasPerBlob
- }
includedTxs = append(includedTxs, tx)
if hashError != nil {
- return nil, nil, NewError(ErrorMissingBlockhash, hashError)
+ return nil, nil, nil, NewError(ErrorMissingBlockhash, hashError)
}
+ blobGasUsed += txBlobGas
gasUsed += msgResult.UsedGas
// Receipt:
@@ -286,22 +309,22 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
reward.Sub(reward, new(big.Int).SetUint64(ommer.Delta))
reward.Mul(reward, blockReward)
reward.Div(reward, big.NewInt(8))
- statedb.AddBalance(ommer.Address, reward)
+ statedb.AddBalance(ommer.Address, uint256.MustFromBig(reward))
}
- statedb.AddBalance(pre.Env.Coinbase, minerReward)
+ statedb.AddBalance(pre.Env.Coinbase, uint256.MustFromBig(minerReward))
}
// Apply withdrawals
for _, w := range pre.Env.Withdrawals {
// Amount is in gwei, turn into wei
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
- statedb.AddBalance(w.Address, amount)
+ statedb.AddBalance(w.Address, uint256.MustFromBig(amount))
}
// Commit block
statedb.Finalise(chainConfig.IsEIP158(vmContext.BlockNumber))
statedb.AccountsIntermediateRoot()
root, _, err := statedb.Commit(vmContext.BlockNumber.Uint64(), nil)
if err != nil {
- return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
+ return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
}
execRs := &ExecutionResult{
StateRoot: root,
@@ -319,17 +342,18 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
execRs.WithdrawalsRoot = &h
}
- if vmContext.ExcessBlobGas != nil {
- execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(vmContext.ExcessBlobGas)
+ if vmContext.BlobBaseFee != nil {
+ execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
}
// Re-create statedb instance with new root upon the updated database
// for accessing latest states.
statedb, err = state.New(root, statedb.Database(), nil)
if err != nil {
- return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
+ return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
}
- return statedb, execRs, nil
+ body, _ := rlp.EncodeToBytes(includedTxs)
+ return statedb, execRs, body, nil
}
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB {
@@ -338,7 +362,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
for addr, a := range accounts {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce)
- statedb.SetBalance(addr, a.Balance)
+ statedb.SetBalance(addr, uint256.MustFromBig(a.Balance))
for k, v := range a.Storage {
statedb.SetState(addr, k, v)
}
diff --git a/cmd/evm/internal/t8ntool/flags.go b/cmd/evm/internal/t8ntool/flags.go
index de19dbc851..c2eca8cc21 100644
--- a/cmd/evm/internal/t8ntool/flags.go
+++ b/cmd/evm/internal/t8ntool/flags.go
@@ -28,12 +28,15 @@ import (
var (
TraceFlag = &cli.BoolFlag{
Name: "trace",
- Usage: "Output full trace logs to files .jsonl",
+ Usage: "Configures the use of the JSON opcode tracer. This tracer emits traces to files as trace--.jsonl",
}
- TraceDisableMemoryFlag = &cli.BoolFlag{
- Name: "trace.nomemory",
- Value: true,
- Usage: "Disable full memory dump in traces (deprecated)",
+ TraceTracerFlag = &cli.StringFlag{
+ Name: "trace.tracer",
+ Usage: "Configures the use of a custom tracer, e.g native or js tracers. Examples are callTracer and 4byteTracer. These tracers emit results into files as trace--.json",
+ }
+ TraceTracerConfigFlag = &cli.StringFlag{
+ Name: "trace.jsonconfig",
+ Usage: "The configurations for the custom tracer specified by --trace.tracer. If provided, must be in JSON format",
}
TraceEnableMemoryFlag = &cli.BoolFlag{
Name: "trace.memory",
@@ -43,11 +46,6 @@ var (
Name: "trace.nostack",
Usage: "Disable stack output in traces",
}
- TraceDisableReturnDataFlag = &cli.BoolFlag{
- Name: "trace.noreturndata",
- Value: true,
- Usage: "Disable return data output in traces (deprecated)",
- }
TraceEnableReturnDataFlag = &cli.BoolFlag{
Name: "trace.returndata",
Usage: "Enable return data output in traces",
diff --git a/cmd/evm/internal/t8ntool/gen_header.go b/cmd/evm/internal/t8ntool/gen_header.go
index 76228394dc..a8c8668978 100644
--- a/cmd/evm/internal/t8ntool/gen_header.go
+++ b/cmd/evm/internal/t8ntool/gen_header.go
@@ -18,23 +18,26 @@ var _ = (*headerMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (h header) MarshalJSON() ([]byte, error) {
type header struct {
- ParentHash common.Hash `json:"parentHash"`
- OmmerHash *common.Hash `json:"sha3Uncles"`
- Coinbase *common.Address `json:"miner"`
- Root common.Hash `json:"stateRoot" gencodec:"required"`
- TxHash *common.Hash `json:"transactionsRoot"`
- ReceiptHash *common.Hash `json:"receiptsRoot"`
- Bloom types.Bloom `json:"logsBloom"`
- Difficulty *math.HexOrDecimal256 `json:"difficulty"`
- Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
- GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
- GasUsed math.HexOrDecimal64 `json:"gasUsed"`
- Time math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
- Extra hexutil.Bytes `json:"extraData"`
- MixDigest common.Hash `json:"mixHash"`
- Nonce *types.BlockNonce `json:"nonce"`
- BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
- WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
+ ParentHash common.Hash `json:"parentHash"`
+ OmmerHash *common.Hash `json:"sha3Uncles"`
+ Coinbase *common.Address `json:"miner"`
+ Root common.Hash `json:"stateRoot" gencodec:"required"`
+ TxHash *common.Hash `json:"transactionsRoot"`
+ ReceiptHash *common.Hash `json:"receiptsRoot"`
+ Bloom types.Bloom `json:"logsBloom"`
+ Difficulty *math.HexOrDecimal256 `json:"difficulty"`
+ Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
+ GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
+ GasUsed math.HexOrDecimal64 `json:"gasUsed"`
+ Time math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
+ Extra hexutil.Bytes `json:"extraData"`
+ MixDigest common.Hash `json:"mixHash"`
+ Nonce *types.BlockNonce `json:"nonce"`
+ BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
+ WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
+ BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
}
var enc header
enc.ParentHash = h.ParentHash
@@ -54,29 +57,35 @@ func (h header) MarshalJSON() ([]byte, error) {
enc.Nonce = h.Nonce
enc.BaseFee = (*math.HexOrDecimal256)(h.BaseFee)
enc.WithdrawalsHash = h.WithdrawalsHash
+ enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed)
+ enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas)
+ enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (h *header) UnmarshalJSON(input []byte) error {
type header struct {
- ParentHash *common.Hash `json:"parentHash"`
- OmmerHash *common.Hash `json:"sha3Uncles"`
- Coinbase *common.Address `json:"miner"`
- Root *common.Hash `json:"stateRoot" gencodec:"required"`
- TxHash *common.Hash `json:"transactionsRoot"`
- ReceiptHash *common.Hash `json:"receiptsRoot"`
- Bloom *types.Bloom `json:"logsBloom"`
- Difficulty *math.HexOrDecimal256 `json:"difficulty"`
- Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
- GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
- GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
- Time *math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
- Extra *hexutil.Bytes `json:"extraData"`
- MixDigest *common.Hash `json:"mixHash"`
- Nonce *types.BlockNonce `json:"nonce"`
- BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
- WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
+ ParentHash *common.Hash `json:"parentHash"`
+ OmmerHash *common.Hash `json:"sha3Uncles"`
+ Coinbase *common.Address `json:"miner"`
+ Root *common.Hash `json:"stateRoot" gencodec:"required"`
+ TxHash *common.Hash `json:"transactionsRoot"`
+ ReceiptHash *common.Hash `json:"receiptsRoot"`
+ Bloom *types.Bloom `json:"logsBloom"`
+ Difficulty *math.HexOrDecimal256 `json:"difficulty"`
+ Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
+ GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
+ GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
+ Time *math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
+ Extra *hexutil.Bytes `json:"extraData"`
+ MixDigest *common.Hash `json:"mixHash"`
+ Nonce *types.BlockNonce `json:"nonce"`
+ BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
+ WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
+ BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
}
var dec header
if err := json.Unmarshal(input, &dec); err != nil {
@@ -137,5 +146,14 @@ func (h *header) UnmarshalJSON(input []byte) error {
if dec.WithdrawalsHash != nil {
h.WithdrawalsHash = dec.WithdrawalsHash
}
+ if dec.BlobGasUsed != nil {
+ h.BlobGasUsed = (*uint64)(dec.BlobGasUsed)
+ }
+ if dec.ExcessBlobGas != nil {
+ h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
+ }
+ if dec.ParentBeaconBlockRoot != nil {
+ h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
+ }
return nil
}
diff --git a/cmd/evm/internal/t8ntool/gen_stenv.go b/cmd/evm/internal/t8ntool/gen_stenv.go
index f50fee5e31..d47db4a876 100644
--- a/cmd/evm/internal/t8ntool/gen_stenv.go
+++ b/cmd/evm/internal/t8ntool/gen_stenv.go
@@ -17,25 +17,26 @@ var _ = (*stEnvMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (s stEnv) MarshalJSON() ([]byte, error) {
type stEnv struct {
- Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
- Random *math.HexOrDecimal256 `json:"currentRandom"`
- ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
- ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
- ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
- ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
- GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
- Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
- Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
- ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
- BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
- Ommers []ommer `json:"ommers,omitempty"`
- Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
- BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
- ParentUncleHash common.Hash `json:"parentUncleHash"`
- ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
- ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
- ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
+ Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
+ Random *math.HexOrDecimal256 `json:"currentRandom"`
+ ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
+ ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
+ ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
+ ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
+ GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
+ Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
+ Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
+ ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
+ BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
+ Ommers []ommer `json:"ommers,omitempty"`
+ Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
+ BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
+ ParentUncleHash common.Hash `json:"parentUncleHash"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
+ ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
+ ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
var enc stEnv
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
@@ -57,31 +58,33 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
+ enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (s *stEnv) UnmarshalJSON(input []byte) error {
type stEnv struct {
- Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
- Random *math.HexOrDecimal256 `json:"currentRandom"`
- ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
- ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
- ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
- ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
- GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
- Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
- Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
- ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
- BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
- Ommers []ommer `json:"ommers,omitempty"`
- Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
- BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
- ParentUncleHash *common.Hash `json:"parentUncleHash"`
- ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty"`
- ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
- ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
+ Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"`
+ Random *math.HexOrDecimal256 `json:"currentRandom"`
+ ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"`
+ ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"`
+ ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"`
+ ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"`
+ GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
+ Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
+ Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
+ ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"`
+ BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"`
+ Ommers []ommer `json:"ommers,omitempty"`
+ Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
+ BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
+ ParentUncleHash *common.Hash `json:"parentUncleHash"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
+ ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
+ ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
}
var dec stEnv
if err := json.Unmarshal(input, &dec); err != nil {
@@ -148,5 +151,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
if dec.ParentBlobGasUsed != nil {
s.ParentBlobGasUsed = (*uint64)(dec.ParentBlobGasUsed)
}
+ if dec.ParentBeaconBlockRoot != nil {
+ s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
+ }
return nil
}
diff --git a/cmd/evm/internal/t8ntool/tracewriter.go b/cmd/evm/internal/t8ntool/tracewriter.go
new file mode 100644
index 0000000000..86747c72f9
--- /dev/null
+++ b/cmd/evm/internal/t8ntool/tracewriter.go
@@ -0,0 +1,85 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package t8ntool
+
+import (
+ "encoding/json"
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// traceWriter is an vm.EVMLogger which also holds an inner logger/tracer.
+// When the TxEnd event happens, the inner tracer result is written to the file, and
+// the file is closed.
+type traceWriter struct {
+ inner vm.EVMLogger
+ f io.WriteCloser
+}
+
+// Compile-time interface check
+var _ = vm.EVMLogger((*traceWriter)(nil))
+
+func (t *traceWriter) CaptureTxEnd(restGas uint64) {
+ t.inner.CaptureTxEnd(restGas)
+ defer t.f.Close()
+
+ if tracer, ok := t.inner.(tracers.Tracer); ok {
+ result, err := tracer.GetResult()
+ if err != nil {
+ log.Warn("Error in tracer", "err", err)
+ return
+ }
+ err = json.NewEncoder(t.f).Encode(result)
+ if err != nil {
+ log.Warn("Error writing tracer output", "err", err)
+ return
+ }
+ }
+}
+
+func (t *traceWriter) CaptureTxStart(gasLimit uint64) { t.inner.CaptureTxStart(gasLimit) }
+func (t *traceWriter) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ t.inner.CaptureStart(env, from, to, create, input, gas, value)
+}
+
+func (t *traceWriter) CaptureEnd(output []byte, gasUsed uint64, err error) {
+ t.inner.CaptureEnd(output, gasUsed, err)
+}
+
+func (t *traceWriter) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ t.inner.CaptureEnter(typ, from, to, input, gas, value)
+}
+
+func (t *traceWriter) CaptureExit(output []byte, gasUsed uint64, err error) {
+ t.inner.CaptureExit(output, gasUsed, err)
+}
+
+func (t *traceWriter) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+ t.inner.CaptureState(pc, op, gas, cost, scope, rData, depth, err)
+}
+func (t *traceWriter) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+ t.inner.CaptureFault(pc, op, gas, cost, scope, depth, err)
+}
+
+func (t *traceWriter) CaptureSystemTxEnd(intrinsicGas uint64) {
+ t.inner.CaptureSystemTxEnd(intrinsicGas)
+}
diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go
index 03a2e2eb99..8533b78637 100644
--- a/cmd/evm/internal/t8ntool/transaction.go
+++ b/cmd/evm/internal/t8ntool/transaction.go
@@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests"
@@ -65,11 +64,6 @@ func (r *result) MarshalJSON() ([]byte, error) {
}
func Transaction(ctx *cli.Context) error {
- // Configure the go-ethereum logger
- glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
- glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
- log.Root().SetHandler(glogger)
-
var (
err error
)
diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go
index e9173ff040..45b945c8a7 100644
--- a/cmd/evm/internal/t8ntool/transition.go
+++ b/cmd/evm/internal/t8ntool/transition.go
@@ -17,14 +17,12 @@
package t8ntool
import (
- "crypto/ecdsa"
"encoding/json"
"errors"
"fmt"
"math/big"
"os"
"path"
- "strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -33,11 +31,10 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2"
)
@@ -84,63 +81,43 @@ type input struct {
}
func Transition(ctx *cli.Context) error {
- // Configure the go-ethereum logger
- glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
- glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
- log.Root().SetHandler(glogger)
+ var getTracer = func(txIndex int, txHash common.Hash) (vm.EVMLogger, error) { return nil, nil }
- var (
- err error
- tracer vm.EVMLogger
- baseDir string
- )
- var getTracer func(txIndex int, txHash common.Hash) (vm.EVMLogger, error)
-
- baseDir, err = createBasedir(ctx)
+ baseDir, err := createBasedir(ctx)
if err != nil {
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
}
- if ctx.Bool(TraceFlag.Name) {
- if ctx.IsSet(TraceDisableMemoryFlag.Name) && ctx.IsSet(TraceEnableMemoryFlag.Name) {
- return NewError(ErrorConfig, fmt.Errorf("can't use both flags --%s and --%s", TraceDisableMemoryFlag.Name, TraceEnableMemoryFlag.Name))
- }
- if ctx.IsSet(TraceDisableReturnDataFlag.Name) && ctx.IsSet(TraceEnableReturnDataFlag.Name) {
- return NewError(ErrorConfig, fmt.Errorf("can't use both flags --%s and --%s", TraceDisableReturnDataFlag.Name, TraceEnableReturnDataFlag.Name))
- }
- if ctx.IsSet(TraceDisableMemoryFlag.Name) {
- log.Warn(fmt.Sprintf("--%s has been deprecated in favour of --%s", TraceDisableMemoryFlag.Name, TraceEnableMemoryFlag.Name))
- }
- if ctx.IsSet(TraceDisableReturnDataFlag.Name) {
- log.Warn(fmt.Sprintf("--%s has been deprecated in favour of --%s", TraceDisableReturnDataFlag.Name, TraceEnableReturnDataFlag.Name))
- }
+
+ if ctx.Bool(TraceFlag.Name) { // JSON opcode tracing
// Configure the EVM logger
logConfig := &logger.Config{
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
- EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name) || ctx.Bool(TraceEnableMemoryFlag.Name),
- EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name) || ctx.Bool(TraceEnableReturnDataFlag.Name),
+ EnableMemory: ctx.Bool(TraceEnableMemoryFlag.Name),
+ EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
Debug: true,
}
- var prevFile *os.File
- // This one closes the last file
- defer func() {
- if prevFile != nil {
- prevFile.Close()
- }
- }()
getTracer = func(txIndex int, txHash common.Hash) (vm.EVMLogger, error) {
- if prevFile != nil {
- prevFile.Close()
- }
traceFile, err := os.Create(path.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
if err != nil {
return nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
}
- prevFile = traceFile
- return logger.NewJSONLogger(logConfig, traceFile), nil
+ return &traceWriter{logger.NewJSONLogger(logConfig, traceFile), traceFile}, nil
}
- } else {
- getTracer = func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error) {
- return nil, nil
+ } else if ctx.IsSet(TraceTracerFlag.Name) {
+ var config json.RawMessage
+ if ctx.IsSet(TraceTracerConfigFlag.Name) {
+ config = []byte(ctx.String(TraceTracerConfigFlag.Name))
+ }
+ getTracer = func(txIndex int, txHash common.Hash) (vm.EVMLogger, error) {
+ traceFile, err := os.Create(path.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String())))
+ if err != nil {
+ return nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
+ }
+ tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config)
+ if err != nil {
+ return nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err))
+ }
+ return &traceWriter{tracer, traceFile}, nil
}
}
// We need to load three things: alloc, env and transactions. May be either in
@@ -148,7 +125,7 @@ func Transition(ctx *cli.Context) error {
// Check if anything needs to be read from stdin
var (
prestate Prestate
- txs types.Transactions // txs to apply
+ txIt txIterator // txs to apply
allocStr = ctx.String(InputAllocFlag.Name)
envStr = ctx.String(InputEnvFlag.Name)
@@ -179,9 +156,7 @@ func Transition(ctx *cli.Context) error {
}
prestate.Env = *inputData.Env
- vmConfig := vm.Config{
- Tracer: tracer,
- }
+ vmConfig := vm.Config{}
// Construct the chainconfig
var chainConfig *params.ChainConfig
if cConf, extraEips, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil {
@@ -193,94 +168,71 @@ func Transition(ctx *cli.Context) error {
// Set the chain id
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
- var txsWithKeys []*txWithKey
- if txStr != stdinSelector {
- inFile, err := os.Open(txStr)
- if err != nil {
- return NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
- }
- defer inFile.Close()
- decoder := json.NewDecoder(inFile)
- if strings.HasSuffix(txStr, ".rlp") {
- var body hexutil.Bytes
- if err := decoder.Decode(&body); err != nil {
- return err
- }
- var txs types.Transactions
- if err := rlp.DecodeBytes(body, &txs); err != nil {
- return err
- }
- for _, tx := range txs {
- txsWithKeys = append(txsWithKeys, &txWithKey{
- key: nil,
- tx: tx,
- })
- }
- } else {
- if err := decoder.Decode(&txsWithKeys); err != nil {
- return NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
- }
- }
- } else {
- if len(inputData.TxRlp) > 0 {
- // Decode the body of already signed transactions
- body := common.FromHex(inputData.TxRlp)
- var txs types.Transactions
- if err := rlp.DecodeBytes(body, &txs); err != nil {
- return err
- }
- for _, tx := range txs {
- txsWithKeys = append(txsWithKeys, &txWithKey{
- key: nil,
- tx: tx,
- })
- }
- } else {
- // JSON encoded transactions
- txsWithKeys = inputData.Txs
- }
+ if txIt, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil {
+ return err
+ }
+ if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
+ return err
+ }
+ if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil {
+ return err
+ }
+ if err := applyMergeChecks(&prestate.Env, chainConfig); err != nil {
+ return err
+ }
+ if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil {
+ return err
+ }
+ // Run the test and aggregate the result
+ s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name), getTracer)
+ if err != nil {
+ return err
}
- // We may have to sign the transactions.
- signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp)
+ // Dump the execution result
+ collector := make(Alloc)
+ s.DumpToCollector(collector, nil)
+ return dispatchOutput(ctx, baseDir, result, collector, body)
+}
- if txs, err = signUnsignedTransactions(txsWithKeys, signer); err != nil {
- return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err))
+func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
+ if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) {
+ return nil
}
// Sanity check, to not `panic` in state_transition
- if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) {
- if prestate.Env.BaseFee != nil {
- // Already set, base fee has precedent over parent base fee.
- } else if prestate.Env.ParentBaseFee != nil && prestate.Env.Number != 0 {
- parent := &types.Header{
- Number: new(big.Int).SetUint64(prestate.Env.Number - 1),
- BaseFee: prestate.Env.ParentBaseFee,
- GasUsed: prestate.Env.ParentGasUsed,
- GasLimit: prestate.Env.ParentGasLimit,
- }
- prestate.Env.BaseFee = eip1559.CalcBaseFee(chainConfig, parent)
- } else {
- return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
- }
+ if env.BaseFee != nil {
+ // Already set, base fee has precedent over parent base fee.
+ return nil
+ }
+ if env.ParentBaseFee == nil || env.Number == 0 {
+ return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
}
- if chainConfig.IsShanghai(big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp) && prestate.Env.Withdrawals == nil {
+ env.BaseFee = eip1559.CalcBaseFee(chainConfig, &types.Header{
+ Number: new(big.Int).SetUint64(env.Number - 1),
+ BaseFee: env.ParentBaseFee,
+ GasUsed: env.ParentGasUsed,
+ GasLimit: env.ParentGasLimit,
+ })
+ return nil
+}
+
+func applyShanghaiChecks(env *stEnv, chainConfig *params.ChainConfig) error {
+ if !chainConfig.IsShanghai(big.NewInt(int64(env.Number)), env.Timestamp) {
+ return nil
+ }
+ if chainConfig.Parlia == nil && env.Withdrawals == nil {
return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section"))
}
+ return nil
+}
+
+func applyMergeChecks(env *stEnv, chainConfig *params.ChainConfig) error {
isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0
- env := prestate.Env
- if isMerged {
- // post-merge:
- // - random must be supplied
- // - difficulty must be zero
- switch {
- case env.Random == nil:
- return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env"))
- case env.Difficulty != nil && env.Difficulty.BitLen() != 0:
- return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
+ if !isMerged {
+ // pre-merge: If difficulty was not provided by caller, we need to calculate it.
+ if env.Difficulty != nil {
+ // already set
+ return nil
}
- prestate.Env.Difficulty = nil
- } else if env.Difficulty == nil {
- // pre-merge:
- // If difficulty was not provided by caller, we need to calculate it.
switch {
case env.ParentDifficulty == nil:
return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty"))
@@ -290,102 +242,36 @@ func Transition(ctx *cli.Context) error {
return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)",
env.Timestamp, env.ParentTimestamp))
}
- prestate.Env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp,
+ env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp,
env.ParentTimestamp, env.ParentDifficulty, env.ParentUncleHash)
+ return nil
}
- // Run the test and aggregate the result
- s, result, err := prestate.Apply(vmConfig, chainConfig, txs, ctx.Int64(RewardFlag.Name), getTracer)
- if err != nil {
- return err
+ // post-merge:
+ // - random must be supplied
+ // - difficulty must be zero
+ switch {
+ case env.Random == nil:
+ return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env"))
+ case env.Difficulty != nil && env.Difficulty.BitLen() != 0:
+ return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
}
- body, _ := rlp.EncodeToBytes(txs)
- // Dump the excution result
- collector := make(Alloc)
- s.DumpToCollector(collector, nil)
- return dispatchOutput(ctx, baseDir, result, collector, body)
-}
-
-// txWithKey is a helper-struct, to allow us to use the types.Transaction along with
-// a `secretKey`-field, for input
-type txWithKey struct {
- key *ecdsa.PrivateKey
- tx *types.Transaction
- protected bool
+ env.Difficulty = nil
+ return nil
}
-func (t *txWithKey) UnmarshalJSON(input []byte) error {
- // Read the metadata, if present
- type txMetadata struct {
- Key *common.Hash `json:"secretKey"`
- Protected *bool `json:"protected"`
- }
- var data txMetadata
- if err := json.Unmarshal(input, &data); err != nil {
- return err
- }
- if data.Key != nil {
- k := data.Key.Hex()[2:]
- if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
- return err
- } else {
- t.key = ecdsaKey
- }
+func applyCancunChecks(env *stEnv, chainConfig *params.ChainConfig) error {
+ if !chainConfig.IsCancun(big.NewInt(int64(env.Number)), env.Timestamp) {
+ env.ParentBeaconBlockRoot = nil // un-set it if it has been set too early
+ return nil
}
- if data.Protected != nil {
- t.protected = *data.Protected
- } else {
- t.protected = true
+ // Post-cancun
+ // We require EIP-4788 beacon root to be set in the env
+ if env.ParentBeaconBlockRoot == nil {
+ return NewError(ErrorConfig, errors.New("post-cancun env requires parentBeaconBlockRoot to be set"))
}
- // Now, read the transaction itself
- var tx types.Transaction
- if err := json.Unmarshal(input, &tx); err != nil {
- return err
- }
- t.tx = &tx
return nil
}
-// signUnsignedTransactions converts the input txs to canonical transactions.
-//
-// The transactions can have two forms, either
-// 1. unsigned or
-// 2. signed
-//
-// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set.
-// If so, we sign it here and now, with the given `secretKey`
-// If the condition above is not met, then it's considered a signed transaction.
-//
-// To manage this, we read the transactions twice, first trying to read the secretKeys,
-// and secondly to read them with the standard tx json format
-func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
- var signedTxs []*types.Transaction
- for i, txWithKey := range txs {
- tx := txWithKey.tx
- key := txWithKey.key
- v, r, s := tx.RawSignatureValues()
- if key != nil && v.BitLen()+r.BitLen()+s.BitLen() == 0 {
- // This transaction needs to be signed
- var (
- signed *types.Transaction
- err error
- )
- if txWithKey.protected {
- signed, err = types.SignTx(tx, signer, key)
- } else {
- signed, err = types.SignTx(tx, types.FrontierSigner{}, key)
- }
- if err != nil {
- return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
- }
- signedTxs = append(signedTxs, signed)
- } else {
- // Already signed
- signedTxs = append(signedTxs, tx)
- }
- }
- return signedTxs, nil
-}
-
type Alloc map[common.Address]core.GenesisAccount
func (g Alloc) OnRoot(common.Hash) {}
@@ -394,7 +280,7 @@ func (g Alloc) OnAccount(addr *common.Address, dumpAccount state.DumpAccount) {
if addr == nil {
return
}
- balance, _ := new(big.Int).SetString(dumpAccount.Balance, 10)
+ balance, _ := new(big.Int).SetString(dumpAccount.Balance, 0)
var storage map[common.Hash]common.Hash
if dumpAccount.Storage != nil {
storage = make(map[common.Hash]common.Hash)
diff --git a/cmd/evm/internal/t8ntool/tx_iterator.go b/cmd/evm/internal/t8ntool/tx_iterator.go
new file mode 100644
index 0000000000..8f28dc7022
--- /dev/null
+++ b/cmd/evm/internal/t8ntool/tx_iterator.go
@@ -0,0 +1,194 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package t8ntool
+
+import (
+ "bytes"
+ "crypto/ecdsa"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "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"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// txWithKey is a helper-struct, to allow us to use the types.Transaction along with
+// a `secretKey`-field, for input
+type txWithKey struct {
+ key *ecdsa.PrivateKey
+ tx *types.Transaction
+ protected bool
+}
+
+func (t *txWithKey) UnmarshalJSON(input []byte) error {
+ // Read the metadata, if present
+ type txMetadata struct {
+ Key *common.Hash `json:"secretKey"`
+ Protected *bool `json:"protected"`
+ }
+ var data txMetadata
+ if err := json.Unmarshal(input, &data); err != nil {
+ return err
+ }
+ if data.Key != nil {
+ k := data.Key.Hex()[2:]
+ if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
+ return err
+ } else {
+ t.key = ecdsaKey
+ }
+ }
+ if data.Protected != nil {
+ t.protected = *data.Protected
+ } else {
+ t.protected = true
+ }
+ // Now, read the transaction itself
+ var tx types.Transaction
+ if err := json.Unmarshal(input, &tx); err != nil {
+ return err
+ }
+ t.tx = &tx
+ return nil
+}
+
+// signUnsignedTransactions converts the input txs to canonical transactions.
+//
+// The transactions can have two forms, either
+// 1. unsigned or
+// 2. signed
+//
+// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set.
+// If so, we sign it here and now, with the given `secretKey`
+// If the condition above is not met, then it's considered a signed transaction.
+//
+// To manage this, we read the transactions twice, first trying to read the secretKeys,
+// and secondly to read them with the standard tx json format
+func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
+ var signedTxs []*types.Transaction
+ for i, tx := range txs {
+ var (
+ v, r, s = tx.tx.RawSignatureValues()
+ signed *types.Transaction
+ err error
+ )
+ if tx.key == nil || v.BitLen()+r.BitLen()+s.BitLen() != 0 {
+ // Already signed
+ signedTxs = append(signedTxs, tx.tx)
+ continue
+ }
+ // This transaction needs to be signed
+ if tx.protected {
+ signed, err = types.SignTx(tx.tx, signer, tx.key)
+ } else {
+ signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key)
+ }
+ if err != nil {
+ return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
+ }
+ signedTxs = append(signedTxs, signed)
+ }
+ return signedTxs, nil
+}
+
+func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (txIterator, error) {
+ var txsWithKeys []*txWithKey
+ if txStr != stdinSelector {
+ data, err := os.ReadFile(txStr)
+ if err != nil {
+ return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
+ }
+ if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list
+ var body hexutil.Bytes
+ if err := json.Unmarshal(data, &body); err != nil {
+ return nil, err
+ }
+ return newRlpTxIterator(body), nil
+ }
+ if err := json.Unmarshal(data, &txsWithKeys); err != nil {
+ return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
+ }
+ } else {
+ if len(inputData.TxRlp) > 0 {
+ // Decode the body of already signed transactions
+ return newRlpTxIterator(common.FromHex(inputData.TxRlp)), nil
+ }
+ // JSON encoded transactions
+ txsWithKeys = inputData.Txs
+ }
+ // We may have to sign the transactions.
+ signer := types.LatestSignerForChainID(chainConfig.ChainID)
+ txs, err := signUnsignedTransactions(txsWithKeys, signer)
+ return newSliceTxIterator(txs), err
+}
+
+type txIterator interface {
+ // Next returns true until EOF
+ Next() bool
+ // Tx returns the next transaction, OR an error.
+ Tx() (*types.Transaction, error)
+}
+
+type sliceTxIterator struct {
+ idx int
+ txs []*types.Transaction
+}
+
+func newSliceTxIterator(transactions types.Transactions) txIterator {
+ return &sliceTxIterator{0, transactions}
+}
+
+func (ait *sliceTxIterator) Next() bool {
+ return ait.idx < len(ait.txs)
+}
+
+func (ait *sliceTxIterator) Tx() (*types.Transaction, error) {
+ if ait.idx < len(ait.txs) {
+ ait.idx++
+ return ait.txs[ait.idx-1], nil
+ }
+ return nil, io.EOF
+}
+
+type rlpTxIterator struct {
+ in *rlp.Stream
+}
+
+func newRlpTxIterator(rlpData []byte) txIterator {
+ in := rlp.NewStream(bytes.NewBuffer(rlpData), 1024*1024)
+ in.List()
+ return &rlpTxIterator{in}
+}
+
+func (it *rlpTxIterator) Next() bool {
+ return it.in.MoreDataInList()
+}
+
+func (it *rlpTxIterator) Tx() (*types.Transaction, error) {
+ var a types.Transaction
+ if err := it.in.Decode(&a); err != nil {
+ return nil, err
+ }
+ return &a, nil
+}
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index 024be62b9c..c3e6a4af91 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -23,121 +23,134 @@ import (
"os"
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
+ "github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/urfave/cli/v2"
+
+ // Force-load the tracer engines to trigger registration
+ _ "github.com/ethereum/go-ethereum/eth/tracers/js"
+ _ "github.com/ethereum/go-ethereum/eth/tracers/native"
)
var (
DebugFlag = &cli.BoolFlag{
- Name: "debug",
- Usage: "output full trace logs",
- }
- MemProfileFlag = &cli.StringFlag{
- Name: "memprofile",
- Usage: "creates a memory profile at the given path",
- }
- CPUProfileFlag = &cli.StringFlag{
- Name: "cpuprofile",
- Usage: "creates a CPU profile at the given path",
+ Name: "debug",
+ Usage: "output full trace logs",
+ Category: flags.VMCategory,
}
StatDumpFlag = &cli.BoolFlag{
- Name: "statdump",
- Usage: "displays stack and heap memory information",
+ Name: "statdump",
+ Usage: "displays stack and heap memory information",
+ Category: flags.VMCategory,
}
CodeFlag = &cli.StringFlag{
- Name: "code",
- Usage: "EVM code",
+ Name: "code",
+ Usage: "EVM code",
+ Category: flags.VMCategory,
}
CodeFileFlag = &cli.StringFlag{
- Name: "codefile",
- Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
+ Name: "codefile",
+ Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
+ Category: flags.VMCategory,
}
GasFlag = &cli.Uint64Flag{
- Name: "gas",
- Usage: "gas limit for the evm",
- Value: 10000000000,
+ Name: "gas",
+ Usage: "gas limit for the evm",
+ Value: 10000000000,
+ Category: flags.VMCategory,
}
PriceFlag = &flags.BigFlag{
- Name: "price",
- Usage: "price set for the evm",
- Value: new(big.Int),
+ Name: "price",
+ Usage: "price set for the evm",
+ Value: new(big.Int),
+ Category: flags.VMCategory,
}
ValueFlag = &flags.BigFlag{
- Name: "value",
- Usage: "value set for the evm",
- Value: new(big.Int),
+ Name: "value",
+ Usage: "value set for the evm",
+ Value: new(big.Int),
+ Category: flags.VMCategory,
}
DumpFlag = &cli.BoolFlag{
- Name: "dump",
- Usage: "dumps the state after the run",
+ Name: "dump",
+ Usage: "dumps the state after the run",
+ Category: flags.VMCategory,
}
InputFlag = &cli.StringFlag{
- Name: "input",
- Usage: "input for the EVM",
+ Name: "input",
+ Usage: "input for the EVM",
+ Category: flags.VMCategory,
}
InputFileFlag = &cli.StringFlag{
- Name: "inputfile",
- Usage: "file containing input for the EVM",
- }
- VerbosityFlag = &cli.IntFlag{
- Name: "verbosity",
- Usage: "sets the verbosity level",
+ Name: "inputfile",
+ Usage: "file containing input for the EVM",
+ Category: flags.VMCategory,
}
BenchFlag = &cli.BoolFlag{
- Name: "bench",
- Usage: "benchmark the execution",
+ Name: "bench",
+ Usage: "benchmark the execution",
+ Category: flags.VMCategory,
}
CreateFlag = &cli.BoolFlag{
- Name: "create",
- Usage: "indicates the action should be create rather than call",
+ Name: "create",
+ Usage: "indicates the action should be create rather than call",
+ Category: flags.VMCategory,
}
GenesisFlag = &cli.StringFlag{
- Name: "prestate",
- Usage: "JSON file with prestate (genesis) config",
+ Name: "prestate",
+ Usage: "JSON file with prestate (genesis) config",
+ Category: flags.VMCategory,
}
MachineFlag = &cli.BoolFlag{
- Name: "json",
- Usage: "output trace logs in machine readable format (json)",
+ Name: "json",
+ Usage: "output trace logs in machine readable format (json)",
+ Category: flags.VMCategory,
}
SenderFlag = &cli.StringFlag{
- Name: "sender",
- Usage: "The transaction origin",
+ Name: "sender",
+ Usage: "The transaction origin",
+ Category: flags.VMCategory,
}
ReceiverFlag = &cli.StringFlag{
- Name: "receiver",
- Usage: "The transaction receiver (execution context)",
+ Name: "receiver",
+ Usage: "The transaction receiver (execution context)",
+ Category: flags.VMCategory,
}
DisableMemoryFlag = &cli.BoolFlag{
- Name: "nomemory",
- Value: true,
- Usage: "disable memory output",
+ Name: "nomemory",
+ Value: true,
+ Usage: "disable memory output",
+ Category: flags.VMCategory,
}
DisableStackFlag = &cli.BoolFlag{
- Name: "nostack",
- Usage: "disable stack output",
+ Name: "nostack",
+ Usage: "disable stack output",
+ Category: flags.VMCategory,
}
DisableStorageFlag = &cli.BoolFlag{
- Name: "nostorage",
- Usage: "disable storage output",
+ Name: "nostorage",
+ Usage: "disable storage output",
+ Category: flags.VMCategory,
}
DisableReturnDataFlag = &cli.BoolFlag{
- Name: "noreturndata",
- Value: true,
- Usage: "enable return data output",
+ Name: "noreturndata",
+ Value: true,
+ Usage: "enable return data output",
+ Category: flags.VMCategory,
}
)
var stateTransitionCommand = &cli.Command{
Name: "transition",
Aliases: []string{"t8n"},
- Usage: "executes a full state transition",
+ Usage: "Executes a full state transition",
Action: t8ntool.Transition,
Flags: []cli.Flag{
t8ntool.TraceFlag,
- t8ntool.TraceDisableMemoryFlag,
+ t8ntool.TraceTracerFlag,
+ t8ntool.TraceTracerConfigFlag,
t8ntool.TraceEnableMemoryFlag,
t8ntool.TraceDisableStackFlag,
- t8ntool.TraceDisableReturnDataFlag,
t8ntool.TraceEnableReturnDataFlag,
t8ntool.OutputBasedir,
t8ntool.OutputAllocFlag,
@@ -149,27 +162,25 @@ var stateTransitionCommand = &cli.Command{
t8ntool.ForknameFlag,
t8ntool.ChainIDFlag,
t8ntool.RewardFlag,
- t8ntool.VerbosityFlag,
},
}
var transactionCommand = &cli.Command{
Name: "transaction",
Aliases: []string{"t9n"},
- Usage: "performs transaction validation",
+ Usage: "Performs transaction validation",
Action: t8ntool.Transaction,
Flags: []cli.Flag{
t8ntool.InputTxsFlag,
t8ntool.ChainIDFlag,
t8ntool.ForknameFlag,
- t8ntool.VerbosityFlag,
},
}
var blockBuilderCommand = &cli.Command{
Name: "block-builder",
Aliases: []string{"b11r"},
- Usage: "builds a block",
+ Usage: "Builds a block",
Action: t8ntool.BuildBlock,
Flags: []cli.Flag{
t8ntool.OutputBasedir,
@@ -179,38 +190,41 @@ var blockBuilderCommand = &cli.Command{
t8ntool.InputWithdrawalsFlag,
t8ntool.InputTxsRlpFlag,
t8ntool.SealCliqueFlag,
- t8ntool.VerbosityFlag,
},
}
+// vmFlags contains flags related to running the EVM.
+var vmFlags = []cli.Flag{
+ CodeFlag,
+ CodeFileFlag,
+ CreateFlag,
+ GasFlag,
+ PriceFlag,
+ ValueFlag,
+ InputFlag,
+ InputFileFlag,
+ GenesisFlag,
+ SenderFlag,
+ ReceiverFlag,
+}
+
+// traceFlags contains flags that configure tracing output.
+var traceFlags = []cli.Flag{
+ BenchFlag,
+ DebugFlag,
+ DumpFlag,
+ MachineFlag,
+ StatDumpFlag,
+ DisableMemoryFlag,
+ DisableStackFlag,
+ DisableStorageFlag,
+ DisableReturnDataFlag,
+}
+
var app = flags.NewApp("the evm command line interface")
func init() {
- app.Flags = []cli.Flag{
- BenchFlag,
- CreateFlag,
- DebugFlag,
- VerbosityFlag,
- CodeFlag,
- CodeFileFlag,
- GasFlag,
- PriceFlag,
- ValueFlag,
- DumpFlag,
- InputFlag,
- InputFileFlag,
- MemProfileFlag,
- CPUProfileFlag,
- StatDumpFlag,
- GenesisFlag,
- MachineFlag,
- SenderFlag,
- ReceiverFlag,
- DisableMemoryFlag,
- DisableStackFlag,
- DisableStorageFlag,
- DisableReturnDataFlag,
- }
+ app.Flags = flags.Merge(vmFlags, traceFlags, debug.Flags)
app.Commands = []*cli.Command{
compileCommand,
disasmCommand,
@@ -221,6 +235,14 @@ func init() {
transactionCommand,
blockBuilderCommand,
}
+ app.Before = func(ctx *cli.Context) error {
+ flags.MigrateGlobalFlags(ctx)
+ return debug.Setup(ctx)
+ }
+ app.After = func(ctx *cli.Context) error {
+ debug.Exit()
+ return nil
+ }
}
func main() {
diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index 73a4169b1d..b22c3efd65 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -24,7 +24,6 @@ import (
"math/big"
"os"
goruntime "runtime"
- "runtime/pprof"
"testing"
"time"
@@ -34,12 +33,10 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm/runtime"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/internal/flags"
- "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
@@ -49,9 +46,10 @@ import (
var runCommand = &cli.Command{
Action: runCmd,
Name: "run",
- Usage: "run arbitrary evm binary",
+ Usage: "Run arbitrary evm binary",
ArgsUsage: "",
Description: `The run command runs arbitrary EVM code.`,
+ Flags: flags.Merge(vmFlags, traceFlags),
}
// readGenesis will read the given JSON format genesis file and return
@@ -109,9 +107,6 @@ func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []by
}
func runCmd(ctx *cli.Context) error {
- glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
- glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
- log.Root().SetHandler(glogger)
logconfig := &logger.Config{
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
DisableStack: ctx.Bool(DisableStackFlag.Name),
@@ -121,15 +116,15 @@ func runCmd(ctx *cli.Context) error {
}
var (
- tracer vm.EVMLogger
- debugLogger *logger.StructLogger
- statedb *state.StateDB
- chainConfig *params.ChainConfig
- sender = common.BytesToAddress([]byte("sender"))
- receiver = common.BytesToAddress([]byte("receiver"))
- genesisConfig *core.Genesis
- preimages = ctx.Bool(DumpFlag.Name)
- blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
+ tracer vm.EVMLogger
+ debugLogger *logger.StructLogger
+ statedb *state.StateDB
+ chainConfig *params.ChainConfig
+ sender = common.BytesToAddress([]byte("sender"))
+ receiver = common.BytesToAddress([]byte("receiver"))
+ preimages = ctx.Bool(DumpFlag.Name)
+ blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
+ blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests
)
if ctx.Bool(MachineFlag.Name) {
tracer = logger.NewJSONLogger(logconfig, os.Stdout)
@@ -139,30 +134,30 @@ func runCmd(ctx *cli.Context) error {
} else {
debugLogger = logger.NewStructLogger(logconfig)
}
+
+ initialGas := ctx.Uint64(GasFlag.Name)
+ genesisConfig := new(core.Genesis)
+ genesisConfig.GasLimit = initialGas
if ctx.String(GenesisFlag.Name) != "" {
- gen := readGenesis(ctx.String(GenesisFlag.Name))
- genesisConfig = gen
- db := rawdb.NewMemoryDatabase()
- triedb := trie.NewDatabase(db, &trie.Config{
- Preimages: preimages,
- HashDB: hashdb.Defaults,
- })
- defer triedb.Close()
- genesis := gen.MustCommit(db, triedb)
- sdb := state.NewDatabaseWithNodeDB(db, triedb)
- statedb, _ = state.New(genesis.Root(), sdb, nil)
- chainConfig = gen.Config
+ genesisConfig = readGenesis(ctx.String(GenesisFlag.Name))
+ if genesisConfig.GasLimit != 0 {
+ initialGas = genesisConfig.GasLimit
+ }
} else {
- db := rawdb.NewMemoryDatabase()
- triedb := trie.NewDatabase(db, &trie.Config{
- Preimages: preimages,
- HashDB: hashdb.Defaults,
- })
- defer triedb.Close()
- sdb := state.NewDatabaseWithNodeDB(db, triedb)
- statedb, _ = state.New(types.EmptyRootHash, sdb, nil)
- genesisConfig = new(core.Genesis)
+ genesisConfig.Config = params.AllDevChainProtocolChanges
}
+
+ db := rawdb.NewMemoryDatabase()
+ triedb := trie.NewDatabase(db, &trie.Config{
+ Preimages: preimages,
+ HashDB: hashdb.Defaults,
+ })
+ defer triedb.Close()
+ genesis := genesisConfig.MustCommit(db, triedb)
+ sdb := state.NewDatabaseWithNodeDB(db, triedb)
+ statedb, _ = state.New(genesis.Root(), sdb, nil)
+ chainConfig = genesisConfig.Config
+
if ctx.String(SenderFlag.Name) != "" {
sender = common.HexToAddress(ctx.String(SenderFlag.Name))
}
@@ -216,10 +211,6 @@ func runCmd(ctx *cli.Context) error {
}
code = common.Hex2Bytes(bin)
}
- initialGas := ctx.Uint64(GasFlag.Name)
- if genesisConfig.GasLimit != 0 {
- initialGas = genesisConfig.GasLimit
- }
runtimeConfig := runtime.Config{
Origin: sender,
State: statedb,
@@ -231,24 +222,12 @@ func runCmd(ctx *cli.Context) error {
Coinbase: genesisConfig.Coinbase,
BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
BlobHashes: blobHashes,
+ BlobBaseFee: blobBaseFee,
EVMConfig: vm.Config{
Tracer: tracer,
},
}
- if cpuProfilePath := ctx.String(CPUProfileFlag.Name); cpuProfilePath != "" {
- f, err := os.Create(cpuProfilePath)
- if err != nil {
- fmt.Println("could not create CPU profile: ", err)
- os.Exit(1)
- }
- if err := pprof.StartCPUProfile(f); err != nil {
- fmt.Println("could not start CPU profile: ", err)
- os.Exit(1)
- }
- defer pprof.StopCPUProfile()
- }
-
if chainConfig != nil {
runtimeConfig.ChainConfig = chainConfig
} else {
@@ -297,19 +276,6 @@ func runCmd(ctx *cli.Context) error {
fmt.Println(string(statedb.Dump(nil)))
}
- if memProfilePath := ctx.String(MemProfileFlag.Name); memProfilePath != "" {
- f, err := os.Create(memProfilePath)
- if err != nil {
- fmt.Println("could not create memory profile: ", err)
- os.Exit(1)
- }
- if err := pprof.WriteHeapProfile(f); err != nil {
- fmt.Println("could not write memory profile: ", err)
- os.Exit(1)
- }
- f.Close()
- }
-
if ctx.Bool(DebugFlag.Name) {
if debugLogger != nil {
fmt.Fprintln(os.Stderr, "#### TRACE ####")
diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go
index a29c4b18f6..6e751b630f 100644
--- a/cmd/evm/staterunner.go
+++ b/cmd/evm/staterunner.go
@@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
- "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2"
)
@@ -52,11 +51,6 @@ type StatetestResult struct {
}
func stateTestCmd(ctx *cli.Context) error {
- // Configure the go-ethereum logger
- glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
- glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
- log.Root().SetHandler(glogger)
-
// Configure the EVM logger
config := &logger.Config{
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
@@ -106,20 +100,23 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
for _, st := range test.Subtests() {
// Run the test and aggregate the result
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
- test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- if err != nil {
- // Test failed, mark as so and dump any state to aid debugging
- result.Pass, result.Error = false, err.Error()
- if dump {
- dump := state.RawDump(nil)
- result.State = &dump
- }
- } else {
- root := state.IntermediateRoot(false)
+ test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, statedb *state.StateDB) {
+ var root common.Hash
+ if statedb != nil {
+ root = statedb.IntermediateRoot(false)
result.Root = &root
if jsonOut {
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
}
+ if dump { // Dump any state to aid debugging
+ cpy, _ := state.New(root, statedb.Database(), nil)
+ dump := cpy.RawDump(nil)
+ result.State = &dump
+ }
+ }
+ if err != nil {
+ // Test failed, mark as so
+ result.Pass, result.Error = false, err.Error()
}
})
results = append(results, *result)
diff --git a/cmd/evm/t8n_test.go b/cmd/evm/t8n_test.go
index 7037039854..363b48c3ff 100644
--- a/cmd/evm/t8n_test.go
+++ b/cmd/evm/t8n_test.go
@@ -24,9 +24,9 @@ import (
"strings"
"testing"
- "github.com/docker/docker/pkg/reexec"
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
"github.com/ethereum/go-ethereum/internal/cmdtest"
+ "github.com/ethereum/go-ethereum/internal/reexec"
)
func TestMain(m *testing.M) {
@@ -106,6 +106,7 @@ func (args *t8nOutput) get() (out []string) {
}
func TestT8n(t *testing.T) {
+ t.Parallel()
tt := new(testT8n)
tt.TestCmd = cmdtest.NewTestCmd(t, tt)
for i, tc := range []struct {
@@ -262,17 +263,30 @@ func TestT8n(t *testing.T) {
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
- // TODO(Nathan): Cancun not ready
- /*
- { // Cancun tests
- base: "./testdata/28",
- input: t8nInput{
- "alloc.json", "txs.rlp", "env.json", "Cancun", "",
- },
- output: t8nOutput{alloc: true, result: true},
- expOut: "exp.json",
+ { // Cancun tests
+ base: "./testdata/28",
+ input: t8nInput{
+ "alloc.json", "txs.rlp", "env.json", "Cancun", "",
},
- */
+ output: t8nOutput{alloc: true, result: true},
+ expOut: "exp.json",
+ },
+ { // More cancun tests
+ base: "./testdata/29",
+ input: t8nInput{
+ "alloc.json", "txs.json", "env.json", "Cancun", "",
+ },
+ output: t8nOutput{alloc: true, result: true},
+ expOut: "exp.json",
+ },
+ { // More cancun test, plus example of rlp-transaction that cannot be decoded properly
+ base: "./testdata/30",
+ input: t8nInput{
+ "alloc.json", "txs_more.rlp", "env.json", "Cancun", "",
+ },
+ output: t8nOutput{alloc: true, result: true},
+ expOut: "exp.json",
+ },
} {
args := []string{"t8n"}
args = append(args, tc.output.get()...)
@@ -328,6 +342,7 @@ func (args *t9nInput) get(base string) []string {
}
func TestT9n(t *testing.T) {
+ t.Parallel()
tt := new(testT8n)
tt.TestCmd = cmdtest.NewTestCmd(t, tt)
for i, tc := range []struct {
@@ -463,6 +478,7 @@ func (args *b11rInput) get(base string) []string {
}
func TestB11r(t *testing.T) {
+ t.Parallel()
tt := new(testT8n)
tt.TestCmd = cmdtest.NewTestCmd(t, tt)
for i, tc := range []struct {
diff --git a/cmd/evm/testdata/28/env.json b/cmd/evm/testdata/28/env.json
index 83c12dcfc3..82f22ac62f 100644
--- a/cmd/evm/testdata/28/env.json
+++ b/cmd/evm/testdata/28/env.json
@@ -9,8 +9,7 @@
"parentDifficulty" : "0x00",
"parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "withdrawals" : [
- ],
+ "withdrawals" : [],
"parentBaseFee" : "0x0a",
"parentGasUsed" : "0x00",
"parentGasLimit" : "0x7fffffffffffffff",
@@ -18,5 +17,6 @@
"parentBlobGasUsed" : "0x00",
"blockHashes" : {
"0" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6"
- }
-}
\ No newline at end of file
+ },
+ "parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
+}
diff --git a/cmd/evm/testdata/28/exp.json b/cmd/evm/testdata/28/exp.json
index a55ce0aec4..75c715e972 100644
--- a/cmd/evm/testdata/28/exp.json
+++ b/cmd/evm/testdata/28/exp.json
@@ -42,6 +42,6 @@
"currentBaseFee": "0x9",
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"currentExcessBlobGas": "0x0",
- "currentBlobGasUsed": "0x20000"
+ "blobGasUsed": "0x20000"
}
-}
\ No newline at end of file
+}
diff --git a/cmd/evm/testdata/29/alloc.json b/cmd/evm/testdata/29/alloc.json
new file mode 100644
index 0000000000..d2c879a45c
--- /dev/null
+++ b/cmd/evm/testdata/29/alloc.json
@@ -0,0 +1,16 @@
+{
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0x016345785d8a0000",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" : {
+ "balance" : "0x1",
+ "code" : "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+}
\ No newline at end of file
diff --git a/cmd/evm/testdata/29/env.json b/cmd/evm/testdata/29/env.json
new file mode 100644
index 0000000000..e752a909ad
--- /dev/null
+++ b/cmd/evm/testdata/29/env.json
@@ -0,0 +1,20 @@
+{
+ "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
+ "currentNumber" : "0x01",
+ "currentTimestamp" : "0x079e",
+ "currentGasLimit" : "0x7fffffffffffffff",
+ "previousHash" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6",
+ "currentBlobGasUsed" : "0x00",
+ "parentTimestamp" : "0x03b6",
+ "parentDifficulty" : "0x00",
+ "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "withdrawals" : [
+ ],
+ "parentBaseFee" : "0x0a",
+ "parentGasUsed" : "0x00",
+ "parentGasLimit" : "0x7fffffffffffffff",
+ "parentExcessBlobGas" : "0x00",
+ "parentBlobGasUsed" : "0x00",
+ "parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
+}
\ No newline at end of file
diff --git a/cmd/evm/testdata/29/exp.json b/cmd/evm/testdata/29/exp.json
new file mode 100644
index 0000000000..c4c001ec14
--- /dev/null
+++ b/cmd/evm/testdata/29/exp.json
@@ -0,0 +1,45 @@
+{
+ "alloc": {
+ "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": {
+ "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e",
+ "0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
+ },
+ "balance": "0x1"
+ },
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
+ "balance": "0x16345785d871db8",
+ "nonce": "0x1"
+ }
+ },
+ "result": {
+ "stateRoot": "0x19a4f821a7c0a6f4c934f9acb0fe9ce5417b68086e12513ecbc3e3f57e01573c",
+ "txRoot": "0x248074fabe112f7d93917f292b64932394f835bb98da91f21501574d58ec92ab",
+ "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
+ "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "receipts": [
+ {
+ "type": "0x2",
+ "root": "0x",
+ "status": "0x1",
+ "cumulativeGasUsed": "0x5208",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "logs": null,
+ "transactionHash": "0x84f70aba406a55628a0620f26d260f90aeb6ccc55fed6ec2ac13dd4f727032ed",
+ "contractAddress": "0x0000000000000000000000000000000000000000",
+ "gasUsed": "0x5208",
+ "effectiveGasPrice": null,
+ "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "transactionIndex": "0x0"
+ }
+ ],
+ "currentDifficulty": null,
+ "gasUsed": "0x5208",
+ "currentBaseFee": "0x9",
+ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "currentExcessBlobGas": "0x0",
+ "blobGasUsed": "0x0"
+ }
+}
diff --git a/cmd/evm/testdata/29/readme.md b/cmd/evm/testdata/29/readme.md
new file mode 100644
index 0000000000..ab02ce9cf8
--- /dev/null
+++ b/cmd/evm/testdata/29/readme.md
@@ -0,0 +1,29 @@
+## EIP 4788
+
+This test contains testcases for EIP-4788. The 4788-contract is
+located at address `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`, and this test executes a simple transaction. It also
+implicitly invokes the system tx, which sets calls the contract and sets the
+storage values
+
+```
+$ dir=./testdata/29/ && go run . t8n --state.fork=Cancun --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout
+INFO [09-27|15:34:53.049] Trie dumping started root=19a4f8..01573c
+INFO [09-27|15:34:53.049] Trie dumping complete accounts=2 elapsed="192.759µs"
+INFO [09-27|15:34:53.050] Wrote file file=result.json
+{
+ "alloc": {
+ "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": {
+ "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
+ "storage": {
+ "0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e",
+ "0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00"
+ },
+ "balance": "0x1"
+ },
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
+ "balance": "0x16345785d871db8",
+ "nonce": "0x1"
+ }
+ }
+}
+```
diff --git a/cmd/evm/testdata/29/txs.json b/cmd/evm/testdata/29/txs.json
new file mode 100644
index 0000000000..d6743cc4d2
--- /dev/null
+++ b/cmd/evm/testdata/29/txs.json
@@ -0,0 +1,19 @@
+[
+ {
+ "input" : "0x",
+ "gas" : "0x10000000",
+ "nonce" : "0x0",
+ "to" : "0x1111111111111111111111111111111111111111",
+ "value" : "0x0",
+ "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "chainId" : "0x1",
+ "type" : "0x2",
+ "v": "0x0",
+ "r": "0x0",
+ "s": "0x0",
+ "maxFeePerGas" : "0xfa0",
+ "maxPriorityFeePerGas" : "0x0",
+ "accessList" : [
+ ]
+ }
+]
\ No newline at end of file
diff --git a/cmd/evm/testdata/30/README.txt b/cmd/evm/testdata/30/README.txt
new file mode 100644
index 0000000000..84c92de853
--- /dev/null
+++ b/cmd/evm/testdata/30/README.txt
@@ -0,0 +1,77 @@
+This example comes from https://github.com/ethereum/go-ethereum/issues/27730.
+The input transactions contain three transactions, number `0` and `2` are taken from
+`testdata/13`, whereas number `1` is taken from #27730.
+
+The problematic second transaction cannot be RLP-decoded, and the expectation is
+that that particular transaction should be rejected, but number `0` and `1` should
+still be accepted.
+
+```
+$ go run . t8n --input.alloc=./testdata/30/alloc.json --input.txs=./testdata/30/txs_more.rlp --input.env=./testdata/30/env.json --output.result=stdout --output.alloc=stdout --state.fork=Cancun
+WARN [10-22|15:38:03.283] rejected tx index=1 error="rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To"
+INFO [10-22|15:38:03.284] Trie dumping started root=348312..915c93
+INFO [10-22|15:38:03.284] Trie dumping complete accounts=3 elapsed="160.831µs"
+{
+ "alloc": {
+ "0x095e7baea6a6c7c4c2dfeb977efac326af552d87": {
+ "code": "0x60004960005500",
+ "balance": "0xde0b6b3a7640000"
+ },
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
+ "balance": "0xde0b6b3a7640000"
+ },
+ "0xd02d72e067e77158444ef2020ff2d325f929b363": {
+ "balance": "0xfffffffb8390",
+ "nonce": "0x3"
+ }
+ },
+ "result": {
+ "stateRoot": "0x3483124b6710486c9fb3e07975669c66924697c88cccdcc166af5e1218915c93",
+ "txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d",
+ "receiptsRoot": "0x75308898d571eafb5cd8cde8278bf5b3d13c5f6ec074926de3bb895b519264e1",
+ "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "receipts": [
+ {
+ "type": "0x2",
+ "root": "0x",
+ "status": "0x1",
+ "cumulativeGasUsed": "0x5208",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "logs": null,
+ "transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
+ "contractAddress": "0x0000000000000000000000000000000000000000",
+ "gasUsed": "0x5208",
+ "effectiveGasPrice": null,
+ "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "transactionIndex": "0x0"
+ },
+ {
+ "type": "0x2",
+ "root": "0x",
+ "status": "0x1",
+ "cumulativeGasUsed": "0xa410",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "logs": null,
+ "transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
+ "contractAddress": "0x0000000000000000000000000000000000000000",
+ "gasUsed": "0x5208",
+ "effectiveGasPrice": null,
+ "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "transactionIndex": "0x1"
+ }
+ ],
+ "rejected": [
+ {
+ "index": 1,
+ "error": "rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To"
+ }
+ ],
+ "currentDifficulty": null,
+ "gasUsed": "0xa410",
+ "currentBaseFee": "0x7",
+ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
+ }
+}
+
+```
\ No newline at end of file
diff --git a/cmd/evm/testdata/30/alloc.json b/cmd/evm/testdata/30/alloc.json
new file mode 100644
index 0000000000..6bc93d2552
--- /dev/null
+++ b/cmd/evm/testdata/30/alloc.json
@@ -0,0 +1,23 @@
+{
+ "0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
+ "balance" : "0x0de0b6b3a7640000",
+ "code" : "0x60004960005500",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ },
+ "0xd02d72e067e77158444ef2020ff2d325f929b363" : {
+ "balance": "0x01000000000000",
+ "code": "0x",
+ "nonce": "0x01",
+ "storage": {
+ }
+ },
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "0x0de0b6b3a7640000",
+ "code" : "0x",
+ "nonce" : "0x00",
+ "storage" : {
+ }
+ }
+}
\ No newline at end of file
diff --git a/cmd/evm/testdata/30/env.json b/cmd/evm/testdata/30/env.json
new file mode 100644
index 0000000000..4acd9794be
--- /dev/null
+++ b/cmd/evm/testdata/30/env.json
@@ -0,0 +1,23 @@
+{
+ "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
+ "currentNumber" : "0x01",
+ "currentTimestamp" : "0x03e8",
+ "currentGasLimit" : "0x1000000000",
+ "previousHash" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da",
+ "currentDataGasUsed" : "0x2000",
+ "parentTimestamp" : "0x00",
+ "parentDifficulty" : "0x00",
+ "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "parentBeaconBlockRoot" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "currentRandom" : "0x0000000000000000000000000000000000000000000000000000000000020000",
+ "withdrawals" : [
+ ],
+ "parentBaseFee" : "0x08",
+ "parentGasUsed" : "0x00",
+ "parentGasLimit" : "0x1000000000",
+ "parentExcessBlobGas" : "0x1000",
+ "parentBlobGasUsed" : "0x2000",
+ "blockHashes" : {
+ "0" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da"
+ }
+}
\ No newline at end of file
diff --git a/cmd/evm/testdata/30/exp.json b/cmd/evm/testdata/30/exp.json
new file mode 100644
index 0000000000..f0b19c6b3d
--- /dev/null
+++ b/cmd/evm/testdata/30/exp.json
@@ -0,0 +1,64 @@
+{
+ "alloc": {
+ "0x095e7baea6a6c7c4c2dfeb977efac326af552d87": {
+ "code": "0x60004960005500",
+ "balance": "0xde0b6b3a7640000"
+ },
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
+ "balance": "0xde0b6b3a7640000"
+ },
+ "0xd02d72e067e77158444ef2020ff2d325f929b363": {
+ "balance": "0xfffffffb8390",
+ "nonce": "0x3"
+ }
+ },
+ "result": {
+ "stateRoot": "0x3483124b6710486c9fb3e07975669c66924697c88cccdcc166af5e1218915c93",
+ "txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d",
+ "receiptsRoot": "0x75308898d571eafb5cd8cde8278bf5b3d13c5f6ec074926de3bb895b519264e1",
+ "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "receipts": [
+ {
+ "type": "0x2",
+ "root": "0x",
+ "status": "0x1",
+ "cumulativeGasUsed": "0x5208",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "logs": null,
+ "transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
+ "contractAddress": "0x0000000000000000000000000000000000000000",
+ "gasUsed": "0x5208",
+ "effectiveGasPrice": null,
+ "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "transactionIndex": "0x0"
+ },
+ {
+ "type": "0x2",
+ "root": "0x",
+ "status": "0x1",
+ "cumulativeGasUsed": "0xa410",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "logs": null,
+ "transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
+ "contractAddress": "0x0000000000000000000000000000000000000000",
+ "gasUsed": "0x5208",
+ "effectiveGasPrice": null,
+ "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "transactionIndex": "0x1"
+ }
+ ],
+ "rejected": [
+ {
+ "index": 1,
+ "error": "rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To"
+ }
+ ],
+ "currentDifficulty": null,
+ "gasUsed": "0xa410",
+ "currentBaseFee": "0x7",
+ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "currentExcessBlobGas": "0x0",
+ "blobGasUsed": "0x0"
+ }
+}
\ No newline at end of file
diff --git a/cmd/evm/testdata/30/txs.rlp b/cmd/evm/testdata/30/txs.rlp
new file mode 100644
index 0000000000..620c1a13ac
--- /dev/null
+++ b/cmd/evm/testdata/30/txs.rlp
@@ -0,0 +1 @@
+"0xf8dbb8d903f8d601800285012a05f200833d090080830186a000f85bf85994095e7baea6a6c7c4c2dfeb977efac326af552d87f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d880a0fc12b67159a3567f8bdbc49e0be369a2e20e09d57a51c41310543a4128409464a02de0cfe5495c4f58ff60645ceda0afd67a4c90a70bc89fe207269435b35e5b67"
\ No newline at end of file
diff --git a/cmd/evm/testdata/30/txs_more.rlp b/cmd/evm/testdata/30/txs_more.rlp
new file mode 100644
index 0000000000..35af8d1f23
--- /dev/null
+++ b/cmd/evm/testdata/30/txs_more.rlp
@@ -0,0 +1 @@
+"0xf901adb86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b8d903f8d601800285012a05f200833d090080830186a000f85bf85994095e7baea6a6c7c4c2dfeb977efac326af552d87f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d880a0fc12b67159a3567f8bdbc49e0be369a2e20e09d57a51c41310543a4128409464a02de0cfe5495c4f58ff60645ceda0afd67a4c90a70bc89fe207269435b35e5b67b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9"
\ No newline at end of file
diff --git a/cmd/evm/testdata/8/readme.md b/cmd/evm/testdata/8/readme.md
index 4dffdab91e..85aae18924 100644
--- a/cmd/evm/testdata/8/readme.md
+++ b/cmd/evm/testdata/8/readme.md
@@ -32,7 +32,7 @@ dir=./testdata/8 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json
{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"}
```
-Simlarly, we can provide the input transactions via `stdin` instead of as file:
+Similarly, we can provide the input transactions via `stdin` instead of as file:
```
$ dir=./testdata/8 \
diff --git a/cmd/evm/testdata/9/readme.md b/cmd/evm/testdata/9/readme.md
index 5394780288..357e200682 100644
--- a/cmd/evm/testdata/9/readme.md
+++ b/cmd/evm/testdata/9/readme.md
@@ -1,6 +1,6 @@
## EIP-1559 testing
-This test contains testcases for EIP-1559, which uses an new transaction type and has a new block parameter.
+This test contains testcases for EIP-1559, which uses a new transaction type and has a new block parameter.
### Prestate
diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go
index 2b1c08b8ac..6f5505ad0d 100644
--- a/cmd/faucet/faucet.go
+++ b/cmd/faucet/faucet.go
@@ -89,7 +89,7 @@ var websiteTmpl string
func main() {
// Parse the flags and set up the logger to print everything requested
flag.Parse()
- log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*logFlag), log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.FromLegacyLevel(*logFlag), true)))
// Construct the payout tiers
amounts := make([]string, *tiersFlag)
diff --git a/cmd/geth/accountcmd_test.go b/cmd/geth/accountcmd_test.go
index 84b9c33c24..ea3a7c3b64 100644
--- a/cmd/geth/accountcmd_test.go
+++ b/cmd/geth/accountcmd_test.go
@@ -43,11 +43,13 @@ func tmpDatadirWithKeystore(t *testing.T) string {
}
func TestAccountListEmpty(t *testing.T) {
+ t.Parallel()
geth := runGeth(t, "account", "list")
geth.ExpectExit()
}
func TestAccountList(t *testing.T) {
+ t.Parallel()
datadir := tmpDatadirWithKeystore(t)
var want = `
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
@@ -74,6 +76,7 @@ Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}\k
}
func TestAccountNew(t *testing.T) {
+ t.Parallel()
geth := runGeth(t, "account", "new", "--lightkdf")
defer geth.ExpectExit()
geth.Expect(`
@@ -96,6 +99,7 @@ Path of the secret key file: .*UTC--.+--[0-9a-f]{40}
}
func TestAccountImport(t *testing.T) {
+ t.Parallel()
tests := []struct{ name, key, output string }{
{
name: "correct account",
@@ -118,6 +122,7 @@ func TestAccountImport(t *testing.T) {
}
func TestAccountHelp(t *testing.T) {
+ t.Parallel()
geth := runGeth(t, "account", "-h")
geth.WaitExit()
if have, want := geth.ExitStatus(), 0; have != want {
@@ -147,6 +152,7 @@ func importAccountWithExpect(t *testing.T, key string, expected string) {
}
func TestAccountNewBadRepeat(t *testing.T) {
+ t.Parallel()
geth := runGeth(t, "account", "new", "--lightkdf")
defer geth.ExpectExit()
geth.Expect(`
@@ -159,6 +165,7 @@ Fatal: Passwords do not match
}
func TestAccountUpdate(t *testing.T) {
+ t.Parallel()
datadir := tmpDatadirWithKeystore(t)
geth := runGeth(t, "account", "update",
"--datadir", datadir, "--lightkdf",
@@ -175,6 +182,7 @@ Repeat password: {{.InputLine "foobar2"}}
}
func TestWalletImport(t *testing.T) {
+ t.Parallel()
geth := runGeth(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json")
defer geth.ExpectExit()
geth.Expect(`
@@ -190,6 +198,7 @@ Address: {d4584b5f6229b7be90727b0fc8c6b91bb427821f}
}
func TestWalletImportBadPassword(t *testing.T) {
+ t.Parallel()
geth := runGeth(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json")
defer geth.ExpectExit()
geth.Expect(`
@@ -200,6 +209,7 @@ Fatal: could not decrypt key with given password
}
func TestUnlockFlag(t *testing.T) {
+ t.Parallel()
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "console", "--exec", "loadScript('testdata/empty.js')")
geth.Expect(`
@@ -222,6 +232,7 @@ undefined
}
func TestUnlockFlagWrongPassword(t *testing.T) {
+ t.Parallel()
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "console", "--exec", "loadScript('testdata/empty.js')")
@@ -240,6 +251,7 @@ Fatal: Failed to unlock account f466859ead1932d743d622cb74fc058882e8648a (could
// https://github.com/ethereum/go-ethereum/issues/1785
func TestUnlockFlagMultiIndex(t *testing.T) {
+ t.Parallel()
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--unlock", "0,2", "console", "--exec", "loadScript('testdata/empty.js')")
@@ -266,6 +278,7 @@ undefined
}
func TestUnlockFlagPasswordFile(t *testing.T) {
+ t.Parallel()
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--password", "testdata/passwords.txt", "--unlock", "0,2", "console", "--exec", "loadScript('testdata/empty.js')")
@@ -287,6 +300,7 @@ undefined
}
func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) {
+ t.Parallel()
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--password",
"testdata/wrong-passwords.txt", "--unlock", "0,2")
@@ -297,6 +311,7 @@ Fatal: Failed to unlock account 0 (could not decrypt key with given password)
}
func TestUnlockFlagAmbiguous(t *testing.T) {
+ t.Parallel()
store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--keystore",
@@ -336,6 +351,7 @@ undefined
}
func TestUnlockFlagAmbiguousWrongPassword(t *testing.T) {
+ t.Parallel()
store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--keystore",
diff --git a/cmd/geth/blsaccountcmd.go b/cmd/geth/blsaccountcmd.go
index 8b0e19dfa3..64c7926755 100644
--- a/cmd/geth/blsaccountcmd.go
+++ b/cmd/geth/blsaccountcmd.go
@@ -5,6 +5,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
+ "math/big"
"os"
"path/filepath"
"strings"
@@ -14,6 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v4/io/prompt"
+ validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client"
"github.com/prysmaticlabs/prysm/v4/validator/accounts"
"github.com/prysmaticlabs/prysm/v4/validator/accounts/iface"
"github.com/prysmaticlabs/prysm/v4/validator/accounts/petnames"
@@ -25,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/signer/core"
)
@@ -46,6 +49,10 @@ var (
Usage: "Password file path for the imported BLS account , which contains the password to get the private key by decrypting the keystore file",
Category: flags.AccountCategory,
}
+ chainIdFlag = &cli.Int64Flag{
+ Name: "chain-id",
+ Usage: "The chain id of the network that the validator will be created at",
+ }
)
var (
@@ -188,6 +195,22 @@ Print summary of existing BLS accounts in the current BLS wallet.`,
Delete the selected BLS account from the BLS wallet.`,
},
+ {
+ Name: "generate-proof",
+ Usage: "Generate ownership proof for the selected BLS account from the BLS wallet",
+ Action: blsAccountGenerateProof,
+ ArgsUsage: " ",
+ Category: "BLS ACCOUNT COMMANDS",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ utils.BLSPasswordFileFlag,
+ chainIdFlag,
+ },
+ Description: `
+ geth bls account generate-proof
+
+Generate ownership proof for the selected BLS account from the BLS wallet. The proof is used to prove the ownership of the BLS account when creating validator on BSC after feynman upgrade.`,
+ },
},
},
},
@@ -607,3 +630,74 @@ func blsAccountDelete(ctx *cli.Context) error {
return nil
}
+
+// blsAccountGenerateProof generate ownership proof for a selected BLS account.
+func blsAccountGenerateProof(ctx *cli.Context) error {
+ addrString := ctx.Args().First()
+ if addrString == "" {
+ utils.Fatalf("Operator account must be given as argument.")
+ }
+ addr := common.HexToAddress(addrString)
+
+ blsPubkeyString := ctx.Args().Get(1)
+ if blsPubkeyString == "" {
+ utils.Fatalf("BLS pubkey must be given as argument.")
+ }
+ blsPubkeyBz, err := hex.DecodeString(strings.TrimPrefix(blsPubkeyString, "0x"))
+ if err != nil {
+ utils.Fatalf("Could not decode string %s as hex.", blsPubkeyString)
+ }
+ blsPublicKey, err := bls.PublicKeyFromBytes(blsPubkeyBz)
+ if err != nil {
+ utils.Fatalf("%#x is not a valid BLS public key.", blsPubkeyBz)
+ }
+
+ cfg := gethConfig{Node: defaultNodeConfig()}
+ // Load config file.
+ if file := ctx.String(configFileFlag.Name); file != "" {
+ if err := loadConfig(file, &cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ }
+ utils.SetNodeConfig(ctx, &cfg.Node)
+
+ walletDir := filepath.Join(cfg.Node.DataDir, BLSWalletPath)
+ dirExists, err := wallet.Exists(walletDir)
+ if err != nil || !dirExists {
+ utils.Fatalf("BLS wallet not exists.")
+ }
+
+ walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
+ w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
+ WalletDir: walletDir,
+ WalletPassword: walletPassword,
+ })
+ if err != nil {
+ utils.Fatalf("Open BLS wallet failed: %v.", err)
+ }
+ km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
+ if err != nil {
+ utils.Fatalf("Initialize key manager failed: %v.", err)
+ }
+
+ chainIdInt64 := ctx.Int64(chainIdFlag.Name)
+ if chainIdInt64 == 0 {
+ utils.Fatalf("Chain id is required.")
+ }
+ chainId := new(big.Int).SetInt64(chainIdInt64)
+ paddedChainIdBytes := make([]byte, 32)
+ copy(paddedChainIdBytes[32-len(chainId.Bytes()):], chainId.Bytes())
+ msgHash := crypto.Keccak256(append(addr.Bytes(), append(blsPublicKey.Marshal(), paddedChainIdBytes...)...))
+
+ req := &validatorpb.SignRequest{
+ PublicKey: blsPublicKey.Marshal(),
+ SigningRoot: msgHash,
+ }
+ sig, err := km.Sign(context.Background(), req)
+ if err != nil {
+ utils.Fatalf("Generate signature failed: %v.", err)
+ }
+ fmt.Printf("Proof: %#x\n", sig.Marshal())
+
+ return nil
+}
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index 6ce1e52553..1b88aecb52 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -59,8 +59,9 @@ var (
ArgsUsage: "",
Flags: flags.Merge([]cli.Flag{
utils.CachePreimagesFlag,
- utils.StateSchemeFlag,
- }, utils.DatabasePathFlags),
+ utils.OverrideCancun,
+ utils.OverrideVerkle,
+ }, utils.DatabaseFlags),
Description: `
The init command initializes a new genesis block and definition for the network.
This is a destructive action and changes the network in which you will be
@@ -123,9 +124,8 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
utils.MetricsInfluxDBOrganizationFlag,
utils.TxLookupLimitFlag,
utils.TransactionHistoryFlag,
- utils.StateSchemeFlag,
utils.StateHistoryFlag,
- }, utils.DatabasePathFlags),
+ }, utils.DatabaseFlags),
Description: `
The import command imports blocks from an RLP-encoded form. The form can be one file
with several RLP-encoded blocks, or several files can be used.
@@ -141,8 +141,7 @@ processing will proceed even if an individual RLP-file import failure occurs.`,
Flags: flags.Merge([]cli.Flag{
utils.CacheFlag,
utils.SyncModeFlag,
- utils.StateSchemeFlag,
- }, utils.DatabasePathFlags),
+ }, utils.DatabaseFlags),
Description: `
Requires a first argument of the file to write to.
Optional second and third arguments control the first and
@@ -158,26 +157,13 @@ be gzipped.`,
Flags: flags.Merge([]cli.Flag{
utils.CacheFlag,
utils.SyncModeFlag,
- }, utils.DatabasePathFlags),
+ }, utils.DatabaseFlags),
Description: `
The import-preimages command imports hash preimages from an RLP encoded stream.
It's deprecated, please use "geth db import" instead.
`,
}
- exportPreimagesCommand = &cli.Command{
- Action: exportPreimages,
- Name: "export-preimages",
- Usage: "Export the preimage database into an RLP stream",
- ArgsUsage: "",
- Flags: flags.Merge([]cli.Flag{
- utils.CacheFlag,
- utils.SyncModeFlag,
- }, utils.DatabasePathFlags),
- Description: `
-The export-preimages command exports hash preimages to an RLP encoded stream.
-It's deprecated, please use "geth db export" instead.
-`,
- }
+
dumpCommand = &cli.Command{
Action: dump,
Name: "dump",
@@ -191,8 +177,7 @@ It's deprecated, please use "geth db export" instead.
utils.IncludeIncompletesFlag,
utils.StartKeyFlag,
utils.DumpLimitFlag,
- utils.StateSchemeFlag,
- }, utils.DatabasePathFlags),
+ }, utils.DatabaseFlags),
Description: `
This command dumps out the state for a given block (or latest, if none provided).
If you use "dump" command in path mode, please firstly use "dump-roothash" command to get all available state root hash.
@@ -202,9 +187,7 @@ If you use "dump" command in path mode, please firstly use "dump-roothash" comma
Action: dumpAllRootHashInPath,
Name: "dump-roothash",
Usage: "Dump all available state root hash in path mode",
- Flags: flags.Merge([]cli.Flag{
- utils.StateSchemeFlag,
- }, utils.DatabasePathFlags),
+ Flags: flags.Merge([]cli.Flag{}, utils.DatabaseFlags),
Description: `
The dump-roothash command dump all available state root hash in path mode.
If you use "dump" command in path mode, please note that it only keeps at most 129 blocks which belongs to diffLayer or diskLayer.
@@ -238,6 +221,15 @@ func initGenesis(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
+ var overrides core.ChainOverrides
+ if ctx.IsSet(utils.OverrideCancun.Name) {
+ v := ctx.Uint64(utils.OverrideCancun.Name)
+ overrides.OverrideCancun = &v
+ }
+ if ctx.IsSet(utils.OverrideVerkle.Name) {
+ v := ctx.Uint64(utils.OverrideVerkle.Name)
+ overrides.OverrideVerkle = &v
+ }
for _, name := range []string{"chaindata", "lightchaindata"} {
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false, false, false, false)
if err != nil {
@@ -245,14 +237,14 @@ func initGenesis(ctx *cli.Context) error {
}
defer chaindb.Close()
- triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false)
+ triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
defer triedb.Close()
- _, hash, err := core.SetupGenesisBlock(chaindb, triedb, genesis)
+ _, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
if err != nil {
utils.Fatalf("Failed to write genesis block: %v", err)
}
- log.Info(fmt.Sprintf("Successfully wrote genesis state database=%v hash=%v", name, hash))
+ log.Info("Successfully wrote genesis state", "database", name, "hash", hash.String())
}
return nil
}
@@ -418,14 +410,21 @@ func initNetwork(ctx *cli.Context) error {
}
func dumpGenesis(ctx *cli.Context) error {
- // if there is a testnet preset enabled, dump that
+ // check if there is a testnet preset enabled
+ var genesis *core.Genesis
if utils.IsNetworkPreset(ctx) {
- genesis := utils.MakeGenesis(ctx)
+ genesis = utils.MakeGenesis(ctx)
+ } else if ctx.IsSet(utils.DeveloperFlag.Name) && !ctx.IsSet(utils.DataDirFlag.Name) {
+ genesis = core.DeveloperGenesisBlock(11_500_000, nil)
+ }
+
+ if genesis != nil {
if err := json.NewEncoder(os.Stdout).Encode(genesis); err != nil {
utils.Fatalf("could not encode genesis: %s", err)
}
return nil
}
+
// dump whatever already exists in the datadir
stack, _ := makeConfigNode(ctx)
for _, name := range []string{"chaindata", "lightchaindata"} {
@@ -450,7 +449,7 @@ func dumpGenesis(ctx *cli.Context) error {
if ctx.IsSet(utils.DataDirFlag.Name) {
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
}
- utils.Fatalf("no network preset provided, no existing genesis in the default datadir")
+ utils.Fatalf("no network preset provided, and no genesis exists in the default datadir")
return nil
}
@@ -541,7 +540,8 @@ func exportChain(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- chain, _ := utils.MakeChain(ctx, stack, true)
+ chain, db := utils.MakeChain(ctx, stack, true)
+ defer db.Close()
start := time.Now()
var err error
@@ -572,6 +572,9 @@ func exportChain(ctx *cli.Context) error {
}
// importPreimages imports preimage data from the specified file.
+// it is deprecated, and the export function has been removed, but
+// the import function is kept around for the time being so that
+// older file formats can still be imported.
func importPreimages(ctx *cli.Context) error {
if ctx.Args().Len() < 1 {
utils.Fatalf("This command requires an argument.")
@@ -581,6 +584,7 @@ func importPreimages(ctx *cli.Context) error {
defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, false, false)
+ defer db.Close()
start := time.Now()
if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil {
@@ -590,30 +594,13 @@ func importPreimages(ctx *cli.Context) error {
return nil
}
-// exportPreimages dumps the preimage data to specified json file in streaming way.
-func exportPreimages(ctx *cli.Context) error {
- if ctx.Args().Len() < 1 {
- utils.Fatalf("This command requires an argument.")
- }
- stack, _ := makeConfigNode(ctx)
- defer stack.Close()
-
- db := utils.MakeChainDatabase(ctx, stack, true, false)
- start := time.Now()
-
- if err := utils.ExportPreimages(db, ctx.Args().First()); err != nil {
- utils.Fatalf("Export error: %v\n", err)
- }
- fmt.Printf("Export done in %v\n", time.Since(start))
- return nil
-}
-
func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, ethdb.Database, common.Hash, error) {
if ctx.NArg() > 1 {
return nil, nil, common.Hash{}, fmt.Errorf("expected 1 argument (number or hash), got %d", ctx.NArg())
}
db := utils.MakeChainDatabase(ctx, stack, true, false)
+ defer db.Close()
scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db)
if err != nil {
return nil, nil, common.Hash{}, err
@@ -622,7 +609,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
fmt.Println("You are using geth dump in path mode, please use `geth dump-roothash` command to get all available blocks.")
}
- header := &types.Header{}
+ var header *types.Header
if ctx.NArg() == 1 {
arg := ctx.Args().First()
if hashish(arg) {
@@ -696,7 +683,7 @@ func dump(ctx *cli.Context) error {
if err != nil {
return err
}
- triedb := utils.MakeTrieDatabase(ctx, db, true, true) // always enable preimage lookup
+ triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
defer triedb.Close()
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
@@ -706,11 +693,6 @@ func dump(ctx *cli.Context) error {
if ctx.Bool(utils.IterativeOutputFlag.Name) {
state.IterativeDump(conf, json.NewEncoder(os.Stdout))
} else {
- if conf.OnlyWithAddresses {
- fmt.Fprintf(os.Stderr, "If you want to include accounts with missing preimages, you need iterative output, since"+
- " otherwise the accounts will overwrite each other in the resulting mapping.")
- return errors.New("incompatible options")
- }
fmt.Println(string(state.Dump(conf)))
}
return nil
diff --git a/cmd/geth/config.go b/cmd/geth/config.go
index f83441d510..94c2317e95 100644
--- a/cmd/geth/config.go
+++ b/cmd/geth/config.go
@@ -22,11 +22,10 @@ import (
"fmt"
"os"
"reflect"
+ "runtime"
+ "strings"
"unicode"
- "github.com/naoina/toml"
- "github.com/urfave/cli/v2"
-
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/external"
"github.com/ethereum/go-ethereum/accounts/keystore"
@@ -43,6 +42,8 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
+ "github.com/naoina/toml"
+ "github.com/urfave/cli/v2"
)
var (
@@ -198,7 +199,25 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
v := ctx.Uint64(utils.OverrideVerkle.Name)
cfg.Eth.OverrideVerkle = &v
}
- backend, _ := utils.RegisterEthService(stack, &cfg.Eth)
+ if ctx.IsSet(utils.OverrideFeynman.Name) {
+ v := ctx.Uint64(utils.OverrideFeynman.Name)
+ cfg.Eth.OverrideFeynman = &v
+ }
+ backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
+
+ // Create gauge with geth system and build information
+ if eth != nil { // The 'eth' backend may be nil in light mode
+ var protos []string
+ for _, p := range eth.Protocols() {
+ protos = append(protos, fmt.Sprintf("%v/%d", p.Name, p.Version))
+ }
+ metrics.NewRegisteredGaugeInfo("geth/info", nil).Update(metrics.GaugeInfoValue{
+ "arch": runtime.GOARCH,
+ "os": runtime.GOOS,
+ "version": cfg.Node.Version,
+ "protocols": strings.Join(protos, ","),
+ })
+ }
// Configure log filter RPC API.
filterSystem := utils.RegisterFilterAPI(stack, backend, &cfg.Eth)
@@ -207,7 +226,6 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
if ctx.IsSet(utils.GraphQLEnabledFlag.Name) {
utils.RegisterGraphQLService(stack, backend, filterSystem, &cfg.Node)
}
-
// Add the Ethereum Stats daemon if requested.
if cfg.Ethstats.URL != "" {
utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL)
diff --git a/cmd/geth/consolecmd_test.go b/cmd/geth/consolecmd_test.go
index 58872a71c9..59c0e0015e 100644
--- a/cmd/geth/consolecmd_test.go
+++ b/cmd/geth/consolecmd_test.go
@@ -30,7 +30,7 @@ import (
)
const (
- ipcAPIs = "admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 parlia:1.0 rpc:1.0 txpool:1.0 web3:1.0"
+ ipcAPIs = "admin:1.0 debug:1.0 eth:1.0 mev:1.0 miner:1.0 net:1.0 parlia:1.0 rpc:1.0 txpool:1.0 web3:1.0"
httpAPIs = "eth:1.0 net:1.0 rpc:1.0 web3:1.0"
)
@@ -49,6 +49,7 @@ func runMinimalGeth(t *testing.T, args ...string) *testgeth {
// Tests that a node embedded within a console can be started up properly and
// then terminated by closing the input stream.
func TestConsoleWelcome(t *testing.T) {
+ t.Parallel()
coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
// Start a geth console, make sure it's cleaned up and terminate the console
diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go
index 275dc1fa50..677bae5d12 100644
--- a/cmd/geth/dbcmd.go
+++ b/cmd/geth/dbcmd.go
@@ -45,12 +45,22 @@ import (
)
var (
+ removeStateDataFlag = &cli.BoolFlag{
+ Name: "remove.state",
+ Usage: "If set, selects the state data for removal",
+ }
+ removeChainDataFlag = &cli.BoolFlag{
+ Name: "remove.chain",
+ Usage: "If set, selects the state data for removal",
+ }
+
removedbCommand = &cli.Command{
Action: removeDB,
Name: "removedb",
Usage: "Remove blockchain and state databases",
ArgsUsage: "",
- Flags: utils.DatabasePathFlags,
+ Flags: flags.Merge(utils.DatabaseFlags,
+ []cli.Flag{removeStateDataFlag, removeChainDataFlag}),
Description: `
Remove blockchain and state databases`,
}
@@ -86,7 +96,7 @@ Remove blockchain and state databases`,
ArgsUsage: " ",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
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.`,
}
@@ -105,7 +115,7 @@ Remove blockchain and state databases`,
Action: checkStateContent,
Name: "check-state-content",
ArgsUsage: "",
- Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
+ Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
Usage: "Verify that state data is cryptographically correct",
Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes.
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
@@ -158,7 +168,7 @@ a data corruption.`,
Usage: "Print leveldb statistics",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
}
dbCompactCmd = &cli.Command{
Action: dbCompact,
@@ -168,8 +178,8 @@ a data corruption.`,
utils.SyncModeFlag,
utils.CacheFlag,
utils.CacheDatabaseFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
- Description: `This command performs a database compaction.
+ }, utils.NetworkFlags, utils.DatabaseFlags),
+ Description: `This command performs a database compaction.
WARNING: This operation may take a very long time to finish, and may cause database
corruption if it is aborted during execution'!`,
}
@@ -180,7 +190,7 @@ corruption if it is aborted during execution'!`,
ArgsUsage: "",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
Description: "This command looks up the specified database key from the database.",
}
dbDeleteCmd = &cli.Command{
@@ -190,8 +200,8 @@ corruption if it is aborted during execution'!`,
ArgsUsage: "",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
- Description: `This command deletes the specified database key from the database.
+ }, utils.NetworkFlags, utils.DatabaseFlags),
+ Description: `This command deletes the specified database key from the database.
WARNING: This is a low-level operation which may cause database corruption!`,
}
dbPutCmd = &cli.Command{
@@ -201,8 +211,8 @@ WARNING: This is a low-level operation which may cause database corruption!`,
ArgsUsage: " ",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
- Description: `This command sets a given database key to the given value.
+ }, utils.NetworkFlags, utils.DatabaseFlags),
+ Description: `This command sets a given database key to the given value.
WARNING: This is a low-level operation which may cause database corruption!`,
}
dbGetSlotsCmd = &cli.Command{
@@ -212,8 +222,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
ArgsUsage: " ",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- utils.StateSchemeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
Description: "This command looks up the specified database key from the database.",
}
dbDumpFreezerIndex = &cli.Command{
@@ -223,7 +232,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
ArgsUsage: " ",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
Description: "This command displays information about the freezer index.",
}
dbImportCmd = &cli.Command{
@@ -233,7 +242,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
ArgsUsage: " ",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
}
dbMetadataCmd = &cli.Command{
@@ -252,7 +261,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
Usage: "Shows metadata about the chain status.",
Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
Description: "Shows metadata about the chain status.",
}
ancientInspectCmd = &cli.Command{
@@ -270,60 +279,85 @@ of ancientStore, will also displays the reserved number of blocks in ancientStor
func removeDB(ctx *cli.Context) error {
stack, config := makeConfigNode(ctx)
- // Remove the full node state database
- path := stack.ResolvePath("chaindata")
- if common.FileExist(path) {
- confirmAndRemoveDB(path, "full node state database")
- } else {
- log.Info("Full node state database missing", "path", path)
- }
- // Remove the full node ancient database
- path = config.Eth.DatabaseFreezer
+ // Resolve folder paths.
+ var (
+ rootDir = stack.ResolvePath("chaindata")
+ ancientDir = config.Eth.DatabaseFreezer
+ )
switch {
- case path == "":
- path = filepath.Join(stack.ResolvePath("chaindata"), "ancient")
- case !filepath.IsAbs(path):
- path = config.Node.ResolvePath(path)
- }
- if common.FileExist(path) {
- confirmAndRemoveDB(path, "full node ancient database")
- } else {
- log.Info("Full node ancient database missing", "path", path)
- }
- // Remove the light node database
- path = stack.ResolvePath("lightchaindata")
- if common.FileExist(path) {
- confirmAndRemoveDB(path, "light node database")
- } else {
- log.Info("Light node database missing", "path", path)
- }
+ case ancientDir == "":
+ ancientDir = filepath.Join(stack.ResolvePath("chaindata"), "ancient")
+ case !filepath.IsAbs(ancientDir):
+ ancientDir = config.Node.ResolvePath(ancientDir)
+ }
+ // Delete state data
+ statePaths := []string{rootDir, filepath.Join(ancientDir, rawdb.StateFreezerName)}
+ confirmAndRemoveDB(statePaths, "state data", ctx, removeStateDataFlag.Name)
+
+ // Delete ancient chain
+ chainPaths := []string{filepath.Join(ancientDir, rawdb.ChainFreezerName)}
+ confirmAndRemoveDB(chainPaths, "ancient chain", ctx, removeChainDataFlag.Name)
return nil
}
+// removeFolder deletes all files (not folders) inside the directory 'dir' (but
+// not files in subfolders).
+func removeFolder(dir string) {
+ filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+ // If we're at the top level folder, recurse into
+ if path == dir {
+ return nil
+ }
+ // Delete all the files, but not subfolders
+ if !info.IsDir() {
+ os.Remove(path)
+ return nil
+ }
+ return filepath.SkipDir
+ })
+}
+
// confirmAndRemoveDB prompts the user for a last confirmation and removes the
-// folder if accepted.
-func confirmAndRemoveDB(database string, kind string) {
- confirm, err := prompt.Stdin.PromptConfirm(fmt.Sprintf("Remove %s (%s)?", kind, database))
+// list of folders if accepted.
+func confirmAndRemoveDB(paths []string, kind string, ctx *cli.Context, removeFlagName string) {
+ var (
+ confirm bool
+ err error
+ )
+ msg := fmt.Sprintf("Location(s) of '%s': \n", kind)
+ for _, path := range paths {
+ msg += fmt.Sprintf("\t- %s\n", path)
+ }
+ fmt.Println(msg)
+ if ctx.IsSet(removeFlagName) {
+ confirm = ctx.Bool(removeFlagName)
+ if confirm {
+ fmt.Printf("Remove '%s'? [y/n] y\n", kind)
+ } else {
+ fmt.Printf("Remove '%s'? [y/n] n\n", kind)
+ }
+ } else {
+ confirm, err = prompt.Stdin.PromptConfirm(fmt.Sprintf("Remove '%s'?", kind))
+ }
switch {
case err != nil:
utils.Fatalf("%v", err)
case !confirm:
- log.Info("Database deletion skipped", "path", database)
+ log.Info("Database deletion skipped", "kind", kind, "paths", paths)
default:
- start := time.Now()
- filepath.Walk(database, func(path string, info os.FileInfo, err error) error {
- // If we're at the top level folder, recurse into
- if path == database {
- return nil
- }
- // Delete all the files, but not subfolders
- if !info.IsDir() {
- os.Remove(path)
- return nil
+ var (
+ deleted []string
+ start = time.Now()
+ )
+ for _, path := range paths {
+ if common.FileExist(path) {
+ removeFolder(path)
+ deleted = append(deleted, path)
+ } else {
+ log.Info("Folder is not existent", "path", path)
}
- return filepath.SkipDir
- })
- log.Info("Database successfully deleted", "path", database, "elapsed", common.PrettyDuration(time.Since(start)))
+ }
+ log.Info("Database successfully deleted", "kind", kind, "paths", deleted, "elapsed", common.PrettyDuration(time.Since(start)))
}
}
@@ -776,7 +810,7 @@ func dbDumpTrie(ctx *cli.Context) error {
db := utils.MakeChainDatabase(ctx, stack, true, false)
defer db.Close()
- triedb := utils.MakeTrieDatabase(ctx, db, false, true)
+ triedb := utils.MakeTrieDatabase(ctx, db, false, true, false)
defer triedb.Close()
var (
@@ -888,6 +922,7 @@ func importLDBdata(ctx *cli.Context) error {
close(stop)
}()
db := utils.MakeChainDatabase(ctx, stack, false, false)
+ defer db.Close()
return utils.ImportLDBData(db, fName, int64(start), stop)
}
@@ -984,6 +1019,7 @@ func exportChaindata(ctx *cli.Context) error {
close(stop)
}()
db := utils.MakeChainDatabase(ctx, stack, true, false)
+ defer db.Close()
return utils.ExportChaindata(ctx.Args().Get(1), kind, exporter(db), stop)
}
@@ -991,6 +1027,7 @@ func showMetaData(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, true, false)
+ defer db.Close()
ancients, err := db.Ancients()
if err != nil {
fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err)
diff --git a/cmd/geth/exportcmd_test.go b/cmd/geth/exportcmd_test.go
index bbf08d820e..9570b1ffd2 100644
--- a/cmd/geth/exportcmd_test.go
+++ b/cmd/geth/exportcmd_test.go
@@ -27,6 +27,7 @@ import (
// TestExport does a basic test of "geth export", exporting the test-genesis.
func TestExport(t *testing.T) {
+ t.Parallel()
outfile := fmt.Sprintf("%v/testExport.out", os.TempDir())
defer os.Remove(outfile)
geth := runGeth(t, "--datadir", initGeth(t), "export", outfile)
diff --git a/cmd/geth/logging_test.go b/cmd/geth/logging_test.go
new file mode 100644
index 0000000000..b5ce03f4b8
--- /dev/null
+++ b/cmd/geth/logging_test.go
@@ -0,0 +1,237 @@
+//go:build integrationtests
+
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "math/rand"
+ "os"
+ "os/exec"
+ "strings"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/internal/reexec"
+)
+
+func runSelf(args ...string) ([]byte, error) {
+ cmd := &exec.Cmd{
+ Path: reexec.Self(),
+ Args: append([]string{"geth-test"}, args...),
+ }
+ return cmd.CombinedOutput()
+}
+
+func split(input io.Reader) []string {
+ var output []string
+ scanner := bufio.NewScanner(input)
+ scanner.Split(bufio.ScanLines)
+ for scanner.Scan() {
+ output = append(output, strings.TrimSpace(scanner.Text()))
+ }
+ return output
+}
+
+func censor(input string, start, end int) string {
+ if len(input) < end {
+ return input
+ }
+ return input[:start] + strings.Repeat("X", end-start) + input[end:]
+}
+
+func TestLogging(t *testing.T) {
+ t.Parallel()
+ testConsoleLogging(t, "terminal", 6, 24)
+ testConsoleLogging(t, "logfmt", 2, 26)
+}
+
+func testConsoleLogging(t *testing.T, format string, tStart, tEnd int) {
+ haveB, err := runSelf("--log.format", format, "logtest")
+ if err != nil {
+ t.Fatal(err)
+ }
+ readFile, err := os.Open(fmt.Sprintf("testdata/logging/logtest-%v.txt", format))
+ if err != nil {
+ t.Fatal(err)
+ }
+ wantLines := split(readFile)
+ haveLines := split(bytes.NewBuffer(haveB))
+ for i, want := range wantLines {
+ if i > len(haveLines)-1 {
+ t.Fatalf("format %v, line %d missing, want:%v", format, i, want)
+ }
+ have := haveLines[i]
+ for strings.Contains(have, "Unknown config environment variable") {
+ // This can happen on CI runs. Drop it.
+ haveLines = append(haveLines[:i], haveLines[i+1:]...)
+ have = haveLines[i]
+ }
+
+ // Black out the timestamp
+ have = censor(have, tStart, tEnd)
+ want = censor(want, tStart, tEnd)
+ if have != want {
+ t.Logf(nicediff([]byte(have), []byte(want)))
+ t.Fatalf("format %v, line %d\nhave %v\nwant %v", format, i, have, want)
+ }
+ }
+ if len(haveLines) != len(wantLines) {
+ t.Errorf("format %v, want %d lines, have %d", format, len(haveLines), len(wantLines))
+ }
+}
+
+func TestJsonLogging(t *testing.T) {
+ t.Parallel()
+ haveB, err := runSelf("--log.format", "json", "logtest")
+ if err != nil {
+ t.Fatal(err)
+ }
+ readFile, err := os.Open("testdata/logging/logtest-json.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ wantLines := split(readFile)
+ haveLines := split(bytes.NewBuffer(haveB))
+ for i, wantLine := range wantLines {
+ if i > len(haveLines)-1 {
+ t.Fatalf("format %v, line %d missing, want:%v", "json", i, wantLine)
+ }
+ haveLine := haveLines[i]
+ for strings.Contains(haveLine, "Unknown config environment variable") {
+ // This can happen on CI runs. Drop it.
+ haveLines = append(haveLines[:i], haveLines[i+1:]...)
+ haveLine = haveLines[i]
+ }
+ var have, want []byte
+ {
+ var h map[string]any
+ if err := json.Unmarshal([]byte(haveLine), &h); err != nil {
+ t.Fatal(err)
+ }
+ h["t"] = "xxx"
+ have, _ = json.Marshal(h)
+ }
+ {
+ var w map[string]any
+ if err := json.Unmarshal([]byte(wantLine), &w); err != nil {
+ t.Fatal(err)
+ }
+ w["t"] = "xxx"
+ want, _ = json.Marshal(w)
+ }
+ if !bytes.Equal(have, want) {
+ // show an intelligent diff
+ t.Logf(nicediff(have, want))
+ t.Errorf("file content wrong")
+ }
+ }
+}
+
+func TestVmodule(t *testing.T) {
+ t.Parallel()
+ checkOutput := func(level int, want, wantNot string) {
+ t.Helper()
+ output, err := runSelf("--log.format", "terminal", "--verbosity=0", "--log.vmodule", fmt.Sprintf("logtestcmd_active.go=%d", level), "logtest")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(want) > 0 && !strings.Contains(string(output), want) { // trace should be present at 5
+ t.Errorf("failed to find expected string ('%s') in output", want)
+ }
+ if len(wantNot) > 0 && strings.Contains(string(output), wantNot) { // trace should be present at 5
+ t.Errorf("string ('%s') should not be present in output", wantNot)
+ }
+ }
+ checkOutput(5, "log at level trace", "") // trace should be present at 5
+ checkOutput(4, "log at level debug", "log at level trace") // debug should be present at 4, but trace should be missing
+ checkOutput(3, "log at level info", "log at level debug") // info should be present at 3, but debug should be missing
+ checkOutput(2, "log at level warn", "log at level info") // warn should be present at 2, but info should be missing
+ checkOutput(1, "log at level error", "log at level warn") // error should be present at 1, but warn should be missing
+}
+
+func nicediff(have, want []byte) string {
+ var i = 0
+ for ; i < len(have) && i < len(want); i++ {
+ if want[i] != have[i] {
+ break
+ }
+ }
+ var end = i + 40
+ var start = i - 50
+ if start < 0 {
+ start = 0
+ }
+ var h, w string
+ if end < len(have) {
+ h = string(have[start:end])
+ } else {
+ h = string(have[start:])
+ }
+ if end < len(want) {
+ w = string(want[start:end])
+ } else {
+ w = string(want[start:])
+ }
+ return fmt.Sprintf("have vs want:\n%q\n%q\n", h, w)
+}
+
+func TestFileOut(t *testing.T) {
+ t.Parallel()
+ var (
+ have, want []byte
+ err error
+ path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63())
+ )
+ t.Cleanup(func() { os.Remove(path) })
+ if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "logtest"); err != nil {
+ t.Fatal(err)
+ }
+ if have, err = os.ReadFile(path); err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(have, want) {
+ // show an intelligent diff
+ t.Logf(nicediff(have, want))
+ t.Errorf("file content wrong")
+ }
+}
+
+func TestRotatingFileOut(t *testing.T) {
+ t.Parallel()
+ var (
+ have, want []byte
+ err error
+ path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63())
+ )
+ t.Cleanup(func() { os.Remove(path) })
+ if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "--log.rotate", "logtest"); err != nil {
+ t.Fatal(err)
+ }
+ if have, err = os.ReadFile(path); err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(have, want) {
+ // show an intelligent diff
+ t.Logf(nicediff(have, want))
+ t.Errorf("file content wrong")
+ }
+}
diff --git a/cmd/geth/logtestcmd_active.go b/cmd/geth/logtestcmd_active.go
new file mode 100644
index 0000000000..f2a2c5ded5
--- /dev/null
+++ b/cmd/geth/logtestcmd_active.go
@@ -0,0 +1,171 @@
+//go:build integrationtests
+
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package main
+
+import (
+ "errors"
+ "fmt"
+ "math"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/holiman/uint256"
+ "github.com/urfave/cli/v2"
+)
+
+var logTestCommand = &cli.Command{
+ Action: logTest,
+ Name: "logtest",
+ Usage: "Print some log messages",
+ ArgsUsage: " ",
+ Description: `
+This command is only meant for testing.
+`}
+
+type customQuotedStringer struct {
+}
+
+func (c customQuotedStringer) String() string {
+ return "output with 'quotes'"
+}
+
+// logTest is an entry point which spits out some logs. This is used by testing
+// to verify expected outputs
+func logTest(ctx *cli.Context) error {
+ { // big.Int
+ ba, _ := new(big.Int).SetString("111222333444555678999", 10) // "111,222,333,444,555,678,999"
+ bb, _ := new(big.Int).SetString("-111222333444555678999", 10) // "-111,222,333,444,555,678,999"
+ bc, _ := new(big.Int).SetString("11122233344455567899900", 10) // "11,122,233,344,455,567,899,900"
+ bd, _ := new(big.Int).SetString("-11122233344455567899900", 10) // "-11,122,233,344,455,567,899,900"
+ log.Info("big.Int", "111,222,333,444,555,678,999", ba)
+ log.Info("-big.Int", "-111,222,333,444,555,678,999", bb)
+ log.Info("big.Int", "11,122,233,344,455,567,899,900", bc)
+ log.Info("-big.Int", "-11,122,233,344,455,567,899,900", bd)
+ }
+ { //uint256
+ ua, _ := uint256.FromDecimal("111222333444555678999")
+ ub, _ := uint256.FromDecimal("11122233344455567899900")
+ log.Info("uint256", "111,222,333,444,555,678,999", ua)
+ log.Info("uint256", "11,122,233,344,455,567,899,900", ub)
+ }
+ { // int64
+ log.Info("int64", "1,000,000", int64(1000000))
+ log.Info("int64", "-1,000,000", int64(-1000000))
+ log.Info("int64", "9,223,372,036,854,775,807", int64(math.MaxInt64))
+ log.Info("int64", "-9,223,372,036,854,775,808", int64(math.MinInt64))
+ }
+ { // uint64
+ log.Info("uint64", "1,000,000", uint64(1000000))
+ log.Info("uint64", "18,446,744,073,709,551,615", uint64(math.MaxUint64))
+ }
+ { // Special characters
+ log.Info("Special chars in value", "key", "special \r\n\t chars")
+ log.Info("Special chars in key", "special \n\t chars", "value")
+
+ log.Info("nospace", "nospace", "nospace")
+ log.Info("with space", "with nospace", "with nospace")
+
+ log.Info("Bash escapes in value", "key", "\u001b[1G\u001b[K\u001b[1A")
+ log.Info("Bash escapes in key", "\u001b[1G\u001b[K\u001b[1A", "value")
+
+ log.Info("Bash escapes in message \u001b[1G\u001b[K\u001b[1A end", "key", "value")
+
+ colored := fmt.Sprintf("\u001B[%dmColored\u001B[0m[", 35)
+ log.Info(colored, colored, colored)
+ err := errors.New("this is an 'error'")
+ log.Info("an error message with quotes", "error", err)
+ }
+ { // Custom Stringer() - type
+ log.Info("Custom Stringer value", "2562047h47m16.854s", common.PrettyDuration(time.Duration(9223372036854775807)))
+ var c customQuotedStringer
+ log.Info("a custom stringer that emits quoted text", "output", c)
+ }
+ { // Multi-line message
+ log.Info("A message with wonky \U0001F4A9 characters")
+ log.Info("A multiline message \nINFO [10-18|14:11:31.106] with wonky characters \U0001F4A9")
+ log.Info("A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above")
+ }
+ { // Miscellaneous json-quirks
+ // This will check if the json output uses strings or json-booleans to represent bool values
+ log.Info("boolean", "true", true, "false", false)
+ // Handling of duplicate keys.
+ // This is actually ill-handled by the current handler: the format.go
+ // uses a global 'fieldPadding' map and mixes up the two keys. If 'alpha'
+ // is shorter than beta, it sometimes causes erroneous padding -- and what's more
+ // it causes _different_ padding in multi-handler context, e.g. both file-
+ // and console output, making the two mismatch.
+ log.Info("repeated-key 1", "foo", "alpha", "foo", "beta")
+ log.Info("repeated-key 2", "xx", "short", "xx", "longer")
+ }
+ { // loglevels
+ log.Debug("log at level debug")
+ log.Trace("log at level trace")
+ log.Info("log at level info")
+ log.Warn("log at level warn")
+ log.Error("log at level error")
+ }
+ {
+ // The current log formatter has a global map of paddings, storing the
+ // longest seen padding per key in a map. This results in a statefulness
+ // which has some odd side-effects. Demonstrated here:
+ log.Info("test", "bar", "short", "a", "aligned left")
+ log.Info("test", "bar", "a long message", "a", 1)
+ log.Info("test", "bar", "short", "a", "aligned right")
+ }
+ {
+ // This sequence of logs should be output with alignment, so each field becoems a column.
+ log.Info("The following logs should align so that the key-fields make 5 columns")
+ log.Info("Inserted known block", "number", 1_012, "hash", common.HexToHash("0x1234"), "txs", 200, "gas", 1_123_123, "other", "first")
+ log.Info("Inserted new block", "number", 1, "hash", common.HexToHash("0x1235"), "txs", 2, "gas", 1_123, "other", "second")
+ log.Info("Inserted known block", "number", 99, "hash", common.HexToHash("0x12322"), "txs", 10, "gas", 1, "other", "third")
+ log.Warn("Inserted known block", "number", 1_012, "hash", common.HexToHash("0x1234"), "txs", 200, "gas", 99, "other", "fourth")
+ }
+ { // Various types of nil
+ type customStruct struct {
+ A string
+ B *uint64
+ }
+ log.Info("(*big.Int)(nil)", "", (*big.Int)(nil))
+ log.Info("(*uint256.Int)(nil)", "", (*uint256.Int)(nil))
+ log.Info("(fmt.Stringer)(nil)", "res", (fmt.Stringer)(nil))
+ log.Info("nil-concrete-stringer", "res", (*time.Time)(nil))
+
+ log.Info("error(nil) ", "res", error(nil))
+ log.Info("nil-concrete-error", "res", (*customError)(nil))
+
+ log.Info("nil-custom-struct", "res", (*customStruct)(nil))
+ log.Info("raw nil", "res", nil)
+ log.Info("(*uint64)(nil)", "res", (*uint64)(nil))
+ }
+ { // Logging with 'reserved' keys
+ log.Info("Using keys 't', 'lvl', 'time', 'level' and 'msg'", "t", "t", "time", "time", "lvl", "lvl", "level", "level", "msg", "msg")
+ }
+ { // Logging with wrong attr-value pairs
+ log.Info("Odd pair (1 attr)", "key")
+ log.Info("Odd pair (3 attr)", "key", "value", "key2")
+ }
+ return nil
+}
+
+// customError is a type which implements error
+type customError struct{}
+
+func (c *customError) Error() string { return "" }
diff --git a/cmd/geth/logtestcmd_inactive.go b/cmd/geth/logtestcmd_inactive.go
new file mode 100644
index 0000000000..691ab5bcd8
--- /dev/null
+++ b/cmd/geth/logtestcmd_inactive.go
@@ -0,0 +1,23 @@
+//go:build !integrationtests
+
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package main
+
+import "github.com/urfave/cli/v2"
+
+var logTestCommand *cli.Command
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index f11d56d53a..e1242912f2 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see .
-// geth is the official command-line client for Ethereum.
+// geth is a command-line client for Ethereum.
package main
import (
@@ -74,6 +74,7 @@ var (
utils.OverrideKepler,
utils.OverrideCancun,
utils.OverrideVerkle,
+ utils.OverrideFeynman,
utils.EnablePersonal,
utils.TxPoolLocalsFlag,
utils.TxPoolNoLocalsFlag,
@@ -92,13 +93,12 @@ var (
utils.BlobPoolPriceBumpFlag,
utils.SyncModeFlag,
utils.TriesVerifyModeFlag,
- utils.SyncTargetFlag,
+ // utils.SyncTargetFlag,
utils.ExitWhenSyncedFlag,
utils.GCModeFlag,
utils.SnapshotFlag,
utils.TxLookupLimitFlag, // deprecated
utils.TransactionHistoryFlag,
- utils.StateSchemeFlag,
utils.StateHistoryFlag,
utils.PathDBSyncFlag,
utils.LightServeFlag, // deprecated
@@ -170,7 +170,9 @@ var (
utils.BLSPasswordFileFlag,
utils.BLSWalletDirFlag,
utils.VoteJournalDirFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags)
+ utils.LogDebugFlag,
+ utils.LogBacktraceAtFlag,
+ }, utils.NetworkFlags, utils.DatabaseFlags)
rpcFlags = []cli.Flag{
utils.HTTPEnabledFlag,
@@ -227,7 +229,6 @@ var app = flags.NewApp("the go-ethereum command line interface")
func init() {
// Initialize the CLI app and start Geth
app.Action = geth
- app.Copyright = "Copyright 2013-2023 The go-ethereum Authors and BSC Authors"
app.Commands = []*cli.Command{
// See chaincmd.go:
initCommand,
@@ -235,7 +236,6 @@ func init() {
importCommand,
exportCommand,
importPreimagesCommand,
- exportPreimagesCommand,
removedbCommand,
dumpCommand,
dumpGenesisCommand,
@@ -263,6 +263,9 @@ func init() {
// See verkle.go
verkleCommand,
}
+ if logTestCommand != nil {
+ app.Commands = append(app.Commands, logTestCommand)
+ }
sort.Sort(cli.CommandsByName(app.Commands))
app.Flags = flags.Merge(
@@ -272,11 +275,16 @@ func init() {
debug.Flags,
metricsFlags,
)
+ flags.AutoEnvVars(app.Flags, "GETH")
app.Before = func(ctx *cli.Context) error {
maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota.
flags.MigrateGlobalFlags(ctx)
- return debug.Setup(ctx)
+ if err := debug.Setup(ctx); err != nil {
+ return err
+ }
+ flags.CheckEnvVars(ctx, app.Flags, "GETH")
+ return nil
}
app.After = func(ctx *cli.Context) error {
debug.Exit()
diff --git a/cmd/geth/pruneblock_test.go b/cmd/geth/pruneblock_test.go
index 8361559212..feb2f532e1 100644
--- a/cmd/geth/pruneblock_test.go
+++ b/cmd/geth/pruneblock_test.go
@@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/ethdb/leveldb"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
@@ -69,6 +70,19 @@ func TestOfflineBlockPrune(t *testing.T) {
testOfflineBlockPruneWithAmountReserved(t, 100)
}
+func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient string, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) {
+ kvdb, err := leveldb.New(file, cache, handles, namespace, readonly)
+ if err != nil {
+ return nil, err
+ }
+ frdb, err := rawdb.NewDatabaseWithFreezer(kvdb, ancient, namespace, readonly, disableFreeze, isLastOffset, pruneAncientData)
+ if err != nil {
+ kvdb.Close()
+ return nil, err
+ }
+ return frdb, nil
+}
+
func testOfflineBlockPruneWithAmountReserved(t *testing.T, amountReserved uint64) {
datadir := t.TempDir()
@@ -86,7 +100,7 @@ func testOfflineBlockPruneWithAmountReserved(t *testing.T, amountReserved uint64
t.Fatalf("Failed to back up block: %v", err)
}
- dbBack, err := rawdb.NewLevelDBDatabaseWithFreezer(chaindbPath, 0, 0, newAncientPath, "", false, true, false, false)
+ dbBack, err := NewLevelDBDatabaseWithFreezer(chaindbPath, 0, 0, newAncientPath, "", false, true, false, false)
if err != nil {
t.Fatalf("failed to create database with ancient backend")
}
@@ -132,7 +146,7 @@ func testOfflineBlockPruneWithAmountReserved(t *testing.T, amountReserved uint64
func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemain uint64) (ethdb.Database, []*types.Block, []*types.Block, []types.Receipts, []*big.Int, uint64, *core.BlockChain) {
//create a database with ancient freezer
- db, err := rawdb.NewLevelDBDatabaseWithFreezer(chaindbPath, 0, 0, AncientPath, "", false, false, false, false)
+ db, err := NewLevelDBDatabaseWithFreezer(chaindbPath, 0, 0, AncientPath, "", false, false, false, false)
if err != nil {
t.Fatalf("failed to create database with ancient backend")
}
diff --git a/cmd/geth/run_test.go b/cmd/geth/run_test.go
index a60b71c12b..1d32880325 100644
--- a/cmd/geth/run_test.go
+++ b/cmd/geth/run_test.go
@@ -23,8 +23,8 @@ import (
"testing"
"time"
- "github.com/docker/docker/pkg/reexec"
"github.com/ethereum/go-ethereum/internal/cmdtest"
+ "github.com/ethereum/go-ethereum/internal/reexec"
"github.com/ethereum/go-ethereum/rpc"
)
diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go
index c6ce0c7840..73453c0f91 100644
--- a/cmd/geth/snapshot.go
+++ b/cmd/geth/snapshot.go
@@ -62,7 +62,7 @@ var (
Flags: flags.Merge([]cli.Flag{
utils.BloomFilterSizeFlag,
utils.TriesInMemoryFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
Description: `
geth snapshot prune-state
will prune historical state data with the help of the state snapshot.
@@ -104,9 +104,7 @@ so it's very necessary to do block data prune, this feature will handle it.
Usage: "Recalculate state hash based on the snapshot for verification",
ArgsUsage: "",
Action: verifyState,
- Flags: flags.Merge([]cli.Flag{
- utils.StateSchemeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
Description: `
geth snapshot verify-state
will traverse the whole accounts and storages set based on the specified
@@ -142,10 +140,10 @@ the trie clean cache with default directory will be deleted.
Usage: "Check that there is no 'dangling' snap storage",
ArgsUsage: "",
Action: checkDanglingStorage,
- Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
+ Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
Description: `
-geth snapshot check-dangling-storage traverses the snap storage
-data, and verifies that all snapshot storage data has a corresponding account.
+geth snapshot check-dangling-storage traverses the snap storage
+data, and verifies that all snapshot storage data has a corresponding account.
`,
},
{
@@ -153,10 +151,10 @@ data, and verifies that all snapshot storage data has a corresponding account.
Usage: "Check all snapshot layers for the a specific account",
ArgsUsage: "",
Action: checkAccount,
- Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
+ Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
Description: `
geth snapshot inspect-account checks all snapshot layers and prints out
-information about the specified address.
+information about the specified address.
`,
},
{
@@ -164,9 +162,7 @@ information about the specified address.
Usage: "Traverse the state with given root hash and perform quick verification",
ArgsUsage: "",
Action: traverseState,
- Flags: flags.Merge([]cli.Flag{
- utils.StateSchemeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
Description: `
geth snapshot traverse-state
will traverse the whole state from the given state root and will abort if any
@@ -181,15 +177,13 @@ It's also usable without snapshot enabled.
Usage: "Traverse the state with given root hash and perform detailed verification",
ArgsUsage: "",
Action: traverseRawState,
- Flags: flags.Merge([]cli.Flag{
- utils.StateSchemeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
Description: `
geth snapshot traverse-rawstate
will traverse the whole state from the given root and will abort if any referenced
trie node or contract code is missing. This command can be used for state integrity
verification. The default checking target is the HEAD state. It's basically identical
-to traverse-state, but the check granularity is smaller.
+to traverse-state, but the check granularity is smaller.
It's also usable without snapshot enabled.
`,
@@ -205,14 +199,24 @@ It's also usable without snapshot enabled.
utils.StartKeyFlag,
utils.DumpLimitFlag,
utils.TriesInMemoryFlag,
- utils.StateSchemeFlag,
- }, utils.NetworkFlags, utils.DatabasePathFlags),
+ }, utils.NetworkFlags, utils.DatabaseFlags),
Description: `
This command is semantically equivalent to 'geth dump', but uses the snapshots
-as the backend data source, making this command a lot faster.
+as the backend data source, making this command a lot faster.
The argument is interpreted as block number or hash. If none is provided, the latest
block is used.
+`,
+ },
+ {
+ Action: snapshotExportPreimages,
+ Name: "export-preimages",
+ Usage: "Export the preimage in snapshot enumeration order",
+ ArgsUsage: " []",
+ Flags: utils.DatabaseFlags,
+ Description: `
+The export-preimages command exports hash preimages to a flat file, in exactly
+the expected order for the overlay tree migration.
`,
},
},
@@ -517,7 +521,7 @@ func verifyState(ctx *cli.Context) error {
log.Error("Failed to load head block")
return errors.New("no head block")
}
- triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
+ triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close()
snapConfig := snapshot.Config{
@@ -557,7 +561,9 @@ func checkDanglingStorage(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
defer stack.Close()
- return snapshot.CheckDanglingStorage(utils.MakeChainDatabase(ctx, stack, true, false))
+ db := utils.MakeChainDatabase(ctx, stack, true, false)
+ defer db.Close()
+ return snapshot.CheckDanglingStorage(db)
}
// traverseState is a helper function used for pruning verification.
@@ -570,7 +576,7 @@ func traverseState(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
defer chaindb.Close()
- triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
+ triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb)
@@ -637,6 +643,11 @@ func traverseState(ctx *cli.Context) error {
storageIter := trie.NewIterator(storageIt)
for storageIter.Next() {
slots += 1
+
+ if time.Since(lastReport) > time.Second*8 {
+ log.Info("Traversing state", "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start)))
+ lastReport = time.Now()
+ }
}
if storageIter.Err != nil {
log.Error("Failed to traverse storage trie", "root", acc.Root, "err", storageIter.Err)
@@ -674,7 +685,7 @@ func traverseRawState(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
defer chaindb.Close()
- triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true)
+ triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb)
@@ -791,6 +802,10 @@ func traverseRawState(ctx *cli.Context) error {
if storageIter.Leaf() {
slots += 1
}
+ if time.Since(lastReport) > time.Second*8 {
+ log.Info("Traversing state", "nodes", nodes, "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start)))
+ lastReport = time.Now()
+ }
}
if storageIter.Error() != nil {
log.Error("Failed to traverse storage trie", "root", acc.Root, "err", storageIter.Error())
@@ -834,7 +849,7 @@ func dumpState(ctx *cli.Context) error {
if err != nil {
return err
}
- triedb := utils.MakeTrieDatabase(ctx, db, false, true)
+ triedb := utils.MakeTrieDatabase(ctx, db, false, true, false)
defer triedb.Close()
snapConfig := snapshot.Config{
@@ -844,7 +859,7 @@ func dumpState(ctx *cli.Context) error {
AsyncBuild: false,
}
triesInMemory := ctx.Uint64(utils.TriesInMemoryFlag.Name)
- snaptree, err := snapshot.New(snapConfig, db, trie.NewDatabase(db, nil), root, int(triesInMemory), false)
+ snaptree, err := snapshot.New(snapConfig, db, triedb, root, int(triesInMemory), false)
if err != nil {
return err
}
@@ -870,11 +885,11 @@ func dumpState(ctx *cli.Context) error {
return err
}
da := &state.DumpAccount{
- Balance: account.Balance.String(),
- Nonce: account.Nonce,
- Root: account.Root.Bytes(),
- CodeHash: account.CodeHash,
- SecureKey: accIt.Hash().Bytes(),
+ Balance: account.Balance.String(),
+ Nonce: account.Nonce,
+ Root: account.Root.Bytes(),
+ CodeHash: account.CodeHash,
+ AddressHash: accIt.Hash().Bytes(),
}
if !conf.SkipCode && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash))
@@ -906,6 +921,48 @@ func dumpState(ctx *cli.Context) error {
return nil
}
+// snapshotExportPreimages dumps the preimage data to a flat file.
+func snapshotExportPreimages(ctx *cli.Context) error {
+ if ctx.NArg() < 1 {
+ utils.Fatalf("This command requires an argument.")
+ }
+ stack, _ := makeConfigNode(ctx)
+ defer stack.Close()
+
+ chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
+ defer chaindb.Close()
+
+ triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
+ defer triedb.Close()
+
+ var root common.Hash
+ if ctx.NArg() > 1 {
+ rootBytes := common.FromHex(ctx.Args().Get(1))
+ if len(rootBytes) != common.HashLength {
+ return fmt.Errorf("invalid hash: %s", ctx.Args().Get(1))
+ }
+ root = common.BytesToHash(rootBytes)
+ } else {
+ headBlock := rawdb.ReadHeadBlock(chaindb)
+ if headBlock == nil {
+ log.Error("Failed to load head block")
+ return errors.New("no head block")
+ }
+ root = headBlock.Root()
+ }
+ snapConfig := snapshot.Config{
+ CacheSize: 256,
+ Recovery: false,
+ NoBuild: true,
+ AsyncBuild: false,
+ }
+ snaptree, err := snapshot.New(snapConfig, chaindb, triedb, root, 128, false)
+ if err != nil {
+ return err
+ }
+ return utils.ExportSnapshotPreimages(chaindb, snaptree, ctx.Args().First(), root)
+}
+
// checkAccount iterates the snap data layers, and looks up the given account
// across all layers.
func checkAccount(ctx *cli.Context) error {
diff --git a/cmd/geth/testdata/logging/logtest-json.txt b/cmd/geth/testdata/logging/logtest-json.txt
new file mode 100644
index 0000000000..d2bd0ad91a
--- /dev/null
+++ b/cmd/geth/testdata/logging/logtest-json.txt
@@ -0,0 +1,52 @@
+{"t":"2023-11-22T15:42:00.407963+08:00","lvl":"info","msg":"big.Int","111,222,333,444,555,678,999":"111222333444555678999"}
+{"t":"2023-11-22T15:42:00.408084+08:00","lvl":"info","msg":"-big.Int","-111,222,333,444,555,678,999":"-111222333444555678999"}
+{"t":"2023-11-22T15:42:00.408092+08:00","lvl":"info","msg":"big.Int","11,122,233,344,455,567,899,900":"11122233344455567899900"}
+{"t":"2023-11-22T15:42:00.408097+08:00","lvl":"info","msg":"-big.Int","-11,122,233,344,455,567,899,900":"-11122233344455567899900"}
+{"t":"2023-11-22T15:42:00.408127+08:00","lvl":"info","msg":"uint256","111,222,333,444,555,678,999":"111222333444555678999"}
+{"t":"2023-11-22T15:42:00.408133+08:00","lvl":"info","msg":"uint256","11,122,233,344,455,567,899,900":"11122233344455567899900"}
+{"t":"2023-11-22T15:42:00.408137+08:00","lvl":"info","msg":"int64","1,000,000":1000000}
+{"t":"2023-11-22T15:42:00.408145+08:00","lvl":"info","msg":"int64","-1,000,000":-1000000}
+{"t":"2023-11-22T15:42:00.408149+08:00","lvl":"info","msg":"int64","9,223,372,036,854,775,807":9223372036854775807}
+{"t":"2023-11-22T15:42:00.408153+08:00","lvl":"info","msg":"int64","-9,223,372,036,854,775,808":-9223372036854775808}
+{"t":"2023-11-22T15:42:00.408156+08:00","lvl":"info","msg":"uint64","1,000,000":1000000}
+{"t":"2023-11-22T15:42:00.40816+08:00","lvl":"info","msg":"uint64","18,446,744,073,709,551,615":18446744073709551615}
+{"t":"2023-11-22T15:42:00.408164+08:00","lvl":"info","msg":"Special chars in value","key":"special \r\n\t chars"}
+{"t":"2023-11-22T15:42:00.408167+08:00","lvl":"info","msg":"Special chars in key","special \n\t chars":"value"}
+{"t":"2023-11-22T15:42:00.408171+08:00","lvl":"info","msg":"nospace","nospace":"nospace"}
+{"t":"2023-11-22T15:42:00.408174+08:00","lvl":"info","msg":"with space","with nospace":"with nospace"}
+{"t":"2023-11-22T15:42:00.408178+08:00","lvl":"info","msg":"Bash escapes in value","key":"\u001b[1G\u001b[K\u001b[1A"}
+{"t":"2023-11-22T15:42:00.408182+08:00","lvl":"info","msg":"Bash escapes in key","\u001b[1G\u001b[K\u001b[1A":"value"}
+{"t":"2023-11-22T15:42:00.408186+08:00","lvl":"info","msg":"Bash escapes in message \u001b[1G\u001b[K\u001b[1A end","key":"value"}
+{"t":"2023-11-22T15:42:00.408194+08:00","lvl":"info","msg":"\u001b[35mColored\u001b[0m[","\u001b[35mColored\u001b[0m[":"\u001b[35mColored\u001b[0m["}
+{"t":"2023-11-22T15:42:00.408197+08:00","lvl":"info","msg":"an error message with quotes","error":"this is an 'error'"}
+{"t":"2023-11-22T15:42:00.408202+08:00","lvl":"info","msg":"Custom Stringer value","2562047h47m16.854s":"2562047h47m16.854s"}
+{"t":"2023-11-22T15:42:00.408208+08:00","lvl":"info","msg":"a custom stringer that emits quoted text","output":"output with 'quotes'"}
+{"t":"2023-11-22T15:42:00.408219+08:00","lvl":"info","msg":"A message with wonky 💩 characters"}
+{"t":"2023-11-22T15:42:00.408222+08:00","lvl":"info","msg":"A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩"}
+{"t":"2023-11-22T15:42:00.408226+08:00","lvl":"info","msg":"A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above"}
+{"t":"2023-11-22T15:42:00.408229+08:00","lvl":"info","msg":"boolean","true":true,"false":false}
+{"t":"2023-11-22T15:42:00.408234+08:00","lvl":"info","msg":"repeated-key 1","foo":"alpha","foo":"beta"}
+{"t":"2023-11-22T15:42:00.408237+08:00","lvl":"info","msg":"repeated-key 2","xx":"short","xx":"longer"}
+{"t":"2023-11-22T15:42:00.408241+08:00","lvl":"info","msg":"log at level info"}
+{"t":"2023-11-22T15:42:00.408244+08:00","lvl":"warn","msg":"log at level warn"}
+{"t":"2023-11-22T15:42:00.408247+08:00","lvl":"error","msg":"log at level error"}
+{"t":"2023-11-22T15:42:00.408251+08:00","lvl":"info","msg":"test","bar":"short","a":"aligned left"}
+{"t":"2023-11-22T15:42:00.408254+08:00","lvl":"info","msg":"test","bar":"a long message","a":1}
+{"t":"2023-11-22T15:42:00.408258+08:00","lvl":"info","msg":"test","bar":"short","a":"aligned right"}
+{"t":"2023-11-22T15:42:00.408261+08:00","lvl":"info","msg":"The following logs should align so that the key-fields make 5 columns"}
+{"t":"2023-11-22T15:42:00.408275+08:00","lvl":"info","msg":"Inserted known block","number":1012,"hash":"0x0000000000000000000000000000000000000000000000000000000000001234","txs":200,"gas":1123123,"other":"first"}
+{"t":"2023-11-22T15:42:00.408281+08:00","lvl":"info","msg":"Inserted new block","number":1,"hash":"0x0000000000000000000000000000000000000000000000000000000000001235","txs":2,"gas":1123,"other":"second"}
+{"t":"2023-11-22T15:42:00.408287+08:00","lvl":"info","msg":"Inserted known block","number":99,"hash":"0x0000000000000000000000000000000000000000000000000000000000012322","txs":10,"gas":1,"other":"third"}
+{"t":"2023-11-22T15:42:00.408296+08:00","lvl":"warn","msg":"Inserted known block","number":1012,"hash":"0x0000000000000000000000000000000000000000000000000000000000001234","txs":200,"gas":99,"other":"fourth"}
+{"t":"2023-11-22T15:42:00.4083+08:00","lvl":"info","msg":"(*big.Int)(nil)","":""}
+{"t":"2023-11-22T15:42:00.408303+08:00","lvl":"info","msg":"(*uint256.Int)(nil)","":""}
+{"t":"2023-11-22T15:42:00.408311+08:00","lvl":"info","msg":"(fmt.Stringer)(nil)","res":null}
+{"t":"2023-11-22T15:42:00.408318+08:00","lvl":"info","msg":"nil-concrete-stringer","res":""}
+{"t":"2023-11-22T15:42:00.408322+08:00","lvl":"info","msg":"error(nil) ","res":null}
+{"t":"2023-11-22T15:42:00.408326+08:00","lvl":"info","msg":"nil-concrete-error","res":""}
+{"t":"2023-11-22T15:42:00.408334+08:00","lvl":"info","msg":"nil-custom-struct","res":null}
+{"t":"2023-11-22T15:42:00.40835+08:00","lvl":"info","msg":"raw nil","res":null}
+{"t":"2023-11-22T15:42:00.408354+08:00","lvl":"info","msg":"(*uint64)(nil)","res":null}
+{"t":"2023-11-22T15:42:00.408361+08:00","lvl":"info","msg":"Using keys 't', 'lvl', 'time', 'level' and 'msg'","t":"t","time":"time","lvl":"lvl","level":"level","msg":"msg"}
+{"t":"2023-11-29T15:13:00.195655931+01:00","lvl":"info","msg":"Odd pair (1 attr)","key":null,"LOG_ERROR":"Normalized odd number of arguments by adding nil"}
+{"t":"2023-11-29T15:13:00.195681832+01:00","lvl":"info","msg":"Odd pair (3 attr)","key":"value","key2":null,"LOG_ERROR":"Normalized odd number of arguments by adding nil"}
diff --git a/cmd/geth/testdata/logging/logtest-logfmt.txt b/cmd/geth/testdata/logging/logtest-logfmt.txt
new file mode 100644
index 0000000000..5c5316b7d9
--- /dev/null
+++ b/cmd/geth/testdata/logging/logtest-logfmt.txt
@@ -0,0 +1,52 @@
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=big.Int 111,222,333,444,555,678,999=111222333444555678999
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=-big.Int -111,222,333,444,555,678,999=-111222333444555678999
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=big.Int 11,122,233,344,455,567,899,900=11122233344455567899900
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=-big.Int -11,122,233,344,455,567,899,900=-11122233344455567899900
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=uint256 111,222,333,444,555,678,999=111222333444555678999
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=uint256 11,122,233,344,455,567,899,900=11122233344455567899900
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=int64 1,000,000=1000000
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=int64 -1,000,000=-1000000
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=int64 9,223,372,036,854,775,807=9223372036854775807
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=int64 -9,223,372,036,854,775,808=-9223372036854775808
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=uint64 1,000,000=1000000
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=uint64 18,446,744,073,709,551,615=18446744073709551615
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Special chars in value" key="special \r\n\t chars"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Special chars in key" "special \n\t chars"=value
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=nospace nospace=nospace
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="with space" "with nospace"="with nospace"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Bash escapes in value" key="\x1b[1G\x1b[K\x1b[1A"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Bash escapes in key" "\x1b[1G\x1b[K\x1b[1A"=value
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Bash escapes in message \x1b[1G\x1b[K\x1b[1A end" key=value
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="\x1b[35mColored\x1b[0m[" "\x1b[35mColored\x1b[0m["="\x1b[35mColored\x1b[0m["
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="an error message with quotes" error="this is an 'error'"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Custom Stringer value" 2562047h47m16.854s=2562047h47m16.854s
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="a custom stringer that emits quoted text" output="output with 'quotes'"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="A message with wonky 💩 characters"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=boolean true=true false=false
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="repeated-key 1" foo=alpha foo=beta
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="repeated-key 2" xx=short xx=longer
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="log at level info"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=warn msg="log at level warn"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=error msg="log at level error"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar=short a="aligned left"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar="a long message" a=1
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar=short a="aligned right"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="The following logs should align so that the key-fields make 5 columns"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Inserted known block" number=1012 hash=0x0000000000000000000000000000000000000000000000000000000000001234 txs=200 gas=1123123 other=first
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Inserted new block" number=1 hash=0x0000000000000000000000000000000000000000000000000000000000001235 txs=2 gas=1123 other=second
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Inserted known block" number=99 hash=0x0000000000000000000000000000000000000000000000000000000000012322 txs=10 gas=1 other=third
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=warn msg="Inserted known block" number=1012 hash=0x0000000000000000000000000000000000000000000000000000000000001234 txs=200 gas=99 other=fourth
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=(*big.Int)(nil) =
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=(*uint256.Int)(nil) =
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=(fmt.Stringer)(nil) res=
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=nil-concrete-stringer res=
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="error(nil) " res=
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=nil-concrete-error res=""
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=nil-custom-struct res=
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="raw nil" res=
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=(*uint64)(nil) res=
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Using keys 't', 'lvl', 'time', 'level' and 'msg'" t=t time=time lvl=lvl level=level msg=msg
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Odd pair (1 attr)" key= LOG_ERROR="Normalized odd number of arguments by adding nil"
+t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Odd pair (3 attr)" key=value key2= LOG_ERROR="Normalized odd number of arguments by adding nil"
diff --git a/cmd/geth/testdata/logging/logtest-terminal.txt b/cmd/geth/testdata/logging/logtest-terminal.txt
new file mode 100644
index 0000000000..e3b562117c
--- /dev/null
+++ b/cmd/geth/testdata/logging/logtest-terminal.txt
@@ -0,0 +1,53 @@
+INFO [xx-xx|xx:xx:xx.xxx] big.Int 111,222,333,444,555,678,999=111,222,333,444,555,678,999
+INFO [xx-xx|xx:xx:xx.xxx] -big.Int -111,222,333,444,555,678,999=-111,222,333,444,555,678,999
+INFO [xx-xx|xx:xx:xx.xxx] big.Int 11,122,233,344,455,567,899,900=11,122,233,344,455,567,899,900
+INFO [xx-xx|xx:xx:xx.xxx] -big.Int -11,122,233,344,455,567,899,900=-11,122,233,344,455,567,899,900
+INFO [xx-xx|xx:xx:xx.xxx] uint256 111,222,333,444,555,678,999=111,222,333,444,555,678,999
+INFO [xx-xx|xx:xx:xx.xxx] uint256 11,122,233,344,455,567,899,900=11,122,233,344,455,567,899,900
+INFO [xx-xx|xx:xx:xx.xxx] int64 1,000,000=1,000,000
+INFO [xx-xx|xx:xx:xx.xxx] int64 -1,000,000=-1,000,000
+INFO [xx-xx|xx:xx:xx.xxx] int64 9,223,372,036,854,775,807=9,223,372,036,854,775,807
+INFO [xx-xx|xx:xx:xx.xxx] int64 -9,223,372,036,854,775,808=-9,223,372,036,854,775,808
+INFO [xx-xx|xx:xx:xx.xxx] uint64 1,000,000=1,000,000
+INFO [xx-xx|xx:xx:xx.xxx] uint64 18,446,744,073,709,551,615=18,446,744,073,709,551,615
+INFO [xx-xx|xx:xx:xx.xxx] Special chars in value key="special \r\n\t chars"
+INFO [xx-xx|xx:xx:xx.xxx] Special chars in key "special \n\t chars"=value
+INFO [xx-xx|xx:xx:xx.xxx] nospace nospace=nospace
+INFO [xx-xx|xx:xx:xx.xxx] with space "with nospace"="with nospace"
+INFO [xx-xx|xx:xx:xx.xxx] Bash escapes in value key="\x1b[1G\x1b[K\x1b[1A"
+INFO [xx-xx|xx:xx:xx.xxx] Bash escapes in key "\x1b[1G\x1b[K\x1b[1A"=value
+INFO [xx-xx|xx:xx:xx.xxx] "Bash escapes in message \x1b[1G\x1b[K\x1b[1A end" key=value
+INFO [xx-xx|xx:xx:xx.xxx] "\x1b[35mColored\x1b[0m[" "\x1b[35mColored\x1b[0m["="\x1b[35mColored\x1b[0m["
+INFO [xx-xx|xx:xx:xx.xxx] an error message with quotes error="this is an 'error'"
+INFO [xx-xx|xx:xx:xx.xxx] Custom Stringer value 2562047h47m16.854s=2562047h47m16.854s
+INFO [xx-xx|xx:xx:xx.xxx] a custom stringer that emits quoted text output="output with 'quotes'"
+INFO [xx-xx|xx:xx:xx.xxx] "A message with wonky 💩 characters"
+INFO [xx-xx|xx:xx:xx.xxx] "A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩"
+INFO [xx-xx|xx:xx:xx.xxx] A multiline message
+LALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above
+INFO [xx-xx|xx:xx:xx.xxx] boolean true=true false=false
+INFO [xx-xx|xx:xx:xx.xxx] repeated-key 1 foo=alpha foo=beta
+INFO [xx-xx|xx:xx:xx.xxx] repeated-key 2 xx=short xx=longer
+INFO [xx-xx|xx:xx:xx.xxx] log at level info
+WARN [xx-xx|xx:xx:xx.xxx] log at level warn
+ERROR[xx-xx|xx:xx:xx.xxx] log at level error
+INFO [xx-xx|xx:xx:xx.xxx] test bar=short a="aligned left"
+INFO [xx-xx|xx:xx:xx.xxx] test bar="a long message" a=1
+INFO [xx-xx|xx:xx:xx.xxx] test bar=short a="aligned right"
+INFO [xx-xx|xx:xx:xx.xxx] The following logs should align so that the key-fields make 5 columns
+INFO [xx-xx|xx:xx:xx.xxx] Inserted known block number=1012 hash=000000..001234 txs=200 gas=1,123,123 other=first
+INFO [xx-xx|xx:xx:xx.xxx] Inserted new block number=1 hash=000000..001235 txs=2 gas=1123 other=second
+INFO [xx-xx|xx:xx:xx.xxx] Inserted known block number=99 hash=000000..012322 txs=10 gas=1 other=third
+WARN [xx-xx|xx:xx:xx.xxx] Inserted known block number=1012 hash=000000..001234 txs=200 gas=99 other=fourth
+INFO [xx-xx|xx:xx:xx.xxx] (*big.Int)(nil) =
+INFO [xx-xx|xx:xx:xx.xxx] (*uint256.Int)(nil) =
+INFO [xx-xx|xx:xx:xx.xxx] (fmt.Stringer)(nil) res=
+INFO [xx-xx|xx:xx:xx.xxx] nil-concrete-stringer res=
+INFO [xx-xx|xx:xx:xx.xxx] error(nil) res=
+INFO [xx-xx|xx:xx:xx.xxx] nil-concrete-error res=
+INFO [xx-xx|xx:xx:xx.xxx] nil-custom-struct res=
+INFO [xx-xx|xx:xx:xx.xxx] raw nil res=
+INFO [xx-xx|xx:xx:xx.xxx] (*uint64)(nil) res=
+INFO [xx-xx|xx:xx:xx.xxx] Using keys 't', 'lvl', 'time', 'level' and 'msg' t=t time=time lvl=lvl level=level msg=msg
+INFO [xx-xx|xx:xx:xx.xxx] Odd pair (1 attr) key= LOG_ERROR="Normalized odd number of arguments by adding nil"
+INFO [xx-xx|xx:xx:xx.xxx] Odd pair (3 attr) key=value key2= LOG_ERROR="Normalized odd number of arguments by adding nil"
diff --git a/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig b/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig
new file mode 100644
index 0000000000..eaea9f9053
--- /dev/null
+++ b/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig
@@ -0,0 +1,4 @@
+untrusted comment: signature from minisign secret key
+RUQkliYstQBOKLK05Sy5f3bVRMBqJT26ABo6Vbp3BNJAVjejoqYCu4GWE/+7qcDfHBqYIniDCbFIUvYEnOHxV6vZ93wO1xJWDQw=
+trusted comment: timestamp:1693986492 file:data.json hashed
+6Fdw2H+W1ZXK7QXSF77Z5AWC7+AEFAfDmTSxNGylU5HLT1AuSJQmxslj+VjtUBamYCvOuET7plbXza942AlWDw==
diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go
index e3953ed5b7..e962dcdd84 100644
--- a/cmd/geth/verkle.go
+++ b/cmd/geth/verkle.go
@@ -45,7 +45,7 @@ var (
Usage: "verify the conversion of a MPT into a verkle tree",
ArgsUsage: "",
Action: verifyVerkle,
- Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
+ Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
Description: `
geth verkle verify
This command takes a root commitment and attempts to rebuild the tree.
@@ -56,7 +56,7 @@ This command takes a root commitment and attempts to rebuild the tree.
Usage: "Dump a verkle tree to a DOT file",
ArgsUsage: " [ ...]",
Action: expandVerkle,
- Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
+ Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
Description: `
geth verkle dump [ ...]
This command will produce a dot file representing the tree, rooted at .
@@ -84,7 +84,7 @@ func checkChildren(root verkle.VerkleNode, resolver verkle.NodeResolverFn) error
return fmt.Errorf("could not find child %x in db: %w", childC, err)
}
// depth is set to 0, the tree isn't rebuilt so it's not a problem
- childN, err := verkle.ParseNode(childS, 0, childC[:])
+ childN, err := verkle.ParseNode(childS, 0)
if err != nil {
return fmt.Errorf("decode error child %x in db: %w", child.Commitment().Bytes(), err)
}
@@ -115,6 +115,7 @@ func verifyVerkle(ctx *cli.Context) error {
defer stack.Close()
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
+ defer chaindb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil {
log.Error("Failed to load head block")
@@ -144,7 +145,7 @@ func verifyVerkle(ctx *cli.Context) error {
if err != nil {
return err
}
- root, err := verkle.ParseNode(serializedRoot, 0, rootC[:])
+ root, err := verkle.ParseNode(serializedRoot, 0)
if err != nil {
return err
}
@@ -163,6 +164,7 @@ func expandVerkle(ctx *cli.Context) error {
defer stack.Close()
chaindb := utils.MakeChainDatabase(ctx, stack, true, false)
+ defer chaindb.Close()
var (
rootC common.Hash
keylist [][]byte
@@ -193,7 +195,7 @@ func expandVerkle(ctx *cli.Context) error {
if err != nil {
return err
}
- root, err := verkle.ParseNode(serializedRoot, 0, rootC[:])
+ root, err := verkle.ParseNode(serializedRoot, 0)
if err != nil {
return err
}
diff --git a/cmd/geth/version_check_test.go b/cmd/geth/version_check_test.go
index bd4d820a79..3676d25d00 100644
--- a/cmd/geth/version_check_test.go
+++ b/cmd/geth/version_check_test.go
@@ -30,17 +30,28 @@ import (
)
func TestVerification(t *testing.T) {
- // Signatures generated with `minisign`
- t.Run("minisig", func(t *testing.T) {
- // For this test, the pubkey is in testdata/minisign.pub
+ t.Parallel()
+ // Signatures generated with `minisign`. Legacy format, not pre-hashed file.
+ t.Run("minisig-legacy", func(t *testing.T) {
+ t.Parallel()
+ // For this test, the pubkey is in testdata/vcheck/minisign.pub
// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
testVerification(t, pub, "./testdata/vcheck/minisig-sigs/")
})
+ t.Run("minisig-new", func(t *testing.T) {
+ t.Parallel()
+ // For this test, the pubkey is in testdata/vcheck/minisign.pub
+ // (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
+ // `minisign -S -s ./minisign.sec -m data.json -x ./minisig-sigs-new/data.json.minisig`
+ pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
+ testVerification(t, pub, "./testdata/vcheck/minisig-sigs-new/")
+ })
// Signatures generated with `signify-openbsd`
t.Run("signify-openbsd", func(t *testing.T) {
+ t.Parallel()
t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2")
- // For this test, the pubkey is in testdata/signifykey.pub
+ // For this test, the pubkey is in testdata/vcheck/signifykey.pub
// (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' )
pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/"
testVerification(t, pub, "./testdata/vcheck/signify-sigs/")
@@ -58,6 +69,9 @@ func testVerification(t *testing.T, pubkey, sigdir string) {
if err != nil {
t.Fatal(err)
}
+ if len(files) == 0 {
+ t.Fatal("Missing tests")
+ }
for _, f := range files {
sig, err := os.ReadFile(filepath.Join(sigdir, f.Name()))
if err != nil {
@@ -87,6 +101,7 @@ func versionUint(v string) int {
// TestMatching can be used to check that the regexps are correct
func TestMatching(t *testing.T) {
+ t.Parallel()
data, _ := os.ReadFile("./testdata/vcheck/vulnerabilities.json")
var vulns []vulnJson
if err := json.Unmarshal(data, &vulns); err != nil {
@@ -131,6 +146,7 @@ func TestMatching(t *testing.T) {
}
func TestGethPubKeysParseable(t *testing.T) {
+ t.Parallel()
for _, pubkey := range gethPubKeys {
_, err := minisign.NewPublicKey(pubkey)
if err != nil {
@@ -140,6 +156,7 @@ func TestGethPubKeysParseable(t *testing.T) {
}
func TestKeyID(t *testing.T) {
+ t.Parallel()
type args struct {
id [8]byte
}
@@ -153,7 +170,9 @@ func TestKeyID(t *testing.T) {
{"third key", args{id: extractKeyId(gethPubKeys[2])}, "FD9813B2D2098484"},
}
for _, tt := range tests {
+ tt := tt
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
if got := keyID(tt.args.id); got != tt.want {
t.Errorf("keyID() = %v, want %v", got, tt.want)
}
diff --git a/cmd/maliciousvote-submit/json_encoding_helper_test.go b/cmd/maliciousvote-submit/json_encoding_helper_test.go
index 9b1585b6e4..bf8d9f70f5 100644
--- a/cmd/maliciousvote-submit/json_encoding_helper_test.go
+++ b/cmd/maliciousvote-submit/json_encoding_helper_test.go
@@ -8,7 +8,7 @@ import (
)
func TestSlashIndicatorFinalityEvidenceEncoding(t *testing.T) {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
evidence := `{"VoteA":{"SrcNum":1234,"SrcHash":"36068b819f244d27b5411d975f9ffd6d18c6084b50fb5595104ffd9de561a9f8","TarNum":1234,"TarHash":"36068b819f244d27b5411d975f9ffd6d18c6084b50fb5595104ffd9de561a9f8","Sig":"893682ebf26440a06daaff5695945ee2012146268f800c217bad9906ac64dc46996cd435e3e829529aa0445b52530070893682ebf26440a06daaff5695945ee2012146268f800c217bad9906ac64dc46996cd435e3e829529aa0445b52530070"},"VoteB":{"SrcNum":1234,"SrcHash":"36068b819f244d27b5411d975f9ffd6d18c6084b50fb5595104ffd9de561a9f8","TarNum":1234,"TarHash":"36068b819f244d27b5411d975f9ffd6d18c6084b50fb5595104ffd9de561a9f8","Sig":"893682ebf26440a06daaff5695945ee2012146268f800c217bad9906ac64dc46996cd435e3e829529aa0445b52530070893682ebf26440a06daaff5695945ee2012146268f800c217bad9906ac64dc46996cd435e3e829529aa0445b52530070"},"VoteAddr":"893682ebf26440a06daaff5695945ee2012146268f800c217bad9906ac64dc46996cd435e3e829529aa0445b52530070"}`
slashIndicatorFinalityEvidence := &SlashIndicatorFinalityEvidence{}
diff --git a/cmd/maliciousvote-submit/main.go b/cmd/maliciousvote-submit/main.go
index c83610710a..0ded3fbe02 100644
--- a/cmd/maliciousvote-submit/main.go
+++ b/cmd/maliciousvote-submit/main.go
@@ -128,7 +128,7 @@ func submitMaliciousVotes(c *cli.Context) error {
}
func main() {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)
diff --git a/cmd/p2psim/main.go b/cmd/p2psim/main.go
index a3546d405b..a0f5f0d288 100644
--- a/cmd/p2psim/main.go
+++ b/cmd/p2psim/main.go
@@ -417,9 +417,7 @@ func rpcNode(ctx *cli.Context) error {
}
func rpcSubscribe(client *rpc.Client, out io.Writer, method string, args ...string) error {
- parts := strings.SplitN(method, "_", 2)
- namespace := parts[0]
- method = parts[1]
+ namespace, method, _ := strings.Cut(method, "_")
ch := make(chan interface{})
subArgs := make([]interface{}, len(args)+1)
subArgs[0] = method
diff --git a/cmd/rlpdump/main.go b/cmd/rlpdump/main.go
index 70337749ae..7e1d314d49 100644
--- a/cmd/rlpdump/main.go
+++ b/cmd/rlpdump/main.go
@@ -25,7 +25,9 @@ import (
"flag"
"fmt"
"io"
+ "math"
"os"
+ "strconv"
"strings"
"github.com/ethereum/go-ethereum/common"
@@ -37,6 +39,7 @@ var (
reverseMode = flag.Bool("reverse", false, "convert ASCII to rlp")
noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably")
single = flag.Bool("single", false, "print only the first element, discard the rest")
+ showpos = flag.Bool("pos", false, "display element byte posititions")
)
func init() {
@@ -52,17 +55,17 @@ If the filename is omitted, data is read from stdin.`)
func main() {
flag.Parse()
- var r io.Reader
+ var r *inStream
switch {
case *hexMode != "":
data, err := hex.DecodeString(strings.TrimPrefix(*hexMode, "0x"))
if err != nil {
die(err)
}
- r = bytes.NewReader(data)
+ r = newInStream(bytes.NewReader(data), int64(len(data)))
case flag.NArg() == 0:
- r = os.Stdin
+ r = newInStream(bufio.NewReader(os.Stdin), 0)
case flag.NArg() == 1:
fd, err := os.Open(flag.Arg(0))
@@ -70,13 +73,19 @@ func main() {
die(err)
}
defer fd.Close()
- r = fd
+ var size int64
+ finfo, err := fd.Stat()
+ if err == nil {
+ size = finfo.Size()
+ }
+ r = newInStream(bufio.NewReader(fd), size)
default:
fmt.Fprintln(os.Stderr, "Error: too many arguments")
flag.Usage()
os.Exit(2)
}
+
out := os.Stdout
if *reverseMode {
data, err := textToRlp(r)
@@ -93,10 +102,10 @@ func main() {
}
}
-func rlpToText(r io.Reader, out io.Writer) error {
- s := rlp.NewStream(r, 0)
+func rlpToText(in *inStream, out io.Writer) error {
+ stream := rlp.NewStream(in, 0)
for {
- if err := dump(s, 0, out); err != nil {
+ if err := dump(in, stream, 0, out); err != nil {
if err != io.EOF {
return err
}
@@ -110,7 +119,10 @@ func rlpToText(r io.Reader, out io.Writer) error {
return nil
}
-func dump(s *rlp.Stream, depth int, out io.Writer) error {
+func dump(in *inStream, s *rlp.Stream, depth int, out io.Writer) error {
+ if *showpos {
+ fmt.Fprintf(out, "%s: ", in.posLabel())
+ }
kind, size, err := s.Kind()
if err != nil {
return err
@@ -137,7 +149,7 @@ func dump(s *rlp.Stream, depth int, out io.Writer) error {
if i > 0 {
fmt.Fprint(out, ",\n")
}
- if err := dump(s, depth+1, out); err == rlp.EOL {
+ if err := dump(in, s, depth+1, out); err == rlp.EOL {
break
} else if err != nil {
return err
@@ -208,3 +220,36 @@ func textToRlp(r io.Reader) ([]byte, error) {
data, err := rlp.EncodeToBytes(obj[0])
return data, err
}
+
+type inStream struct {
+ br rlp.ByteReader
+ pos int
+ columns int
+}
+
+func newInStream(br rlp.ByteReader, totalSize int64) *inStream {
+ col := int(math.Ceil(math.Log10(float64(totalSize))))
+ return &inStream{br: br, columns: col}
+}
+
+func (rc *inStream) Read(b []byte) (n int, err error) {
+ n, err = rc.br.Read(b)
+ rc.pos += n
+ return n, err
+}
+
+func (rc *inStream) ReadByte() (byte, error) {
+ b, err := rc.br.ReadByte()
+ if err == nil {
+ rc.pos++
+ }
+ return b, err
+}
+
+func (rc *inStream) posLabel() string {
+ l := strconv.FormatInt(int64(rc.pos), 10)
+ if len(l) < rc.columns {
+ l = strings.Repeat(" ", rc.columns-len(l)) + l
+ }
+ return l
+}
diff --git a/cmd/rlpdump/rlpdump_test.go b/cmd/rlpdump/rlpdump_test.go
index a9ab57fdb8..4b0ae680ac 100644
--- a/cmd/rlpdump/rlpdump_test.go
+++ b/cmd/rlpdump/rlpdump_test.go
@@ -27,13 +27,15 @@ import (
)
func TestRoundtrip(t *testing.T) {
+ t.Parallel()
for i, want := range []string{
"0xf880806482520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a1010000000000000000000000000000000000000000000000000000000000000001801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28",
"0xd5c0d3cb84746573742a2a808213378667617a6f6e6b",
"0xc780c0c1c0825208",
} {
var out strings.Builder
- err := rlpToText(bytes.NewReader(common.FromHex(want)), &out)
+ in := newInStream(bytes.NewReader(common.FromHex(want)), 0)
+ err := rlpToText(in, &out)
if err != nil {
t.Fatal(err)
}
@@ -51,6 +53,7 @@ func TestRoundtrip(t *testing.T) {
}
func TestTextToRlp(t *testing.T) {
+ t.Parallel()
type tc struct {
text string
want string
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 16b1260572..8b571be1ef 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig"
@@ -374,6 +375,101 @@ func ExportPreimages(db ethdb.Database, fn string) error {
return nil
}
+// ExportSnapshotPreimages exports the preimages corresponding to the enumeration of
+// the snapshot for a given root.
+func ExportSnapshotPreimages(chaindb ethdb.Database, snaptree *snapshot.Tree, fn string, root common.Hash) error {
+ log.Info("Exporting preimages", "file", fn)
+
+ fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
+ if err != nil {
+ return err
+ }
+ defer fh.Close()
+
+ // Enable gzip compressing if file name has gz suffix.
+ var writer io.Writer = fh
+ if strings.HasSuffix(fn, ".gz") {
+ gz := gzip.NewWriter(writer)
+ defer gz.Close()
+ writer = gz
+ }
+ buf := bufio.NewWriter(writer)
+ defer buf.Flush()
+ writer = buf
+
+ type hashAndPreimageSize struct {
+ Hash common.Hash
+ Size int
+ }
+ hashCh := make(chan hashAndPreimageSize)
+
+ var (
+ start = time.Now()
+ logged = time.Now()
+ preimages int
+ )
+ go func() {
+ defer close(hashCh)
+ accIt, err := snaptree.AccountIterator(root, common.Hash{})
+ if err != nil {
+ log.Error("Failed to create account iterator", "error", err)
+ return
+ }
+ defer accIt.Release()
+
+ for accIt.Next() {
+ acc, err := types.FullAccount(accIt.Account())
+ if err != nil {
+ log.Error("Failed to get full account", "error", err)
+ return
+ }
+ preimages += 1
+ hashCh <- hashAndPreimageSize{Hash: accIt.Hash(), Size: common.AddressLength}
+
+ if acc.Root != (common.Hash{}) && acc.Root != types.EmptyRootHash {
+ stIt, err := snaptree.StorageIterator(root, accIt.Hash(), common.Hash{})
+ if err != nil {
+ log.Error("Failed to create storage iterator", "error", err)
+ return
+ }
+ for stIt.Next() {
+ preimages += 1
+ hashCh <- hashAndPreimageSize{Hash: stIt.Hash(), Size: common.HashLength}
+
+ if time.Since(logged) > time.Second*8 {
+ logged = time.Now()
+ log.Info("Exporting preimages", "count", preimages, "elapsed", common.PrettyDuration(time.Since(start)))
+ }
+ }
+ stIt.Release()
+ }
+ if time.Since(logged) > time.Second*8 {
+ logged = time.Now()
+ log.Info("Exporting preimages", "count", preimages, "elapsed", common.PrettyDuration(time.Since(start)))
+ }
+ }
+ }()
+
+ for item := range hashCh {
+ preimage := rawdb.ReadPreimage(chaindb, item.Hash)
+ if len(preimage) == 0 {
+ return fmt.Errorf("missing preimage for %v", item.Hash)
+ }
+ if len(preimage) != item.Size {
+ return fmt.Errorf("invalid preimage size, have %d", len(preimage))
+ }
+ rlpenc, err := rlp.EncodeToBytes(preimage)
+ if err != nil {
+ return fmt.Errorf("error encoding preimage: %w", err)
+ }
+ if _, err := writer.Write(rlpenc); err != nil {
+ return fmt.Errorf("failed to write preimage: %w", err)
+ }
+ }
+ log.Info("Exported preimages", "count", preimages, "elapsed", common.PrettyDuration(time.Since(start)), "file", fn)
+ return nil
+}
+
// exportHeader is used in the export/import flow. When we do an export,
// the first element we output is the exportHeader.
// Whenever a backwards-incompatible change is made, the Version header
@@ -460,7 +556,7 @@ func ImportLDBData(db ethdb.Database, f string, startIndex int64, interrupt chan
case OpBatchAdd:
batch.Put(key, val)
default:
- return fmt.Errorf("unknown op %d\n", op)
+ return fmt.Errorf("unknown op %d", op)
}
if batch.ValueSize() > ethdb.IdealBatchSize {
if err := batch.Write(); err != nil {
diff --git a/cmd/utils/export_test.go b/cmd/utils/export_test.go
index 445e3fac37..84ba8d0c31 100644
--- a/cmd/utils/export_test.go
+++ b/cmd/utils/export_test.go
@@ -170,6 +170,7 @@ func testDeletion(t *testing.T, f string) {
// TestImportFutureFormat tests that we reject unsupported future versions.
func TestImportFutureFormat(t *testing.T) {
+ t.Parallel()
f := fmt.Sprintf("%v/tempdump-future", os.TempDir())
defer func() {
os.Remove(f)
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 3b79a54029..3514734c90 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -18,7 +18,6 @@
package utils
import (
- "bufio"
"context"
"crypto/ecdsa"
"encoding/hex"
@@ -36,11 +35,6 @@ import (
"strings"
"time"
- "github.com/fatih/structs"
- pcsclite "github.com/gballet/go-libpcsclite"
- gopsutil "github.com/shirou/gopsutil/mem"
- "github.com/urfave/cli/v2"
-
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
@@ -78,6 +72,10 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/fatih/structs"
+ pcsclite "github.com/gballet/go-libpcsclite"
+ gopsutil "github.com/shirou/gopsutil/mem"
+ "github.com/urfave/cli/v2"
)
// These are all the command line flags we support.
@@ -315,6 +313,11 @@ var (
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
+ OverrideFeynman = &cli.Uint64Flag{
+ Name: "override.feynman",
+ Usage: "Manually specify the Feynman fork timestamp, overriding the bundled setting",
+ Category: flags.EthCategory,
+ }
SyncModeFlag = &flags.TextMarshalerFlag{
Name: "syncmode",
Usage: `Blockchain sync mode ("snap" or "full")`,
@@ -651,9 +654,9 @@ var (
}
// MISC settings
- SyncTargetFlag = &cli.PathFlag{
+ SyncTargetFlag = &cli.StringFlag{
Name: "synctarget",
- Usage: `File for containing the hex-encoded block-rlp as sync target(dev feature)`,
+ Usage: `Hash of the block to full sync to (dev testing feature)`,
TakesFile: true,
Category: flags.MiscCategory,
}
@@ -1101,12 +1104,13 @@ var (
// NetworkFlags is the flag group of all built-in supported networks.
NetworkFlags = append([]cli.Flag{BSCMainnetFlag}, TestnetFlags...)
- // DatabasePathFlags is the flag group of all database path flags.
- DatabasePathFlags = []cli.Flag{
+ // DatabaseFlags is the flag group of all database flags.
+ DatabaseFlags = []cli.Flag{
DataDirFlag,
AncientFlag,
RemoteDBFlag,
DBEngineFlag,
+ StateSchemeFlag,
HttpHeaderFlag,
}
)
@@ -1124,7 +1128,7 @@ func MakeDataDir(ctx *cli.Context) string {
// setNodeKey creates a node key from set command line flags, either loading it
// from a file or as a specified hex value. If neither flags were provided, this
-// method returns nil and an emphemeral key is to be generated.
+// method returns nil and an ephemeral key is to be generated.
func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
var (
hex = ctx.String(NodeKeyHexFlag.Name)
@@ -1157,26 +1161,37 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
// setBootstrapNodes creates a list of bootstrap nodes from the command line
// flags, reverting to pre-configured ones if none have been specified.
+// Priority order for bootnodes configuration:
+//
+// 1. --bootnodes flag
+// 2. Config file
+// 3. Network preset flags (e.g. --goerli)
+// 4. default to mainnet nodes
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
urls := params.MainnetBootnodes
- switch {
- case ctx.IsSet(BootnodesFlag.Name):
+ if ctx.IsSet(BootnodesFlag.Name) {
urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
- case cfg.BootstrapNodes != nil:
- return // already set, don't apply defaults.
+ } else {
+ if cfg.BootstrapNodes != nil {
+ return // Already set by config file, don't apply defaults.
+ }
}
+ cfg.BootstrapNodes = mustParseBootnodes(urls)
+}
- cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls))
+func mustParseBootnodes(urls []string) []*enode.Node {
+ nodes := make([]*enode.Node, 0, len(urls))
for _, url := range urls {
if url != "" {
node, err := enode.Parse(enode.ValidSchemes, url)
if err != nil {
log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
- continue
+ return nil
}
- cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
+ nodes = append(nodes, node)
}
}
+ return nodes
}
// setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
@@ -1582,6 +1597,13 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
log.Info(fmt.Sprintf("Using %s as db engine", dbEngine))
cfg.DBEngine = dbEngine
}
+ // deprecation notice for log debug flags (TODO: find a more appropriate place to put these?)
+ if ctx.IsSet(LogBacktraceAtFlag.Name) {
+ log.Warn("log.backtrace flag is deprecated")
+ }
+ if ctx.IsSet(LogDebugFlag.Name) {
+ log.Warn("log.debug flag is deprecated")
+ }
}
func setSmartCard(ctx *cli.Context, cfg *node.Config) {
@@ -1822,7 +1844,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
godebug.SetGCPercent(int(gogc))
- if ctx.IsSet(SyncModeFlag.Name) {
+ if ctx.IsSet(SyncTargetFlag.Name) {
+ cfg.SyncMode = downloader.FullSync // dev sync target forces full sync
+ } else if ctx.IsSet(SyncModeFlag.Name) {
cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
}
if ctx.IsSet(NetworkIdFlag.Name) {
@@ -1884,7 +1908,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(StateHistoryFlag.Name) {
cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name)
}
- scheme, err := CompareStateSchemeCLIWithConfig(ctx)
+ scheme, err := ParseCLIAndConfigStateScheme(ctx.String(StateSchemeFlag.Name), cfg.StateScheme)
if err != nil {
Fatalf("%v", err)
}
@@ -1892,12 +1916,14 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// Parse transaction history flag, if user is still using legacy config
// file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'.
if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit {
- log.Crit("The config option 'TxLookupLimit' is deprecated and may cause unexpected performance degradation issues, please use 'TransactionHistory' instead")
+ log.Warn("The config option 'TxLookupLimit' is deprecated and will be removed, please use 'TransactionHistory'")
+ cfg.TransactionHistory = cfg.TxLookupLimit
}
if ctx.IsSet(TransactionHistoryFlag.Name) {
cfg.TransactionHistory = ctx.Uint64(TransactionHistoryFlag.Name)
} else if ctx.IsSet(TxLookupLimitFlag.Name) {
- log.Crit("The flag --txlookuplimit is deprecated and may cause unexpected performance degradation issues. Please use --history.transactions instead")
+ log.Warn("The flag --txlookuplimit is deprecated and will be removed, please use --history.transactions")
+ cfg.TransactionHistory = ctx.Uint64(TxLookupLimitFlag.Name)
}
if ctx.IsSet(PathDBSyncFlag.Name) {
cfg.PathSyncFlush = true
@@ -1929,10 +1955,16 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(CacheLogSizeFlag.Name) {
cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name)
}
- if !ctx.Bool(SnapshotFlag.Name) {
+ if !ctx.Bool(SnapshotFlag.Name) || cfg.SnapshotCache == 0 {
// If snap-sync is requested, this flag is also required
if cfg.SyncMode == downloader.SnapSync {
- log.Info("Snap sync requested, enabling --snapshot")
+ if !ctx.Bool(SnapshotFlag.Name) {
+ log.Warn("Snap sync requested, enabling --snapshot")
+ }
+ if cfg.SnapshotCache == 0 {
+ log.Warn("Snap sync requested, resetting --cache.snapshot")
+ cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * CacheSnapshotFlag.Value / 100
+ }
} else {
cfg.TrieCleanCache += cfg.SnapshotCache
cfg.SnapshotCache = 0 // Disabled
@@ -2033,7 +2065,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
log.Info("Using developer account", "address", developer.Address)
// Create a new developer genesis block or reuse existing one
- cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address)
+ cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), &developer.Address)
if ctx.IsSet(DataDirFlag.Name) {
// If datadir doesn't exist we need to open db in write-mode
// so leveldb can create files.
@@ -2046,6 +2078,21 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
chaindb := MakeChainDatabase(ctx, stack, readonly, false)
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
cfg.Genesis = nil // fallback to db content
+
+ //validate genesis has PoS enabled in block 0
+ genesis, err := core.ReadGenesis(chaindb)
+ if err != nil {
+ Fatalf("Could not read genesis from database: %v", err)
+ }
+ if !genesis.Config.TerminalTotalDifficultyPassed {
+ Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficultyPassed must be true in developer mode")
+ }
+ if genesis.Config.TerminalTotalDifficulty == nil {
+ Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified.")
+ }
+ if genesis.Difficulty.Cmp(genesis.Config.TerminalTotalDifficulty) != 1 {
+ Fatalf("Bad developer-mode genesis configuration: genesis block difficulty must be > terminalTotalDifficulty")
+ }
}
chaindb.Close()
}
@@ -2247,12 +2294,11 @@ func SplitTagsFlag(tagsFlag string) map[string]string {
return tagsMap
}
-// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
+// MakeChainDatabase opens a database using the flags passed to the client and will hard crash if it fails.
func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly, disableFreeze bool) ethdb.Database {
var (
cache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
-
err error
chainDb ethdb.Database
)
@@ -2310,7 +2356,7 @@ func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error)
}
var opts []rpc.ClientOption
if len(headers) > 0 {
- var customHeaders = make(http.Header)
+ customHeaders := make(http.Header)
for _, h := range headers {
kv := strings.Split(h, ":")
if len(kv) != 2 {
@@ -2353,11 +2399,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
}
- provided, err := CompareStateSchemeCLIWithConfig(ctx)
- if err != nil {
- Fatalf("%v", err)
- }
- scheme, err := rawdb.ParseStateScheme(provided, chainDb)
+ scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), chainDb)
if err != nil {
Fatalf("%v", err)
}
@@ -2421,15 +2463,12 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
}
// MakeTrieDatabase constructs a trie database based on the configured scheme.
-func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool) *trie.Database {
+func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *trie.Database {
config := &trie.Config{
Preimages: preimage,
+ IsVerkle: isVerkle,
}
- provided, err := CompareStateSchemeCLIWithConfig(ctx)
- if err != nil {
- Fatalf("%v", err)
- }
- scheme, err := rawdb.ParseStateScheme(provided, disk)
+ scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), disk)
if err != nil {
Fatalf("%v", err)
}
@@ -2448,27 +2487,15 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
return trie.NewDatabase(disk, config)
}
-// CompareStateSchemeCLIWithConfig compare state scheme in CLI with config whether are equal.
-func CompareStateSchemeCLIWithConfig(ctx *cli.Context) (string, error) {
- var (
- cfgScheme string
- err error
- )
- if file := ctx.String("config"); file != "" {
- // we don't validate cfgScheme because it's already checked in cmd/geth/loadBaseConfig
- if cfgScheme, err = scanConfigForStateScheme(file); err != nil {
- log.Error("Failed to parse config file", "error", err)
- return "", err
- }
- }
- if !ctx.IsSet(StateSchemeFlag.Name) {
+// ParseCLIAndConfigStateScheme parses state scheme in CLI and config.
+func ParseCLIAndConfigStateScheme(cliScheme, cfgScheme string) (string, error) {
+ if cliScheme == "" {
if cfgScheme != "" {
log.Info("Use config state scheme", "config", cfgScheme)
}
return cfgScheme, nil
}
- cliScheme := ctx.String(StateSchemeFlag.Name)
if !rawdb.ValidateStateScheme(cliScheme) {
return "", fmt.Errorf("invalid state scheme in CLI: %s", cliScheme)
}
@@ -2478,35 +2505,3 @@ func CompareStateSchemeCLIWithConfig(ctx *cli.Context) (string, error) {
}
return "", fmt.Errorf("incompatible state scheme, CLI: %s, config: %s", cliScheme, cfgScheme)
}
-
-func scanConfigForStateScheme(file string) (string, error) {
- f, err := os.Open(file)
- if err != nil {
- return "", err
- }
- defer f.Close()
-
- scanner := bufio.NewScanner(f)
- targetStr := "StateScheme"
- for scanner.Scan() {
- line := scanner.Text()
- if strings.Contains(line, targetStr) {
- return indexStateScheme(line), nil
- }
- }
-
- if err = scanner.Err(); err != nil {
- return "", err
- }
- return "", nil
-}
-
-func indexStateScheme(str string) string {
- i1 := strings.Index(str, "\"")
- i2 := strings.LastIndex(str, "\"")
-
- if i1 != -1 && i2 != -1 && i1 < i2 {
- return str[i1+1 : i2]
- }
- return ""
-}
diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go
index 00237fecaf..243abd8311 100644
--- a/cmd/utils/flags_legacy.go
+++ b/cmd/utils/flags_legacy.go
@@ -45,6 +45,8 @@ var DeprecatedFlags = []cli.Flag{
LightMaxPeersFlag,
LightNoPruneFlag,
LightNoSyncServeFlag,
+ LogBacktraceAtFlag,
+ LogDebugFlag,
}
var (
@@ -118,6 +120,18 @@ var (
Usage: "Enables serving light clients before syncing (deprecated)",
Category: flags.LightCategory,
}
+ // Deprecated November 2023
+ LogBacktraceAtFlag = &cli.StringFlag{
+ Name: "log.backtrace",
+ Usage: "Request a stack trace at a specific logging statement (deprecated)",
+ Value: "",
+ Category: flags.DeprecatedCategory,
+ }
+ LogDebugFlag = &cli.BoolFlag{
+ Name: "log.debug",
+ Usage: "Prepends log messages with call-site location (deprecated)",
+ Category: flags.DeprecatedCategory,
+ }
)
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
diff --git a/cmd/utils/flags_test.go b/cmd/utils/flags_test.go
index f8bcd96cf8..00c73a5264 100644
--- a/cmd/utils/flags_test.go
+++ b/cmd/utils/flags_test.go
@@ -18,16 +18,12 @@
package utils
import (
- "os"
"reflect"
"testing"
-
- "github.com/stretchr/testify/assert"
-
- "github.com/ethereum/go-ethereum/core/rawdb"
)
func Test_SplitTagsFlag(t *testing.T) {
+ t.Parallel()
tests := []struct {
name string
args string
@@ -60,133 +56,12 @@ func Test_SplitTagsFlag(t *testing.T) {
},
}
for _, tt := range tests {
+ tt := tt
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
if got := SplitTagsFlag(tt.args); !reflect.DeepEqual(got, tt.want) {
t.Errorf("splitTagsFlag() = %v, want %v", got, tt.want)
}
})
}
}
-
-func Test_parseConfig(t *testing.T) {
- tests := []struct {
- name string
- fn func() string
- wantedResult string
- wantedIsErr bool
- wantedErrStr string
- }{
- {
- name: "path",
- fn: func() string {
- tomlString := `[Eth]NetworkId = 56StateScheme = "path"`
- return createTempTomlFile(t, tomlString)
- },
- wantedResult: rawdb.PathScheme,
- wantedIsErr: false,
- wantedErrStr: "",
- },
- {
- name: "hash",
- fn: func() string {
- tomlString := `[Eth]NetworkId = 56StateScheme = "hash"`
- return createTempTomlFile(t, tomlString)
- },
- wantedResult: rawdb.HashScheme,
- wantedIsErr: false,
- wantedErrStr: "",
- },
- {
- name: "empty state scheme",
- fn: func() string {
- tomlString := `[Eth]NetworkId = 56StateScheme = ""`
- return createTempTomlFile(t, tomlString)
- },
- wantedResult: "",
- wantedIsErr: false,
- wantedErrStr: "",
- },
- {
- name: "unset state scheme",
- fn: func() string {
- tomlString := `[Eth]NetworkId = 56`
- return createTempTomlFile(t, tomlString)
- },
- wantedResult: "",
- wantedIsErr: false,
- wantedErrStr: "",
- },
- {
- name: "failed to open file",
- fn: func() string { return "" },
- wantedResult: "",
- wantedIsErr: true,
- wantedErrStr: "open : no such file or directory",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result, err := scanConfigForStateScheme(tt.fn())
- if tt.wantedIsErr {
- assert.Contains(t, err.Error(), tt.wantedErrStr)
- } else {
- assert.Nil(t, err)
- }
- assert.Equal(t, tt.wantedResult, result)
- })
- }
-}
-
-// createTempTomlFile is a helper function to create a temp file with the provided TOML content
-func createTempTomlFile(t *testing.T, content string) string {
- t.Helper()
-
- dir := t.TempDir()
- file, err := os.CreateTemp(dir, "config.toml")
- if err != nil {
- t.Fatalf("Unable to create temporary file: %v", err)
- }
- defer file.Close()
-
- _, err = file.WriteString(content)
- if err != nil {
- t.Fatalf("Unable to write to temporary file: %v", err)
- }
- return file.Name()
-}
-
-func Test_parseString(t *testing.T) {
- tests := []struct {
- name string
- arg string
- wantResult string
- }{
- {
- name: "hash string",
- arg: "\"hash\"",
- wantResult: rawdb.HashScheme,
- },
- {
- name: "path string",
- arg: "\"path\"",
- wantResult: rawdb.PathScheme,
- },
- {
- name: "empty string",
- arg: "",
- wantResult: "",
- },
- {
- name: "empty string",
- arg: "\"\"",
- wantResult: "",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if got := indexStateScheme(tt.arg); got != tt.wantResult {
- t.Errorf("parseString() = %v, want %v", got, tt.wantResult)
- }
- })
- }
-}
diff --git a/cmd/utils/prompt_test.go b/cmd/utils/prompt_test.go
index 86ee8b6525..889bf71de3 100644
--- a/cmd/utils/prompt_test.go
+++ b/cmd/utils/prompt_test.go
@@ -22,6 +22,7 @@ import (
)
func TestGetPassPhraseWithList(t *testing.T) {
+ t.Parallel()
type args struct {
text string
confirmation bool
@@ -65,7 +66,9 @@ func TestGetPassPhraseWithList(t *testing.T) {
},
}
for _, tt := range tests {
+ tt := tt
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
if got := GetPassPhraseWithList(tt.args.text, tt.args.confirmation, tt.args.index, tt.args.passwords); got != tt.want {
t.Errorf("GetPassPhraseWithList() = %v, want %v", got, tt.want)
}
diff --git a/common/bidutil/bidutil.go b/common/bidutil/bidutil.go
new file mode 100644
index 0000000000..d2735808c6
--- /dev/null
+++ b/common/bidutil/bidutil.go
@@ -0,0 +1,23 @@
+package bidutil
+
+import (
+ "time"
+
+ "github.com/ethereum/go-ethereum/core/types"
+)
+
+// BidBetterBefore returns the time when the next bid better be received, considering the delay and bid simulation.
+// BidBetterBefore is earlier than BidMustBefore.
+func BidBetterBefore(parentHeader *types.Header, blockPeriod uint64, delayLeftOver, simulationLeftOver time.Duration) time.Time {
+ nextHeaderTime := BidMustBefore(parentHeader, blockPeriod, delayLeftOver)
+ nextHeaderTime = nextHeaderTime.Add(-simulationLeftOver)
+ return nextHeaderTime
+}
+
+// BidMustBefore returns the time when the next bid must be received,
+// only considering the consensus delay but not bid simulation duration.
+func BidMustBefore(parentHeader *types.Header, blockPeriod uint64, delayLeftOver time.Duration) time.Time {
+ nextHeaderTime := time.Unix(int64(parentHeader.Time+blockPeriod), 0)
+ nextHeaderTime = nextHeaderTime.Add(-delayLeftOver)
+ return nextHeaderTime
+}
diff --git a/common/big.go b/common/big.go
index 65d4377bf7..cbb562a28e 100644
--- a/common/big.go
+++ b/common/big.go
@@ -16,7 +16,11 @@
package common
-import "math/big"
+import (
+ "math/big"
+
+ "github.com/holiman/uint256"
+)
// Common big integers often used
var (
@@ -27,4 +31,6 @@ var (
Big32 = big.NewInt(32)
Big256 = big.NewInt(256)
Big257 = big.NewInt(257)
+
+ U2560 = uint256.NewInt(0)
)
diff --git a/common/bitutil/compress_test.go b/common/bitutil/compress_test.go
index 13a13011dc..c6f6fe8bcf 100644
--- a/common/bitutil/compress_test.go
+++ b/common/bitutil/compress_test.go
@@ -18,6 +18,7 @@ package bitutil
import (
"bytes"
+ "fmt"
"math/rand"
"testing"
@@ -48,19 +49,23 @@ func TestEncodingCycle(t *testing.T) {
"0xdf7070533534333636313639343638373532313536346c1bc333393438373130707063363430353639343638373532313536346c1bc333393438336336346c65fe",
}
for i, tt := range tests {
- data := hexutil.MustDecode(tt)
-
- proc, err := bitsetDecodeBytes(bitsetEncodeBytes(data), len(data))
- if err != nil {
- t.Errorf("test %d: failed to decompress compressed data: %v", i, err)
- continue
- }
- if !bytes.Equal(data, proc) {
- t.Errorf("test %d: compress/decompress mismatch: have %x, want %x", i, proc, data)
+ if err := testEncodingCycle(hexutil.MustDecode(tt)); err != nil {
+ t.Errorf("test %d: %v", i, err)
}
}
}
+func testEncodingCycle(data []byte) error {
+ proc, err := bitsetDecodeBytes(bitsetEncodeBytes(data), len(data))
+ if err != nil {
+ return fmt.Errorf("failed to decompress compressed data: %v", err)
+ }
+ if !bytes.Equal(data, proc) {
+ return fmt.Errorf("compress/decompress mismatch: have %x, want %x", proc, data)
+ }
+ return nil
+}
+
// Tests that data bitset decoding and rencoding works and is bijective.
func TestDecodingCycle(t *testing.T) {
tests := []struct {
@@ -179,3 +184,40 @@ func benchmarkEncoding(b *testing.B, bytes int, fill float64) {
bitsetDecodeBytes(bitsetEncodeBytes(data), len(data))
}
}
+
+func FuzzEncoder(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ if err := testEncodingCycle(data); err != nil {
+ t.Fatal(err)
+ }
+ })
+}
+func FuzzDecoder(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzDecode(data)
+ })
+}
+
+// fuzzDecode implements a go-fuzz fuzzer method to test the bit decoding and
+// reencoding algorithm.
+func fuzzDecode(data []byte) {
+ blob, err := DecompressBytes(data, 1024)
+ if err != nil {
+ return
+ }
+ // re-compress it (it's OK if the re-compressed differs from the
+ // original - the first input may not have been compressed at all)
+ comp := CompressBytes(blob)
+ if len(comp) > len(blob) {
+ // After compression, it must be smaller or equal
+ panic("bad compression")
+ }
+ // But decompressing it once again should work
+ decomp, err := DecompressBytes(data, 1024)
+ if err != nil {
+ panic(err)
+ }
+ if !bytes.Equal(decomp, blob) {
+ panic("content mismatch")
+ }
+}
diff --git a/common/hexutil/json.go b/common/hexutil/json.go
index 50db208118..e0ac98f52d 100644
--- a/common/hexutil/json.go
+++ b/common/hexutil/json.go
@@ -23,6 +23,8 @@ import (
"math/big"
"reflect"
"strconv"
+
+ "github.com/holiman/uint256"
)
var (
@@ -30,6 +32,7 @@ var (
bigT = reflect.TypeOf((*Big)(nil))
uintT = reflect.TypeOf(Uint(0))
uint64T = reflect.TypeOf(Uint64(0))
+ u256T = reflect.TypeOf((*uint256.Int)(nil))
)
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
@@ -225,6 +228,48 @@ func (b *Big) UnmarshalGraphQL(input interface{}) error {
return err
}
+// U256 marshals/unmarshals as a JSON string with 0x prefix.
+// The zero value marshals as "0x0".
+type U256 uint256.Int
+
+// MarshalText implements encoding.TextMarshaler
+func (b U256) MarshalText() ([]byte, error) {
+ u256 := (*uint256.Int)(&b)
+ return []byte(u256.Hex()), nil
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (b *U256) UnmarshalJSON(input []byte) error {
+ // The uint256.Int.UnmarshalJSON method accepts "dec", "0xhex"; we must be
+ // more strict, hence we check string and invoke SetFromHex directly.
+ if !isString(input) {
+ return errNonString(u256T)
+ }
+ // The hex decoder needs to accept empty string ("") as '0', which uint256.Int
+ // would reject.
+ if len(input) == 2 {
+ (*uint256.Int)(b).Clear()
+ return nil
+ }
+ err := (*uint256.Int)(b).SetFromHex(string(input[1 : len(input)-1]))
+ if err != nil {
+ return &json.UnmarshalTypeError{Value: err.Error(), Type: u256T}
+ }
+ return nil
+}
+
+// UnmarshalText implements encoding.TextUnmarshaler
+func (b *U256) UnmarshalText(input []byte) error {
+ // The uint256.Int.UnmarshalText method accepts "dec", "0xhex"; we must be
+ // more strict, hence we check string and invoke SetFromHex directly.
+ return (*uint256.Int)(b).SetFromHex(string(input))
+}
+
+// String returns the hex encoding of b.
+func (b *U256) String() string {
+ return (*uint256.Int)(b).Hex()
+}
+
// Uint64 marshals/unmarshals as a JSON string with 0x prefix.
// The zero value marshals as "0x0".
type Uint64 uint64
diff --git a/common/hexutil/json_test.go b/common/hexutil/json_test.go
index ed7d6fad1a..7cca300951 100644
--- a/common/hexutil/json_test.go
+++ b/common/hexutil/json_test.go
@@ -23,6 +23,8 @@ import (
"errors"
"math/big"
"testing"
+
+ "github.com/holiman/uint256"
)
func checkError(t *testing.T, input string, got, want error) bool {
@@ -176,6 +178,64 @@ func TestUnmarshalBig(t *testing.T) {
}
}
+var unmarshalU256Tests = []unmarshalTest{
+ // invalid encoding
+ {input: "", wantErr: errJSONEOF},
+ {input: "null", wantErr: errNonString(u256T)},
+ {input: "10", wantErr: errNonString(u256T)},
+ {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, u256T)},
+ {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, u256T)},
+ {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, u256T)},
+ {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, u256T)},
+ {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, u256T)},
+ {
+ input: `"0x10000000000000000000000000000000000000000000000000000000000000000"`,
+ wantErr: wrapTypeError(ErrBig256Range, u256T),
+ },
+
+ // valid encoding
+ {input: `""`, want: big.NewInt(0)},
+ {input: `"0x0"`, want: big.NewInt(0)},
+ {input: `"0x2"`, want: big.NewInt(0x2)},
+ {input: `"0x2F2"`, want: big.NewInt(0x2f2)},
+ {input: `"0X2F2"`, want: big.NewInt(0x2f2)},
+ {input: `"0x1122aaff"`, want: big.NewInt(0x1122aaff)},
+ {input: `"0xbBb"`, want: big.NewInt(0xbbb)},
+ {input: `"0xfffffffff"`, want: big.NewInt(0xfffffffff)},
+ {
+ input: `"0x112233445566778899aabbccddeeff"`,
+ want: referenceBig("112233445566778899aabbccddeeff"),
+ },
+ {
+ input: `"0xffffffffffffffffffffffffffffffffffff"`,
+ want: referenceBig("ffffffffffffffffffffffffffffffffffff"),
+ },
+ {
+ input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`,
+ want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
+ },
+}
+
+func TestUnmarshalU256(t *testing.T) {
+ for _, test := range unmarshalU256Tests {
+ var v U256
+ err := json.Unmarshal([]byte(test.input), &v)
+ if !checkError(t, test.input, err, test.wantErr) {
+ continue
+ }
+ if test.want == nil {
+ continue
+ }
+ want := new(uint256.Int)
+ want.SetFromBig(test.want.(*big.Int))
+ have := (*uint256.Int)(&v)
+ if want.Cmp(have) != 0 {
+ t.Errorf("input %s: value mismatch: have %x, want %x", test.input, have, want)
+ continue
+ }
+ }
+}
+
func BenchmarkUnmarshalBig(b *testing.B) {
input := []byte(`"0x123456789abcdef123456789abcdef"`)
for i := 0; i < b.N; i++ {
diff --git a/common/types.go b/common/types.go
index e0d89fca5a..aadca87f82 100644
--- a/common/types.go
+++ b/common/types.go
@@ -245,9 +245,6 @@ func (a Address) Cmp(other Address) int {
// Bytes gets the string representation of the underlying address.
func (a Address) Bytes() []byte { return a[:] }
-// Hash converts an address to a hash by left-padding it with zeros.
-func (a Address) Hash() Hash { return BytesToHash(a[:]) }
-
// Big converts an address to a big integer.
func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) }
diff --git a/common/types_test.go b/common/types_test.go
index ad892671b5..cec689ea39 100644
--- a/common/types_test.go
+++ b/common/types_test.go
@@ -25,6 +25,7 @@ import (
"reflect"
"strings"
"testing"
+ "time"
)
func TestBytesConversion(t *testing.T) {
@@ -583,3 +584,14 @@ func TestAddressEIP55(t *testing.T) {
t.Fatal("Unexpected address after unmarshal")
}
}
+
+func BenchmarkPrettyDuration(b *testing.B) {
+ var x = PrettyDuration(time.Duration(int64(1203123912312)))
+ b.Logf("Pre %s", time.Duration(x).String())
+ var a string
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ a = x.String()
+ }
+ b.Logf("Post %s", a)
+}
diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go
index 14764c08e3..9e1c39b99a 100644
--- a/consensus/beacon/consensus.go
+++ b/consensus/beacon/consensus.go
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
// Proof-of-stake protocol constants.
@@ -270,15 +271,21 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
if !shanghai && header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
}
- // Verify the existence / non-existence of excessBlobGas
+ // Verify the existence / non-existence of cancun-specific header fields
cancun := chain.Config().IsCancun(header.Number, header.Time)
- if !cancun && header.ExcessBlobGas != nil {
- return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
- }
- if !cancun && header.BlobGasUsed != nil {
- return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
- }
- if cancun {
+ if !cancun {
+ switch {
+ case header.ExcessBlobGas != nil:
+ return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
+ case header.BlobGasUsed != nil:
+ 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)
+ }
+ } else {
+ if header.ParentBeaconRoot == nil {
+ return errors.New("header is missing beaconRoot")
+ }
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
return err
}
@@ -326,6 +333,11 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [
return abort, results
}
+// NextInTurnValidator return the next in-turn validator for header
+func (beacon *Beacon) NextInTurnValidator(chain consensus.ChainHeaderReader, header *types.Header) (common.Address, error) {
+ return common.Address{}, errors.New("not implemented")
+}
+
// Prepare implements consensus.Engine, initializing the difficulty field of a
// header to conform to the beacon protocol. The changes are done inline.
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
@@ -355,8 +367,8 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
// Withdrawals processing.
for _, w := range withdrawals {
// Convert amount from gwei to wei.
- amount := new(big.Int).SetUint64(w.Amount)
- amount = amount.Mul(amount, big.NewInt(params.GWei))
+ amount := new(uint256.Int).SetUint64(w.Amount)
+ amount = amount.Mul(amount, uint256.NewInt(params.GWei))
state.AddBalance(w.Address, amount)
}
// No block reward which is issued by consensus layer instead.
diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go
index 2f4873a8c2..bad64b24af 100644
--- a/consensus/clique/clique.go
+++ b/consensus/clique/clique.go
@@ -303,9 +303,22 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
if chain.Config().IsShanghai(header.Number, header.Time) {
return errors.New("clique does not support shanghai fork")
}
+ // Verify the non-existence of withdrawalsHash.
+ if header.WithdrawalsHash != nil {
+ return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
+ }
if chain.Config().IsCancun(header.Number, header.Time) {
return errors.New("clique does not support cancun fork")
}
+ // Verify the non-existence of cancun-specific header fields
+ switch {
+ case header.ExcessBlobGas != nil:
+ return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
+ case header.BlobGasUsed != nil:
+ 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)
+ }
// All basic checks passed, verify cascading fields
return c.verifyCascadingFields(chain, header, parents)
}
@@ -498,6 +511,11 @@ func (c *Clique) verifySeal(snap *Snapshot, header *types.Header, parents []*typ
return nil
}
+// NextInTurnValidator return the next in-turn validator for header
+func (c *Clique) NextInTurnValidator(chain consensus.ChainHeaderReader, header *types.Header) (common.Address, error) {
+ return common.Address{}, errors.New("not implemented")
+}
+
// Prepare implements consensus.Engine, preparing all the consensus fields of the
// header for running the transactions on top.
func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
@@ -760,6 +778,15 @@ func encodeSigHeader(w io.Writer, header *types.Header) {
if header.WithdrawalsHash != nil {
panic("unexpected withdrawal hash value in clique")
}
+ if header.ExcessBlobGas != nil {
+ panic("unexpected excess blob gas value in clique")
+ }
+ if header.BlobGasUsed != nil {
+ panic("unexpected blob gas used value in clique")
+ }
+ if header.ParentBeaconRoot != nil {
+ panic("unexpected parent beacon root value in clique")
+ }
if err := rlp.Encode(w, enc); err != nil {
panic("can't encode: " + err.Error())
}
diff --git a/consensus/consensus.go b/consensus/consensus.go
index 855821c215..7b7648878b 100644
--- a/consensus/consensus.go
+++ b/consensus/consensus.go
@@ -38,6 +38,9 @@ type ChainHeaderReader interface {
// Config retrieves the blockchain's chain configuration.
Config() *params.ChainConfig
+ // GenesisHeader retrieves the chain's genesis block header.
+ GenesisHeader() *types.Header
+
// CurrentHeader retrieves the current header from the local chain.
CurrentHeader() *types.Header
@@ -91,6 +94,9 @@ type Engine interface {
// rules of a given engine.
VerifyUncles(chain ChainReader, block *types.Block) error
+ // NextInTurnValidator return the next in-turn validator for header
+ NextInTurnValidator(chain ChainHeaderReader, header *types.Header) (common.Address, error)
+
// Prepare initializes the consensus fields of a block header according to the
// rules of a particular engine. The changes are executed inline.
Prepare(chain ChainHeaderReader, header *types.Header) error
diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go
index 118dee839c..db730fab29 100644
--- a/consensus/ethash/consensus.go
+++ b/consensus/ethash/consensus.go
@@ -33,16 +33,17 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
// Ethash proof-of-work protocol constants.
var (
- FrontierBlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block
- ByzantiumBlockReward = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium
- ConstantinopleBlockReward = big.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople
- maxUncles = 2 // Maximum number of uncles allowed in a single block
- allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks
+ FrontierBlockReward = uint256.NewInt(5e+18) // Block reward in wei for successfully mining a block
+ ByzantiumBlockReward = uint256.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium
+ ConstantinopleBlockReward = uint256.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople
+ maxUncles = 2 // Maximum number of uncles allowed in a single block
+ allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks
// calcDifficultyEip5133 is the difficulty adjustment algorithm as specified by EIP 5133.
// It offsets the bomb a total of 11.4M blocks.
@@ -266,9 +267,22 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
if chain.Config().IsShanghai(header.Number, header.Time) {
return errors.New("ethash does not support shanghai fork")
}
+ // Verify the non-existence of withdrawalsHash.
+ if header.WithdrawalsHash != nil {
+ return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
+ }
if chain.Config().IsCancun(header.Number, header.Time) {
return errors.New("ethash does not support cancun fork")
}
+ // Verify the non-existence of cancun-specific header fields
+ switch {
+ case header.ExcessBlobGas != nil:
+ return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
+ case header.BlobGasUsed != nil:
+ 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)
+ }
// Add some fake checks for tests
if ethash.fakeDelay != nil {
time.Sleep(*ethash.fakeDelay)
@@ -475,6 +489,11 @@ var FrontierDifficultyCalculator = calcDifficultyFrontier
var HomesteadDifficultyCalculator = calcDifficultyHomestead
var DynamicDifficultyCalculator = makeDifficultyCalculator
+// NextInTurnValidator return the next in-turn validator for header
+func (ethash *Ethash) NextInTurnValidator(chain consensus.ChainHeaderReader, header *types.Header) (common.Address, error) {
+ return common.Address{}, errors.New("not implemented")
+}
+
// Prepare implements consensus.Engine, initializing the difficulty field of a
// header to conform to the ethash protocol. The changes are done inline.
func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
@@ -540,6 +559,15 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
if header.WithdrawalsHash != nil {
panic("withdrawal hash set on ethash")
}
+ if header.ExcessBlobGas != nil {
+ panic("excess blob gas set on ethash")
+ }
+ if header.BlobGasUsed != nil {
+ panic("blob gas used set on ethash")
+ }
+ if header.ParentBeaconRoot != nil {
+ panic("parent beacon root set on ethash")
+ }
rlp.Encode(hasher, enc)
hasher.Sum(hash[:0])
return hash
@@ -547,8 +575,8 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
// Some weird constants to avoid constant memory allocs for them.
var (
- big8 = big.NewInt(8)
- big32 = big.NewInt(32)
+ u256_8 = uint256.NewInt(8)
+ u256_32 = uint256.NewInt(32)
)
// AccumulateRewards credits the coinbase of the given block with the mining
@@ -564,16 +592,18 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
blockReward = ConstantinopleBlockReward
}
// Accumulate the rewards for the miner and any included uncles
- reward := new(big.Int).Set(blockReward)
- r := new(big.Int)
+ reward := new(uint256.Int).Set(blockReward)
+ r := new(uint256.Int)
+ hNum, _ := uint256.FromBig(header.Number)
for _, uncle := range uncles {
- r.Add(uncle.Number, big8)
- r.Sub(r, header.Number)
+ uNum, _ := uint256.FromBig(uncle.Number)
+ r.AddUint64(uNum, 8)
+ r.Sub(r, hNum)
r.Mul(r, blockReward)
- r.Div(r, big8)
+ r.Div(r, u256_8)
state.AddBalance(uncle.Coinbase, r)
- r.Div(blockReward, big32)
+ r.Div(blockReward, u256_32)
reward.Add(reward, r)
}
state.AddBalance(header.Coinbase, reward)
diff --git a/consensus/misc/dao.go b/consensus/misc/dao.go
index 96995616de..e21a44f63d 100644
--- a/consensus/misc/dao.go
+++ b/consensus/misc/dao.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
var (
@@ -81,6 +82,6 @@ func ApplyDAOHardFork(statedb *state.StateDB) {
// Move every DAO account and extra-balance account funds into the refund contract
for _, addr := range params.DAODrainList() {
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr))
- statedb.SetBalance(addr, new(big.Int))
+ statedb.SetBalance(addr, new(uint256.Int))
}
}
diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go
index d5e906f784..780a4e32df 100644
--- a/consensus/misc/eip1559/eip1559.go
+++ b/consensus/misc/eip1559/eip1559.go
@@ -59,7 +59,7 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade
// CalcBaseFee calculates the basefee of the header.
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
if config.Parlia != nil {
- return new(big.Int).SetUint64(params.InitialBaseFee)
+ return new(big.Int).SetUint64(params.InitialBaseFeeForBSC)
}
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go
index e2dbfd1825..54f91046e3 100644
--- a/consensus/misc/eip1559/eip1559_test.go
+++ b/consensus/misc/eip1559/eip1559_test.go
@@ -118,9 +118,9 @@ func TestCalcBaseFee(t *testing.T) {
parentGasUsed uint64
expectedBaseFee int64
}{
- {params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFee}, // usage == target
- {params.InitialBaseFee, 20000000, 9000000, params.InitialBaseFee}, // usage below target
- {params.InitialBaseFee, 20000000, 11000000, params.InitialBaseFee}, // usage above target
+ {params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFeeForBSC}, // usage == target
+ {params.InitialBaseFee, 20000000, 9000000, params.InitialBaseFeeForBSC}, // usage below target
+ {params.InitialBaseFee, 20000000, 11000000, params.InitialBaseFeeForBSC}, // usage above target
}
for i, test := range tests {
parent := &types.Header{
diff --git a/consensus/misc/eip4844/eip4844.go b/consensus/misc/eip4844/eip4844.go
index 583bcdeecd..2dad9a0cd3 100644
--- a/consensus/misc/eip4844/eip4844.go
+++ b/consensus/misc/eip4844/eip4844.go
@@ -42,8 +42,8 @@ func VerifyEIP4844Header(parent, header *types.Header) error {
return errors.New("header is missing blobGasUsed")
}
// Verify that the blob gas used remains within reasonable limits.
- if *header.BlobGasUsed > params.BlobTxMaxBlobGasPerBlock {
- return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.BlobTxMaxBlobGasPerBlock)
+ if *header.BlobGasUsed > params.MaxBlobGasPerBlock {
+ return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.MaxBlobGasPerBlock)
}
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
diff --git a/consensus/misc/eip4844/eip4844_test.go b/consensus/misc/eip4844/eip4844_test.go
index 677cdd252c..ec417380fc 100644
--- a/consensus/misc/eip4844/eip4844_test.go
+++ b/consensus/misc/eip4844/eip4844_test.go
@@ -45,14 +45,14 @@ func TestCalcExcessBlobGas(t *testing.T) {
// The excess blob gas should decrease by however much the target was
// under-shot, capped at zero.
{params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock},
- {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxBlobGasPerBlob},
- {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, 0},
+ {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxTargetBlobGasPerBlock - params.BlobTxBlobGasPerBlob},
+ {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxTargetBlobGasPerBlock - (2 * params.BlobTxBlobGasPerBlob)},
{params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0},
}
- for _, tt := range tests {
+ for i, tt := range tests {
result := CalcExcessBlobGas(tt.excess, tt.blobs*params.BlobTxBlobGasPerBlob)
if result != tt.want {
- t.Errorf("excess blob gas mismatch: have %v, want %v", result, tt.want)
+ t.Errorf("test %d: excess blob gas mismatch: have %v, want %v", i, result, tt.want)
}
}
}
@@ -63,9 +63,9 @@ func TestCalcBlobFee(t *testing.T) {
blobfee int64
}{
{0, 1},
- {1542706, 1},
- {1542707, 2},
- {10 * 1024 * 1024, 111},
+ {2314057, 1},
+ {2314058, 2},
+ {10 * 1024 * 1024, 23},
}
for i, tt := range tests {
have := CalcBlobFee(tt.excessBlobGas)
diff --git a/consensus/misc/gaslimit.go b/consensus/misc/gaslimit.go
index 25f35300b9..dfcabd9a80 100644
--- a/consensus/misc/gaslimit.go
+++ b/consensus/misc/gaslimit.go
@@ -17,7 +17,6 @@
package misc
import (
- "errors"
"fmt"
"github.com/ethereum/go-ethereum/params"
@@ -36,7 +35,7 @@ func VerifyGaslimit(parentGasLimit, headerGasLimit uint64) error {
return fmt.Errorf("invalid gas limit: have %d, want %d +-= %d", headerGasLimit, parentGasLimit, limit-1)
}
if headerGasLimit < params.MinGasLimit {
- return errors.New("invalid gas limit below 5000")
+ return fmt.Errorf("invalid gas limit below %d", params.MinGasLimit)
}
return nil
}
diff --git a/consensus/parlia/abi.go b/consensus/parlia/abi.go
index ffe97a45ce..0d9ab54cd5 100644
--- a/consensus/parlia/abi.go
+++ b/consensus/parlia/abi.go
@@ -1393,1731 +1393,4466 @@ const validatorSetABIBeforeLuban = `
const validatorSetABI = `
[
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"batchTransfer",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- },
- {
- "indexed":false,
- "internalType":"string",
- "name":"reason",
- "type":"string"
- }
- ],
- "name":"batchTransferFailed",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- },
- {
- "indexed":false,
- "internalType":"bytes",
- "name":"reason",
- "type":"bytes"
- }
- ],
- "name":"batchTransferLowerFailed",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- },
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"deprecatedDeposit",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- },
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"deprecatedFinalityRewardDeposit",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address payable",
- "name":"validator",
- "type":"address"
- },
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"directTransfer",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address payable",
- "name":"validator",
- "type":"address"
- },
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"directTransferFail",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":false,
- "internalType":"string",
- "name":"message",
- "type":"string"
- }
- ],
- "name":"failReasonWithStr",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"feeBurned",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- },
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"finalityRewardDeposit",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":false,
- "internalType":"string",
- "name":"key",
- "type":"string"
- },
- {
- "indexed":false,
- "internalType":"bytes",
- "name":"value",
- "type":"bytes"
- }
- ],
- "name":"paramChange",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"systemTransfer",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":false,
- "internalType":"uint8",
- "name":"channelId",
- "type":"uint8"
- },
- {
- "indexed":false,
- "internalType":"bytes",
- "name":"msgBytes",
- "type":"bytes"
- }
- ],
- "name":"unexpectedPackage",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- },
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"validatorDeposit",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- }
- ],
- "name":"validatorEmptyJailed",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- }
- ],
- "name":"validatorEnterMaintenance",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- }
- ],
- "name":"validatorExitMaintenance",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- },
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"validatorFelony",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- }
- ],
- "name":"validatorJailed",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
- {
- "indexed":true,
- "internalType":"address",
- "name":"validator",
- "type":"address"
- },
- {
- "indexed":false,
- "internalType":"uint256",
- "name":"amount",
- "type":"uint256"
- }
- ],
- "name":"validatorMisdemeanor",
- "type":"event"
- },
- {
- "anonymous":false,
- "inputs":[
-
- ],
- "name":"validatorSetUpdated",
- "type":"event"
- },
- {
- "inputs":[
-
- ],
- "name":"BIND_CHANNELID",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"BURN_ADDRESS",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"BURN_RATIO_SCALE",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"CODE_OK",
- "outputs":[
- {
- "internalType":"uint32",
- "name":"",
- "type":"uint32"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"CROSS_CHAIN_CONTRACT_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"CROSS_STAKE_CHANNELID",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"DUSTY_INCOMING",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"EPOCH",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"ERROR_FAIL_CHECK_VALIDATORS",
- "outputs":[
- {
- "internalType":"uint32",
- "name":"",
- "type":"uint32"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"ERROR_FAIL_DECODE",
- "outputs":[
- {
- "internalType":"uint32",
- "name":"",
- "type":"uint32"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"ERROR_LEN_OF_VAL_MISMATCH",
- "outputs":[
- {
- "internalType":"uint32",
- "name":"",
- "type":"uint32"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"ERROR_RELAYFEE_TOO_LARGE",
- "outputs":[
- {
- "internalType":"uint32",
- "name":"",
- "type":"uint32"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"ERROR_UNKNOWN_PACKAGE_TYPE",
- "outputs":[
- {
- "internalType":"uint32",
- "name":"",
- "type":"uint32"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"EXPIRE_TIME_SECOND_GAP",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"GOV_CHANNELID",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"GOV_HUB_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"INCENTIVIZE_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"INIT_BURN_RATIO",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"INIT_FINALITY_REWARD_RATIO",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"INIT_MAINTAIN_SLASH_SCALE",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"INIT_MAX_NUM_OF_MAINTAINING",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"INIT_NUM_OF_CABINETS",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"INIT_VALIDATORSET_BYTES",
- "outputs":[
- {
- "internalType":"bytes",
- "name":"",
- "type":"bytes"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"JAIL_MESSAGE_TYPE",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"LIGHT_CLIENT_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"MAX_NUM_OF_VALIDATORS",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"PRECISION",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"RELAYERHUB_CONTRACT_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"SLASH_CHANNELID",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"SLASH_CONTRACT_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"STAKING_CHANNELID",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"STAKING_CONTRACT_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"SYSTEM_REWARD_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"TOKEN_HUB_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"TOKEN_MANAGER_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"TRANSFER_IN_CHANNELID",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"TRANSFER_OUT_CHANNELID",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"VALIDATORS_UPDATE_MESSAGE_TYPE",
- "outputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"VALIDATOR_CONTRACT_ADDR",
- "outputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"alreadyInit",
- "outputs":[
- {
- "internalType":"bool",
- "name":"",
- "type":"bool"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"bscChainID",
- "outputs":[
- {
- "internalType":"uint16",
- "name":"",
- "type":"uint16"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"burnRatio",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"burnRatioInitialized",
- "outputs":[
- {
- "internalType":"bool",
- "name":"",
- "type":"bool"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"uint256",
- "name":"index",
- "type":"uint256"
- }
- ],
- "name":"canEnterMaintenance",
- "outputs":[
- {
- "internalType":"bool",
- "name":"",
- "type":"bool"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "name":"currentValidatorSet",
- "outputs":[
- {
- "internalType":"address",
- "name":"consensusAddress",
- "type":"address"
- },
- {
- "internalType":"address payable",
- "name":"feeAddress",
- "type":"address"
- },
- {
- "internalType":"address",
- "name":"BBCFeeAddress",
- "type":"address"
- },
- {
- "internalType":"uint64",
- "name":"votingPower",
- "type":"uint64"
- },
- {
- "internalType":"bool",
- "name":"jailed",
- "type":"bool"
- },
- {
- "internalType":"uint256",
- "name":"incoming",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"address",
- "name":"",
- "type":"address"
- }
- ],
- "name":"currentValidatorSetMap",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"address",
- "name":"valAddr",
- "type":"address"
- }
- ],
- "name":"deposit",
- "outputs":[
-
- ],
- "stateMutability":"payable",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"address[]",
- "name":"valAddrs",
- "type":"address[]"
- },
- {
- "internalType":"uint256[]",
- "name":"weights",
- "type":"uint256[]"
- }
- ],
- "name":"distributeFinalityReward",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"enterMaintenance",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"exitMaintenance",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"expireTimeSecondGap",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"address",
- "name":"validator",
- "type":"address"
- }
- ],
- "name":"felony",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"finalityRewardRatio",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"address",
- "name":"_validator",
- "type":"address"
- }
- ],
- "name":"getCurrentValidatorIndex",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"address",
- "name":"validator",
- "type":"address"
- }
- ],
- "name":"getIncoming",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"getLivingValidators",
- "outputs":[
- {
- "internalType":"address[]",
- "name":"",
- "type":"address[]"
- },
- {
- "internalType":"bytes[]",
- "name":"",
- "type":"bytes[]"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"getMiningValidators",
- "outputs":[
- {
- "internalType":"address[]",
- "name":"",
- "type":"address[]"
- },
- {
- "internalType":"bytes[]",
- "name":"",
- "type":"bytes[]"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"getValidators",
- "outputs":[
- {
- "internalType":"address[]",
- "name":"",
- "type":"address[]"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"getWorkingValidatorCount",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"workingValidatorCount",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"uint8",
- "name":"channelId",
- "type":"uint8"
- },
- {
- "internalType":"bytes",
- "name":"msgBytes",
- "type":"bytes"
- }
- ],
- "name":"handleAckPackage",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"uint8",
- "name":"channelId",
- "type":"uint8"
- },
- {
- "internalType":"bytes",
- "name":"msgBytes",
- "type":"bytes"
- }
- ],
- "name":"handleFailAckPackage",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"uint8",
- "name":"",
- "type":"uint8"
- },
- {
- "internalType":"bytes",
- "name":"msgBytes",
- "type":"bytes"
- }
- ],
- "name":"handleSynPackage",
- "outputs":[
- {
- "internalType":"bytes",
- "name":"responsePayload",
- "type":"bytes"
- }
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"init",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"address",
- "name":"validator",
- "type":"address"
- }
- ],
- "name":"isCurrentValidator",
- "outputs":[
- {
- "internalType":"bool",
- "name":"",
- "type":"bool"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"uint256",
- "name":"index",
- "type":"uint256"
- }
- ],
- "name":"isWorkingValidator",
- "outputs":[
- {
- "internalType":"bool",
- "name":"",
- "type":"bool"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"maintainSlashScale",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"maxNumOfCandidates",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"maxNumOfMaintaining",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"maxNumOfWorkingCandidates",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"address",
- "name":"validator",
- "type":"address"
- }
- ],
- "name":"misdemeanor",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"numOfCabinets",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"numOfJailed",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"numOfMaintaining",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"previousHeight",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
-
- ],
- "name":"totalInComing",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"string",
- "name":"key",
- "type":"string"
- },
- {
- "internalType":"bytes",
- "name":"value",
- "type":"bytes"
- }
- ],
- "name":"updateParam",
- "outputs":[
-
- ],
- "stateMutability":"nonpayable",
- "type":"function"
- },
- {
- "inputs":[
- {
- "internalType":"uint256",
- "name":"",
- "type":"uint256"
- }
- ],
- "name":"validatorExtraSet",
- "outputs":[
- {
- "internalType":"uint256",
- "name":"enterMaintenanceHeight",
- "type":"uint256"
- },
- {
- "internalType":"bool",
- "name":"isMaintaining",
- "type":"bool"
- },
- {
- "internalType":"bytes",
- "name":"voteAddress",
- "type":"bytes"
- }
- ],
- "stateMutability":"view",
- "type":"function"
- },
- {
- "stateMutability":"payable",
- "type":"receive"
- }
+ {
+ "type": "receive",
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "BC_FUSION_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "BIND_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "BLOCK_FEES_RATIO_SCALE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "BURN_ADDRESS",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "CODE_OK",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "CROSS_CHAIN_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "CROSS_STAKE_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "DUSTY_INCOMING",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "EPOCH",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "ERROR_FAIL_CHECK_VALIDATORS",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "ERROR_FAIL_DECODE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "ERROR_LEN_OF_VAL_MISMATCH",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "ERROR_RELAYFEE_TOO_LARGE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "ERROR_UNKNOWN_PACKAGE_TYPE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "EXPIRE_TIME_SECOND_GAP",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "GOVERNOR_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "GOV_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "GOV_HUB_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "GOV_TOKEN_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INCENTIVIZE_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INIT_BURN_RATIO",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INIT_MAINTAIN_SLASH_SCALE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INIT_MAX_NUM_OF_MAINTAINING",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INIT_NUM_OF_CABINETS",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INIT_SYSTEM_REWARD_RATIO",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INIT_VALIDATORSET_BYTES",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "JAIL_MESSAGE_TYPE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "LIGHT_CLIENT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "MAX_NUM_OF_VALIDATORS",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "MAX_SYSTEM_REWARD_BALANCE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "PRECISION",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "RELAYERHUB_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "SLASH_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "SLASH_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKE_CREDIT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKE_HUB_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKING_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKING_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "SYSTEM_REWARD_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TIMELOCK_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TOKEN_HUB_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TOKEN_MANAGER_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TOKEN_RECOVER_PORTAL_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TRANSFER_IN_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TRANSFER_OUT_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "VALIDATORS_UPDATE_MESSAGE_TYPE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "VALIDATOR_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "alreadyInit",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "bscChainID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint16",
+ "internalType": "uint16"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "burnRatio",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "burnRatioInitialized",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "canEnterMaintenance",
+ "inputs": [
+ {
+ "name": "index",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "currentValidatorSet",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "consensusAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "feeAddress",
+ "type": "address",
+ "internalType": "address payable"
+ },
+ {
+ "name": "BBCFeeAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "votingPower",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "jailed",
+ "type": "bool",
+ "internalType": "bool"
+ },
+ {
+ "name": "incoming",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "currentValidatorSetMap",
+ "inputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "currentVoteAddrFullSet",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "deposit",
+ "inputs": [
+ {
+ "name": "valAddr",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "distributeFinalityReward",
+ "inputs": [
+ {
+ "name": "valAddrs",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "weights",
+ "type": "uint256[]",
+ "internalType": "uint256[]"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "enterMaintenance",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "exitMaintenance",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "expireTimeSecondGap",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "felony",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "getCurrentValidatorIndex",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getIncoming",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getLivingValidators",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "",
+ "type": "bytes[]",
+ "internalType": "bytes[]"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getMiningValidators",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "",
+ "type": "bytes[]",
+ "internalType": "bytes[]"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidators",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address[]",
+ "internalType": "address[]"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getWorkingValidatorCount",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "workingValidatorCount",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "handleAckPackage",
+ "inputs": [
+ {
+ "name": "channelId",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "handleFailAckPackage",
+ "inputs": [
+ {
+ "name": "channelId",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "handleSynPackage",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "responsePayload",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "init",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "isCurrentValidator",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "isMonitoredForMaliciousVote",
+ "inputs": [
+ {
+ "name": "voteAddr",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "isSystemRewardIncluded",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "isWorkingValidator",
+ "inputs": [
+ {
+ "name": "index",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "maintainSlashScale",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "maxNumOfCandidates",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "maxNumOfMaintaining",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "maxNumOfWorkingCandidates",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "misdemeanor",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "numOfCabinets",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "numOfJailed",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "numOfMaintaining",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "previousBalanceOfSystemReward",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "previousHeight",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "previousVoteAddrFullSet",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "removeTmpMigratedValidator",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "systemRewardRatio",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "totalInComing",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "updateParam",
+ "inputs": [
+ {
+ "name": "key",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "updateValidatorSetV2",
+ "inputs": [
+ {
+ "name": "_consensusAddrs",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "_votingPowers",
+ "type": "uint64[]",
+ "internalType": "uint64[]"
+ },
+ {
+ "name": "_voteAddrs",
+ "type": "bytes[]",
+ "internalType": "bytes[]"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "validatorExtraSet",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "enterMaintenanceHeight",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "isMaintaining",
+ "type": "bool",
+ "internalType": "bool"
+ },
+ {
+ "name": "voteAddress",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "event",
+ "name": "batchTransfer",
+ "inputs": [
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "batchTransferFailed",
+ "inputs": [
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": true,
+ "internalType": "uint256"
+ },
+ {
+ "name": "reason",
+ "type": "string",
+ "indexed": false,
+ "internalType": "string"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "batchTransferLowerFailed",
+ "inputs": [
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": true,
+ "internalType": "uint256"
+ },
+ {
+ "name": "reason",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "deprecatedDeposit",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "deprecatedFinalityRewardDeposit",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "directTransfer",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address payable"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "directTransferFail",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address payable"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "failReasonWithStr",
+ "inputs": [
+ {
+ "name": "message",
+ "type": "string",
+ "indexed": false,
+ "internalType": "string"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "feeBurned",
+ "inputs": [
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "finalityRewardDeposit",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "paramChange",
+ "inputs": [
+ {
+ "name": "key",
+ "type": "string",
+ "indexed": false,
+ "internalType": "string"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "systemTransfer",
+ "inputs": [
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "tmpValidatorSetUpdated",
+ "inputs": [
+ {
+ "name": "validatorsNum",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "unexpectedPackage",
+ "inputs": [
+ {
+ "name": "channelId",
+ "type": "uint8",
+ "indexed": false,
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorDeposit",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorEmptyJailed",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorEnterMaintenance",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorExitMaintenance",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorFelony",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorJailed",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorMisdemeanor",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "amount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorSetUpdated",
+ "inputs": [],
+ "anonymous": false
+ }
]
`
const slashABI = `
[
- {
- "anonymous": false,
- "inputs": [],
- "name": "indicatorCleaned",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "internalType": "address",
- "name": "validator",
- "type": "address"
- }
- ],
- "name": "validatorSlashed",
- "type": "event"
- },
- {
- "inputs": [],
- "name": "FELONY_THRESHOLD",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "stateMutability": "view",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "MISDEMEANOR_THRESHOLD",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "stateMutability": "view",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "SYSTEM_ADDRESS",
- "outputs": [
- {
- "internalType": "address",
- "name": "",
- "type": "address"
- }
- ],
- "stateMutability": "view",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "VALIDATOR_CONTRACT_ADDR",
- "outputs": [
- {
- "internalType": "address",
- "name": "",
- "type": "address"
- }
- ],
- "stateMutability": "view",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "previousHeight",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "stateMutability": "view",
- "type": "function"
- },
- {
- "inputs": [
- {
- "internalType": "address",
- "name": "validator",
- "type": "address"
- }
- ],
- "name": "slash",
- "outputs": [],
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "inputs": [],
- "name": "clean",
- "outputs": [],
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "inputs": [
- {
- "internalType": "address",
- "name": "validator",
- "type": "address"
- }
- ],
- "name": "getSlashIndicator",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "stateMutability": "view",
- "type": "function"
- }
- ]
+ {
+ "type": "function",
+ "name": "BC_FUSION_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "BIND_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "CODE_OK",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "CROSS_CHAIN_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "CROSS_STAKE_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "DECREASE_RATE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "ERROR_FAIL_DECODE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint32",
+ "internalType": "uint32"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "FELONY_THRESHOLD",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "GOVERNOR_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "GOV_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "GOV_HUB_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "GOV_TOKEN_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INCENTIVIZE_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INIT_FELONY_SLASH_REWARD_RATIO",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "INIT_FELONY_SLASH_SCOPE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "LIGHT_CLIENT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "MISDEMEANOR_THRESHOLD",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "RELAYERHUB_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "SLASH_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "SLASH_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKE_CREDIT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKE_HUB_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKING_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKING_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "SYSTEM_REWARD_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TIMELOCK_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TOKEN_HUB_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TOKEN_MANAGER_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TOKEN_RECOVER_PORTAL_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TRANSFER_IN_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "TRANSFER_OUT_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "VALIDATOR_CONTRACT_ADDR",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "alreadyInit",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "bscChainID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint16",
+ "internalType": "uint16"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "clean",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "downtimeSlash",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "count",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "enableMaliciousVoteSlash",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "felonySlashRewardRatio",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "felonySlashScope",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "felonyThreshold",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getSlashIndicator",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getSlashThresholds",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "handleAckPackage",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "handleFailAckPackage",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "handleSynPackage",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "indicators",
+ "inputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "height",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "count",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "exist",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "init",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "misdemeanorThreshold",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "previousHeight",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "sendFelonyPackage",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "slash",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "submitDoubleSignEvidence",
+ "inputs": [
+ {
+ "name": "header1",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "header2",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "submitFinalityViolationEvidence",
+ "inputs": [
+ {
+ "name": "_evidence",
+ "type": "tuple",
+ "internalType": "struct SlashIndicator.FinalityEvidence",
+ "components": [
+ {
+ "name": "voteA",
+ "type": "tuple",
+ "internalType": "struct SlashIndicator.VoteData",
+ "components": [
+ {
+ "name": "srcNum",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "srcHash",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "tarNum",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "tarHash",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "sig",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ },
+ {
+ "name": "voteB",
+ "type": "tuple",
+ "internalType": "struct SlashIndicator.VoteData",
+ "components": [
+ {
+ "name": "srcNum",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "srcHash",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "tarNum",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "tarHash",
+ "type": "bytes32",
+ "internalType": "bytes32"
+ },
+ {
+ "name": "sig",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ },
+ {
+ "name": "voteAddr",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "updateParam",
+ "inputs": [
+ {
+ "name": "key",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "validators",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "event",
+ "name": "crashResponse",
+ "inputs": [],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "failedFelony",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "slashCount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "failReason",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "indicatorCleaned",
+ "inputs": [],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "knownResponse",
+ "inputs": [
+ {
+ "name": "code",
+ "type": "uint32",
+ "indexed": false,
+ "internalType": "uint32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "maliciousVoteSlashed",
+ "inputs": [
+ {
+ "name": "voteAddrSlice",
+ "type": "bytes32",
+ "indexed": true,
+ "internalType": "bytes32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "paramChange",
+ "inputs": [
+ {
+ "name": "key",
+ "type": "string",
+ "indexed": false,
+ "internalType": "string"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "unKnownResponse",
+ "inputs": [
+ {
+ "name": "code",
+ "type": "uint32",
+ "indexed": false,
+ "internalType": "uint32"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "validatorSlashed",
+ "inputs": [
+ {
+ "name": "validator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ }
+]
+`
+
+const stakeABI = `
+[
+ {
+ "type": "receive",
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "BC_FUSION_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "BREATHE_BLOCK_INTERVAL",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "DEAD_ADDRESS",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "LOCK_AMOUNT",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "REDELEGATE_FEE_RATE_BASE",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "STAKING_CHANNELID",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "addToBlackList",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "blackList",
+ "inputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "claim",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "requestNumber",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "claimBatch",
+ "inputs": [
+ {
+ "name": "operatorAddresses",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "requestNumbers",
+ "type": "uint256[]",
+ "internalType": "uint256[]"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "consensusExpiration",
+ "inputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "consensusToOperator",
+ "inputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "createValidator",
+ "inputs": [
+ {
+ "name": "consensusAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "voteAddress",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "blsProof",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "commission",
+ "type": "tuple",
+ "internalType": "struct StakeHub.Commission",
+ "components": [
+ {
+ "name": "rate",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "maxRate",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "maxChangeRate",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ },
+ {
+ "name": "description",
+ "type": "tuple",
+ "internalType": "struct StakeHub.Description",
+ "components": [
+ {
+ "name": "moniker",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "identity",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "website",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "details",
+ "type": "string",
+ "internalType": "string"
+ }
+ ]
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "delegate",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "delegateVotePower",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "distributeReward",
+ "inputs": [
+ {
+ "name": "consensusAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "payable"
+ },
+ {
+ "type": "function",
+ "name": "doubleSignSlash",
+ "inputs": [
+ {
+ "name": "consensusAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "downtimeJailTime",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "downtimeSlash",
+ "inputs": [
+ {
+ "name": "consensusAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "downtimeSlashAmount",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "editCommissionRate",
+ "inputs": [
+ {
+ "name": "commissionRate",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "editConsensusAddress",
+ "inputs": [
+ {
+ "name": "newConsensusAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "editDescription",
+ "inputs": [
+ {
+ "name": "description",
+ "type": "tuple",
+ "internalType": "struct StakeHub.Description",
+ "components": [
+ {
+ "name": "moniker",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "identity",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "website",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "details",
+ "type": "string",
+ "internalType": "string"
+ }
+ ]
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "editVoteAddress",
+ "inputs": [
+ {
+ "name": "newVoteAddress",
+ "type": "bytes",
+ "internalType": "bytes"
+ },
+ {
+ "name": "blsProof",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "felonyJailTime",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "felonySlashAmount",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorBasicInfo",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "createdTime",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "jailed",
+ "type": "bool",
+ "internalType": "bool"
+ },
+ {
+ "name": "jailUntil",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorCommission",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "tuple",
+ "internalType": "struct StakeHub.Commission",
+ "components": [
+ {
+ "name": "rate",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "maxRate",
+ "type": "uint64",
+ "internalType": "uint64"
+ },
+ {
+ "name": "maxChangeRate",
+ "type": "uint64",
+ "internalType": "uint64"
+ }
+ ]
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorConsensusAddress",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "consensusAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorCreditContract",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "creditContract",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorDescription",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "tuple",
+ "internalType": "struct StakeHub.Description",
+ "components": [
+ {
+ "name": "moniker",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "identity",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "website",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "details",
+ "type": "string",
+ "internalType": "string"
+ }
+ ]
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorElectionInfo",
+ "inputs": [
+ {
+ "name": "offset",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "limit",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "consensusAddrs",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "votingPowers",
+ "type": "uint256[]",
+ "internalType": "uint256[]"
+ },
+ {
+ "name": "voteAddrs",
+ "type": "bytes[]",
+ "internalType": "bytes[]"
+ },
+ {
+ "name": "totalLength",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorRewardRecord",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "index",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorTotalPooledBNBRecord",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "index",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidatorVoteAddress",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "voteAddress",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "getValidators",
+ "inputs": [
+ {
+ "name": "offset",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "limit",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "operatorAddrs",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "creditAddrs",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "totalLength",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "handleAckPackage",
+ "inputs": [
+ {
+ "name": "channelId",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "handleFailAckPackage",
+ "inputs": [
+ {
+ "name": "channelId",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "handleSynPackage",
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint8",
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "initialize",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "isPaused",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "maliciousVoteSlash",
+ "inputs": [
+ {
+ "name": "voteAddress",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "maxElectedValidators",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "maxFelonyBetweenBreatheBlock",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "minDelegationBNBChange",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "minSelfDelegationBNB",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "numOfJailed",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "pause",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "redelegate",
+ "inputs": [
+ {
+ "name": "srcValidator",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "dstValidator",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "shares",
+ "type": "uint256",
+ "internalType": "uint256"
+ },
+ {
+ "name": "delegateVotePower",
+ "type": "bool",
+ "internalType": "bool"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "redelegateFeeRate",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "removeFromBlackList",
+ "inputs": [
+ {
+ "name": "account",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "resume",
+ "inputs": [],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "syncGovToken",
+ "inputs": [
+ {
+ "name": "operatorAddresses",
+ "type": "address[]",
+ "internalType": "address[]"
+ },
+ {
+ "name": "account",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "transferGasLimit",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "unbondPeriod",
+ "inputs": [],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "undelegate",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ },
+ {
+ "name": "shares",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "unjail",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "updateParam",
+ "inputs": [
+ {
+ "name": "key",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [],
+ "stateMutability": "nonpayable"
+ },
+ {
+ "type": "function",
+ "name": "voteExpiration",
+ "inputs": [
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256",
+ "internalType": "uint256"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "function",
+ "name": "voteToOperator",
+ "inputs": [
+ {
+ "name": "",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ "internalType": "address"
+ }
+ ],
+ "stateMutability": "view"
+ },
+ {
+ "type": "event",
+ "name": "BlackListed",
+ "inputs": [
+ {
+ "name": "target",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Claimed",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "delegator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "bnbAmount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "CommissionRateEdited",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newCommissionRate",
+ "type": "uint64",
+ "indexed": false,
+ "internalType": "uint64"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ConsensusAddressEdited",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newConsensusAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Delegated",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "delegator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "shares",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "bnbAmount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "DescriptionEdited",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Initialized",
+ "inputs": [
+ {
+ "name": "version",
+ "type": "uint8",
+ "indexed": false,
+ "internalType": "uint8"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "MigrateFailed",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "delegator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "bnbAmount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "respCode",
+ "type": "uint8",
+ "indexed": false,
+ "internalType": "enum StakeHub.StakeMigrationRespCode"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "MigrateSuccess",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "delegator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "shares",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "bnbAmount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ParamChange",
+ "inputs": [
+ {
+ "name": "key",
+ "type": "string",
+ "indexed": false,
+ "internalType": "string"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Paused",
+ "inputs": [],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ProtectorChanged",
+ "inputs": [
+ {
+ "name": "oldProtector",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newProtector",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Redelegated",
+ "inputs": [
+ {
+ "name": "srcValidator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "dstValidator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "delegator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "oldShares",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "newShares",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "bnbAmount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Resumed",
+ "inputs": [],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RewardDistributeFailed",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "failReason",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "RewardDistributed",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "reward",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "StakeCreditInitialized",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "creditContract",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "UnBlackListed",
+ "inputs": [
+ {
+ "name": "target",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "Undelegated",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "delegator",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "shares",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "bnbAmount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "UnexpectedPackage",
+ "inputs": [
+ {
+ "name": "channelId",
+ "type": "uint8",
+ "indexed": false,
+ "internalType": "uint8"
+ },
+ {
+ "name": "msgBytes",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ValidatorCreated",
+ "inputs": [
+ {
+ "name": "consensusAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "creditContract",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "voteAddress",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ValidatorEmptyJailed",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ValidatorJailed",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ValidatorSlashed",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "jailUntil",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "slashAmount",
+ "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256"
+ },
+ {
+ "name": "slashType",
+ "type": "uint8",
+ "indexed": false,
+ "internalType": "enum StakeHub.SlashType"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "ValidatorUnjailed",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "event",
+ "name": "VoteAddressEdited",
+ "inputs": [
+ {
+ "name": "operatorAddress",
+ "type": "address",
+ "indexed": true,
+ "internalType": "address"
+ },
+ {
+ "name": "newVoteAddress",
+ "type": "bytes",
+ "indexed": false,
+ "internalType": "bytes"
+ }
+ ],
+ "anonymous": false
+ },
+ {
+ "type": "error",
+ "name": "AlreadyPaused",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "AlreadySlashed",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ConsensusAddressExpired",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "DelegationAmountTooSmall",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "DuplicateConsensusAddress",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "DuplicateMoniker",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "DuplicateVoteAddress",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InBlackList",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidCommission",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidConsensusAddress",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidMoniker",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidRequest",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidSynPackage",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "InvalidValue",
+ "inputs": [
+ {
+ "name": "key",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "InvalidVoteAddress",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "JailTimeNotExpired",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "NoMoreFelonyAllowed",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "NotPaused",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "OnlyCoinbase",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "OnlyProtector",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "OnlySelfDelegation",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "OnlySystemContract",
+ "inputs": [
+ {
+ "name": "systemContract",
+ "type": "address",
+ "internalType": "address"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "OnlyZeroGasPrice",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "SameValidator",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "SelfDelegationNotEnough",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "TransferFailed",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "UnknownParam",
+ "inputs": [
+ {
+ "name": "key",
+ "type": "string",
+ "internalType": "string"
+ },
+ {
+ "name": "value",
+ "type": "bytes",
+ "internalType": "bytes"
+ }
+ ]
+ },
+ {
+ "type": "error",
+ "name": "UpdateTooFrequently",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ValidatorExisted",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ValidatorNotExisted",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ValidatorNotJailed",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "VoteAddressExpired",
+ "inputs": []
+ },
+ {
+ "type": "error",
+ "name": "ZeroShares",
+ "inputs": []
+ }
+]
`
diff --git a/consensus/parlia/feynmanfork.go b/consensus/parlia/feynmanfork.go
new file mode 100644
index 0000000000..c6a958e215
--- /dev/null
+++ b/consensus/parlia/feynmanfork.go
@@ -0,0 +1,235 @@
+package parlia
+
+import (
+ "container/heap"
+ "context"
+ "fmt"
+ "math"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/systemcontracts"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+const SecondsPerDay uint64 = 86400
+
+// the params should be two blocks' time(timestamp)
+func sameDayInUTC(first, second uint64) bool {
+ return first/SecondsPerDay == second/SecondsPerDay
+}
+
+func isBreatheBlock(lastBlockTime, blockTime uint64) bool {
+ return lastBlockTime != 0 && !sameDayInUTC(lastBlockTime, blockTime)
+}
+
+// initializeFeynmanContract initialize new contracts of Feynman fork
+func (p *Parlia) initializeFeynmanContract(state *state.StateDB, header *types.Header, chain core.ChainContext,
+ txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
+) error {
+ // method
+ method := "initialize"
+
+ // initialize contracts
+ contracts := []string{
+ systemcontracts.StakeHubContract,
+ systemcontracts.GovernorContract,
+ systemcontracts.GovTokenContract,
+ systemcontracts.TimelockContract,
+ systemcontracts.TokenRecoverPortalContract,
+ }
+ // get packed data
+ data, err := p.stakeHubABI.Pack(method)
+ if err != nil {
+ log.Error("Unable to pack tx for initialize feynman contracts", "error", err)
+ return err
+ }
+ for _, c := range contracts {
+ msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0)
+ // apply message
+ log.Info("initialize feynman contract", "block number", header.Number.Uint64(), "contract", c)
+ err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type ValidatorItem struct {
+ address common.Address
+ votingPower *big.Int
+ voteAddress []byte
+}
+
+// An ValidatorHeap is a max-heap of validator's votingPower.
+type ValidatorHeap []ValidatorItem
+
+func (h *ValidatorHeap) Len() int { return len(*h) }
+
+func (h *ValidatorHeap) Less(i, j int) bool {
+ // We want topK validators with max voting power, so we need a max-heap
+ if (*h)[i].votingPower.Cmp((*h)[j].votingPower) == 0 {
+ return (*h)[i].address.Hex() < (*h)[j].address.Hex()
+ } else {
+ return (*h)[i].votingPower.Cmp((*h)[j].votingPower) == 1
+ }
+}
+
+func (h *ValidatorHeap) Swap(i, j int) { (*h)[i], (*h)[j] = (*h)[j], (*h)[i] }
+
+func (h *ValidatorHeap) Push(x interface{}) {
+ *h = append(*h, x.(ValidatorItem))
+}
+
+func (h *ValidatorHeap) Pop() interface{} {
+ old := *h
+ n := len(old)
+ x := old[n-1]
+ *h = old[0 : n-1]
+ return x
+}
+
+func (p *Parlia) updateValidatorSetV2(state *state.StateDB, header *types.Header, chain core.ChainContext,
+ txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool,
+) error {
+ // 1. get all validators and its voting power
+ blockNr := rpc.BlockNumberOrHashWithHash(header.ParentHash, false)
+ validatorItems, err := p.getValidatorElectionInfo(blockNr)
+ if err != nil {
+ return err
+ }
+ maxElectedValidators, err := p.getMaxElectedValidators(blockNr)
+ if err != nil {
+ return err
+ }
+
+ // 2. sort by voting power
+ eValidators, eVotingPowers, eVoteAddrs := getTopValidatorsByVotingPower(validatorItems, maxElectedValidators)
+
+ // 3. update validator set to system contract
+ method := "updateValidatorSetV2"
+ data, err := p.validatorSetABI.Pack(method, eValidators, eVotingPowers, eVoteAddrs)
+ if err != nil {
+ log.Error("Unable to pack tx for updateValidatorSetV2", "error", err)
+ return err
+ }
+
+ // get system message
+ msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0)
+ // apply message
+ return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
+}
+
+func (p *Parlia) getValidatorElectionInfo(blockNr rpc.BlockNumberOrHash) ([]ValidatorItem, error) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ method := "getValidatorElectionInfo"
+ toAddress := common.HexToAddress(systemcontracts.StakeHubContract)
+ gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
+
+ data, err := p.stakeHubABI.Pack(method, big.NewInt(0), big.NewInt(0))
+ if err != nil {
+ log.Error("Unable to pack tx for getValidatorElectionInfo", "error", err)
+ return nil, err
+ }
+ msgData := (hexutil.Bytes)(data)
+
+ result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
+ Gas: &gas,
+ To: &toAddress,
+ Data: &msgData,
+ }, &blockNr, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var validators []common.Address
+ var votingPowers []*big.Int
+ var voteAddrs [][]byte
+ var totalLength *big.Int
+ if err := p.stakeHubABI.UnpackIntoInterface(&[]interface{}{&validators, &votingPowers, &voteAddrs, &totalLength}, method, result); err != nil {
+ return nil, err
+ }
+ if totalLength.Int64() != int64(len(validators)) || totalLength.Int64() != int64(len(votingPowers)) || totalLength.Int64() != int64(len(voteAddrs)) {
+ return nil, fmt.Errorf("validator length not match")
+ }
+
+ validatorItems := make([]ValidatorItem, len(validators))
+ for i := 0; i < len(validators); i++ {
+ validatorItems[i] = ValidatorItem{
+ address: validators[i],
+ votingPower: votingPowers[i],
+ voteAddress: voteAddrs[i],
+ }
+ }
+
+ return validatorItems, nil
+}
+
+func (p *Parlia) getMaxElectedValidators(blockNr rpc.BlockNumberOrHash) (maxElectedValidators *big.Int, err error) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ method := "maxElectedValidators"
+ toAddress := common.HexToAddress(systemcontracts.StakeHubContract)
+ gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
+
+ data, err := p.stakeHubABI.Pack(method)
+ if err != nil {
+ log.Error("Unable to pack tx for maxElectedValidators", "error", err)
+ return nil, err
+ }
+ msgData := (hexutil.Bytes)(data)
+
+ result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
+ Gas: &gas,
+ To: &toAddress,
+ Data: &msgData,
+ }, &blockNr, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := p.stakeHubABI.UnpackIntoInterface(&maxElectedValidators, method, result); err != nil {
+ return nil, err
+ }
+
+ return maxElectedValidators, nil
+}
+
+func getTopValidatorsByVotingPower(validatorItems []ValidatorItem, maxElectedValidators *big.Int) ([]common.Address, []uint64, [][]byte) {
+ var validatorHeap ValidatorHeap
+ for i := 0; i < len(validatorItems); i++ {
+ // only keep validators with voting power > 0
+ if validatorItems[i].votingPower.Cmp(big.NewInt(0)) == 1 {
+ validatorHeap = append(validatorHeap, validatorItems[i])
+ }
+ }
+ hp := &validatorHeap
+ heap.Init(hp)
+
+ topN := int(maxElectedValidators.Int64())
+ if topN > len(validatorHeap) {
+ topN = len(validatorHeap)
+ }
+ eValidators := make([]common.Address, topN)
+ eVotingPowers := make([]uint64, topN)
+ eVoteAddrs := make([][]byte, topN)
+ for i := 0; i < topN; i++ {
+ item := heap.Pop(hp).(ValidatorItem)
+ eValidators[i] = item.address
+ // as the decimal in BNB Beacon Chain is 1e8 and in BNB Smart Chain is 1e18, we need to divide it by 1e10
+ eVotingPowers[i] = new(big.Int).Div(item.votingPower, big.NewInt(1e10)).Uint64()
+ eVoteAddrs[i] = item.voteAddress
+ }
+
+ return eValidators, eVotingPowers, eVoteAddrs
+}
diff --git a/consensus/parlia/feynmanfork_test.go b/consensus/parlia/feynmanfork_test.go
new file mode 100644
index 0000000000..2863eddab7
--- /dev/null
+++ b/consensus/parlia/feynmanfork_test.go
@@ -0,0 +1,166 @@
+package parlia
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func TestValidatorHeap(t *testing.T) {
+ testCases := []struct {
+ description string
+ k int64
+ validators []ValidatorItem
+ expected []common.Address
+ }{
+ {
+ description: "normal case",
+ k: 2,
+ validators: []ValidatorItem{
+ {
+ address: common.HexToAddress("0x1"),
+ votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
+ voteAddress: []byte("0x1"),
+ },
+ {
+ address: common.HexToAddress("0x2"),
+ votingPower: new(big.Int).Mul(big.NewInt(200), big.NewInt(1e10)),
+ voteAddress: []byte("0x2"),
+ },
+ {
+ address: common.HexToAddress("0x3"),
+ votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
+ voteAddress: []byte("0x3"),
+ },
+ },
+ expected: []common.Address{
+ common.HexToAddress("0x1"),
+ common.HexToAddress("0x2"),
+ },
+ },
+ {
+ description: "same voting power",
+ k: 2,
+ validators: []ValidatorItem{
+ {
+ address: common.HexToAddress("0x1"),
+ votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
+ voteAddress: []byte("0x1"),
+ },
+ {
+ address: common.HexToAddress("0x2"),
+ votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
+ voteAddress: []byte("0x2"),
+ },
+ {
+ address: common.HexToAddress("0x3"),
+ votingPower: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e10)),
+ voteAddress: []byte("0x3"),
+ },
+ },
+ expected: []common.Address{
+ common.HexToAddress("0x1"),
+ common.HexToAddress("0x2"),
+ },
+ },
+ {
+ description: "zero voting power and k > len(validators)",
+ k: 5,
+ validators: []ValidatorItem{
+ {
+ address: common.HexToAddress("0x1"),
+ votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
+ voteAddress: []byte("0x1"),
+ },
+ {
+ address: common.HexToAddress("0x2"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x2"),
+ },
+ {
+ address: common.HexToAddress("0x3"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x3"),
+ },
+ {
+ address: common.HexToAddress("0x4"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x4"),
+ },
+ },
+ expected: []common.Address{
+ common.HexToAddress("0x1"),
+ },
+ },
+ {
+ description: "zero voting power and k < len(validators)",
+ k: 2,
+ validators: []ValidatorItem{
+ {
+ address: common.HexToAddress("0x1"),
+ votingPower: new(big.Int).Mul(big.NewInt(300), big.NewInt(1e10)),
+ voteAddress: []byte("0x1"),
+ },
+ {
+ address: common.HexToAddress("0x2"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x2"),
+ },
+ {
+ address: common.HexToAddress("0x3"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x3"),
+ },
+ {
+ address: common.HexToAddress("0x4"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x4"),
+ },
+ },
+ expected: []common.Address{
+ common.HexToAddress("0x1"),
+ },
+ },
+ {
+ description: "all zero voting power",
+ k: 2,
+ validators: []ValidatorItem{
+ {
+ address: common.HexToAddress("0x1"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x1"),
+ },
+ {
+ address: common.HexToAddress("0x2"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x2"),
+ },
+ {
+ address: common.HexToAddress("0x3"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x3"),
+ },
+ {
+ address: common.HexToAddress("0x4"),
+ votingPower: big.NewInt(0),
+ voteAddress: []byte("0x4"),
+ },
+ },
+ expected: []common.Address{},
+ },
+ }
+ for _, tc := range testCases {
+ eligibleValidators, _, _ := getTopValidatorsByVotingPower(tc.validators, big.NewInt(tc.k))
+
+ // check
+ if len(eligibleValidators) != len(tc.expected) {
+ t.Errorf("expected %d, got %d", len(tc.expected), len(eligibleValidators))
+ }
+ for i := 0; i < len(tc.expected); i++ {
+ if eligibleValidators[i] != tc.expected[i] {
+ t.Errorf("expected %s, got %s", tc.expected[i].Hex(), eligibleValidators[i].Hex())
+ }
+ }
+ }
+}
diff --git a/consensus/parlia/lubanFork.go b/consensus/parlia/lubanFork.go
index fa85b7399f..883d6e2561 100644
--- a/consensus/parlia/lubanFork.go
+++ b/consensus/parlia/lubanFork.go
@@ -38,7 +38,7 @@ func (p *Parlia) getCurrentValidatorsBeforeLuban(blockHash common.Hash, blockNum
Gas: &gas,
To: &toAddress,
Data: &msgData,
- }, blockNr, nil, nil)
+ }, &blockNr, nil, nil)
if err != nil {
return nil, err
}
diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go
index 996e44670d..7a8a691c31 100644
--- a/consensus/parlia/parlia.go
+++ b/consensus/parlia/parlia.go
@@ -6,7 +6,6 @@ import (
"encoding/hex"
"errors"
"fmt"
- "io"
"math"
"math/big"
"math/rand"
@@ -16,6 +15,7 @@ import (
"time"
lru "github.com/hashicorp/golang-lru"
+ "github.com/holiman/uint256"
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
"github.com/willf/bitset"
"golang.org/x/crypto/sha3"
@@ -76,7 +76,7 @@ var (
diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures
diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures
// 100 native token
- maxSystemBalance = new(big.Int).Mul(big.NewInt(100), big.NewInt(params.Ether))
+ maxSystemBalance = new(uint256.Int).Mul(uint256.NewInt(100), uint256.NewInt(params.Ether))
verifyVoteAttestationErrorCounter = metrics.NewRegisteredCounter("parlia/verifyVoteAttestation/error", nil)
updateAttestationErrorCounter = metrics.NewRegisteredCounter("parlia/updateAttestation/error", nil)
validVotesfromSelfCounter = metrics.NewRegisteredCounter("parlia/VerifyVote/self", nil)
@@ -91,6 +91,11 @@ var (
common.HexToAddress(systemcontracts.TokenHubContract): true,
common.HexToAddress(systemcontracts.RelayerIncentivizeContract): true,
common.HexToAddress(systemcontracts.CrossChainContract): true,
+ common.HexToAddress(systemcontracts.StakeHubContract): true,
+ common.HexToAddress(systemcontracts.GovernorContract): true,
+ common.HexToAddress(systemcontracts.GovTokenContract): true,
+ common.HexToAddress(systemcontracts.TimelockContract): true,
+ common.HexToAddress(systemcontracts.TokenRecoverPortalContract): true,
}
)
@@ -180,7 +185,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (
signature := header.Extra[len(header.Extra)-extraSeal:]
// Recover the public key and the Ethereum address
- pubkey, err := crypto.Ecrecover(SealHash(header, chainId).Bytes(), signature)
+ pubkey, err := crypto.Ecrecover(types.SealHash(header, chainId).Bytes(), signature)
if err != nil {
return common.Address{}, err
}
@@ -200,7 +205,7 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (
// or not), which could be abused to produce different hashes for the same header.
func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
b := new(bytes.Buffer)
- encodeSigHeader(b, header, chainId)
+ types.EncodeSigHeader(b, header, chainId)
return b.Bytes()
}
@@ -227,6 +232,7 @@ type Parlia struct {
validatorSetABIBeforeLuban abi.ABI
validatorSetABI abi.ABI
slashABI abi.ABI
+ stakeHubABI abi.ABI
// The fields below are for testing only
fakeDiff bool // Skip difficulty verifications
@@ -269,6 +275,10 @@ func New(
if err != nil {
panic(err)
}
+ stABI, err := abi.JSON(strings.NewReader(stakeABI))
+ if err != nil {
+ panic(err)
+ }
c := &Parlia{
chainConfig: chainConfig,
config: parliaConfig,
@@ -280,6 +290,7 @@ func New(
validatorSetABIBeforeLuban: vABIBeforeLuban,
validatorSetABI: vABI,
slashABI: sABI,
+ stakeHubABI: stABI,
signer: types.LatestSigner(chainConfig),
}
@@ -576,8 +587,24 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
if header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
}
- // Verify the existence / non-existence of excessBlobGas
+ // Verify the existence / non-existence of cancun-specific header fields
+ if header.ParentBeaconRoot != nil {
+ return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot)
+ }
cancun := chain.Config().IsCancun(header.Number, header.Time)
+ if !cancun {
+ switch {
+ case header.ExcessBlobGas != nil:
+ return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
+ case header.BlobGasUsed != nil:
+ return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
+ }
+ } else {
+ if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
+ return err
+ }
+ }
+
if !cancun && header.ExcessBlobGas != nil {
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
}
@@ -908,7 +935,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
// Prepare vote address bitset.
for _, valInfo := range snap.Validators {
if _, ok := voteAddrSet[valInfo.VoteAddress]; ok {
- attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) //Index is offset by 1
+ attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) // Index is offset by 1
}
}
validatorsBitSet := bitset.From([]uint64{uint64(attestation.VoteAddressSet)})
@@ -933,6 +960,16 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
return nil
}
+// NextInTurnValidator return the next in-turn validator for header
+func (p *Parlia) NextInTurnValidator(chain consensus.ChainHeaderReader, header *types.Header) (common.Address, error) {
+ snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ return snap.inturnValidator(), nil
+}
+
// Prepare implements consensus.Engine, preparing all the consensus fields of the
// header for running the transactions on top.
func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
@@ -964,7 +1001,7 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header
}
header.Extra = header.Extra[:extraVanity-nextForkHashSize]
- nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, number, header.Time)
+ nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, chain.GenesisHeader().Time, number, header.Time)
header.Extra = append(header.Extra, nextForkHash[:]...)
if err := p.prepareValidators(header); err != nil {
@@ -1105,7 +1142,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
if err != nil {
return err
}
- nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, number, header.Time)
+ nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, chain.GenesisHeader().Time, number, header.Time)
if !snap.isMajorityFork(hex.EncodeToString(nextForkHash[:])) {
log.Debug("there is a possible fork, and your client is not the majority. Please check...", "nextForkHash", hex.EncodeToString(nextForkHash[:]))
}
@@ -1117,6 +1154,22 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
cx := chainContext{Chain: chain, parlia: p}
+ parent := chain.GetHeaderByHash(header.ParentHash)
+ if parent == nil {
+ return errors.New("parent not found")
+ }
+
+ if p.chainConfig.IsFeynman(header.Number, header.Time) {
+ systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state)
+ }
+
+ if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
+ err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
+ if err != nil {
+ log.Error("init feynman contract failed", "error", err)
+ }
+ }
+
// No block rewards in PoA, so the state remains as is and uncles are dropped
if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
@@ -1158,6 +1211,17 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
return err
}
}
+
+ // update validators every day
+ if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
+ // we should avoid update validators in the Feynman upgrade block
+ if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
+ if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false); err != nil {
+ return err
+ }
+ }
+ }
+
if len(*systemTxs) > 0 {
return errors.New("the length of systemTxs do not match")
}
@@ -1176,6 +1240,23 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
if receipts == nil {
receipts = make([]*types.Receipt, 0)
}
+
+ parent := chain.GetHeaderByHash(header.ParentHash)
+ if parent == nil {
+ return nil, nil, errors.New("parent not found")
+ }
+
+ if p.chainConfig.IsFeynman(header.Number, header.Time) {
+ systemcontracts.UpgradeBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state)
+ }
+
+ if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
+ err := p.initializeFeynmanContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
+ if err != nil {
+ log.Error("init feynman contract failed", "error", err)
+ }
+ }
+
if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
if err != nil {
@@ -1220,6 +1301,16 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
}
}
+ // update validators every day
+ if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) {
+ // we should avoid update validators in the Feynman upgrade block
+ if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) {
+ if err := p.updateValidatorSetV2(state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil {
+ return nil, nil, err
+ }
+ }
+ }
+
// should not happen. Once happen, stop the node is better than broadcast the block
if header.GasLimit < header.GasUsed {
return nil, nil, errors.New("gas consumption of system txs exceed the gas limit")
@@ -1422,7 +1513,7 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res
select {
case results <- block.WithSeal(header):
default:
- log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID))
+ log.Warn("Sealing result is not read by miner", "sealhash", types.SealHash(header, p.chainConfig.ChainID))
}
}()
@@ -1496,7 +1587,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
// So it's not the real hash of a block, just used as unique id to distinguish task
func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256()
- encodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
+ types.EncodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
hasher.Sum(hash[:0])
return hash
}
@@ -1547,43 +1638,42 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNum *big.Int)
Gas: &gas,
To: &toAddress,
Data: &msgData,
- }, blockNr, nil, nil)
+ }, &blockNr, nil, nil)
if err != nil {
return nil, nil, err
}
var valSet []common.Address
var voteAddrSet []types.BLSPublicKey
-
if err := p.validatorSetABI.UnpackIntoInterface(&[]interface{}{&valSet, &voteAddrSet}, method, result); err != nil {
return nil, nil, err
}
- voteAddrmap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
+ voteAddrMap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
for i := 0; i < len(valSet); i++ {
- voteAddrmap[valSet[i]] = &(voteAddrSet)[i]
+ voteAddrMap[valSet[i]] = &(voteAddrSet)[i]
}
- return valSet, voteAddrmap, nil
+ return valSet, voteAddrMap, nil
}
-// slash spoiled validators
+// distributeIncoming distributes system incoming of the block
func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
coinbase := header.Coinbase
balance := state.GetBalance(consensus.SystemAddress)
- if balance.Cmp(common.Big0) <= 0 {
+ if balance.Cmp(common.U2560) <= 0 {
return nil
}
- state.SetBalance(consensus.SystemAddress, big.NewInt(0))
+ state.SetBalance(consensus.SystemAddress, common.U2560)
state.AddBalance(coinbase, balance)
doDistributeSysReward := !p.chainConfig.IsKepler(header.Number, header.Time) &&
state.GetBalance(common.HexToAddress(systemcontracts.SystemRewardContract)).Cmp(maxSystemBalance) < 0
if doDistributeSysReward {
- var rewards = new(big.Int)
+ rewards := new(uint256.Int)
rewards = rewards.Rsh(balance, systemRewardPercent)
- if rewards.Cmp(common.Big0) > 0 {
- err := p.distributeToSystem(rewards, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
+ if rewards.Cmp(common.U2560) > 0 {
+ err := p.distributeToSystem(rewards.ToBig(), state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
if err != nil {
return err
}
@@ -1592,7 +1682,7 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he
}
}
log.Trace("distribute to validator contract", "block hash", header.Hash(), "amount", balance)
- return p.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
+ return p.distributeToValidator(balance.ToBig(), val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
}
// slash spoiled validators
@@ -1656,7 +1746,7 @@ func (p *Parlia) distributeToSystem(amount *big.Int, state *state.StateDB, heade
return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining)
}
-// slash spoiled validators
+// distributeToValidator deposits validator reward to validator contract
func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address,
state *state.StateDB, header *types.Header, chain core.ChainContext,
txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error {
@@ -1801,62 +1891,6 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t
}
// =========================== utility function ==========================
-// SealHash returns the hash of a block prior to it being sealed.
-func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) {
- hasher := sha3.NewLegacyKeccak256()
- encodeSigHeader(hasher, header, chainId)
- hasher.Sum(hash[:0])
- return hash
-}
-
-func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
- err := rlp.Encode(w, []interface{}{
- chainId,
- header.ParentHash,
- header.UncleHash,
- header.Coinbase,
- header.Root,
- header.TxHash,
- header.ReceiptHash,
- header.Bloom,
- header.Difficulty,
- header.Number,
- header.GasLimit,
- header.GasUsed,
- header.Time,
- header.Extra[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader
- header.MixDigest,
- header.Nonce,
- })
- if err != nil {
- panic("can't encode: " + err.Error())
- }
-}
-
-func encodeSigHeaderWithoutVoteAttestation(w io.Writer, header *types.Header, chainId *big.Int) {
- err := rlp.Encode(w, []interface{}{
- chainId,
- header.ParentHash,
- header.UncleHash,
- header.Coinbase,
- header.Root,
- header.TxHash,
- header.ReceiptHash,
- header.Bloom,
- header.Difficulty,
- header.Number,
- header.GasLimit,
- header.GasUsed,
- header.Time,
- header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
- header.MixDigest,
- header.Nonce,
- })
- if err != nil {
- panic("can't encode: " + err.Error())
- }
-}
-
func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 {
if snap.inturn(val) {
return 0
@@ -1981,7 +2015,7 @@ func applyMessage(
*msg.To(),
msg.Data(),
msg.Gas(),
- msg.Value(),
+ uint256.MustFromBig(msg.Value()),
)
if err != nil {
log.Error("apply message failed", "msg", string(ret), "err", err)
diff --git a/consensus/parlia/snapshot.go b/consensus/parlia/snapshot.go
index ddfb1811fc..0da0929e7c 100644
--- a/consensus/parlia/snapshot.go
+++ b/consensus/parlia/snapshot.go
@@ -338,6 +338,13 @@ func (s *Snapshot) inturn(validator common.Address) bool {
return validators[offset] == validator
}
+// inturnValidator returns the validator at a given block height.
+func (s *Snapshot) inturnValidator() common.Address {
+ validators := s.validators()
+ offset := (s.Number + 1) % uint64(len(validators))
+ return validators[offset]
+}
+
func (s *Snapshot) enoughDistance(validator common.Address, header *types.Header) bool {
idx := s.indexOfVal(validator)
if idx < 0 {
diff --git a/console/bridge.go b/console/bridge.go
index c67686d6c3..37578041ca 100644
--- a/console/bridge.go
+++ b/console/bridge.go
@@ -78,7 +78,7 @@ func (b *bridge) NewAccount(call jsre.Call) (goja.Value, error) {
return nil, err
}
if password != confirm {
- return nil, errors.New("passwords don't match!")
+ return nil, errors.New("passwords don't match")
}
// A single string password was specified, use that
case len(call.Arguments) == 1 && call.Argument(0).ToString() != nil:
diff --git a/console/console_test.go b/console/console_test.go
index ee5c36be4a..a13be6a99d 100644
--- a/console/console_test.go
+++ b/console/console_test.go
@@ -94,7 +94,7 @@ func newTester(t *testing.T, confOverride func(*ethconfig.Config)) *tester {
t.Fatalf("failed to create node: %v", err)
}
ethConf := ðconfig.Config{
- Genesis: core.DeveloperGenesisBlock(11_500_000, common.Address{}),
+ Genesis: core.DeveloperGenesisBlock(11_500_000, nil),
Miner: miner.Config{
Etherbase: common.HexToAddress(testAddress),
},
diff --git a/core/asm/asm.go b/core/asm/asm.go
index 7c1e14ec01..294eb6ffaa 100644
--- a/core/asm/asm.go
+++ b/core/asm/asm.go
@@ -34,7 +34,7 @@ type instructionIterator struct {
started bool
}
-// NewInstructionIterator create a new instruction iterator.
+// NewInstructionIterator creates a new instruction iterator.
func NewInstructionIterator(code []byte) *instructionIterator {
it := new(instructionIterator)
it.code = code
diff --git a/core/asm/asm_test.go b/core/asm/asm_test.go
index 92b26b67a5..cd7520ec63 100644
--- a/core/asm/asm_test.go
+++ b/core/asm/asm_test.go
@@ -22,53 +22,37 @@ import (
"encoding/hex"
)
-// Tests disassembling the instructions for valid evm code
-func TestInstructionIteratorValid(t *testing.T) {
- cnt := 0
- script, _ := hex.DecodeString("61000000")
-
- it := NewInstructionIterator(script)
- for it.Next() {
- cnt++
- }
-
- if err := it.Error(); err != nil {
- t.Errorf("Expected 2, but encountered error %v instead.", err)
- }
- if cnt != 2 {
- t.Errorf("Expected 2, but got %v instead.", cnt)
- }
-}
-
-// Tests disassembling the instructions for invalid evm code
-func TestInstructionIteratorInvalid(t *testing.T) {
- cnt := 0
- script, _ := hex.DecodeString("6100")
-
- it := NewInstructionIterator(script)
- for it.Next() {
- cnt++
- }
-
- if it.Error() == nil {
- t.Errorf("Expected an error, but got %v instead.", cnt)
- }
-}
-
-// Tests disassembling the instructions for empty evm code
-func TestInstructionIteratorEmpty(t *testing.T) {
- cnt := 0
- script, _ := hex.DecodeString("")
-
- it := NewInstructionIterator(script)
- for it.Next() {
- cnt++
- }
-
- if err := it.Error(); err != nil {
- t.Errorf("Expected 0, but encountered error %v instead.", err)
- }
- if cnt != 0 {
- t.Errorf("Expected 0, but got %v instead.", cnt)
+// Tests disassembling instructions
+func TestInstructionIterator(t *testing.T) {
+ for i, tc := range []struct {
+ want int
+ code string
+ wantErr string
+ }{
+ {2, "61000000", ""}, // valid code
+ {0, "6100", "incomplete push instruction at 0"}, // invalid code
+ {2, "5900", ""}, // push0
+ {0, "", ""}, // empty
+
+ } {
+ var (
+ have int
+ code, _ = hex.DecodeString(tc.code)
+ it = NewInstructionIterator(code)
+ )
+ for it.Next() {
+ have++
+ }
+ var haveErr = ""
+ if it.Error() != nil {
+ haveErr = it.Error().Error()
+ }
+ if haveErr != tc.wantErr {
+ t.Errorf("test %d: encountered error: %q want %q", i, haveErr, tc.wantErr)
+ continue
+ }
+ if have != tc.want {
+ t.Errorf("wrong instruction count, have %d want %d", have, tc.want)
+ }
}
}
diff --git a/core/asm/compiler.go b/core/asm/compiler.go
index 4b1d379206..02c589b2c1 100644
--- a/core/asm/compiler.go
+++ b/core/asm/compiler.go
@@ -17,6 +17,8 @@
package asm
import (
+ "encoding/hex"
+ "errors"
"fmt"
"math/big"
"os"
@@ -30,7 +32,7 @@ import (
// and holds the tokens for the program.
type Compiler struct {
tokens []token
- binary []interface{}
+ out []byte
labels map[string]int
@@ -47,15 +49,13 @@ func NewCompiler(debug bool) *Compiler {
}
}
-// Feed feeds tokens in to ch and are interpreted by
+// Feed feeds tokens into ch and are interpreted by
// the compiler.
//
-// feed is the first pass in the compile stage as it
-// collects the used labels in the program and keeps a
-// program counter which is used to determine the locations
-// of the jump dests. The labels can than be used in the
-// second stage to push labels and determine the right
-// position.
+// feed is the first pass in the compile stage as it collects the used labels in the
+// program and keeps a program counter which is used to determine the locations of the
+// jump dests. The labels can than be used in the second stage to push labels and
+// determine the right position.
func (c *Compiler) Feed(ch <-chan token) {
var prev token
for i := range ch {
@@ -79,7 +79,6 @@ func (c *Compiler) Feed(ch <-chan token) {
c.pc++
}
}
-
c.tokens = append(c.tokens, i)
prev = i
}
@@ -88,12 +87,11 @@ func (c *Compiler) Feed(ch <-chan token) {
}
}
-// Compile compiles the current tokens and returns a
-// binary string that can be interpreted by the EVM
-// and an error if it failed.
+// Compile compiles the current tokens and returns a binary string that can be interpreted
+// by the EVM and an error if it failed.
//
-// compile is the second stage in the compile phase
-// which compiles the tokens to EVM instructions.
+// compile is the second stage in the compile phase which compiles the tokens to EVM
+// instructions.
func (c *Compiler) Compile() (string, []error) {
var errors []error
// continue looping over the tokens until
@@ -105,16 +103,8 @@ func (c *Compiler) Compile() (string, []error) {
}
// turn the binary to hex
- var bin strings.Builder
- for _, v := range c.binary {
- switch v := v.(type) {
- case vm.OpCode:
- bin.WriteString(fmt.Sprintf("%x", []byte{byte(v)}))
- case []byte:
- bin.WriteString(fmt.Sprintf("%x", v))
- }
- }
- return bin.String(), errors
+ h := hex.EncodeToString(c.out)
+ return h, errors
}
// next returns the next token and increments the
@@ -156,87 +146,114 @@ func (c *Compiler) compileLine() error {
return nil
}
-// compileNumber compiles the number to bytes
-func (c *Compiler) compileNumber(element token) {
- num := math.MustParseBig256(element.text).Bytes()
- if len(num) == 0 {
- num = []byte{0}
+// parseNumber compiles the number to bytes
+func parseNumber(tok token) ([]byte, error) {
+ if tok.typ != number {
+ panic("parseNumber of non-number token")
+ }
+ num, ok := math.ParseBig256(tok.text)
+ if !ok {
+ return nil, errors.New("invalid number")
}
- c.pushBin(num)
+ bytes := num.Bytes()
+ if len(bytes) == 0 {
+ bytes = []byte{0}
+ }
+ return bytes, nil
}
// compileElement compiles the element (push & label or both)
// to a binary representation and may error if incorrect statements
// where fed.
func (c *Compiler) compileElement(element token) error {
- // check for a jump. jumps must be read and compiled
- // from right to left.
- if isJump(element.text) {
- rvalue := c.next()
- switch rvalue.typ {
- case number:
- // TODO figure out how to return the error properly
- c.compileNumber(rvalue)
- case stringValue:
- // strings are quoted, remove them.
- c.pushBin(rvalue.text[1 : len(rvalue.text)-2])
- case label:
- c.pushBin(vm.PUSH4)
- pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes()
- pos = append(make([]byte, 4-len(pos)), pos...)
- c.pushBin(pos)
- case lineEnd:
- c.pos--
- default:
- return compileErr(rvalue, rvalue.text, "number, string or label")
- }
- // push the operation
- c.pushBin(toBinary(element.text))
+ switch {
+ case isJump(element.text):
+ return c.compileJump(element.text)
+ case isPush(element.text):
+ return c.compilePush()
+ default:
+ c.outputOpcode(toBinary(element.text))
return nil
- } else if isPush(element.text) {
- // handle pushes. pushes are read from left to right.
- var value []byte
+ }
+}
- rvalue := c.next()
- switch rvalue.typ {
- case number:
- value = math.MustParseBig256(rvalue.text).Bytes()
- if len(value) == 0 {
- value = []byte{0}
- }
- case stringValue:
- value = []byte(rvalue.text[1 : len(rvalue.text)-1])
- case label:
- value = big.NewInt(int64(c.labels[rvalue.text])).Bytes()
- value = append(make([]byte, 4-len(value)), value...)
- default:
- return compileErr(rvalue, rvalue.text, "number, string or label")
+func (c *Compiler) compileJump(jumpType string) error {
+ rvalue := c.next()
+ switch rvalue.typ {
+ case number:
+ numBytes, err := parseNumber(rvalue)
+ if err != nil {
+ return err
}
+ c.outputBytes(numBytes)
- if len(value) > 32 {
- return fmt.Errorf("%d type error: unsupported string or number with size > 32", rvalue.lineno)
- }
+ case stringValue:
+ // strings are quoted, remove them.
+ str := rvalue.text[1 : len(rvalue.text)-2]
+ c.outputBytes([]byte(str))
+
+ case label:
+ c.outputOpcode(vm.PUSH4)
+ pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes()
+ pos = append(make([]byte, 4-len(pos)), pos...)
+ c.outputBytes(pos)
+
+ case lineEnd:
+ // push without argument is supported, it just takes the destination from the stack.
+ c.pos--
- c.pushBin(vm.OpCode(int(vm.PUSH1) - 1 + len(value)))
- c.pushBin(value)
- } else {
- c.pushBin(toBinary(element.text))
+ default:
+ return compileErr(rvalue, rvalue.text, "number, string or label")
}
+ // push the operation
+ c.outputOpcode(toBinary(jumpType))
+ return nil
+}
+func (c *Compiler) compilePush() error {
+ // handle pushes. pushes are read from left to right.
+ var value []byte
+ rvalue := c.next()
+ switch rvalue.typ {
+ case number:
+ value = math.MustParseBig256(rvalue.text).Bytes()
+ if len(value) == 0 {
+ value = []byte{0}
+ }
+ case stringValue:
+ value = []byte(rvalue.text[1 : len(rvalue.text)-1])
+ case label:
+ value = big.NewInt(int64(c.labels[rvalue.text])).Bytes()
+ value = append(make([]byte, 4-len(value)), value...)
+ default:
+ return compileErr(rvalue, rvalue.text, "number, string or label")
+ }
+ if len(value) > 32 {
+ return fmt.Errorf("%d: string or number size > 32 bytes", rvalue.lineno+1)
+ }
+ c.outputOpcode(vm.OpCode(int(vm.PUSH1) - 1 + len(value)))
+ c.outputBytes(value)
return nil
}
// compileLabel pushes a jumpdest to the binary slice.
func (c *Compiler) compileLabel() {
- c.pushBin(vm.JUMPDEST)
+ c.outputOpcode(vm.JUMPDEST)
+}
+
+func (c *Compiler) outputOpcode(op vm.OpCode) {
+ if c.debug {
+ fmt.Printf("%d: %v\n", len(c.out), op)
+ }
+ c.out = append(c.out, byte(op))
}
-// pushBin pushes the value v to the binary stack.
-func (c *Compiler) pushBin(v interface{}) {
+// output pushes the value v to the binary stack.
+func (c *Compiler) outputBytes(b []byte) {
if c.debug {
- fmt.Printf("%d: %v\n", len(c.binary), v)
+ fmt.Printf("%d: %x\n", len(c.out), b)
}
- c.binary = append(c.binary, v)
+ c.out = append(c.out, b...)
}
// isPush returns whether the string op is either any of
@@ -263,13 +280,13 @@ type compileError struct {
}
func (err compileError) Error() string {
- return fmt.Sprintf("%d syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want)
+ return fmt.Sprintf("%d: syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want)
}
func compileErr(c token, got, want string) error {
return compileError{
got: got,
want: want,
- lineno: c.lineno,
+ lineno: c.lineno + 1,
}
}
diff --git a/core/asm/compiler_test.go b/core/asm/compiler_test.go
index ce9df436bd..3d64c96bc8 100644
--- a/core/asm/compiler_test.go
+++ b/core/asm/compiler_test.go
@@ -54,6 +54,14 @@ func TestCompiler(t *testing.T) {
`,
output: "6300000006565b",
},
+ {
+ input: `
+ JUMP @label
+label: ;; comment
+ ADD ;; comment
+`,
+ output: "6300000006565b01",
+ },
}
for _, test := range tests {
ch := Lex([]byte(test.input), false)
diff --git a/core/asm/lex_test.go b/core/asm/lex_test.go
index 53e05fbbba..1e62d776d4 100644
--- a/core/asm/lex_test.go
+++ b/core/asm/lex_test.go
@@ -72,6 +72,16 @@ func TestLexer(t *testing.T) {
input: "@label123",
tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}},
},
+ // Comment after label
+ {
+ input: "@label123 ;; comment",
+ tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}},
+ },
+ // Comment after instruction
+ {
+ input: "push 3 ;; comment\nadd",
+ tokens: []token{{typ: lineStart}, {typ: element, text: "push"}, {typ: number, text: "3"}, {typ: lineEnd, text: "\n"}, {typ: lineStart, lineno: 1}, {typ: element, lineno: 1, text: "add"}, {typ: eof, lineno: 1}},
+ },
}
for _, test := range tests {
diff --git a/core/asm/lexer.go b/core/asm/lexer.go
index fb705848d2..6dd3d7ab16 100644
--- a/core/asm/lexer.go
+++ b/core/asm/lexer.go
@@ -44,6 +44,8 @@ type token struct {
// is able to parse and return.
type tokenType int
+//go:generate go run golang.org/x/tools/cmd/stringer -type tokenType
+
const (
eof tokenType = iota // end of file
lineStart // emitted when a line starts
@@ -54,31 +56,13 @@ const (
labelDef // label definition is emitted when a new label is found
number // number is emitted when a number is found
stringValue // stringValue is emitted when a string has been found
-
- Numbers = "1234567890" // characters representing any decimal number
- HexadecimalNumbers = Numbers + "aAbBcCdDeEfF" // characters representing any hexadecimal
- Alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric
)
-// String implements stringer
-func (it tokenType) String() string {
- if int(it) > len(stringtokenTypes) {
- return "invalid"
- }
- return stringtokenTypes[it]
-}
-
-var stringtokenTypes = []string{
- eof: "EOF",
- lineStart: "new line",
- lineEnd: "end of line",
- invalidStatement: "invalid statement",
- element: "element",
- label: "label",
- labelDef: "label definition",
- number: "number",
- stringValue: "string",
-}
+const (
+ decimalNumbers = "1234567890" // characters representing any decimal number
+ hexNumbers = decimalNumbers + "aAbBcCdDeEfF" // characters representing any hexadecimal
+ alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric
+)
// lexer is the basic construct for parsing
// source code and turning them in to tokens.
@@ -202,7 +186,6 @@ func lexLine(l *lexer) stateFn {
l.emit(lineEnd)
l.ignore()
l.lineno++
-
l.emit(lineStart)
case r == ';' && l.peek() == ';':
return lexComment
@@ -227,6 +210,7 @@ func lexLine(l *lexer) stateFn {
// of the line and discards the text.
func lexComment(l *lexer) stateFn {
l.acceptRunUntil('\n')
+ l.backup()
l.ignore()
return lexLine
@@ -236,7 +220,7 @@ func lexComment(l *lexer) stateFn {
// the lex text state function to advance the parsing
// process.
func lexLabel(l *lexer) stateFn {
- l.acceptRun(Alpha + "_" + Numbers)
+ l.acceptRun(alpha + "_" + decimalNumbers)
l.emit(label)
@@ -255,9 +239,9 @@ func lexInsideString(l *lexer) stateFn {
}
func lexNumber(l *lexer) stateFn {
- acceptance := Numbers
+ acceptance := decimalNumbers
if l.accept("xX") {
- acceptance = HexadecimalNumbers
+ acceptance = hexNumbers
}
l.acceptRun(acceptance)
@@ -267,7 +251,7 @@ func lexNumber(l *lexer) stateFn {
}
func lexElement(l *lexer) stateFn {
- l.acceptRun(Alpha + "_" + Numbers)
+ l.acceptRun(alpha + "_" + decimalNumbers)
if l.peek() == ':' {
l.emit(labelDef)
diff --git a/core/asm/tokentype_string.go b/core/asm/tokentype_string.go
new file mode 100644
index 0000000000..ade76aa360
--- /dev/null
+++ b/core/asm/tokentype_string.go
@@ -0,0 +1,31 @@
+// Code generated by "stringer -type tokenType"; DO NOT EDIT.
+
+package asm
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[eof-0]
+ _ = x[lineStart-1]
+ _ = x[lineEnd-2]
+ _ = x[invalidStatement-3]
+ _ = x[element-4]
+ _ = x[label-5]
+ _ = x[labelDef-6]
+ _ = x[number-7]
+ _ = x[stringValue-8]
+}
+
+const _tokenType_name = "eoflineStartlineEndinvalidStatementelementlabellabelDefnumberstringValue"
+
+var _tokenType_index = [...]uint8{0, 3, 12, 19, 35, 42, 47, 55, 61, 72}
+
+func (i tokenType) String() string {
+ if i < 0 || i >= tokenType(len(_tokenType_index)-1) {
+ return "tokenType(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _tokenType_name[_tokenType_index[i]:_tokenType_index[i+1]]
+}
diff --git a/core/bench_test.go b/core/bench_test.go
index 55fa980a85..951ce2a08c 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -84,7 +84,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
toaddr := common.Address{}
data := make([]byte, nbytes)
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
- signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), gen.header.Time)
+ signer := gen.Signer()
gasPrice := big.NewInt(0)
if gen.header.BaseFee != nil {
gasPrice = gen.header.BaseFee
@@ -128,7 +128,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
if gen.header.BaseFee != nil {
gasPrice = gen.header.BaseFee
}
- signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), gen.header.Time)
+ signer := gen.Signer()
for {
gas -= params.TxGas
if gas < params.TxGas {
@@ -243,7 +243,7 @@ func BenchmarkChainWrite_full_500k(b *testing.B) {
// makeChainForBench writes a given number of headers or empty blocks/receipts
// into a database.
-func makeChainForBench(db ethdb.Database, full bool, count uint64) {
+func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uint64) {
var hash common.Hash
for n := uint64(0); n < count; n++ {
header := &types.Header{
@@ -255,6 +255,9 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyReceiptsHash,
}
+ if n == 0 {
+ header = genesis.ToBlock().Header()
+ }
hash = header.Hash()
rawdb.WriteHeader(db, header)
@@ -262,7 +265,7 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
rawdb.WriteTd(db, hash, n, big.NewInt(int64(n+1)))
if n == 0 {
- rawdb.WriteChainConfig(db, hash, params.AllEthashProtocolChanges)
+ rawdb.WriteChainConfig(db, hash, genesis.Config)
}
rawdb.WriteHeadHeaderHash(db, hash)
@@ -276,13 +279,14 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
}
func benchWriteChain(b *testing.B, full bool, count uint64) {
+ genesis := &Genesis{Config: params.AllEthashProtocolChanges}
for i := 0; i < b.N; i++ {
dir := b.TempDir()
db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false)
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
- makeChainForBench(db, full, count)
+ makeChainForBench(db, genesis, full, count)
db.Close()
}
}
@@ -294,7 +298,8 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
- makeChainForBench(db, full, count)
+ genesis := &Genesis{Config: params.AllEthashProtocolChanges}
+ makeChainForBench(db, genesis, full, count)
db.Close()
cacheConfig := *defaultCacheConfig
cacheConfig.TrieDirtyDisabled = true
@@ -307,7 +312,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
- chain, err := NewBlockChain(db, &cacheConfig, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if err != nil {
b.Fatalf("error creating chain: %v", err)
}
diff --git a/core/block_validator.go b/core/block_validator.go
index deec2d3b27..ce4b95f6c4 100644
--- a/core/block_validator.go
+++ b/core/block_validator.go
@@ -110,12 +110,20 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
}
// Blob transactions may be present after the Cancun fork.
var blobs int
- for _, tx := range block.Transactions() {
+ for i, tx := range block.Transactions() {
// Count the number of blobs to validate against the header's blobGasUsed
blobs += len(tx.BlobHashes())
+
+ // If the tx is a blob tx, it must NOT have a sidecar attached to be valid in a block.
+ if tx.BlobTxSidecar() != nil {
+ return fmt.Errorf("unexpected blob sidecar in transaction at index %d", i)
+ }
+
// The individual checks for blob validity (version-check + not empty)
- // happens in the state_transition check.
+ // happens in StateTransition.
}
+
+ // Check blob gas usage.
if header.BlobGasUsed != nil {
if want := *header.BlobGasUsed / params.BlobTxBlobGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated
return fmt.Errorf("blob gas used mismatch (header %v, calculated %v)", *header.BlobGasUsed, blobs*params.BlobTxBlobGasPerBlob)
diff --git a/core/blockchain.go b/core/blockchain.go
index 8ecf8bd3bf..839ef17726 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -71,6 +71,8 @@ var (
justifiedBlockGauge = metrics.NewRegisteredGauge("chain/head/justified", nil)
finalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
+ chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
+
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
@@ -212,6 +214,14 @@ func DefaultCacheConfigWithScheme(scheme string) *CacheConfig {
type BlockChainOption func(*BlockChain) (*BlockChain, error)
+// txLookup is wrapper over transaction lookup along with the corresponding
+// transaction object.
+
+type txLookup struct {
+ lookup *rawdb.LegacyTxLookupEntry
+ transaction *types.Transaction
+}
+
// BlockChain represents the canonical chain given a database with a genesis
// block. The Blockchain manages chain imports, reverts, chain reorganisations.
//
@@ -239,14 +249,8 @@ type BlockChain struct {
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
triedb *trie.Database // The database handler for maintaining trie nodes.
stateCache state.Database // State database to reuse between imports (contains state cache)
-
- // txLookupLimit is the maximum number of blocks from head whose tx indices
- // are reserved:
- // * 0: means no limit and regenerate any missing indexes
- // * N: means N block limit [HEAD-N+1, HEAD] and delete extra indexes
- // * nil: disable tx reindexer/deleter, but still index new blocks
- txLookupLimit uint64
triesInMemory uint64
+ txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
hc *HeaderChain
rmLogsFeed event.Feed
@@ -272,7 +276,7 @@ type BlockChain struct {
bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue]
receiptsCache *lru.Cache[common.Hash, []*types.Receipt]
blockCache *lru.Cache[common.Hash, *types.Block]
- txLookupCache *lru.Cache[common.Hash, *rawdb.LegacyTxLookupEntry]
+ txLookupCache *lru.Cache[common.Hash, txLookup]
// future blocks are blocks added for later processing
futureBlocks *lru.Cache[common.Hash, *types.Block]
@@ -286,10 +290,10 @@ type BlockChain struct {
diffQueueBuffer chan *types.DiffLayer
diffLayerFreezerBlockLimit uint64
- wg sync.WaitGroup //
- quit chan struct{} // shutdown signal, closed in Stop.
- stopping atomic.Bool // false if chain is running, true when stopped
- procInterrupt atomic.Bool // interrupt signaler for block processing
+ wg sync.WaitGroup
+ quit chan struct{} // shutdown signal, closed in Stop.
+ stopping atomic.Bool // false if chain is running, true when stopped
+ procInterrupt atomic.Bool // interrupt signaler for block processing
engine consensus.Engine
prefetcher Prefetcher
@@ -355,7 +359,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit),
receiptsCache: lru.NewCache[common.Hash, []*types.Receipt](receiptsCacheLimit),
blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit),
- txLookupCache: lru.NewCache[common.Hash, *rawdb.LegacyTxLookupEntry](txLookupCacheLimit),
+ txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit),
futureBlocks: lru.NewCache[common.Hash, *types.Block](maxFutureBlocks),
badBlockCache: lru.NewCache[common.Hash, time.Time](maxBadBlockLimit),
diffLayerCache: diffLayerCache,
@@ -386,6 +390,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bc.currentBlock.Store(nil)
bc.currentSnapBlock.Store(nil)
+ // Update chain info data metrics
+ chainInfoGauge.Update(metrics.GaugeInfoValue{"chain_id": bc.chainConfig.ChainID.String()})
+
// If Geth is initialized with an external ancient store, re-initialize the
// missing chain indexes and chain flags. This procedure can survive crash
// and can be resumed in next restart since chain flags are updated in last step.
@@ -396,37 +403,47 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if err := bc.loadLastState(); err != nil {
return nil, err
}
- // Make sure the state associated with the block is available
+ // Make sure the state associated with the block is available, or log out
+ // if there is no available state, waiting for state sync.
head := bc.CurrentBlock()
- if !bc.stateCache.NoTries() && !bc.HasState(head.Root) {
- // Head state is missing, before the state recovery, find out the
- // disk layer point of snapshot(if it's enabled). Make sure the
- // rewound point is lower than disk layer.
- var diskRoot common.Hash
- if bc.cacheConfig.SnapshotLimit > 0 {
- diskRoot = rawdb.ReadSnapshotRoot(bc.db)
- }
- if bc.triedb.Scheme() == rawdb.PathScheme {
- recoverable, _ := bc.triedb.Recoverable(diskRoot)
- if !bc.HasState(diskRoot) && !recoverable {
- diskRoot = bc.triedb.Head()
+ if !bc.HasState(head.Root) {
+ if head.Number.Uint64() == 0 {
+ // The genesis state is missing, which is only possible in the path-based
+ // scheme. This situation occurs when the initial state sync is not finished
+ // yet, or the chain head is rewound below the pivot point. In both scenarios,
+ // there is no possible recovery approach except for rerunning a snap sync.
+ // Do nothing here until the state syncer picks it up.
+ log.Info("Genesis state is missing, wait state sync")
+ } else {
+ // Head state is missing, before the state recovery, find out the
+ // disk layer point of snapshot(if it's enabled). Make sure the
+ // rewound point is lower than disk layer.
+ var diskRoot common.Hash
+ if bc.cacheConfig.SnapshotLimit > 0 {
+ diskRoot = rawdb.ReadSnapshotRoot(bc.db)
+ }
+ if bc.triedb.Scheme() == rawdb.PathScheme {
+ recoverable, _ := bc.triedb.Recoverable(diskRoot)
+ if !bc.HasState(diskRoot) && !recoverable {
+ diskRoot = bc.triedb.Head()
+ }
}
- }
- if diskRoot != (common.Hash{}) {
- log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "diskRoot", diskRoot)
+ if diskRoot != (common.Hash{}) {
+ log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "diskRoot", diskRoot)
- snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true)
- if err != nil {
- return nil, err
- }
- // Chain rewound, persist old snapshot number to indicate recovery procedure
- if snapDisk != 0 {
- rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk)
- }
- } else {
- log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash())
- if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil {
- return nil, err
+ snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true)
+ if err != nil {
+ return nil, err
+ }
+ // Chain rewound, persist old snapshot number to indicate recovery procedure
+ if snapDisk != 0 {
+ rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk)
+ }
+ } else {
+ log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash())
+ if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil {
+ return nil, err
+ }
}
}
}
@@ -505,7 +522,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
NoBuild: bc.cacheConfig.SnapshotNoBuild,
AsyncBuild: !bc.cacheConfig.SnapshotWait,
}
- bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root, int(bc.cacheConfig.TriesInMemory), bc.stateCache.NoTries())
+ bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root, int(bc.cacheConfig.TriesInMemory), bc.NoTries())
}
// do options before start any routine
for _, option := range options {
@@ -544,12 +561,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
}
- // Start tx indexer/unindexer if required.
+ // Start tx indexer if it's enabled.
if txLookupLimit != nil {
- bc.txLookupLimit = *txLookupLimit
-
- bc.wg.Add(1)
- go bc.maintainTxIndex()
+ bc.txIndexer = newTxIndexer(*txLookupLimit, bc)
}
return bc, nil
}
@@ -559,6 +573,10 @@ func (bc *BlockChain) GetVMConfig() *vm.Config {
return &bc.vmConfig
}
+func (bc *BlockChain) NoTries() bool {
+ return bc.stateCache.NoTries()
+}
+
func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts, block *types.Block) {
// TODO, This is a hot fix for the block hash of logs is `0x0000000000000000000000000000000000000000000000000000000000000000` for system tx
// Please check details in https://github.com/bnb-chain/bsc/issues/443
@@ -576,8 +594,15 @@ func (bc *BlockChain) cacheReceipts(hash common.Hash, receipts types.Receipts, b
log.Warn("transaction and receipt count mismatch")
return
}
+ blockBaseFee := block.BaseFee()
+ if blockBaseFee == nil {
+ blockBaseFee = big.NewInt(0)
+ }
for i, receipt := range receipts {
- receipt.EffectiveGasPrice = txs[i].EffectiveGasTipValue(block.BaseFee()) // basefee is supposed to be nil or zero
+ receipt.EffectiveGasPrice = big.NewInt(0).Add(blockBaseFee, txs[i].EffectiveGasTipValue(blockBaseFee))
+ if receipt.Logs == nil {
+ receipt.Logs = []*types.Log{}
+ }
}
bc.receiptsCache.Add(hash, receipts)
@@ -745,7 +770,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
header := bc.CurrentBlock()
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
if block == nil {
- // This should never happen. In practice, previsouly currentBlock
+ // This should never happen. In practice, previously currentBlock
// contained the entire block whereas now only a "marker", so there
// is an ever so slight chance for a race we should handle.
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
@@ -767,7 +792,7 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
header := bc.CurrentBlock()
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
if block == nil {
- // This should never happen. In practice, previsouly currentBlock
+ // This should never happen. In practice, previously currentBlock
// contained the entire block whereas now only a "marker", so there
// is an ever so slight chance for a race we should handle.
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
@@ -823,26 +848,6 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
pivot := rawdb.ReadLastPivotNumber(bc.db)
frozen, _ := bc.db.Ancients()
- // resetState resets the persistent state to genesis if it's not available.
- resetState := func() {
- log.Info("Reset to block with genesis state", "number", bc.genesisBlock.NumberU64(), "hash", bc.genesisBlock.Hash())
- // Short circuit if the genesis state is already present.
- if bc.HasState(bc.genesisBlock.Root()) {
- return
- }
- // Reset the state database to empty for committing genesis state.
- // Note, it should only happen in path-based scheme and Reset function
- // is also only call-able in this mode.
- if bc.triedb.Scheme() == rawdb.PathScheme {
- if err := bc.triedb.Reset(types.EmptyRootHash); err != nil {
- log.Crit("Failed to clean state", "err", err) // Shouldn't happen
- }
- }
- // Write genesis state into database.
- if err := CommitGenesisState(bc.db, bc.triedb, bc.genesisBlock.Hash()); err != nil {
- log.Crit("Failed to commit genesis state", "err", err)
- }
- }
updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (*types.Header, bool) {
// Rewind the blockchain, ensuring we don't end up with a stateless head
// block. Note, depth equality is permitted to allow using SetHead as a
@@ -852,11 +857,9 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
if newHeadBlock == nil {
log.Error("Gap in the chain, rewinding to genesis", "number", header.Number, "hash", header.Hash())
newHeadBlock = bc.genesisBlock
- resetState()
} else {
- // Block exists, keep rewinding until we find one with state,
- // keeping rewinding until we exceed the optional threshold
- // root hash
+ // Block exists. Keep rewinding until either we find one with state
+ // or until we exceed the optional threshold root hash
beyondRoot := (root == common.Hash{}) // Flag whether we're beyond the requested root (no root, always true)
for {
@@ -880,14 +883,13 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
}
}
if beyondRoot || newHeadBlock.NumberU64() == 0 {
- if newHeadBlock.NumberU64() == 0 {
- resetState()
- } else if !bc.HasState(newHeadBlock.Root()) {
+ if !bc.HasState(newHeadBlock.Root()) && bc.stateRecoverable(newHeadBlock.Root()) {
// Rewind to a block with recoverable state. If the state is
// missing, run the state recovery here.
if err := bc.triedb.Recover(newHeadBlock.Root()); err != nil {
log.Crit("Failed to rollback state", "err", err) // Shouldn't happen
}
+ log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
}
log.Info("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
break
@@ -906,6 +908,15 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
headBlockGauge.Update(int64(newHeadBlock.NumberU64()))
justifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(newHeadBlock.Header())))
finalizedBlockGauge.Update(int64(bc.getFinalizedNumber(newHeadBlock.Header())))
+
+ // The head state is missing, which is only possible in the path-based
+ // scheme. This situation occurs when the chain head is rewound below
+ // the pivot point. In this scenario, there is no possible recovery
+ // approach except for rerunning a snap sync. Do nothing here until the
+ // state syncer picks it up.
+ if !bc.HasState(newHeadBlock.Root()) {
+ log.Info("Chain is stateless, wait state sync", "number", newHeadBlock.Number(), "hash", newHeadBlock.Hash())
+ }
}
// Rewind the snap block in a simpleton way to the target head
if currentSnapBlock := bc.CurrentSnapBlock(); currentSnapBlock != nil && header.Number.Uint64() < currentSnapBlock.Number.Uint64() {
@@ -996,7 +1007,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
// Reset the trie database with the fresh snap synced state.
root := block.Root()
if bc.triedb.Scheme() == rawdb.PathScheme {
- if err := bc.triedb.Reset(root); err != nil {
+ if err := bc.triedb.Enable(root); err != nil {
return err
}
}
@@ -1139,7 +1150,10 @@ func (bc *BlockChain) stopWithoutSaving() {
if !bc.stopping.CompareAndSwap(false, true) {
return
}
-
+ // Signal shutdown tx indexer.
+ if bc.txIndexer != nil {
+ bc.txIndexer.close()
+ }
// Unsubscribe all subscriptions registered from blockchain.
bc.scope.Close()
@@ -1162,13 +1176,14 @@ func (bc *BlockChain) stopWithoutSaving() {
func (bc *BlockChain) Stop() {
bc.stopWithoutSaving()
- // Ensure that the entirety of the state snapshot is journalled to disk.
+ // Ensure that the entirety of the state snapshot is journaled to disk.
var snapBase common.Hash
if bc.snaps != nil {
var err error
if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil {
log.Error("Failed to journal state snapshot", "err", err)
}
+ bc.snaps.Release()
}
if bc.triedb.Scheme() == rawdb.PathScheme {
// Ensure that the in-memory trie nodes are journaled to disk properly.
@@ -1198,18 +1213,10 @@ func (bc *BlockChain) Stop() {
}
}
}
- if snapBase != (common.Hash{}) {
- log.Info("Writing snapshot state to disk", "root", snapBase)
- if err := triedb.Commit(snapBase, true); err != nil {
- log.Error("Failed to commit recent state trie", "err", err)
- } else {
- rawdb.WriteSafePointBlockNumber(bc.db, bc.CurrentBlock().Number.Uint64())
- }
- }
if snapBase != (common.Hash{}) {
log.Info("Writing snapshot state to disk", "root", snapBase)
- if err := bc.triedb.Commit(snapBase, true); err != nil {
+ if err := triedb.Commit(snapBase, true); err != nil {
log.Error("Failed to commit recent state trie", "err", err)
} else {
rawdb.WriteSafePointBlockNumber(bc.db, bc.CurrentBlock().Number.Uint64())
@@ -1282,19 +1289,30 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
ancientReceipts, liveReceipts []types.Receipts
)
// Do a sanity check that the provided chain is actually ordered and linked
- for i := 0; i < len(blockChain); i++ {
+ for i, block := range blockChain {
if i != 0 {
- if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() {
- log.Error("Non contiguous receipt insert", "number", blockChain[i].Number(), "hash", blockChain[i].Hash(), "parent", blockChain[i].ParentHash(),
- "prevnumber", blockChain[i-1].Number(), "prevhash", blockChain[i-1].Hash())
- return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, blockChain[i-1].NumberU64(),
- blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4])
- }
- }
- if blockChain[i].NumberU64() <= ancientLimit {
- ancientBlocks, ancientReceipts = append(ancientBlocks, blockChain[i]), append(ancientReceipts, receiptChain[i])
+ prev := blockChain[i-1]
+ if block.NumberU64() != prev.NumberU64()+1 || block.ParentHash() != prev.Hash() {
+ log.Error("Non contiguous receipt insert",
+ "number", block.Number(), "hash", block.Hash(), "parent", block.ParentHash(),
+ "prevnumber", prev.Number(), "prevhash", prev.Hash())
+ return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])",
+ i-1, prev.NumberU64(), prev.Hash().Bytes()[:4],
+ i, block.NumberU64(), block.Hash().Bytes()[:4], block.ParentHash().Bytes()[:4])
+ }
+ }
+ if block.NumberU64() <= ancientLimit {
+ ancientBlocks, ancientReceipts = append(ancientBlocks, block), append(ancientReceipts, receiptChain[i])
} else {
- liveBlocks, liveReceipts = append(liveBlocks, blockChain[i]), append(liveReceipts, receiptChain[i])
+ liveBlocks, liveReceipts = append(liveBlocks, block), append(liveReceipts, receiptChain[i])
+ }
+
+ // Here we also validate that blob transactions in the block do not contain a sidecar.
+ // While the sidecar does not affect the block hash / tx hash, sending blobs within a block is not allowed.
+ for txIndex, tx := range block.Transactions() {
+ if tx.Type() == types.BlobTxType && tx.BlobTxSidecar() != nil {
+ return 0, fmt.Errorf("block #%d contains unexpected blob sidecar in tx at index %d", block.NumberU64(), txIndex)
+ }
}
}
@@ -1339,14 +1357,13 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// Ensure genesis is in ancients.
if first.NumberU64() == 1 {
if frozen, _ := bc.db.Ancients(); frozen == 0 {
- b := bc.genesisBlock
td := bc.genesisBlock.Difficulty()
- writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{b}, []types.Receipts{nil}, td)
- size += writeSize
+ writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, td)
if err != nil {
log.Error("Error writing genesis to ancients", "err", err)
return 0, err
}
+ size += writeSize
log.Info("Wrote genesis to ancients")
}
}
@@ -1360,44 +1377,11 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// Write all chain data to ancients.
td := bc.GetTd(first.Hash(), first.NumberU64())
writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain, td)
- size += writeSize
if err != nil {
log.Error("Error importing chain data to ancients", "err", err)
return 0, err
}
-
- // Write tx indices if any condition is satisfied:
- // * If user requires to reserve all tx indices(txlookuplimit=0)
- // * If all ancient tx indices are required to be reserved(txlookuplimit is even higher than ancientlimit)
- // * If block number is large enough to be regarded as a recent block
- // It means blocks below the ancientLimit-txlookupLimit won't be indexed.
- //
- // But if the `TxIndexTail` is not nil, e.g. Geth is initialized with
- // an external ancient database, during the setup, blockchain will start
- // a background routine to re-indexed all indices in [ancients - txlookupLimit, ancients)
- // range. In this case, all tx indices of newly imported blocks should be
- // generated.
- var batch = bc.db.NewBatch()
- for i, block := range blockChain {
- if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit || block.NumberU64() >= ancientLimit-bc.txLookupLimit {
- rawdb.WriteTxLookupEntriesByBlock(batch, block)
- } else if rawdb.ReadTxIndexTail(bc.db) != nil {
- rawdb.WriteTxLookupEntriesByBlock(batch, block)
- }
- stats.processed++
-
- if batch.ValueSize() > ethdb.IdealBatchSize || i == len(blockChain)-1 {
- size += int64(batch.ValueSize())
- if err = batch.Write(); err != nil {
- snapBlock := bc.CurrentSnapBlock().Number.Uint64()
- if _, err := bc.db.TruncateHead(snapBlock + 1); err != nil {
- log.Error("Can't truncate ancient store after failed insert", "err", err)
- }
- return 0, err
- }
- batch.Reset()
- }
- }
+ size += writeSize
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
if err := bc.db.Sync(); err != nil {
@@ -1415,8 +1399,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
}
// Delete block data from the main database.
- batch.Reset()
- canonHashes := make(map[common.Hash]struct{})
+ var (
+ batch = bc.db.NewBatch()
+ canonHashes = make(map[common.Hash]struct{})
+ )
for _, block := range blockChain {
canonHashes[block.Hash()] = struct{}{}
if block.NumberU64() == 0 {
@@ -1434,13 +1420,16 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
if err := batch.Write(); err != nil {
return 0, err
}
+ stats.processed += int32(len(blockChain))
return 0, nil
}
// writeLive writes blockchain and corresponding receipt chain into active store.
writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
- skipPresenceCheck := false
- batch := bc.db.NewBatch()
+ var (
+ skipPresenceCheck = false
+ batch = bc.db.NewBatch()
+ )
for i, block := range blockChain {
// Short circuit insertion if shutting down or processing failed
if bc.insertStopped() {
@@ -1465,11 +1454,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// Write all the data out into the database
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
- rawdb.WriteTxLookupEntriesByBlock(batch, block) // Always write tx indices for live blocks, we assume they are needed
// Write everything belongs to the blocks into the database. So that
- // we can ensure all components of body is completed(body, receipts,
- // tx indexes)
+ // we can ensure all components of body is completed(body, receipts)
+ // except transaction indexes(will be created once sync is finished).
if batch.ValueSize() >= ethdb.IdealBatchSize {
if err := batch.Write(); err != nil {
return 0, err
@@ -1501,19 +1489,6 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
return n, err
}
}
- // Write the tx index tail (block number from where we index) before write any live blocks
- if len(liveBlocks) > 0 && liveBlocks[0].NumberU64() == ancientLimit+1 {
- // The tx index tail can only be one of the following two options:
- // * 0: all ancient blocks have been indexed
- // * ancient-limit: the indices of blocks before ancient-limit are ignored
- if tail := rawdb.ReadTxIndexTail(bc.db); tail == nil {
- if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit {
- rawdb.WriteTxIndexTail(bc.db, 0)
- } else {
- rawdb.WriteTxIndexTail(bc.db, ancientLimit-bc.txLookupLimit)
- }
- }
- }
if len(liveBlocks) > 0 {
if n, err := writeLive(liveBlocks, liveReceipts); err != nil {
if err == errInsertionInterrupted {
@@ -1522,13 +1497,14 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
return n, err
}
}
-
- head := blockChain[len(blockChain)-1]
- context := []interface{}{
- "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
- "number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(int64(head.Time()), 0)),
- "size", common.StorageSize(size),
- }
+ var (
+ head = blockChain[len(blockChain)-1]
+ context = []interface{}{
+ "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
+ "number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(int64(head.Time()), 0)),
+ "size", common.StorageSize(size),
+ }
+ )
if stats.ignored > 0 {
context = append(context, []interface{}{"ignored", stats.ignored}...)
}
@@ -1544,7 +1520,6 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
if bc.insertStopped() {
return errInsertionInterrupted
}
-
batch := bc.db.NewBatch()
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td)
rawdb.WriteBlock(batch, block)
@@ -1610,74 +1585,71 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
triedb := bc.stateCache.TrieDB()
// If we're running an archive node, always flush
if bc.cacheConfig.TrieDirtyDisabled {
- err := triedb.Commit(block.Root(), false)
- if err != nil {
- return err
- }
- } else {
- // Full but not archive node, do proper garbage collection
- triedb.Reference(block.Root(), common.Hash{}) // metadata reference to keep trie alive
- bc.triegc.Push(block.Root(), -int64(block.NumberU64()))
-
- if current := block.NumberU64(); current > bc.triesInMemory {
- // If we exceeded our memory allowance, flush matured singleton nodes to disk
- var (
- _, nodes, _, imgs = triedb.Size()
- limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
- )
- if nodes > limit || imgs > 4*1024*1024 {
- triedb.Cap(limit - ethdb.IdealBatchSize)
- }
- // Find the next state trie we need to commit
- chosen := current - bc.triesInMemory
-
- flushInterval := time.Duration(bc.flushInterval.Load())
+ return triedb.Commit(block.Root(), false)
+ }
+ // Full but not archive node, do proper garbage collection
+ triedb.Reference(block.Root(), common.Hash{}) // metadata reference to keep trie alive
+ bc.triegc.Push(block.Root(), -int64(block.NumberU64()))
- // If we exceeded out time allowance, flush an entire trie to disk
- if bc.gcproc > flushInterval {
- canWrite := true
- if posa, ok := bc.engine.(consensus.PoSA); ok {
- if !posa.EnoughDistance(bc, block.Header()) {
- canWrite = false
- }
- }
- if canWrite {
- // If the header is missing (canonical chain behind), we're reorging a low
- // diff sidechain. Suspend committing until this operation is completed.
- header := bc.GetHeaderByNumber(chosen)
- if header == nil {
- log.Warn("Reorg in progress, trie commit postponed", "number", chosen)
- } else {
- // If we're exceeding limits but haven't reached a large enough memory gap,
- // warn the user that the system is becoming unstable.
- if chosen < bc.lastWrite+bc.triesInMemory && bc.gcproc >= 2*flushInterval {
- log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", flushInterval, "optimum", float64(chosen-bc.lastWrite)/float64(bc.triesInMemory))
- }
- // Flush an entire trie and restart the counters
- triedb.Commit(header.Root, true)
- rawdb.WriteSafePointBlockNumber(bc.db, chosen)
- bc.lastWrite = chosen
- bc.gcproc = 0
- }
- }
+ // Flush limits are not considered for the first TriesInMemory blocks.
+ current := block.NumberU64()
+ if current <= TriesInMemory {
+ return nil
+ }
+ // If we exceeded our memory allowance, flush matured singleton nodes to disk
+ var (
+ _, nodes, _, imgs = triedb.Size()
+ limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
+ )
+ if nodes > limit || imgs > 4*1024*1024 {
+ triedb.Cap(limit - ethdb.IdealBatchSize)
+ }
+ // Find the next state trie we need to commit
+ chosen := current - bc.triesInMemory
+ flushInterval := time.Duration(bc.flushInterval.Load())
+ // If we exceeded out time allowance, flush an entire trie to disk
+ if bc.gcproc > flushInterval {
+ canWrite := true
+ if posa, ok := bc.engine.(consensus.PoSA); ok {
+ if !posa.EnoughDistance(bc, block.Header()) {
+ canWrite = false
}
- // Garbage collect anything below our required write retention
- wg2 := sync.WaitGroup{}
- for !bc.triegc.Empty() {
- root, number := bc.triegc.Pop()
- if uint64(-number) > chosen {
- bc.triegc.Push(root, number)
- break
+ }
+ if canWrite {
+ // If the header is missing (canonical chain behind), we're reorging a low
+ // diff sidechain. Suspend committing until this operation is completed.
+ header := bc.GetHeaderByNumber(chosen)
+ if header == nil {
+ log.Warn("Reorg in progress, trie commit postponed", "number", chosen)
+ } else {
+ // If we're exceeding limits but haven't reached a large enough memory gap,
+ // warn the user that the system is becoming unstable.
+ if chosen < bc.lastWrite+bc.triesInMemory && bc.gcproc >= 2*flushInterval {
+ log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", flushInterval, "optimum", float64(chosen-bc.lastWrite)/float64(bc.triesInMemory))
}
- wg2.Add(1)
- go func() {
- triedb.Dereference(root)
- wg2.Done()
- }()
+ // Flush an entire trie and restart the counters
+ triedb.Commit(header.Root, true)
+ rawdb.WriteSafePointBlockNumber(bc.db, chosen)
+ bc.lastWrite = chosen
+ bc.gcproc = 0
}
- wg2.Wait()
}
}
+ // Garbage collect anything below our required write retention
+ wg2 := sync.WaitGroup{}
+ for !bc.triegc.Empty() {
+ root, number := bc.triegc.Pop()
+ if uint64(-number) > chosen {
+ bc.triegc.Push(root, number)
+ break
+ }
+ wg2.Add(1)
+ go func() {
+ triedb.Dereference(root)
+ wg2.Done()
+ }()
+ }
+ wg2.Wait()
return nil
}
// Commit all cached state changes into underlying memory database.
@@ -2109,8 +2081,12 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
stats.processed++
stats.usedGas += usedGas
+ var snapDiffItems, snapBufItems common.StorageSize
+ if bc.snaps != nil {
+ snapDiffItems, snapBufItems, _ = bc.snaps.Size()
+ }
trieDiffNodes, trieBufNodes, trieImmutableBufNodes, _ := bc.triedb.Size()
- stats.report(chain, it.index, trieDiffNodes, trieBufNodes, trieImmutableBufNodes, setHead)
+ stats.report(chain, it.index, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, trieImmutableBufNodes, setHead)
if !setHead {
// After merge we expect few side chains. Simply count
@@ -2807,88 +2783,6 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
return false
}
-// indexBlocks reindexes or unindexes transactions depending on user configuration
-func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) {
- defer func() { close(done) }()
-
- // The tail flag is not existent, it means the node is just initialized
- // and all blocks(may from ancient store) are not indexed yet.
- if tail == nil {
- from := uint64(0)
- if bc.txLookupLimit != 0 && head >= bc.txLookupLimit {
- from = head - bc.txLookupLimit + 1
- }
- rawdb.IndexTransactions(bc.db, from, head+1, bc.quit)
- return
- }
- // The tail flag is existent, but the whole chain is required to be indexed.
- if bc.txLookupLimit == 0 || head < bc.txLookupLimit {
- if *tail > 0 {
- // It can happen when chain is rewound to a historical point which
- // is even lower than the indexes tail, recap the indexing target
- // to new head to avoid reading non-existent block bodies.
- end := *tail
- if end > head+1 {
- end = head + 1
- }
- rawdb.IndexTransactions(bc.db, 0, end, bc.quit)
- }
- return
- }
- // Update the transaction index to the new chain state
- if head-bc.txLookupLimit+1 < *tail {
- // Reindex a part of missing indices and rewind index tail to HEAD-limit
- rawdb.IndexTransactions(bc.db, head-bc.txLookupLimit+1, *tail, bc.quit)
- } else {
- // Unindex a part of stale indices and forward index tail to HEAD-limit
- rawdb.UnindexTransactions(bc.db, *tail, head-bc.txLookupLimit+1, bc.quit)
- }
-}
-
-// maintainTxIndex is responsible for the construction and deletion of the
-// transaction index.
-//
-// User can use flag `txlookuplimit` to specify a "recentness" block, below
-// which ancient tx indices get deleted. If `txlookuplimit` is 0, it means
-// all tx indices will be reserved.
-//
-// The user can adjust the txlookuplimit value for each launch after sync,
-// Geth will automatically construct the missing indices or delete the extra
-// indices.
-func (bc *BlockChain) maintainTxIndex() {
- defer bc.wg.Done()
-
- // Listening to chain events and manipulate the transaction indexes.
- var (
- done chan struct{} // Non-nil if background unindexing or reindexing routine is active.
- headCh = make(chan ChainHeadEvent, 1) // Buffered to avoid locking up the event feed
- )
- sub := bc.SubscribeChainHeadEvent(headCh)
- if sub == nil {
- return
- }
- defer sub.Unsubscribe()
- log.Info("Initialized transaction indexer", "limit", bc.TxLookupLimit())
-
- for {
- select {
- case head := <-headCh:
- if done == nil {
- done = make(chan struct{})
- go bc.indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.Block.NumberU64(), done)
- }
- case <-done:
- done = nil
- case <-bc.quit:
- if done != nil {
- log.Info("Waiting background transaction indexer to exit")
- <-done
- }
- return
- }
- }
-}
-
func (bc *BlockChain) isCachedBadBlock(block *types.Block) bool {
if timeAt, exist := bc.badBlockCache.Get(block.Hash()); exist {
if time.Since(timeAt) >= badBlockCacheExpire {
@@ -3112,7 +3006,7 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
bc.flushInterval.Store(int64(interval))
}
-// GetTrieFlushInterval gets the in-memroy tries flush interval
+// GetTrieFlushInterval gets the in-memory tries flush interval
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
return time.Duration(bc.flushInterval.Load())
}
diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go
index 520feaf277..fafe684aa1 100644
--- a/core/blockchain_insert.go
+++ b/core/blockchain_insert.go
@@ -39,7 +39,7 @@ const statsReportLimit = 8 * time.Second
// report prints statistics if some number of blocks have been processed
// or more than a few seconds have passed since the last message.
-func (st *insertStats) report(chain []*types.Block, index int, trieDiffNodes, trieBufNodes, trieImmutableBufNodes common.StorageSize, setHead bool) {
+func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, trieImmutableBufNodes common.StorageSize, setHead bool) {
// Fetch the timings for the batch
var (
now = mclock.Now()
@@ -63,13 +63,17 @@ func (st *insertStats) report(chain []*types.Block, index int, trieDiffNodes, tr
if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute {
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
}
+ if snapDiffItems != 0 || snapBufItems != 0 { // snapshots enabled
+ context = append(context, []interface{}{"snapdiffs", snapDiffItems}...)
+ if snapBufItems != 0 { // future snapshot refactor
+ context = append(context, []interface{}{"snapdirty", snapBufItems}...)
+ }
+ }
if trieDiffNodes != 0 { // pathdb
context = append(context, []interface{}{"triediffs", trieDiffNodes}...)
- context = append(context, []interface{}{"triedirty", trieBufNodes}...)
- context = append(context, []interface{}{"trieimutabledirty", trieImmutableBufNodes}...)
- } else {
- context = append(context, []interface{}{"triedirty", trieBufNodes}...)
}
+ context = append(context, []interface{}{"triedirty", trieBufNodes}...)
+ context = append(context, []interface{}{"trieimutabledirty", trieImmutableBufNodes}...)
if st.queued > 0 {
context = append(context, []interface{}{"queued", st.queued}...)
diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go
index 8123557861..b3cc434193 100644
--- a/core/blockchain_reader.go
+++ b/core/blockchain_reader.go
@@ -17,6 +17,7 @@
package core
import (
+ "errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -271,20 +272,46 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max
return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical)
}
-// GetTransactionLookup retrieves the lookup associate with the given transaction
-// hash from the cache or database.
-func (bc *BlockChain) GetTransactionLookup(hash common.Hash) *rawdb.LegacyTxLookupEntry {
+// GetTransactionLookup retrieves the lookup along with the transaction
+// itself associate with the given transaction hash.
+//
+// An error will be returned if the transaction is not found, and background
+// indexing for transactions is still in progress. The transaction might be
+// reachable shortly once it's indexed.
+//
+// A null will be returned in the transaction is not found and background
+// transaction indexing is already finished. The transaction is not existent
+// from the node's perspective.
+func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction, error) {
// Short circuit if the txlookup already in the cache, retrieve otherwise
- if lookup, exist := bc.txLookupCache.Get(hash); exist {
- return lookup
+ if item, exist := bc.txLookupCache.Get(hash); exist {
+ return item.lookup, item.transaction, nil
}
tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash)
if tx == nil {
- return nil
+ progress, err := bc.TxIndexProgress()
+ if err != nil {
+ return nil, nil, nil
+ }
+ // The transaction indexing is not finished yet, returning an
+ // error to explicitly indicate it.
+ if !progress.Done() {
+ return nil, nil, errors.New("transaction indexing still in progress")
+ }
+ // The transaction is already indexed, the transaction is either
+ // not existent or not in the range of index, returning null.
+ return nil, nil, nil
+ }
+ lookup := &rawdb.LegacyTxLookupEntry{
+ BlockHash: blockHash,
+ BlockIndex: blockNumber,
+ Index: txIndex,
}
- lookup := &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex}
- bc.txLookupCache.Add(hash, lookup)
- return lookup
+ bc.txLookupCache.Add(hash, txLookup{
+ lookup: lookup,
+ transaction: tx,
+ })
+ return lookup, tx, nil
}
// GetTd retrieves a block's total difficulty in the canonical chain from the
@@ -295,7 +322,7 @@ func (bc *BlockChain) GetTd(hash common.Hash, number uint64) *big.Int {
// HasState checks if state trie is fully present in the database or not.
func (bc *BlockChain) HasState(hash common.Hash) bool {
- if bc.stateCache.NoTries() {
+ if bc.NoTries() {
return bc.snaps != nil && bc.snaps.Snapshot(hash) != nil
}
if bc.pipeCommit && bc.snaps != nil {
@@ -391,16 +418,17 @@ func (bc *BlockChain) Genesis() *types.Block {
return bc.genesisBlock
}
-// SetTxLookupLimit is responsible for updating the txlookup limit to the
-// original one stored in db if the new mismatches with the old one.
-func (bc *BlockChain) SetTxLookupLimit(limit uint64) {
- bc.txLookupLimit = limit
+// GenesisHeader retrieves the chain's genesis block header.
+func (bc *BlockChain) GenesisHeader() *types.Header {
+ return bc.genesisBlock.Header()
}
-// TxLookupLimit retrieves the txlookup limit used by blockchain to prune
-// stale transaction indices.
-func (bc *BlockChain) TxLookupLimit() uint64 {
- return bc.txLookupLimit
+// TxIndexProgress returns the transaction indexing progress.
+func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
+ if bc.txIndexer == nil {
+ return TxIndexProgress{}, errors.New("tx indexer is not enabled")
+ }
+ return bc.txIndexer.txIndexProgress()
}
// TrieDB retrieves the low level trie database used for data storage.
diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go
index acef2e2d59..3cfcdafe4a 100644
--- a/core/blockchain_repair_test.go
+++ b/core/blockchain_repair_test.go
@@ -1767,6 +1767,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
db, err := rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: ancient,
+ Ephemeral: true,
})
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
@@ -1849,6 +1850,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
db, err = rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: ancient,
+ Ephemeral: true,
})
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
@@ -1970,6 +1972,7 @@ func testIssue23496(t *testing.T, scheme string) {
db, err = rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: ancient,
+ Ephemeral: true,
})
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go
index 72c1e56db2..83dd926504 100644
--- a/core/blockchain_sethead_test.go
+++ b/core/blockchain_sethead_test.go
@@ -1971,6 +1971,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
db, err := rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: ancient,
+ Ephemeral: true,
})
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go
index 14d0309988..b2dbe5cb2a 100644
--- a/core/blockchain_snapshot_test.go
+++ b/core/blockchain_snapshot_test.go
@@ -68,6 +68,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
db, err := rawdb.Open(rawdb.OpenOptions{
Directory: datadir,
AncientsDirectory: ancient,
+ Ephemeral: true,
})
if err != nil {
t.Fatalf("Failed to create persistent database: %v", err)
@@ -258,6 +259,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
newdb, err := rawdb.Open(rawdb.OpenOptions{
Directory: snaptest.datadir,
AncientsDirectory: snaptest.ancient,
+ Ephemeral: true,
})
if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err)
@@ -483,6 +485,7 @@ func TestNoCommitCrashWithNewSnapshot(t *testing.T) {
// Expected head fast block: C8
// Expected head block : G
// Expected snapshot disk : C4
+ // TODO
//for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
for _, scheme := range []string{rawdb.HashScheme} {
test := &crashSnapshotTest{
@@ -526,6 +529,7 @@ func TestLowCommitCrashWithNewSnapshot(t *testing.T) {
// Expected head fast block: C8
// Expected head block : C2
// Expected snapshot disk : C4
+ // TODO
//for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
for _, scheme := range []string{rawdb.HashScheme} {
test := &crashSnapshotTest{
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 6bf6d2d881..b337a47b78 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -40,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
// So we can deterministically seed different blockchains
@@ -52,10 +53,10 @@ var (
)
// newCanonical creates a chain database, and injects a deterministic canonical
-// chain. Depending on the full flag, if creates either a full block chain or a
+// chain. Depending on the full flag, it creates either a full block chain or a
// header only chain. The database and genesis specification for block generation
// are also returned in case more test blocks are needed later.
-func newCanonical(engine consensus.Engine, n int, full bool, pipeline bool) (ethdb.Database, *Genesis, *BlockChain, error) {
+func newCanonical(engine consensus.Engine, n int, full bool, scheme string, pipeline bool) (ethdb.Database, *Genesis, *BlockChain, error) {
var (
genesis = &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
@@ -68,7 +69,7 @@ func newCanonical(engine consensus.Engine, n int, full bool, pipeline bool) (eth
if pipeline {
ops = append(ops, EnablePipelineCommit)
}
- blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil, ops...)
+ blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil, ops...)
// Create and inject the requested chain
if n == 0 {
return rawdb.NewMemoryDatabase(), genesis, blockchain, nil
@@ -92,7 +93,7 @@ func newGwei(n int64) *big.Int {
// Test fork of length N starting from block i
func testInvalidStateRootBlockImport(t *testing.T, blockchain *BlockChain, i, n int, pipeline bool) {
// Copy old chain up to #i into a new db
- db, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, true, pipeline)
+ db, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, true, rawdb.HashScheme, pipeline)
if err != nil {
t.Fatal("could not make new canonical in testFork", err)
}
@@ -120,7 +121,7 @@ func testInvalidStateRootBlockImport(t *testing.T, blockchain *BlockChain, i, n
if latestBlock.Hash() != previousBlock.Hash() || latestBlock.Number.Uint64() != previousBlock.Number.Uint64() {
t.Fatalf("rewind do not take effect")
}
- db, _, blockchain3, err := newCanonical(ethash.NewFaker(), i, true, pipeline)
+ db, _, blockchain3, err := newCanonical(ethash.NewFaker(), i, true, rawdb.HashScheme, pipeline)
if err != nil {
t.Fatal("could not make new canonical in testFork", err)
}
@@ -134,9 +135,9 @@ func testInvalidStateRootBlockImport(t *testing.T, blockchain *BlockChain, i, n
}
// Test fork of length N starting from block i
-func testFork(t *testing.T, blockchain *BlockChain, i, n int, full, pipeline bool, comparator func(td1, td2 *big.Int)) {
+func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int), scheme string, pipeline bool) {
// Copy old chain up to #i into a new db
- genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, pipeline)
+ genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, scheme, pipeline)
if err != nil {
t.Fatal("could not make new canonical in testFork", err)
}
@@ -260,7 +261,7 @@ func TestBlockImportVerification(t *testing.T) {
length := 5
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, true, true)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, true, rawdb.HashScheme, true)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -269,9 +270,13 @@ func TestBlockImportVerification(t *testing.T) {
processor, _ = EnablePipelineCommit(processor)
testInvalidStateRootBlockImport(t, processor, length, 10, true)
}
-
func TestLastBlock(t *testing.T) {
- genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, false)
+ testLastBlock(t, rawdb.HashScheme)
+ testLastBlock(t, rawdb.PathScheme)
+}
+
+func testLastBlock(t *testing.T, scheme string) {
+ genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, scheme, false)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -288,9 +293,9 @@ func TestLastBlock(t *testing.T) {
// Test inserts the blocks/headers after the fork choice rule is changed.
// The chain is reorged to whatever specified.
-func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full bool) {
+func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full bool, scheme string) {
// Copy old chain up to #i into a new db
- genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, false)
+ genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, scheme, false)
if err != nil {
t.Fatal("could not make new canonical in testFork", err)
}
@@ -338,19 +343,21 @@ func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full b
// Tests that given a starting canonical chain of a given size, it can be extended
// with various length chains.
func TestExtendCanonicalHeaders(t *testing.T) {
- testExtendCanonical(t, false, false)
+ testExtendCanonical(t, false, rawdb.HashScheme, false)
+ testExtendCanonical(t, false, rawdb.PathScheme, false)
}
func TestExtendCanonicalBlocks(t *testing.T) {
- testExtendCanonical(t, true, false)
- testExtendCanonical(t, true, true)
+ testExtendCanonical(t, true, rawdb.HashScheme, false)
+ testExtendCanonical(t, true, rawdb.PathScheme, false)
+ testExtendCanonical(t, true, rawdb.HashScheme, true)
}
-func testExtendCanonical(t *testing.T, full, pipeline bool) {
+func testExtendCanonical(t *testing.T, full bool, scheme string, pipeline bool) {
length := 5
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -363,44 +370,54 @@ func testExtendCanonical(t *testing.T, full, pipeline bool) {
}
}
// Start fork from current height
- testFork(t, processor, length, 1, full, pipeline, better)
- testFork(t, processor, length, 2, full, pipeline, better)
- testFork(t, processor, length, 5, full, pipeline, better)
- testFork(t, processor, length, 10, full, pipeline, better)
+ testFork(t, processor, length, 1, full, better, scheme, pipeline)
+ testFork(t, processor, length, 2, full, better, scheme, pipeline)
+ testFork(t, processor, length, 5, full, better, scheme, pipeline)
+ testFork(t, processor, length, 10, full, better, scheme, pipeline)
}
// Tests that given a starting canonical chain of a given size, it can be extended
// with various length chains.
-func TestExtendCanonicalHeadersAfterMerge(t *testing.T) { testExtendCanonicalAfterMerge(t, false) }
-func TestExtendCanonicalBlocksAfterMerge(t *testing.T) { testExtendCanonicalAfterMerge(t, true) }
+func TestExtendCanonicalHeadersAfterMerge(t *testing.T) {
+ testExtendCanonicalAfterMerge(t, false, rawdb.HashScheme)
+ testExtendCanonicalAfterMerge(t, false, rawdb.PathScheme)
+}
+func TestExtendCanonicalBlocksAfterMerge(t *testing.T) {
+ testExtendCanonicalAfterMerge(t, true, rawdb.HashScheme)
+ testExtendCanonicalAfterMerge(t, true, rawdb.PathScheme)
+}
-func testExtendCanonicalAfterMerge(t *testing.T, full bool) {
+func testExtendCanonicalAfterMerge(t *testing.T, full bool, scheme string) {
length := 5
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, false)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme, false)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
defer processor.Stop()
- testInsertAfterMerge(t, processor, length, 1, full)
- testInsertAfterMerge(t, processor, length, 10, full)
+ testInsertAfterMerge(t, processor, length, 1, full, scheme)
+ testInsertAfterMerge(t, processor, length, 10, full, scheme)
}
// Tests that given a starting canonical chain of a given size, creating shorter
// forks do not take canonical ownership.
-func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false, false) }
+func TestShorterForkHeaders(t *testing.T) {
+ testShorterFork(t, false, rawdb.HashScheme, false)
+ testShorterFork(t, false, rawdb.PathScheme, false)
+}
func TestShorterForkBlocks(t *testing.T) {
- testShorterFork(t, true, false)
- testShorterFork(t, true, true)
+ testShorterFork(t, true, rawdb.HashScheme, false)
+ testShorterFork(t, true, rawdb.PathScheme, false)
+ testShorterFork(t, true, rawdb.HashScheme, true)
}
-func testShorterFork(t *testing.T, full, pipeline bool) {
+func testShorterFork(t *testing.T, full bool, scheme string, pipeline bool) {
length := 10
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -413,101 +430,119 @@ func testShorterFork(t *testing.T, full, pipeline bool) {
}
}
// Sum of numbers must be less than `length` for this to be a shorter fork
- testFork(t, processor, 0, 3, full, pipeline, worse)
- testFork(t, processor, 0, 7, full, pipeline, worse)
- testFork(t, processor, 1, 1, full, pipeline, worse)
- testFork(t, processor, 1, 7, full, pipeline, worse)
- testFork(t, processor, 5, 3, full, pipeline, worse)
- testFork(t, processor, 5, 4, full, pipeline, worse)
+ testFork(t, processor, 0, 3, full, worse, scheme, pipeline)
+ testFork(t, processor, 0, 7, full, worse, scheme, pipeline)
+ testFork(t, processor, 1, 1, full, worse, scheme, pipeline)
+ testFork(t, processor, 1, 7, full, worse, scheme, pipeline)
+ testFork(t, processor, 5, 3, full, worse, scheme, pipeline)
+ testFork(t, processor, 5, 4, full, worse, scheme, pipeline)
}
// Tests that given a starting canonical chain of a given size, creating shorter
// forks do not take canonical ownership.
-func TestShorterForkHeadersAfterMerge(t *testing.T) { testShorterForkAfterMerge(t, false) }
-func TestShorterForkBlocksAfterMerge(t *testing.T) { testShorterForkAfterMerge(t, true) }
+func TestShorterForkHeadersAfterMerge(t *testing.T) {
+ testShorterForkAfterMerge(t, false, rawdb.HashScheme)
+ testShorterForkAfterMerge(t, false, rawdb.PathScheme)
+}
+func TestShorterForkBlocksAfterMerge(t *testing.T) {
+ testShorterForkAfterMerge(t, true, rawdb.HashScheme)
+ testShorterForkAfterMerge(t, true, rawdb.PathScheme)
+}
-func testShorterForkAfterMerge(t *testing.T, full bool) {
+func testShorterForkAfterMerge(t *testing.T, full bool, scheme string) {
length := 10
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, false)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme, false)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
defer processor.Stop()
- testInsertAfterMerge(t, processor, 0, 3, full)
- testInsertAfterMerge(t, processor, 0, 7, full)
- testInsertAfterMerge(t, processor, 1, 1, full)
- testInsertAfterMerge(t, processor, 1, 7, full)
- testInsertAfterMerge(t, processor, 5, 3, full)
- testInsertAfterMerge(t, processor, 5, 4, full)
+ testInsertAfterMerge(t, processor, 0, 3, full, scheme)
+ testInsertAfterMerge(t, processor, 0, 7, full, scheme)
+ testInsertAfterMerge(t, processor, 1, 1, full, scheme)
+ testInsertAfterMerge(t, processor, 1, 7, full, scheme)
+ testInsertAfterMerge(t, processor, 5, 3, full, scheme)
+ testInsertAfterMerge(t, processor, 5, 4, full, scheme)
}
// Tests that given a starting canonical chain of a given size, creating longer
// forks do take canonical ownership.
func TestLongerForkHeaders(t *testing.T) {
- testLongerFork(t, false, false)
+ testLongerFork(t, false, rawdb.HashScheme, false)
+ testLongerFork(t, false, rawdb.PathScheme, false)
}
func TestLongerForkBlocks(t *testing.T) {
- testLongerFork(t, true, false)
- testLongerFork(t, true, true)
+ testLongerFork(t, true, rawdb.HashScheme, false)
+ testLongerFork(t, true, rawdb.PathScheme, false)
+ testLongerFork(t, true, rawdb.HashScheme, true)
}
-func testLongerFork(t *testing.T, full, pipeline bool) {
+func testLongerFork(t *testing.T, full bool, scheme string, pipeline bool) {
length := 10
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
defer processor.Stop()
- testInsertAfterMerge(t, processor, 0, 11, full)
- testInsertAfterMerge(t, processor, 0, 15, full)
- testInsertAfterMerge(t, processor, 1, 10, full)
- testInsertAfterMerge(t, processor, 1, 12, full)
- testInsertAfterMerge(t, processor, 5, 6, full)
- testInsertAfterMerge(t, processor, 5, 8, full)
+ testInsertAfterMerge(t, processor, 0, 11, full, scheme)
+ testInsertAfterMerge(t, processor, 0, 15, full, scheme)
+ testInsertAfterMerge(t, processor, 1, 10, full, scheme)
+ testInsertAfterMerge(t, processor, 1, 12, full, scheme)
+ testInsertAfterMerge(t, processor, 5, 6, full, scheme)
+ testInsertAfterMerge(t, processor, 5, 8, full, scheme)
}
// Tests that given a starting canonical chain of a given size, creating longer
// forks do take canonical ownership.
-func TestLongerForkHeadersAfterMerge(t *testing.T) { testLongerForkAfterMerge(t, false) }
-func TestLongerForkBlocksAfterMerge(t *testing.T) { testLongerForkAfterMerge(t, true) }
+func TestLongerForkHeadersAfterMerge(t *testing.T) {
+ testLongerForkAfterMerge(t, false, rawdb.HashScheme)
+ testLongerForkAfterMerge(t, false, rawdb.PathScheme)
+}
+func TestLongerForkBlocksAfterMerge(t *testing.T) {
+ testLongerForkAfterMerge(t, true, rawdb.HashScheme)
+ testLongerForkAfterMerge(t, true, rawdb.PathScheme)
+}
-func testLongerForkAfterMerge(t *testing.T, full bool) {
+func testLongerForkAfterMerge(t *testing.T, full bool, scheme string) {
length := 10
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, false)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme, false)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
defer processor.Stop()
- testInsertAfterMerge(t, processor, 0, 11, full)
- testInsertAfterMerge(t, processor, 0, 15, full)
- testInsertAfterMerge(t, processor, 1, 10, full)
- testInsertAfterMerge(t, processor, 1, 12, full)
- testInsertAfterMerge(t, processor, 5, 6, full)
- testInsertAfterMerge(t, processor, 5, 8, full)
+ testInsertAfterMerge(t, processor, 0, 11, full, scheme)
+ testInsertAfterMerge(t, processor, 0, 15, full, scheme)
+ testInsertAfterMerge(t, processor, 1, 10, full, scheme)
+ testInsertAfterMerge(t, processor, 1, 12, full, scheme)
+ testInsertAfterMerge(t, processor, 5, 6, full, scheme)
+ testInsertAfterMerge(t, processor, 5, 8, full, scheme)
}
// Tests that given a starting canonical chain of a given size, creating equal
// forks do take canonical ownership.
-func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false, false) }
+func TestEqualForkHeaders(t *testing.T) {
+ testEqualFork(t, false, rawdb.HashScheme, false)
+ testEqualFork(t, false, rawdb.PathScheme, false)
+}
func TestEqualForkBlocks(t *testing.T) {
- testEqualFork(t, true, true)
- testEqualFork(t, true, false)
+ testEqualFork(t, true, rawdb.HashScheme, false)
+ testEqualFork(t, true, rawdb.PathScheme, false)
+ testEqualFork(t, true, rawdb.HashScheme, true)
}
-func testEqualFork(t *testing.T, full, pipeline bool) {
+func testEqualFork(t *testing.T, full bool, scheme string, pipeline bool) {
length := 10
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -520,47 +555,57 @@ func testEqualFork(t *testing.T, full, pipeline bool) {
}
}
// Sum of numbers must be equal to `length` for this to be an equal fork
- testFork(t, processor, 0, 10, full, pipeline, equal)
- testFork(t, processor, 1, 9, full, pipeline, equal)
- testFork(t, processor, 2, 8, full, pipeline, equal)
- testFork(t, processor, 5, 5, full, pipeline, equal)
- testFork(t, processor, 6, 4, full, pipeline, equal)
- testFork(t, processor, 9, 1, full, pipeline, equal)
+ testFork(t, processor, 0, 10, full, equal, scheme, pipeline)
+ testFork(t, processor, 1, 9, full, equal, scheme, pipeline)
+ testFork(t, processor, 2, 8, full, equal, scheme, pipeline)
+ testFork(t, processor, 5, 5, full, equal, scheme, pipeline)
+ testFork(t, processor, 6, 4, full, equal, scheme, pipeline)
+ testFork(t, processor, 9, 1, full, equal, scheme, pipeline)
}
// Tests that given a starting canonical chain of a given size, creating equal
// forks do take canonical ownership.
-func TestEqualForkHeadersAfterMerge(t *testing.T) { testEqualForkAfterMerge(t, false) }
-func TestEqualForkBlocksAfterMerge(t *testing.T) { testEqualForkAfterMerge(t, true) }
+func TestEqualForkHeadersAfterMerge(t *testing.T) {
+ testEqualForkAfterMerge(t, false, rawdb.HashScheme)
+ testEqualForkAfterMerge(t, false, rawdb.PathScheme)
+}
+func TestEqualForkBlocksAfterMerge(t *testing.T) {
+ testEqualForkAfterMerge(t, true, rawdb.HashScheme)
+ testEqualForkAfterMerge(t, true, rawdb.PathScheme)
+}
-func testEqualForkAfterMerge(t *testing.T, full bool) {
+func testEqualForkAfterMerge(t *testing.T, full bool, scheme string) {
length := 10
// Make first chain starting from genesis
- _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, false)
+ _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme, false)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
defer processor.Stop()
- testInsertAfterMerge(t, processor, 0, 10, full)
- testInsertAfterMerge(t, processor, 1, 9, full)
- testInsertAfterMerge(t, processor, 2, 8, full)
- testInsertAfterMerge(t, processor, 5, 5, full)
- testInsertAfterMerge(t, processor, 6, 4, full)
- testInsertAfterMerge(t, processor, 9, 1, full)
+ testInsertAfterMerge(t, processor, 0, 10, full, scheme)
+ testInsertAfterMerge(t, processor, 1, 9, full, scheme)
+ testInsertAfterMerge(t, processor, 2, 8, full, scheme)
+ testInsertAfterMerge(t, processor, 5, 5, full, scheme)
+ testInsertAfterMerge(t, processor, 6, 4, full, scheme)
+ testInsertAfterMerge(t, processor, 9, 1, full, scheme)
}
// Tests that chains missing links do not get accepted by the processor.
-func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false, false) }
+func TestBrokenHeaderChain(t *testing.T) {
+ testBrokenChain(t, false, rawdb.HashScheme, false)
+ testBrokenChain(t, false, rawdb.PathScheme, false)
+}
func TestBrokenBlockChain(t *testing.T) {
- testBrokenChain(t, true, false)
- testBrokenChain(t, true, true)
+ testBrokenChain(t, true, rawdb.HashScheme, false)
+ testBrokenChain(t, true, rawdb.PathScheme, false)
+ testBrokenChain(t, true, rawdb.HashScheme, true)
}
-func testBrokenChain(t *testing.T, full, pipeline bool) {
+func testBrokenChain(t *testing.T, full bool, scheme string, pipeline bool) {
// Make chain starting from genesis
- genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 10, full, pipeline)
+ genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 10, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to make new canonical chain: %v", err)
}
@@ -582,25 +627,33 @@ func testBrokenChain(t *testing.T, full, pipeline bool) {
// Tests that reorganising a long difficult chain after a short easy one
// overwrites the canonical numbers and links in the database.
-func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false, false) }
+func TestReorgLongHeaders(t *testing.T) {
+ testReorgLong(t, false, rawdb.HashScheme, false)
+ testReorgLong(t, false, rawdb.PathScheme, false)
+}
func TestReorgLongBlocks(t *testing.T) {
- testReorgLong(t, true, false)
- testReorgLong(t, true, true)
+ testReorgLong(t, true, rawdb.HashScheme, false)
+ testReorgLong(t, true, rawdb.PathScheme, false)
+ testReorgLong(t, true, rawdb.HashScheme, true)
}
-func testReorgLong(t *testing.T, full, pipeline bool) {
- testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280+params.GenesisDifficulty.Int64(), full, pipeline)
+func testReorgLong(t *testing.T, full bool, scheme string, pipeline bool) {
+ testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280+params.GenesisDifficulty.Int64(), full, scheme, pipeline)
}
// Tests that reorganising a short difficult chain after a long easy one
// overwrites the canonical numbers and links in the database.
-func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false, false) }
+func TestReorgShortHeaders(t *testing.T) {
+ testReorgShort(t, false, rawdb.HashScheme, false)
+ testReorgShort(t, false, rawdb.PathScheme, false)
+}
func TestReorgShortBlocks(t *testing.T) {
- testReorgShort(t, true, false)
- testReorgShort(t, true, true)
+ testReorgShort(t, true, rawdb.HashScheme, false)
+ testReorgShort(t, true, rawdb.PathScheme, false)
+ testReorgShort(t, true, rawdb.HashScheme, true)
}
-func testReorgShort(t *testing.T, full, pipeline bool) {
+func testReorgShort(t *testing.T, full bool, scheme string, pipeline bool) {
// Create a long easy chain vs. a short heavy one. Due to difficulty adjustment
// we need a fairly long chain of blocks with different difficulties for a short
// one to become heavier than a long one. The 96 is an empirical value.
@@ -612,12 +665,12 @@ func testReorgShort(t *testing.T, full, pipeline bool) {
for i := 0; i < len(diff); i++ {
diff[i] = -9
}
- testReorg(t, easy, diff, 12615120+params.GenesisDifficulty.Int64(), full, pipeline)
+ testReorg(t, easy, diff, 12615120+params.GenesisDifficulty.Int64(), full, scheme, pipeline)
}
-func testReorg(t *testing.T, first, second []int64, td int64, full, pipeline bool) {
+func testReorg(t *testing.T, first, second []int64, td int64, full bool, scheme string, pipeline bool) {
// Create a pristine chain and database
- genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline)
+ genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -685,15 +738,20 @@ func testReorg(t *testing.T, first, second []int64, td int64, full, pipeline boo
}
// Tests that the insertion functions detect banned hashes.
-func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false, false) }
+func TestBadHeaderHashes(t *testing.T) {
+ testBadHashes(t, false, rawdb.HashScheme, false)
+ testBadHashes(t, false, rawdb.PathScheme, false)
+}
+
func TestBadBlockHashes(t *testing.T) {
- testBadHashes(t, true, true)
- testBadHashes(t, true, false)
+ testBadHashes(t, true, rawdb.HashScheme, false)
+ testBadHashes(t, true, rawdb.HashScheme, true)
+ testBadHashes(t, true, rawdb.PathScheme, false)
}
-func testBadHashes(t *testing.T, full, pipeline bool) {
+func testBadHashes(t *testing.T, full bool, scheme string, pipeline bool) {
// Create a pristine chain and database
- genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline)
+ genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -722,15 +780,19 @@ func testBadHashes(t *testing.T, full, pipeline bool) {
// Tests that bad hashes are detected on boot, and the chain rolled back to a
// good state prior to the bad hash.
-func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false, false) }
+func TestReorgBadHeaderHashes(t *testing.T) {
+ testReorgBadHashes(t, false, rawdb.HashScheme, false)
+ testReorgBadHashes(t, false, rawdb.PathScheme, false)
+}
func TestReorgBadBlockHashes(t *testing.T) {
- testReorgBadHashes(t, true, false)
- testReorgBadHashes(t, true, true)
+ testReorgBadHashes(t, true, rawdb.HashScheme, false)
+ testReorgBadHashes(t, true, rawdb.HashScheme, true)
+ testReorgBadHashes(t, true, rawdb.PathScheme, false)
}
-func testReorgBadHashes(t *testing.T, full, pipeline bool) {
+func testReorgBadHashes(t *testing.T, full bool, scheme string, pipeline bool) {
// Create a pristine chain and database
- genDb, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline)
+ genDb, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -760,7 +822,7 @@ func testReorgBadHashes(t *testing.T, full, pipeline bool) {
blockchain.Stop()
// Create a new BlockChain and check that it rolled back the state.
- ncm, err := NewBlockChain(blockchain.db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ ncm, err := NewBlockChain(blockchain.db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create new chain manager: %v", err)
}
@@ -780,16 +842,20 @@ func testReorgBadHashes(t *testing.T, full, pipeline bool) {
}
// Tests chain insertions in the face of one entity containing an invalid nonce.
-func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false, false) }
+func TestHeadersInsertNonceError(t *testing.T) {
+ testInsertNonceError(t, false, rawdb.HashScheme, false)
+ testInsertNonceError(t, false, rawdb.PathScheme, false)
+}
func TestBlocksInsertNonceError(t *testing.T) {
- testInsertNonceError(t, true, false)
- testInsertNonceError(t, true, true)
+ testInsertNonceError(t, true, rawdb.HashScheme, false)
+ testInsertNonceError(t, true, rawdb.HashScheme, true)
+ testInsertNonceError(t, true, rawdb.PathScheme, false)
}
-func testInsertNonceError(t *testing.T, full bool, pipeline bool) {
+func testInsertNonceError(t *testing.T, full bool, scheme string, pipeline bool) {
doTest := func(i int) {
// Create a pristine chain and database
- genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline)
+ genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme, pipeline)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -844,6 +910,11 @@ func testInsertNonceError(t *testing.T, full bool, pipeline bool) {
// Tests that fast importing a block chain produces the same chain data as the
// classical full block processing.
func TestFastVsFullChains(t *testing.T) {
+ testFastVsFullChains(t, rawdb.HashScheme)
+ testFastVsFullChains(t, rawdb.PathScheme)
+}
+
+func testFastVsFullChains(t *testing.T, scheme string) {
// Configure and generate a sample block chain
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@@ -876,7 +947,7 @@ func TestFastVsFullChains(t *testing.T) {
})
// Import the chain as an archive node for the comparison baseline
archiveDb := rawdb.NewMemoryDatabase()
- archive, _ := NewBlockChain(archiveDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ archive, _ := NewBlockChain(archiveDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer archive.Stop()
if n, err := archive.InsertChain(blocks); err != nil {
@@ -884,7 +955,7 @@ func TestFastVsFullChains(t *testing.T) {
}
// Fast import the chain as a non-archive node to test
fastDb := rawdb.NewMemoryDatabase()
- fast, _ := NewBlockChain(fastDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer fast.Stop()
headers := make([]*types.Header, len(blocks))
@@ -903,7 +974,8 @@ func TestFastVsFullChains(t *testing.T) {
t.Fatalf("failed to create temp freezer db: %v", err)
}
defer ancientDb.Close()
- ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+
+ ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop()
if n, err := ancient.InsertHeaderChain(headers); err != nil {
@@ -971,6 +1043,11 @@ func TestFastVsFullChains(t *testing.T) {
// Tests that various import methods move the chain head pointers to the correct
// positions.
func TestLightVsFastVsFullChainHeads(t *testing.T) {
+ testLightVsFastVsFullChainHeads(t, rawdb.HashScheme)
+ testLightVsFastVsFullChainHeads(t, rawdb.PathScheme)
+}
+
+func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
// Configure and generate a sample block chain
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@@ -1016,6 +1093,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
archiveCaching := *defaultCacheConfig
archiveCaching.TrieDirtyDisabled = true
+ archiveCaching.StateScheme = scheme
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if n, err := archive.InsertChain(blocks); err != nil {
@@ -1030,7 +1108,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a non-archive node and ensure all pointers are updated
fastDb := makeDb()
defer fastDb.Close()
- fast, _ := NewBlockChain(fastDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer fast.Stop()
headers := make([]*types.Header, len(blocks))
@@ -1050,7 +1128,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a ancient-first node and ensure all pointers are updated
ancientDb := makeDb()
defer ancientDb.Close()
- ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop()
if n, err := ancient.InsertHeaderChain(headers); err != nil {
@@ -1069,7 +1147,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a light node and ensure all pointers are updated
lightDb := makeDb()
defer lightDb.Close()
- light, _ := NewBlockChain(lightDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ light, _ := NewBlockChain(lightDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if n, err := light.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err)
}
@@ -1082,6 +1160,11 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Tests that chain reorganisations handle transaction removals and reinsertions.
func TestChainTxReorgs(t *testing.T) {
+ testChainTxReorgs(t, rawdb.HashScheme)
+ testChainTxReorgs(t, rawdb.PathScheme)
+}
+
+func testChainTxReorgs(t *testing.T, scheme string) {
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
@@ -1137,7 +1220,7 @@ func TestChainTxReorgs(t *testing.T) {
})
// Import the chain. This runs all block validation rules.
db := rawdb.NewMemoryDatabase()
- blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if i, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
}
@@ -1196,6 +1279,11 @@ func TestChainTxReorgs(t *testing.T) {
}
func TestLogReorgs(t *testing.T) {
+ testLogReorgs(t, rawdb.HashScheme)
+ testLogReorgs(t, rawdb.PathScheme)
+}
+
+func testLogReorgs(t *testing.T, scheme string) {
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
@@ -1206,7 +1294,7 @@ func TestLogReorgs(t *testing.T) {
signer = types.LatestSigner(gspec.Config)
)
- blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
rmLogsCh := make(chan RemovedLogsEvent)
@@ -1251,13 +1339,18 @@ var logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd
// This test checks that log events and RemovedLogsEvent are sent
// when the chain reorganizes.
func TestLogRebirth(t *testing.T) {
+ testLogRebirth(t, rawdb.HashScheme)
+ testLogRebirth(t, rawdb.PathScheme)
+}
+
+func testLogRebirth(t *testing.T, scheme string) {
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
signer = types.LatestSigner(gspec.Config)
engine = ethash.NewFaker()
- blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
+ blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
)
defer blockchain.Stop()
@@ -1328,12 +1421,17 @@ func TestLogRebirth(t *testing.T) {
// This test is a variation of TestLogRebirth. It verifies that log events are emitted
// when a side chain containing log events overtakes the canonical chain.
func TestSideLogRebirth(t *testing.T) {
+ testSideLogRebirth(t, rawdb.HashScheme)
+ testSideLogRebirth(t, rawdb.PathScheme)
+}
+
+func testSideLogRebirth(t *testing.T, scheme string) {
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
signer = types.LatestSigner(gspec.Config)
- blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
)
defer blockchain.Stop()
@@ -1418,6 +1516,11 @@ func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan Re
}
func TestReorgSideEvent(t *testing.T) {
+ testReorgSideEvent(t, rawdb.HashScheme)
+ testReorgSideEvent(t, rawdb.PathScheme)
+}
+
+func testReorgSideEvent(t *testing.T, scheme string) {
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
@@ -1427,7 +1530,7 @@ func TestReorgSideEvent(t *testing.T) {
}
signer = types.LatestSigner(gspec.Config)
)
- blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) {})
@@ -1498,7 +1601,12 @@ done:
// Tests if the canonical block can be fetched from the database during chain insertion.
func TestCanonicalBlockRetrieval(t *testing.T) {
- _, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, false)
+ testCanonicalBlockRetrieval(t, rawdb.HashScheme)
+ testCanonicalBlockRetrieval(t, rawdb.PathScheme)
+}
+
+func testCanonicalBlockRetrieval(t *testing.T, scheme string) {
+ _, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, scheme, false)
if err != nil {
t.Fatalf("failed to create pristine chain: %v", err)
}
@@ -1542,8 +1650,12 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
}
pend.Wait()
}
-
func TestEIP155Transition(t *testing.T) {
+ testEIP155Transition(t, rawdb.HashScheme)
+ testEIP155Transition(t, rawdb.PathScheme)
+}
+
+func testEIP155Transition(t *testing.T, scheme string) {
// Configure and generate a sample block chain
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@@ -1602,7 +1714,7 @@ func TestEIP155Transition(t *testing.T) {
}
})
- blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
if _, err := blockchain.InsertChain(blocks); err != nil {
@@ -1652,8 +1764,12 @@ func TestEIP155Transition(t *testing.T) {
t.Errorf("have %v, want %v", have, want)
}
}
-
func TestEIP161AccountRemoval(t *testing.T) {
+ testEIP161AccountRemoval(t, rawdb.HashScheme)
+ testEIP161AccountRemoval(t, rawdb.PathScheme)
+}
+
+func testEIP161AccountRemoval(t *testing.T, scheme string) {
// Configure and generate a sample block chain
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@@ -1691,7 +1807,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
block.AddTx(tx)
})
// account must exist pre eip 161
- blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
@@ -1724,6 +1840,11 @@ func TestEIP161AccountRemoval(t *testing.T) {
//
// https://github.com/ethereum/go-ethereum/pull/15941
func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
+ testBlockchainHeaderchainReorgConsistency(t, rawdb.HashScheme)
+ testBlockchainHeaderchainReorgConsistency(t, rawdb.PathScheme)
+}
+
+func testBlockchainHeaderchainReorgConsistency(t *testing.T, scheme string) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
genesis := &Genesis{
@@ -1744,7 +1865,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
}
// Import the canonical and fork chain side by side, verifying the current block
// and current header consistency
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -1803,11 +1924,11 @@ func TestTrieForkGC(t *testing.T) {
}
}
// Dereference all the recent tries and ensure no past trie is left in
- for i := 0; i < TestTriesInMemory; i++ {
- chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
- chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
+ for i := 0; i < TriesInMemory; i++ {
+ chain.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
+ chain.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
}
- if _, nodes, _, _ := chain.TrieDB().Size(); nodes > 0 {
+ if _, nodes, _, _ := chain.TrieDB().Size(); nodes > 0 { // all memory is returned in the nodes return for hashdb
t.Fatalf("stale tries still alive after garbase collection")
}
}
@@ -1815,6 +1936,11 @@ func TestTrieForkGC(t *testing.T) {
// Tests that doing large reorgs works even if the state associated with the
// forking point is not available any more.
func TestLargeReorgTrieGC(t *testing.T) {
+ testLargeReorgTrieGC(t, rawdb.HashScheme)
+ testLargeReorgTrieGC(t, rawdb.PathScheme)
+}
+
+func testLargeReorgTrieGC(t *testing.T, scheme string) {
// Generate the original common chain segment and the two competing forks
engine := ethash.NewFaker()
genesis := &Genesis{
@@ -1826,7 +1952,10 @@ func TestLargeReorgTrieGC(t *testing.T) {
competitor, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
// Import the shared chain and the original canonical one
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil)
+ db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
+ defer db.Close()
+
+ chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -1839,7 +1968,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
t.Fatalf("failed to insert original chain: %v", err)
}
// Ensure that the state associated with the forking point is pruned away
- if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil {
+ if chain.HasState(shared[len(shared)-1].Root()) {
t.Fatalf("common-but-old ancestor still cache")
}
// Import the competitor chain without exceeding the canonical's TD and ensure
@@ -1848,7 +1977,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
t.Fatalf("failed to insert competitor chain: %v", err)
}
for i, block := range competitor[:len(competitor)-2] {
- if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
+ if chain.HasState(block.Root()) {
t.Fatalf("competitor %d: low TD chain became processed", i)
}
}
@@ -1857,14 +1986,30 @@ func TestLargeReorgTrieGC(t *testing.T) {
if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil {
t.Fatalf("failed to finalize competitor chain: %v", err)
}
- for i, block := range competitor[:len(competitor)-TestTriesInMemory] {
- if node, err := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
- t.Fatalf("competitor %d: competing chain state missing, err: %v", i, err)
+ // In path-based trie database implementation, it will keep 128 diff + 1 disk
+ // layers, totally 129 latest states available. In hash-based it's 128.
+ states := TestTriesInMemory
+ if scheme == rawdb.PathScheme {
+ states = states + 1
+ }
+ for i, block := range competitor[:len(competitor)-states] {
+ if chain.HasState(block.Root()) {
+ t.Fatalf("competitor %d: unexpected competing chain state", i)
+ }
+ }
+ for i, block := range competitor[len(competitor)-states:] {
+ if !chain.HasState(block.Root()) {
+ t.Fatalf("competitor %d: competing chain state missing", i)
}
}
}
func TestBlockchainRecovery(t *testing.T) {
+ testBlockchainRecovery(t, rawdb.HashScheme)
+ testBlockchainRecovery(t, rawdb.PathScheme)
+}
+
+func testBlockchainRecovery(t *testing.T, scheme string) {
// Configure and generate a sample block chain
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@@ -1881,7 +2026,7 @@ func TestBlockchainRecovery(t *testing.T) {
t.Fatalf("failed to create temp freezer db: %v", err)
}
defer ancientDb.Close()
- ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
@@ -1901,7 +2046,7 @@ func TestBlockchainRecovery(t *testing.T) {
rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())
// Reopen broken blockchain again
- ancient, _ = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ ancient, _ = NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop()
if num := ancient.CurrentBlock().Number.Uint64(); num != 0 {
t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
@@ -1916,8 +2061,13 @@ func TestBlockchainRecovery(t *testing.T) {
// This test checks that InsertReceiptChain will roll back correctly when attempting to insert a side chain.
func TestInsertReceiptChainRollback(t *testing.T) {
+ testInsertReceiptChainRollback(t, rawdb.HashScheme)
+ testInsertReceiptChainRollback(t, rawdb.PathScheme)
+}
+
+func testInsertReceiptChainRollback(t *testing.T, scheme string) {
// Generate forked chain. The returned BlockChain object is used to process the side chain blocks.
- tmpChain, sideblocks, canonblocks, gspec, err := getLongAndShortChains()
+ tmpChain, sideblocks, canonblocks, gspec, err := getLongAndShortChains(scheme)
if err != nil {
t.Fatal(err)
}
@@ -1948,7 +2098,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
}
defer ancientDb.Close()
- ancientChain, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
+ ancientChain, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancientChain.Stop()
// Import the canonical header chain.
@@ -1993,6 +2143,11 @@ func TestInsertReceiptChainRollback(t *testing.T) {
// - https://github.com/ethereum/go-ethereum/issues/18977
// - https://github.com/ethereum/go-ethereum/pull/18988
func TestLowDiffLongChain(t *testing.T) {
+ testLowDiffLongChain(t, rawdb.HashScheme)
+ testLowDiffLongChain(t, rawdb.PathScheme)
+}
+
+func testLowDiffLongChain(t *testing.T, scheme string) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
genesis := &Genesis{
@@ -2007,11 +2162,14 @@ func TestLowDiffLongChain(t *testing.T) {
})
// Import the canonical chain
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil)
+ diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
+ defer diskdb.Close()
+
+ chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
- defer chain.stopWithoutSaving()
+ defer chain.Stop()
if n, err := chain.InsertChain(blocks); err != nil {
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
@@ -2191,11 +2349,20 @@ func TestPrunedImportSideWithMerging(t *testing.T) {
testSideImport(t, 1, -10, 1)
}
-func TestInsertKnownHeaders(t *testing.T) { testInsertKnownChainData(t, "headers") }
-func TestInsertKnownReceiptChain(t *testing.T) { testInsertKnownChainData(t, "receipts") }
-func TestInsertKnownBlocks(t *testing.T) { testInsertKnownChainData(t, "blocks") }
+func TestInsertKnownHeaders(t *testing.T) {
+ testInsertKnownChainData(t, "headers", rawdb.HashScheme)
+ testInsertKnownChainData(t, "headers", rawdb.PathScheme)
+}
+func TestInsertKnownReceiptChain(t *testing.T) {
+ testInsertKnownChainData(t, "receipts", rawdb.HashScheme)
+ testInsertKnownChainData(t, "receipts", rawdb.PathScheme)
+}
+func TestInsertKnownBlocks(t *testing.T) {
+ testInsertKnownChainData(t, "blocks", rawdb.HashScheme)
+ testInsertKnownChainData(t, "blocks", rawdb.PathScheme)
+}
-func testInsertKnownChainData(t *testing.T, typ string) {
+func testInsertKnownChainData(t *testing.T, typ string, scheme string) {
engine := ethash.NewFaker()
genesis := &Genesis{
Config: params.TestChainConfig,
@@ -2218,7 +2385,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
}
defer chaindb.Close()
- chain, err := NewBlockChain(chaindb, nil, genesis, nil, engine, vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(chaindb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -2491,7 +2658,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
}
// getLongAndShortChains returns two chains: A is longer, B is heavier.
-func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, *Genesis, error) {
+func getLongAndShortChains(scheme string) (*BlockChain, []*types.Block, []*types.Block, *Genesis, error) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
genesis := &Genesis{
@@ -2503,7 +2670,7 @@ func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, *Gene
genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{1})
})
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
if err != nil {
return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
}
@@ -2549,7 +2716,12 @@ func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, *Gene
// 3. Then there should be no canon mapping for the block at height X
// 4. The forked block should still be retrievable by hash
func TestReorgToShorterRemovesCanonMapping(t *testing.T) {
- chain, canonblocks, sideblocks, _, err := getLongAndShortChains()
+ testReorgToShorterRemovesCanonMapping(t, rawdb.HashScheme)
+ testReorgToShorterRemovesCanonMapping(t, rawdb.PathScheme)
+}
+
+func testReorgToShorterRemovesCanonMapping(t *testing.T, scheme string) {
+ chain, canonblocks, sideblocks, _, err := getLongAndShortChains(scheme)
if err != nil {
t.Fatal(err)
}
@@ -2587,7 +2759,12 @@ func TestReorgToShorterRemovesCanonMapping(t *testing.T) {
// as TestReorgToShorterRemovesCanonMapping, but applied on headerchain
// imports -- that is, for fast sync
func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) {
- chain, canonblocks, sideblocks, _, err := getLongAndShortChains()
+ testReorgToShorterRemovesCanonMappingHeaderChain(t, rawdb.HashScheme)
+ testReorgToShorterRemovesCanonMappingHeaderChain(t, rawdb.PathScheme)
+}
+
+func testReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T, scheme string) {
+ chain, canonblocks, sideblocks, _, err := getLongAndShortChains(scheme)
if err != nil {
t.Fatal(err)
}
@@ -2629,192 +2806,6 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) {
}
}
-func TestTransactionIndices(t *testing.T) {
- // Configure and generate a sample block chain
- var (
- key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- address = crypto.PubkeyToAddress(key.PublicKey)
- funds = big.NewInt(100000000000000000)
- gspec = &Genesis{
- Config: params.TestChainConfig,
- Alloc: GenesisAlloc{address: {Balance: funds}},
- BaseFee: big.NewInt(params.InitialBaseFee),
- }
- signer = types.LatestSigner(gspec.Config)
- )
- _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 128, func(i int, block *BlockGen) {
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key)
- if err != nil {
- panic(err)
- }
- block.AddTx(tx)
- })
-
- check := func(tail *uint64, chain *BlockChain) {
- stored := rawdb.ReadTxIndexTail(chain.db)
- if tail == nil && stored != nil {
- t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *stored)
- }
- if tail != nil && *stored != *tail {
- t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored)
- }
- if tail != nil {
- for i := *tail; i <= chain.CurrentBlock().Number.Uint64(); i++ {
- block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i)
- if block.Transactions().Len() == 0 {
- continue
- }
- for _, tx := range block.Transactions() {
- if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index == nil {
- t.Fatalf("Miss transaction indice, number %d hash %s", i, tx.Hash().Hex())
- }
- }
- }
- for i := uint64(0); i < *tail; i++ {
- block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i)
- if block.Transactions().Len() == 0 {
- continue
- }
- for _, tx := range block.Transactions() {
- if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index != nil {
- t.Fatalf("Transaction indice should be deleted, number %d hash %s", i, tx.Hash().Hex())
- }
- }
- }
- }
- }
- // Init block chain with external ancients, check all needed indices has been indexed.
- limit := []uint64{0, 32, 64, 128}
- for _, l := range limit {
- frdir := t.TempDir()
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false, false)
- if err != nil {
- t.Fatalf("failed to create temp freezer db: %v", err)
- }
- rawdb.WriteAncientBlocks(ancientDb, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), big.NewInt(0))
-
- l := l
- chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
- if err != nil {
- t.Fatalf("failed to create tester chain: %v", err)
- }
- chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{}))
-
- var tail uint64
- if l != 0 {
- tail = uint64(128) - l + 1
- }
- check(&tail, chain)
- chain.Stop()
- ancientDb.Close()
- os.RemoveAll(frdir)
- }
-
- // Reconstruct a block chain which only reserves HEAD-64 tx indices
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
- if err != nil {
- t.Fatalf("failed to create temp freezer db: %v", err)
- }
- defer ancientDb.Close()
-
- rawdb.WriteAncientBlocks(ancientDb, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), big.NewInt(0))
- limit = []uint64{0, 64 /* drop stale */, 32 /* shorten history */, 64 /* extend history */, 0 /* restore all */}
- for _, l := range limit {
- l := l
- chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
- if err != nil {
- t.Fatalf("failed to create tester chain: %v", err)
- }
- var tail uint64
- if l != 0 {
- tail = uint64(128) - l + 1
- }
- chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{}))
- check(&tail, chain)
- chain.Stop()
- }
-}
-
-func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
- // Configure and generate a sample block chain
- var (
- key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- address = crypto.PubkeyToAddress(key.PublicKey)
- funds = big.NewInt(100000000000000000)
- gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
- signer = types.LatestSigner(gspec.Config)
- )
- _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 128, func(i int, block *BlockGen) {
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key)
- if err != nil {
- panic(err)
- }
- block.AddTx(tx)
- })
-
- check := func(tail *uint64, chain *BlockChain) {
- stored := rawdb.ReadTxIndexTail(chain.db)
- if tail == nil && stored != nil {
- t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *stored)
- }
- if tail != nil && *stored != *tail {
- t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored)
- }
- if tail != nil {
- for i := *tail; i <= chain.CurrentBlock().Number.Uint64(); i++ {
- block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i)
- if block.Transactions().Len() == 0 {
- continue
- }
- for _, tx := range block.Transactions() {
- if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index == nil {
- t.Fatalf("Miss transaction indice, number %d hash %s", i, tx.Hash().Hex())
- }
- }
- }
- for i := uint64(0); i < *tail; i++ {
- block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i)
- if block.Transactions().Len() == 0 {
- continue
- }
- for _, tx := range block.Transactions() {
- if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index != nil {
- t.Fatalf("Transaction indice should be deleted, number %d hash %s", i, tx.Hash().Hex())
- }
- }
- }
- }
- }
-
- ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
- if err != nil {
- t.Fatalf("failed to create temp freezer db: %v", err)
- }
- defer ancientDb.Close()
-
- // Import all blocks into ancient db, only HEAD-32 indices are kept.
- l := uint64(32)
- chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
- if err != nil {
- t.Fatalf("failed to create tester chain: %v", err)
- }
- defer chain.Stop()
-
- headers := make([]*types.Header, len(blocks))
- for i, block := range blocks {
- headers[i] = block.Header()
- }
- if n, err := chain.InsertHeaderChain(headers); err != nil {
- t.Fatalf("failed to insert header %d: %v", n, err)
- }
- // The indices before ancient-N(32) should be ignored. After that all blocks should be indexed.
- if n, err := chain.InsertReceiptChain(blocks, receipts, 64); err != nil {
- t.Fatalf("block %d: failed to insert into chain: %v", n, err)
- }
- tail := uint64(32)
- check(&tail, chain)
-}
-
// Benchmarks large blocks with value transfers to non-existing accounts
func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) {
var (
@@ -2928,6 +2919,11 @@ func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
// 2. Downloader starts to sync again
// 3. The blocks fetched are all known and canonical blocks
func TestSideImportPrunedBlocks(t *testing.T) {
+ testSideImportPrunedBlocks(t, rawdb.HashScheme)
+ testSideImportPrunedBlocks(t, rawdb.PathScheme)
+}
+
+func testSideImportPrunedBlocks(t *testing.T, scheme string) {
// Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker()
genesis := &Genesis{
@@ -2937,7 +2933,7 @@ func TestSideImportPrunedBlocks(t *testing.T) {
// Generate and import the canonical chain
_, blocks, _ := GenerateChainWithGenesis(genesis, engine, 2*TriesInMemory, nil)
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -2946,15 +2942,20 @@ func TestSideImportPrunedBlocks(t *testing.T) {
if n, err := chain.InsertChain(blocks); err != nil {
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
}
-
- lastPrunedIndex := len(blocks) - TestTriesInMemory - 1
- lastPrunedBlock := blocks[lastPrunedIndex-1]
+ // In path-based trie database implementation, it will keep 128 diff + 1 disk
+ // layers, totally 129 latest states available. In hash-based it's 128.
+ states := TestTriesInMemory
+ if scheme == rawdb.PathScheme {
+ states = TestTriesInMemory + 1
+ }
+ lastPrunedIndex := len(blocks) - states - 1
+ lastPrunedBlock := blocks[lastPrunedIndex]
// Verify pruning of lastPrunedBlock
if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64())
}
- firstNonPrunedBlock := blocks[len(blocks)-TestTriesInMemory]
+ firstNonPrunedBlock := blocks[len(blocks)-states]
// Verify firstNonPrunedBlock is not pruned
if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
@@ -2976,6 +2977,11 @@ func TestSideImportPrunedBlocks(t *testing.T) {
// each transaction, so this works ok. The rework accumulated writes in memory
// first, but the journal wiped the entire state object on create-revert.
func TestDeleteCreateRevert(t *testing.T) {
+ testDeleteCreateRevert(t, rawdb.HashScheme)
+ testDeleteCreateRevert(t, rawdb.PathScheme)
+}
+
+func testDeleteCreateRevert(t *testing.T, scheme string) {
var (
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb")
@@ -3027,7 +3033,7 @@ func TestDeleteCreateRevert(t *testing.T) {
b.AddTx(tx)
})
// Import the canonical chain
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -3046,6 +3052,11 @@ func TestDeleteCreateRevert(t *testing.T) {
// Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct,
// and then the new slots exist
func TestDeleteRecreateSlots(t *testing.T) {
+ testDeleteRecreateSlots(t, rawdb.HashScheme)
+ testDeleteRecreateSlots(t, rawdb.PathScheme)
+}
+
+func testDeleteRecreateSlots(t *testing.T, scheme string) {
var (
engine = ethash.NewFaker()
@@ -3135,7 +3146,7 @@ func TestDeleteRecreateSlots(t *testing.T) {
b.AddTx(tx)
})
// Import the canonical chain
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
Tracer: logger.NewJSONLogger(nil, os.Stdout),
}, nil, nil)
if err != nil {
@@ -3169,6 +3180,11 @@ func TestDeleteRecreateSlots(t *testing.T) {
// regular value-transfer
// Expected outcome is that _all_ slots are cleared from A
func TestDeleteRecreateAccount(t *testing.T) {
+ testDeleteRecreateAccount(t, rawdb.HashScheme)
+ testDeleteRecreateAccount(t, rawdb.PathScheme)
+}
+
+func testDeleteRecreateAccount(t *testing.T, scheme string) {
var (
engine = ethash.NewFaker()
@@ -3212,7 +3228,7 @@ func TestDeleteRecreateAccount(t *testing.T) {
b.AddTx(tx)
})
// Import the canonical chain
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
Tracer: logger.NewJSONLogger(nil, os.Stdout),
}, nil, nil)
if err != nil {
@@ -3242,6 +3258,11 @@ func TestDeleteRecreateAccount(t *testing.T) {
// Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct,
// and then the new slots exist
func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) {
+ testDeleteRecreateSlotsAcrossManyBlocks(t, rawdb.HashScheme)
+ testDeleteRecreateSlotsAcrossManyBlocks(t, rawdb.PathScheme)
+}
+
+func testDeleteRecreateSlotsAcrossManyBlocks(t *testing.T, scheme string) {
var (
engine = ethash.NewFaker()
@@ -3382,7 +3403,7 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) {
current = exp
})
// Import the canonical chain
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
//Debug: true,
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
}, nil, nil)
@@ -3440,7 +3461,14 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) {
// to the destructset in case something is created "onto" an existing item.
// We need to either roll back the snapDestructs, or not place it into snapDestructs
// in the first place.
+//
+
func TestInitThenFailCreateContract(t *testing.T) {
+ testInitThenFailCreateContract(t, rawdb.HashScheme)
+ testInitThenFailCreateContract(t, rawdb.PathScheme)
+}
+
+func testInitThenFailCreateContract(t *testing.T, scheme string) {
var (
engine = ethash.NewFaker()
@@ -3513,7 +3541,7 @@ func TestInitThenFailCreateContract(t *testing.T) {
})
// Import the canonical chain
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
//Debug: true,
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
}, nil, nil)
@@ -3523,7 +3551,7 @@ func TestInitThenFailCreateContract(t *testing.T) {
defer chain.Stop()
statedb, _ := chain.State()
- if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 {
+ if got, exp := statedb.GetBalance(aa), uint256.NewInt(100000); got.Cmp(exp) != 0 {
t.Fatalf("Genesis err, got %v exp %v", got, exp)
}
// First block tries to create, but fails
@@ -3533,7 +3561,7 @@ func TestInitThenFailCreateContract(t *testing.T) {
t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
}
statedb, _ = chain.State()
- if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 {
+ if got, exp := statedb.GetBalance(aa), uint256.NewInt(100000); got.Cmp(exp) != 0 {
t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp)
}
}
@@ -3553,16 +3581,18 @@ func TestInitThenFailCreateContract(t *testing.T) {
// TestEIP2718TransitionWithTestChainConfig tests EIP-2718 with TestChainConfig.
func TestEIP2718TransitionWithTestChainConfig(t *testing.T) {
- testEIP2718TransitionWithConfig(t, params.TestChainConfig)
+ testEIP2718TransitionWithConfig(t, rawdb.HashScheme, params.TestChainConfig)
+ testEIP2718TransitionWithConfig(t, rawdb.HashScheme, params.TestChainConfig)
}
// TestEIP2718TransitionWithParliaConfig tests EIP-2718 with Parlia Config.
func TestEIP2718TransitionWithParliaConfig(t *testing.T) {
- testEIP2718TransitionWithConfig(t, params.ParliaTestChainConfig)
+ testEIP2718TransitionWithConfig(t, rawdb.HashScheme, params.ParliaTestChainConfig)
+ testEIP2718TransitionWithConfig(t, rawdb.PathScheme, params.ParliaTestChainConfig)
}
// testEIP2718TransitionWithConfig tests EIP02718 with given ChainConfig.
-func testEIP2718TransitionWithConfig(t *testing.T, config *params.ChainConfig) {
+func testEIP2718TransitionWithConfig(t *testing.T, scheme string, config *params.ChainConfig) {
var (
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
engine = ethash.NewFaker()
@@ -3610,7 +3640,7 @@ func testEIP2718TransitionWithConfig(t *testing.T, config *params.ChainConfig) {
})
// Import the canonical chain
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -3640,6 +3670,11 @@ func testEIP2718TransitionWithConfig(t *testing.T, config *params.ChainConfig) {
// gasFeeCap - gasTipCap < baseFee.
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
func TestEIP1559Transition(t *testing.T) {
+ testEIP1559Transition(t, rawdb.HashScheme)
+ testEIP1559Transition(t, rawdb.PathScheme)
+}
+
+func testEIP1559Transition(t *testing.T, scheme string) {
var (
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
engine = ethash.NewFaker()
@@ -3650,8 +3685,9 @@ func TestEIP1559Transition(t *testing.T) {
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
+ config = *params.AllEthashProtocolChanges
gspec = &Genesis{
- Config: params.AllEthashProtocolChanges,
+ Config: &config,
Alloc: GenesisAlloc{
addr1: {Balance: funds},
addr2: {Balance: funds},
@@ -3698,7 +3734,7 @@ func TestEIP1559Transition(t *testing.T) {
b.AddTx(tx)
})
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -3720,17 +3756,17 @@ func TestEIP1559Transition(t *testing.T) {
state, _ := chain.State()
// 3: Ensure that miner received only the tx's tip.
- actual := state.GetBalance(block.Coinbase())
+ actual := state.GetBalance(block.Coinbase()).ToBig()
expected := new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GasTipCap().Uint64()),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}
// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
@@ -3760,17 +3796,17 @@ func TestEIP1559Transition(t *testing.T) {
effectiveTip := block.Transactions()[0].GasTipCap().Uint64() - block.BaseFee().Uint64()
// 6+5: Ensure that miner received only the tx's effective tip.
- actual = state.GetBalance(block.Coinbase())
+ actual = state.GetBalance(block.Coinbase()).ToBig()
expected = new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*effectiveTip),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}
// 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr2))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr2).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
@@ -3780,6 +3816,11 @@ func TestEIP1559Transition(t *testing.T) {
// Tests the scenario the chain is requested to another point with the missing state.
// It expects the state is recovered and all relevant chain markers are set correctly.
func TestSetCanonical(t *testing.T) {
+ testSetCanonical(t, rawdb.HashScheme)
+ testSetCanonical(t, rawdb.PathScheme)
+}
+
+func testSetCanonical(t *testing.T, scheme string) {
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
var (
@@ -3802,7 +3843,10 @@ func TestSetCanonical(t *testing.T) {
}
gen.AddTx(tx)
})
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
+ diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false, false)
+ defer diskdb.Close()
+
+ chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -3859,6 +3903,11 @@ func TestSetCanonical(t *testing.T) {
// TestCanonicalHashMarker tests all the canonical hash markers are updated/deleted
// correctly in case reorg is called.
func TestCanonicalHashMarker(t *testing.T) {
+ testCanonicalHashMarker(t, rawdb.HashScheme)
+ testCanonicalHashMarker(t, rawdb.PathScheme)
+}
+
+func testCanonicalHashMarker(t *testing.T, scheme string) {
var cases = []struct {
forkA int
forkB int
@@ -3906,7 +3955,7 @@ func TestCanonicalHashMarker(t *testing.T) {
_, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {})
// Initialize test chain
- chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -3962,212 +4011,6 @@ func TestCanonicalHashMarker(t *testing.T) {
}
}
-// TestTxIndexer tests the tx indexes are updated correctly.
-func TestTxIndexer(t *testing.T) {
- var (
- testBankKey, _ = crypto.GenerateKey()
- testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
- testBankFunds = big.NewInt(1000000000000000000)
-
- gspec = &Genesis{
- Config: params.TestChainConfig,
- Alloc: GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
- BaseFee: big.NewInt(params.InitialBaseFee),
- }
- engine = ethash.NewFaker()
- nonce = uint64(0)
- )
- _, blocks, receipts := GenerateChainWithGenesis(gspec, engine, 128, func(i int, gen *BlockGen) {
- tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xdeadbeef"), big.NewInt(1000), params.TxGas, big.NewInt(10*params.InitialBaseFee), nil), types.HomesteadSigner{}, testBankKey)
- gen.AddTx(tx)
- nonce += 1
- })
-
- // verifyIndexes checks if the transaction indexes are present or not
- // of the specified block.
- verifyIndexes := func(db ethdb.Database, number uint64, exist bool) {
- if number == 0 {
- return
- }
- block := blocks[number-1]
- for _, tx := range block.Transactions() {
- lookup := rawdb.ReadTxLookupEntry(db, tx.Hash())
- if exist && lookup == nil {
- t.Fatalf("missing %d %x", number, tx.Hash().Hex())
- }
- if !exist && lookup != nil {
- t.Fatalf("unexpected %d %x", number, tx.Hash().Hex())
- }
- }
- }
- // verifyRange runs verifyIndexes for a range of blocks, from and to are included.
- verifyRange := func(db ethdb.Database, from, to uint64, exist bool) {
- for number := from; number <= to; number += 1 {
- verifyIndexes(db, number, exist)
- }
- }
- verify := func(db ethdb.Database, expTail uint64) {
- tail := rawdb.ReadTxIndexTail(db)
- if tail == nil {
- t.Fatal("Failed to write tx index tail")
- }
- if *tail != expTail {
- t.Fatalf("Unexpected tx index tail, want %v, got %d", expTail, *tail)
- }
- if *tail != 0 {
- verifyRange(db, 0, *tail-1, false)
- }
- verifyRange(db, *tail, 128, true)
- }
-
- var cases = []struct {
- limitA uint64
- tailA uint64
- limitB uint64
- tailB uint64
- limitC uint64
- tailC uint64
- }{
- {
- // LimitA: 0
- // TailA: 0
- //
- // all blocks are indexed
- limitA: 0,
- tailA: 0,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- {
- // LimitA: 64
- // TailA: 65
- //
- // block [65, 128] are indexed
- limitA: 64,
- tailA: 65,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- {
- // LimitA: 127
- // TailA: 2
- //
- // block [2, 128] are indexed
- limitA: 127,
- tailA: 2,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- {
- // LimitA: 128
- // TailA: 1
- //
- // block [2, 128] are indexed
- limitA: 128,
- tailA: 1,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- {
- // LimitA: 129
- // TailA: 0
- //
- // block [0, 128] are indexed
- limitA: 129,
- tailA: 0,
-
- // LimitB: 1
- // TailB: 128
- //
- // block-128 is indexed
- limitB: 1,
- tailB: 128,
-
- // LimitB: 64
- // TailB: 65
- //
- // block [65, 128] are indexed
- limitC: 64,
- tailC: 65,
- },
- }
- for _, c := range cases {
- frdir := t.TempDir()
- db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false, false)
- rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), big.NewInt(0))
-
- // Index the initial blocks from ancient store
- chain, _ := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, &c.limitA)
- chain.indexBlocks(nil, 128, make(chan struct{}))
- verify(db, c.tailA)
-
- chain.SetTxLookupLimit(c.limitB)
- chain.indexBlocks(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}))
- verify(db, c.tailB)
-
- chain.SetTxLookupLimit(c.limitC)
- chain.indexBlocks(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}))
- verify(db, c.tailC)
-
- // Recover all indexes
- chain.SetTxLookupLimit(0)
- chain.indexBlocks(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}))
- verify(db, 0)
-
- chain.Stop()
- db.Close()
- os.RemoveAll(frdir)
- }
-}
-
func TestCreateThenDeletePreByzantium(t *testing.T) {
// We use Ropsten chain config instead of Testchain config, this is
// deliberate: we want to use pre-byz rules where we have intermediate state roots
@@ -4262,6 +4105,116 @@ func testCreateThenDelete(t *testing.T, config *params.ChainConfig) {
}
}
+func TestDeleteThenCreate(t *testing.T) {
+ var (
+ engine = ethash.NewFaker()
+ key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ address = crypto.PubkeyToAddress(key.PublicKey)
+ factoryAddr = crypto.CreateAddress(address, 0)
+ funds = big.NewInt(1000000000000000)
+ )
+ /*
+ contract Factory {
+ function deploy(bytes memory code) public {
+ address addr;
+ assembly {
+ addr := create2(0, add(code, 0x20), mload(code), 0)
+ if iszero(extcodesize(addr)) {
+ revert(0, 0)
+ }
+ }
+ }
+ }
+ */
+ factoryBIN := common.Hex2Bytes("608060405234801561001057600080fd5b50610241806100206000396000f3fe608060405234801561001057600080fd5b506004361061002a5760003560e01c80627743601461002f575b600080fd5b610049600480360381019061004491906100d8565b61004b565b005b6000808251602084016000f59050803b61006457600080fd5b5050565b600061007b61007684610146565b610121565b905082815260208101848484011115610097576100966101eb565b5b6100a2848285610177565b509392505050565b600082601f8301126100bf576100be6101e6565b5b81356100cf848260208601610068565b91505092915050565b6000602082840312156100ee576100ed6101f5565b5b600082013567ffffffffffffffff81111561010c5761010b6101f0565b5b610118848285016100aa565b91505092915050565b600061012b61013c565b90506101378282610186565b919050565b6000604051905090565b600067ffffffffffffffff821115610161576101606101b7565b5b61016a826101fa565b9050602081019050919050565b82818337600083830152505050565b61018f826101fa565b810181811067ffffffffffffffff821117156101ae576101ad6101b7565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f830116905091905056fea2646970667358221220ea8b35ed310d03b6b3deef166941140b4d9e90ea2c92f6b41eb441daf49a59c364736f6c63430008070033")
+
+ /*
+ contract C {
+ uint256 value;
+ constructor() {
+ value = 100;
+ }
+ function destruct() public payable {
+ selfdestruct(payable(msg.sender));
+ }
+ receive() payable external {}
+ }
+ */
+ contractABI := common.Hex2Bytes("6080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c63430008070033")
+ contractAddr := crypto.CreateAddress2(factoryAddr, [32]byte{}, crypto.Keccak256(contractABI))
+
+ gspec := &Genesis{
+ Config: params.TestChainConfig,
+ Alloc: GenesisAlloc{
+ address: {Balance: funds},
+ },
+ }
+ nonce := uint64(0)
+ signer := types.HomesteadSigner{}
+ _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2, func(i int, b *BlockGen) {
+ fee := big.NewInt(1)
+ if b.header.BaseFee != nil {
+ fee = b.header.BaseFee
+ }
+ b.SetCoinbase(common.Address{1})
+
+ // Block 1
+ if i == 0 {
+ tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{
+ Nonce: nonce,
+ GasPrice: new(big.Int).Set(fee),
+ Gas: 500000,
+ Data: factoryBIN,
+ })
+ nonce++
+ b.AddTx(tx)
+
+ data := common.Hex2Bytes("00774360000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a76080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c6343000807003300000000000000000000000000000000000000000000000000")
+ tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{
+ Nonce: nonce,
+ GasPrice: new(big.Int).Set(fee),
+ Gas: 500000,
+ To: &factoryAddr,
+ Data: data,
+ })
+ b.AddTx(tx)
+ nonce++
+ } else {
+ // Block 2
+ tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{
+ Nonce: nonce,
+ GasPrice: new(big.Int).Set(fee),
+ Gas: 500000,
+ To: &contractAddr,
+ Data: common.Hex2Bytes("2b68b9c6"), // destruct
+ })
+ nonce++
+ b.AddTx(tx)
+
+ data := common.Hex2Bytes("00774360000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a76080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c6343000807003300000000000000000000000000000000000000000000000000")
+ tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{
+ Nonce: nonce,
+ GasPrice: new(big.Int).Set(fee),
+ Gas: 500000,
+ To: &factoryAddr, // re-creation
+ Data: data,
+ })
+ b.AddTx(tx)
+ nonce++
+ }
+ })
+ // Import the canonical chain
+ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
+ if err != nil {
+ t.Fatalf("failed to create tester chain: %v", err)
+ }
+ for _, block := range blocks {
+ if _, err := chain.InsertChain([]*types.Block{block}); err != nil {
+ t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
+ }
+ }
+}
+
// TestTransientStorageReset ensures the transient storage is wiped correctly
// between transactions.
func TestTransientStorageReset(t *testing.T) {
@@ -4452,14 +4405,14 @@ func TestEIP3651(t *testing.T) {
state, _ := chain.State()
// 3: Ensure that miner received only the tx's tip.
- actual := state.GetBalance(block.Coinbase())
+ actual := state.GetBalance(block.Coinbase()).ToBig()
expected := new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64())
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}
// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
diff --git a/core/bloombits/matcher.go b/core/bloombits/matcher.go
index 2c808dd049..840d0fca20 100644
--- a/core/bloombits/matcher.go
+++ b/core/bloombits/matcher.go
@@ -59,7 +59,7 @@ type partialMatches struct {
// bit with the given number of fetch elements, or a response for such a request.
// It can also have the actual results set to be used as a delivery data struct.
//
-// The contest and error fields are used by the light client to terminate matching
+// The context and error fields are used by the light client to terminate matching
// early if an error is encountered on some path of the pipeline.
type Retrieval struct {
Bit uint
@@ -392,7 +392,7 @@ func (m *Matcher) distributor(dist chan *request, session *MatcherSession) {
shutdown = session.quit // Shutdown request channel, will gracefully wait for pending requests
)
- // assign is a helper method fo try to assign a pending bit an actively
+ // assign is a helper method to try to assign a pending bit an actively
// listening servicer, or schedule it up for later when one arrives.
assign := func(bit uint) {
select {
diff --git a/core/bloombits/matcher_test.go b/core/bloombits/matcher_test.go
index 36764c3f17..7f3d5f279c 100644
--- a/core/bloombits/matcher_test.go
+++ b/core/bloombits/matcher_test.go
@@ -85,7 +85,7 @@ func TestMatcherRandom(t *testing.T) {
}
// Tests that the matcher can properly find matches if the starting block is
-// shifter from a multiple of 8. This is needed to cover an optimisation with
+// shifted from a multiple of 8. This is needed to cover an optimisation with
// bitset matching https://github.com/ethereum/go-ethereum/issues/15309.
func TestMatcherShifted(t *testing.T) {
t.Parallel()
@@ -106,7 +106,7 @@ func TestWildcardMatcher(t *testing.T) {
testMatcherBothModes(t, nil, 0, 10000, 0)
}
-// makeRandomIndexes generates a random filter system, composed on multiple filter
+// makeRandomIndexes generates a random filter system, composed of multiple filter
// criteria, each having one bloom list component for the address and arbitrarily
// many topic bloom list components.
func makeRandomIndexes(lengths []int, max int) [][]bloomIndexes {
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 2988e3b847..932addc396 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/systemcontracts"
@@ -32,14 +33,15 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
// BlockGen creates blocks for testing.
// See GenerateChain for a detailed explanation.
type BlockGen struct {
i int
+ cm *chainMaker
parent *types.Block
- chain []*types.Block
header *types.Header
statedb *state.StateDB
@@ -49,7 +51,6 @@ type BlockGen struct {
uncles []*types.Header
withdrawals []*types.Withdrawal
- config *params.ChainConfig
engine consensus.Engine
}
@@ -88,6 +89,22 @@ func (b *BlockGen) SetPoS() {
b.header.Difficulty = new(big.Int)
}
+// Difficulty returns the currently calculated difficulty of the block.
+func (b *BlockGen) Difficulty() *big.Int {
+ return new(big.Int).Set(b.header.Difficulty)
+}
+
+// SetParentBeaconRoot sets the parent beacon root field of the generated
+// block.
+func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
+ b.header.ParentBeaconRoot = &root
+ var (
+ blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
+ vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.cm.config, vm.Config{})
+ )
+ ProcessBeaconBlockRoot(root, vmenv, b.statedb)
+}
+
// addTx adds a transaction to the generated block. If no coinbase has
// been set, the block's coinbase is set to the zero address.
//
@@ -100,22 +117,25 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
b.SetCoinbase(common.Address{})
}
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
- receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig, NewReceiptBloomGenerator())
+ receipt, err := ApplyTransaction(b.cm.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig, NewReceiptBloomGenerator())
if err != nil {
panic(err)
}
b.txs = append(b.txs, tx)
b.receipts = append(b.receipts, receipt)
+ if b.header.BlobGasUsed != nil {
+ *b.header.BlobGasUsed += receipt.BlobGasUsed
+ }
}
// AddTx adds a transaction to the generated block. If no coinbase has
// been set, the block's coinbase is set to the zero address.
//
-// AddTx panics if the transaction cannot be executed. In addition to
-// the protocol-imposed limitations (gas limit, etc.), there are some
-// further limitations on the content of transactions that can be
-// added. Notably, contract code relying on the BLOCKHASH instruction
-// will panic during execution.
+// AddTx panics if the transaction cannot be executed. In addition to the protocol-imposed
+// limitations (gas limit, etc.), there are some further limitations on the content of
+// transactions that can be added. Notably, contract code relying on the BLOCKHASH
+// instruction will panic during execution if it attempts to access a block number outside
+// of the range created by GenerateChain.
func (b *BlockGen) AddTx(tx *types.Transaction) {
b.addTx(nil, vm.Config{}, tx)
}
@@ -123,11 +143,10 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
// AddTxWithChain adds a transaction to the generated block. If no coinbase has
// been set, the block's coinbase is set to the zero address.
//
-// AddTxWithChain panics if the transaction cannot be executed. In addition to
-// the protocol-imposed limitations (gas limit, etc.), there are some
-// further limitations on the content of transactions that can be
-// added. If contract code relies on the BLOCKHASH instruction,
-// the block in chain will be returned.
+// AddTxWithChain panics if the transaction cannot be executed. In addition to the
+// protocol-imposed limitations (gas limit, etc.), there are some further limitations on
+// the content of transactions that can be added. If contract code relies on the BLOCKHASH
+// instruction, the block in chain will be returned.
func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
b.addTx(bc, vm.Config{}, tx)
}
@@ -140,12 +159,11 @@ func (b *BlockGen) AddTxWithVMConfig(tx *types.Transaction, config vm.Config) {
}
// GetBalance returns the balance of the given address at the generated block.
-func (b *BlockGen) GetBalance(addr common.Address) *big.Int {
+func (b *BlockGen) GetBalance(addr common.Address) *uint256.Int {
return b.statedb.GetBalance(addr)
}
-// AddUncheckedTx forcefully adds a transaction to the block without any
-// validation.
+// AddUncheckedTx forcefully adds a transaction to the block without any validation.
//
// AddUncheckedTx will cause consensus failures when used during real
// chain processing. This is best used in conjunction with raw block insertion.
@@ -168,6 +186,16 @@ func (b *BlockGen) BaseFee() *big.Int {
return new(big.Int).Set(b.header.BaseFee)
}
+// Gas returns the amount of gas left in the current block.
+func (b *BlockGen) Gas() uint64 {
+ return b.header.GasLimit - b.header.GasUsed
+}
+
+// Signer returns a valid signer instance for the current block.
+func (b *BlockGen) Signer() types.Signer {
+ return types.MakeSigner(b.cm.config, b.header.Number, b.header.Time)
+}
+
// AddUncheckedReceipt forcefully adds a receipts to the block without a
// backing transaction.
//
@@ -193,20 +221,19 @@ func (b *BlockGen) AddUncle(h *types.Header) {
var parent *types.Header
for i := b.i - 1; i >= 0; i-- {
- if b.chain[i].Hash() == h.ParentHash {
- parent = b.chain[i].Header()
+ if b.cm.chain[i].Hash() == h.ParentHash {
+ parent = b.cm.chain[i].Header()
break
}
}
- chainreader := &fakeChainReader{config: b.config}
- h.Difficulty = b.engine.CalcDifficulty(chainreader, b.header.Time, parent)
+ h.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, parent)
// The gas limit and price should be derived from the parent
h.GasLimit = parent.GasLimit
- if b.config.IsLondon(h.Number) {
- h.BaseFee = eip1559.CalcBaseFee(b.config, parent)
- if b.config.Parlia == nil && !b.config.IsLondon(parent.Number) {
- parentGasLimit := parent.GasLimit * b.config.ElasticityMultiplier()
+ if b.cm.config.IsLondon(h.Number) {
+ h.BaseFee = eip1559.CalcBaseFee(b.cm.config, parent)
+ if b.cm.config.Parlia == nil && !b.cm.config.IsLondon(parent.Number) {
+ parentGasLimit := parent.GasLimit * b.cm.config.ElasticityMultiplier()
h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
}
}
@@ -228,12 +255,12 @@ func (b *BlockGen) nextWithdrawalIndex() uint64 {
return b.withdrawals[len(b.withdrawals)-1].Index + 1
}
for i := b.i - 1; i >= 0; i-- {
- if wd := b.chain[i].Withdrawals(); len(wd) != 0 {
+ if wd := b.cm.chain[i].Withdrawals(); len(wd) != 0 {
return wd[len(wd)-1].Index + 1
}
if i == 0 {
// Correctly set the index if no parent had withdrawals.
- if wd := b.parent.Withdrawals(); len(wd) != 0 {
+ if wd := b.cm.bottom.Withdrawals(); len(wd) != 0 {
return wd[len(wd)-1].Index + 1
}
}
@@ -249,9 +276,9 @@ func (b *BlockGen) PrevBlock(index int) *types.Block {
panic(fmt.Errorf("block index %d out of range (%d,%d)", index, -1, b.i))
}
if index == -1 {
- return b.parent
+ return b.cm.bottom
}
- return b.chain[index]
+ return b.cm.chain[index]
}
// OffsetTime modifies the time instance of a block, implicitly changing its
@@ -259,11 +286,10 @@ func (b *BlockGen) PrevBlock(index int) *types.Block {
// tied to chain length directly.
func (b *BlockGen) OffsetTime(seconds int64) {
b.header.Time += uint64(seconds)
- if b.header.Time <= b.parent.Header().Time {
+ if b.header.Time <= b.cm.bottom.Header().Time {
panic("block time out of range")
}
- chainreader := &fakeChainReader{config: b.config}
- b.header.Difficulty = b.engine.CalcDifficulty(chainreader, b.header.Time, b.parent.Header())
+ b.header.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, b.parent.Header())
}
// GenerateChain creates a chain of n blocks. The first block's
@@ -282,11 +308,14 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if config == nil {
config = params.TestChainConfig
}
- blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
- chainreader := &fakeChainReader{config: config}
+ if engine == nil {
+ panic("nil consensus engine")
+ }
+ cm := newChainMaker(parent, config, engine)
+
genblock := func(i int, parent *types.Block, triedb *trie.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
- b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine}
- b.header = makeHeader(chainreader, parent, statedb, b.engine)
+ b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
+ b.header = cm.makeHeader(parent, statedb, b.engine)
// Set the difficulty for clique block. The chain maker doesn't have access
// to a chain, so the difficulty will be left unset (nil). Set it here to the
@@ -312,13 +341,17 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 {
misc.ApplyDAOHardFork(statedb)
}
- systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, parent.Time(), b.header.Time, statedb)
+
+ if !config.IsFeynman(b.header.Number, b.header.Time) {
+ systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, parent.Time(), b.header.Time, statedb)
+ }
+
// Execute any user modifications to the block
if gen != nil {
gen(i, b)
}
if b.engine != nil {
- block, _, err := b.engine.FinalizeAndAssemble(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts, b.withdrawals)
+ block, _, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, b.txs, b.uncles, b.receipts, b.withdrawals)
if err != nil {
panic(err)
}
@@ -335,6 +368,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
return nil, nil
}
+
// Forcibly use hash-based state scheme for retaining all nodes in disk.
triedb := trie.NewDatabase(db, trie.HashDefaults)
defer triedb.Close()
@@ -344,12 +378,36 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if err != nil {
panic(err)
}
- block, receipt := genblock(i, parent, triedb, statedb)
- blocks[i] = block
- receipts[i] = receipt
+ block, receipts := genblock(i, parent, triedb, statedb)
+
+ // Post-process the receipts.
+ // Here we assign the final block hash and other info into the receipt.
+ // In order for DeriveFields to work, the transaction and receipt lists need to be
+ // of equal length. If AddUncheckedTx or AddUncheckedReceipt are used, there will be
+ // extra ones, so we just trim the lists here.
+ receiptsCount := len(receipts)
+ txs := block.Transactions()
+ if len(receipts) > len(txs) {
+ receipts = receipts[:len(txs)]
+ } else if len(receipts) < len(txs) {
+ txs = txs[:len(receipts)]
+ }
+ var blobGasPrice *big.Int
+ if block.ExcessBlobGas() != nil {
+ blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas())
+ }
+ if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
+ panic(err)
+ }
+
+ // Re-expand to ensure all receipts are returned.
+ receipts = receipts[:receiptsCount]
+
+ // Advance the chain.
+ cm.add(block, receipts)
parent = block
}
- return blocks, receipts
+ return cm.chain, cm.receipts
}
// GenerateChainWithGenesis is a wrapper of GenerateChain which will initialize
@@ -367,34 +425,39 @@ func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int,
return db, blocks, receipts
}
-func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
- var time uint64
- if parent.Time() == 0 {
- time = 10
- } else {
- time = parent.Time() + 10 // block time is fixed at 10 seconds
- }
+func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
+ time := parent.Time() + 10 // block time is fixed at 10 seconds
header := &types.Header{
- Root: state.IntermediateRoot(chain.Config().IsEIP158(parent.Number())),
+ Root: state.IntermediateRoot(cm.config.IsEIP158(parent.Number())),
ParentHash: parent.Hash(),
Coinbase: parent.Coinbase(),
- Difficulty: engine.CalcDifficulty(chain, time, &types.Header{
- Number: parent.Number(),
- Time: time - 10,
- Difficulty: parent.Difficulty(),
- UncleHash: parent.UncleHash(),
- }),
- GasLimit: parent.GasLimit(),
- Number: new(big.Int).Add(parent.Number(), common.Big1),
- Time: time,
+ Difficulty: engine.CalcDifficulty(cm, time, parent.Header()),
+ GasLimit: parent.GasLimit(),
+ Number: new(big.Int).Add(parent.Number(), common.Big1),
+ Time: time,
}
- if chain.Config().IsLondon(header.Number) {
- header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header())
- if chain.Config().Parlia == nil && !chain.Config().IsLondon(parent.Number()) {
- parentGasLimit := parent.GasLimit() * chain.Config().ElasticityMultiplier()
+
+ if cm.config.IsLondon(header.Number) {
+ header.BaseFee = eip1559.CalcBaseFee(cm.config, parent.Header())
+ if cm.config.Parlia == nil && !cm.config.IsLondon(parent.Number()) {
+ parentGasLimit := parent.GasLimit() * cm.config.ElasticityMultiplier()
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
}
}
+ if cm.config.IsCancun(header.Number, header.Time) {
+ var (
+ parentExcessBlobGas uint64
+ parentBlobGasUsed uint64
+ )
+ if parent.ExcessBlobGas() != nil {
+ parentExcessBlobGas = *parent.ExcessBlobGas()
+ parentBlobGasUsed = *parent.BlobGasUsed()
+ }
+ excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed)
+ header.ExcessBlobGas = &excessBlobGas
+ header.BlobGasUsed = new(uint64)
+ header.ParentBeaconRoot = new(common.Hash)
+ }
return header
}
@@ -434,19 +497,94 @@ func makeBlockChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine,
return db, blocks
}
-type fakeChainReader struct {
- config *params.ChainConfig
+// chainMaker contains the state of chain generation.
+type chainMaker struct {
+ bottom *types.Block
+ engine consensus.Engine
+ config *params.ChainConfig
+ chain []*types.Block
+ chainByHash map[common.Hash]*types.Block
+ receipts []types.Receipts
+}
+
+func newChainMaker(bottom *types.Block, config *params.ChainConfig, engine consensus.Engine) *chainMaker {
+ return &chainMaker{
+ bottom: bottom,
+ config: config,
+ engine: engine,
+ chainByHash: make(map[common.Hash]*types.Block),
+ }
}
-// Config returns the chain configuration.
-func (cr *fakeChainReader) Config() *params.ChainConfig {
- return cr.config
+func (cm *chainMaker) add(b *types.Block, r []*types.Receipt) {
+ cm.chain = append(cm.chain, b)
+ cm.chainByHash[b.Hash()] = b
+ cm.receipts = append(cm.receipts, r)
}
-func (cr *fakeChainReader) CurrentHeader() *types.Header { return nil }
-func (cr *fakeChainReader) GetHeaderByNumber(number uint64) *types.Header { return nil }
-func (cr *fakeChainReader) GetHeaderByHash(hash common.Hash) *types.Header { return nil }
-func (cr *fakeChainReader) GetHeader(hash common.Hash, number uint64) *types.Header { return nil }
-func (cr *fakeChainReader) GetBlock(hash common.Hash, number uint64) *types.Block { return nil }
-func (cr *fakeChainReader) GetHighestVerifiedHeader() *types.Header { return nil }
-func (cr *fakeChainReader) GetTd(hash common.Hash, number uint64) *big.Int { return nil }
+func (cm *chainMaker) blockByNumber(number uint64) *types.Block {
+ if number == cm.bottom.NumberU64() {
+ return cm.bottom
+ }
+ cur := cm.CurrentHeader().Number.Uint64()
+ lowest := cm.bottom.NumberU64() + 1
+ if number < lowest || number > cur {
+ return nil
+ }
+ return cm.chain[number-lowest]
+}
+
+// ChainReader/ChainContext implementation
+
+// Config returns the chain configuration (for consensus.ChainReader).
+func (cm *chainMaker) Config() *params.ChainConfig {
+ return cm.config
+}
+
+// Engine returns the consensus engine (for ChainContext).
+func (cm *chainMaker) Engine() consensus.Engine {
+ return cm.engine
+}
+
+func (cm *chainMaker) CurrentHeader() *types.Header {
+ if len(cm.chain) == 0 {
+ return cm.bottom.Header()
+ }
+ return cm.chain[len(cm.chain)-1].Header()
+}
+
+func (cm *chainMaker) GetHeaderByNumber(number uint64) *types.Header {
+ b := cm.blockByNumber(number)
+ if b == nil {
+ return nil
+ }
+ return b.Header()
+}
+
+func (cm *chainMaker) GetHeaderByHash(hash common.Hash) *types.Header {
+ b := cm.chainByHash[hash]
+ if b == nil {
+ return nil
+ }
+ return b.Header()
+}
+
+func (cm *chainMaker) GenesisHeader() *types.Header {
+ panic("not supported")
+}
+
+func (cm *chainMaker) GetHeader(hash common.Hash, number uint64) *types.Header {
+ return cm.GetHeaderByNumber(number)
+}
+
+func (cm *chainMaker) GetBlock(hash common.Hash, number uint64) *types.Block {
+ return cm.blockByNumber(number)
+}
+
+func (cm *chainMaker) GetTd(hash common.Hash, number uint64) *big.Int {
+ return nil // not supported
+}
+
+func (cm *chainMaker) GetHighestVerifiedHeader() *types.Header {
+ panic("not supported")
+}
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index db220cf24a..84148841f5 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -19,8 +19,10 @@ package core
import (
"fmt"
"math/big"
+ "reflect"
"testing"
+ "github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
@@ -32,7 +34,7 @@ import (
"github.com/ethereum/go-ethereum/trie"
)
-func TestGenerateWithdrawalChain(t *testing.T) {
+func TestGeneratePOSChain(t *testing.T) {
var (
keyHex = "9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"
key, _ = crypto.HexToECDSA(keyHex)
@@ -41,21 +43,25 @@ func TestGenerateWithdrawalChain(t *testing.T) {
bb = common.Address{0xbb}
funds = big.NewInt(0).Mul(big.NewInt(1337), big.NewInt(params.Ether))
config = *params.AllEthashProtocolChanges
+ asm4788 = common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500")
gspec = &Genesis{
- Config: &config,
- Alloc: GenesisAlloc{address: {Balance: funds}},
+ Config: &config,
+ Alloc: GenesisAlloc{
+ address: {Balance: funds},
+ params.BeaconRootsStorageAddress: {Balance: common.Big0, Code: asm4788},
+ },
BaseFee: big.NewInt(params.InitialBaseFee),
Difficulty: common.Big1,
GasLimit: 5_000_000,
}
- gendb = rawdb.NewMemoryDatabase()
- signer = types.LatestSigner(gspec.Config)
- db = rawdb.NewMemoryDatabase()
+ gendb = rawdb.NewMemoryDatabase()
+ db = rawdb.NewMemoryDatabase()
)
config.TerminalTotalDifficultyPassed = true
config.TerminalTotalDifficulty = common.Big0
config.ShanghaiTime = u64(0)
+ config.CancunTime = u64(0)
// init 0xaa with some storage elements
storage := make(map[common.Hash]common.Hash)
@@ -77,9 +83,20 @@ func TestGenerateWithdrawalChain(t *testing.T) {
}
genesis := gspec.MustCommit(gendb, trie.NewDatabase(gendb, trie.HashDefaults))
- chain, _ := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) {
- tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(address), address, big.NewInt(1000), params.TxGas, new(big.Int).Add(gen.BaseFee(), common.Big1), nil), signer, key)
+ genchain, genreceipts := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) {
+ gen.SetParentBeaconRoot(common.Hash{byte(i + 1)})
+
+ // Add value transfer tx.
+ tx := types.MustSignNewTx(key, gen.Signer(), &types.LegacyTx{
+ Nonce: gen.TxNonce(address),
+ To: &address,
+ Value: big.NewInt(1000),
+ Gas: params.TxGas,
+ GasPrice: new(big.Int).Add(gen.BaseFee(), common.Big1),
+ })
gen.AddTx(tx)
+
+ // Add withdrawals.
if i == 1 {
gen.AddWithdrawal(&types.Withdrawal{
Validator: 42,
@@ -110,21 +127,42 @@ func TestGenerateWithdrawalChain(t *testing.T) {
blockchain, _ := NewBlockChain(db, nil, gspec, nil, beacon.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop()
- if i, err := blockchain.InsertChain(chain); err != nil {
- fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
- return
+ if i, err := blockchain.InsertChain(genchain); err != nil {
+ t.Fatalf("insert error (block %d): %v\n", genchain[i].NumberU64(), err)
}
// enforce that withdrawal indexes are monotonically increasing from 0
var (
withdrawalIndex uint64
- head = blockchain.CurrentBlock().Number.Uint64()
)
- for i := 0; i < int(head); i++ {
- block := blockchain.GetBlockByNumber(uint64(i))
+ for i := range genchain {
+ blocknum := genchain[i].NumberU64()
+ block := blockchain.GetBlockByNumber(blocknum)
if block == nil {
- t.Fatalf("block %d not found", i)
+ t.Fatalf("block %d not found", blocknum)
+ }
+
+ // Verify receipts.
+ genBlockReceipts := genreceipts[i]
+ for _, r := range genBlockReceipts {
+ if r.BlockNumber.Cmp(block.Number()) != 0 {
+ t.Errorf("receipt has wrong block number %d, want %d", r.BlockNumber, block.Number())
+ }
+ if r.BlockHash != block.Hash() {
+ t.Errorf("receipt has wrong block hash %v, want %v", r.BlockHash, block.Hash())
+ }
+
+ // patch up empty logs list to make DeepEqual below work
+ if r.Logs == nil {
+ r.Logs = []*types.Log{}
+ }
+ }
+ blockchainReceipts := blockchain.GetReceiptsByHash(block.Hash())
+ if !reflect.DeepEqual(genBlockReceipts, blockchainReceipts) {
+ t.Fatalf("receipts mismatch\ngenerated: %s\nblockchain: %s", spew.Sdump(genBlockReceipts), spew.Sdump(blockchainReceipts))
}
+
+ // Verify withdrawals.
if len(block.Withdrawals()) == 0 {
continue
}
@@ -134,6 +172,18 @@ func TestGenerateWithdrawalChain(t *testing.T) {
}
withdrawalIndex += 1
}
+
+ // Verify parent beacon root.
+ want := common.Hash{byte(blocknum)}
+ if got := block.BeaconRoot(); *got != want {
+ t.Fatalf("block %d, wrong parent beacon root: got %s, want %s", i, got, want)
+ }
+ state, _ := blockchain.State()
+ idx := block.Time()%8191 + 8191
+ got := state.GetState(params.BeaconRootsStorageAddress, common.BigToHash(new(big.Int).SetUint64(idx)))
+ if got != want {
+ t.Fatalf("block %d, wrong parent beacon root in state: got %s, want %s", i, got, want)
+ }
}
}
diff --git a/core/error.go b/core/error.go
index 028c16733a..07ff770432 100644
--- a/core/error.go
+++ b/core/error.go
@@ -113,4 +113,10 @@ var (
// ErrBlobFeeCapTooLow is returned if the transaction fee cap is less than the
// blob gas fee of the block.
ErrBlobFeeCapTooLow = errors.New("max fee per blob gas less than block blob gas fee")
+
+ // ErrMissingBlobHashes is returned if a blob transaction has no blob hashes.
+ ErrMissingBlobHashes = errors.New("blob transaction missing blob hashes")
+
+ // ErrBlobTxCreate is returned if a blob transaction has no explicit to field.
+ ErrBlobTxCreate = errors.New("blob transaction of type create")
)
diff --git a/core/evm.go b/core/evm.go
index 104f2c09dc..73f6d7bc20 100644
--- a/core/evm.go
+++ b/core/evm.go
@@ -21,8 +21,10 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/holiman/uint256"
)
// ChainContext supports retrieving headers and consensus parameters from the
@@ -40,6 +42,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
var (
beneficiary common.Address
baseFee *big.Int
+ blobBaseFee *big.Int
random *common.Hash
)
@@ -52,31 +55,38 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
if header.BaseFee != nil {
baseFee = new(big.Int).Set(header.BaseFee)
}
+ if header.ExcessBlobGas != nil {
+ blobBaseFee = eip4844.CalcBlobFee(*header.ExcessBlobGas)
+ }
if header.Difficulty.Cmp(common.Big0) == 0 {
random = &header.MixDigest
}
return vm.BlockContext{
- CanTransfer: CanTransfer,
- Transfer: Transfer,
- GetHash: GetHashFn(header, chain),
- Coinbase: beneficiary,
- BlockNumber: new(big.Int).Set(header.Number),
- Time: header.Time,
- Difficulty: new(big.Int).Set(header.Difficulty),
- BaseFee: baseFee,
- GasLimit: header.GasLimit,
- Random: random,
- ExcessBlobGas: header.ExcessBlobGas,
+ CanTransfer: CanTransfer,
+ Transfer: Transfer,
+ GetHash: GetHashFn(header, chain),
+ Coinbase: beneficiary,
+ BlockNumber: new(big.Int).Set(header.Number),
+ Time: header.Time,
+ Difficulty: new(big.Int).Set(header.Difficulty),
+ BaseFee: baseFee,
+ BlobBaseFee: blobBaseFee,
+ GasLimit: header.GasLimit,
+ Random: random,
}
}
// NewEVMTxContext creates a new transaction context for a single transaction.
func NewEVMTxContext(msg *Message) vm.TxContext {
- return vm.TxContext{
+ ctx := vm.TxContext{
Origin: msg.From,
GasPrice: new(big.Int).Set(msg.GasPrice),
BlobHashes: msg.BlobHashes,
}
+ if msg.BlobGasFeeCap != nil {
+ ctx.BlobFeeCap = new(big.Int).Set(msg.BlobGasFeeCap)
+ }
+ return ctx
}
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
@@ -120,12 +130,12 @@ func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash
// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
// This does not take the necessary gas in to account to make the transfer valid.
-func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
+func CanTransfer(db vm.StateDB, addr common.Address, amount *uint256.Int) bool {
return db.GetBalance(addr).Cmp(amount) >= 0
}
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
-func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {
+func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int) {
db.SubBalance(sender, amount)
db.AddBalance(recipient, amount)
}
diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go
index 85b0daa96b..1000b18530 100644
--- a/core/forkid/forkid.go
+++ b/core/forkid/forkid.go
@@ -73,12 +73,12 @@ type ID struct {
type Filter func(id ID) error
// NewID calculates the Ethereum fork ID from the chain config, genesis hash, head and time.
-func NewID(config *params.ChainConfig, genesis common.Hash, head, time uint64) ID {
+func NewID(config *params.ChainConfig, genesis *types.Block, head, time uint64) ID {
// Calculate the starting checksum from the genesis hash
- hash := crc32.ChecksumIEEE(genesis[:])
+ hash := crc32.ChecksumIEEE(genesis.Hash().Bytes())
// Calculate the current fork checksum and the next fork block
- forksByBlock, forksByTime := gatherForks(config)
+ forksByBlock, forksByTime := gatherForks(config, genesis.Time())
for _, fork := range forksByBlock {
if fork <= head {
// Fork already passed, checksum the previous hash and the fork number
@@ -99,12 +99,12 @@ func NewID(config *params.ChainConfig, genesis common.Hash, head, time uint64) I
}
// NextForkHash calculates the forkHash from genesis to the next fork block number or time
-func NextForkHash(config *params.ChainConfig, genesis common.Hash, head uint64, time uint64) [4]byte {
+func NextForkHash(config *params.ChainConfig, genesisHash common.Hash, genesisTime uint64, head uint64, time uint64) [4]byte {
// Calculate the starting checksum from the genesis hash
- hash := crc32.ChecksumIEEE(genesis[:])
+ hash := crc32.ChecksumIEEE(genesisHash[:])
// Calculate the next fork checksum
- forksByBlock, forksByTime := gatherForks(config)
+ forksByBlock, forksByTime := gatherForks(config, genesisTime)
for _, fork := range forksByBlock {
if fork > head {
// Checksum the previous hash and nextFork number and return
@@ -130,7 +130,7 @@ func NewIDWithChain(chain Blockchain) ID {
return NewID(
chain.Config(),
- chain.Genesis().Hash(),
+ chain.Genesis(),
head.Number.Uint64(),
head.Time,
)
@@ -141,7 +141,7 @@ func NewIDWithChain(chain Blockchain) ID {
func NewFilter(chain Blockchain) Filter {
return newFilter(
chain.Config(),
- chain.Genesis().Hash(),
+ chain.Genesis(),
func() (uint64, uint64) {
head := chain.CurrentHeader()
return head.Number.Uint64(), head.Time
@@ -150,7 +150,7 @@ func NewFilter(chain Blockchain) Filter {
}
// NewStaticFilter creates a filter at block zero.
-func NewStaticFilter(config *params.ChainConfig, genesis common.Hash) Filter {
+func NewStaticFilter(config *params.ChainConfig, genesis *types.Block) Filter {
head := func() (uint64, uint64) { return 0, 0 }
return newFilter(config, genesis, head)
}
@@ -158,14 +158,14 @@ func NewStaticFilter(config *params.ChainConfig, genesis common.Hash) Filter {
// newFilter is the internal version of NewFilter, taking closures as its arguments
// instead of a chain. The reason is to allow testing it without having to simulate
// an entire blockchain.
-func newFilter(config *params.ChainConfig, genesis common.Hash, headfn func() (uint64, uint64)) Filter {
+func newFilter(config *params.ChainConfig, genesis *types.Block, headfn func() (uint64, uint64)) Filter {
// Calculate the all the valid fork hash and fork next combos
var (
- forksByBlock, forksByTime = gatherForks(config)
+ forksByBlock, forksByTime = gatherForks(config, genesis.Time())
forks = append(append([]uint64{}, forksByBlock...), forksByTime...)
sums = make([][4]byte, len(forks)+1) // 0th is the genesis
)
- hash := crc32.ChecksumIEEE(genesis[:])
+ hash := crc32.ChecksumIEEE(genesis.Hash().Bytes())
sums[0] = checksumToBytes(hash)
for i, fork := range forks {
hash = checksumUpdate(hash, fork)
@@ -266,7 +266,7 @@ func checksumToBytes(hash uint32) [4]byte {
// gatherForks gathers all the known forks and creates two sorted lists out of
// them, one for the block number based forks and the second for the timestamps.
-func gatherForks(config *params.ChainConfig) ([]uint64, []uint64) {
+func gatherForks(config *params.ChainConfig, genesis uint64) ([]uint64, []uint64) {
// Gather all the fork block numbers via reflection
kind := reflect.TypeOf(params.ChainConfig{})
conf := reflect.ValueOf(config).Elem()
@@ -316,7 +316,8 @@ func gatherForks(config *params.ChainConfig) ([]uint64, []uint64) {
if len(forksByBlock) > 0 && forksByBlock[0] == 0 {
forksByBlock = forksByBlock[1:]
}
- if len(forksByTime) > 0 && forksByTime[0] == 0 {
+ // Skip any forks before genesis.
+ for len(forksByTime) > 0 && forksByTime[0] <= genesis {
forksByTime = forksByTime[1:]
}
return forksByBlock, forksByTime
diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go
index d8fa2cd2a3..0034e68d72 100644
--- a/core/forkid/forkid_test.go
+++ b/core/forkid/forkid_test.go
@@ -18,10 +18,14 @@ package forkid
import (
"bytes"
+ "hash/crc32"
"math"
+ "math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -36,13 +40,13 @@ func TestCreation(t *testing.T) {
}
tests := []struct {
config *params.ChainConfig
- genesis common.Hash
+ genesis *types.Block
cases []testcase
}{
// Mainnet test cases
{
params.MainnetChainConfig,
- params.MainnetGenesisHash,
+ core.DefaultGenesisBlock().ToBlock(),
[]testcase{
{0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Unsynced
{1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Last Frontier block
@@ -323,8 +327,9 @@ func TestValidation(t *testing.T) {
// TODO(karalabe): Enable this when Cancun is specced
//{params.MainnetChainConfig, 20999999, 1677999999, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, ErrLocalIncompatibleOrStale},
}
+ genesis := core.DefaultGenesisBlock().ToBlock()
for i, tt := range tests {
- filter := newFilter(tt.config, params.MainnetGenesisHash, func() (uint64, uint64) { return tt.head, tt.time })
+ filter := newFilter(tt.config, genesis, func() (uint64, uint64) { return tt.head, tt.time })
if err := filter(tt.id); err != tt.err {
t.Errorf("test %d: validation error mismatch: have %v, want %v", i, err, tt.err)
}
@@ -353,3 +358,55 @@ func TestEncoding(t *testing.T) {
}
}
}
+
+// Tests that time-based forks which are active at genesis are not included in
+// forkid hash.
+func TestTimeBasedForkInGenesis(t *testing.T) {
+ var (
+ time = uint64(1690475657)
+ genesis = types.NewBlockWithHeader(&types.Header{Time: time})
+ forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes()))
+ config = func(shanghai, cancun uint64) *params.ChainConfig {
+ return ¶ms.ChainConfig{
+ ChainID: big.NewInt(1337),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ TerminalTotalDifficulty: big.NewInt(0),
+ TerminalTotalDifficultyPassed: true,
+ MergeNetsplitBlock: big.NewInt(0),
+ ShanghaiTime: &shanghai,
+ CancunTime: &cancun,
+ Ethash: new(params.EthashConfig),
+ }
+ }
+ )
+ tests := []struct {
+ config *params.ChainConfig
+ want ID
+ }{
+ // Shanghai active before genesis, skip
+ {config(time-1, time+1), ID{Hash: forkidHash, Next: time + 1}},
+
+ // Shanghai active at genesis, skip
+ {config(time, time+1), ID{Hash: forkidHash, Next: time + 1}},
+
+ // Shanghai not active, skip
+ {config(time+1, time+2), ID{Hash: forkidHash, Next: time + 1}},
+ }
+ for _, tt := range tests {
+ if have := NewID(tt.config, genesis, 0, time); have != tt.want {
+ t.Fatalf("incorrect forkid hash: have %x, want %x", have, tt.want)
+ }
+ }
+}
diff --git a/core/gen_genesis.go b/core/gen_genesis.go
index 5cd006917c..38614252a3 100644
--- a/core/gen_genesis.go
+++ b/core/gen_genesis.go
@@ -31,8 +31,8 @@ func (g Genesis) MarshalJSON() ([]byte, error) {
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
- ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty" toml:",omitempty"`
- BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty" toml:",omitempty"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
+ BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
}
var enc Genesis
enc.Config = g.Config
@@ -74,8 +74,8 @@ func (g *Genesis) UnmarshalJSON(input []byte) error {
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
ParentHash *common.Hash `json:"parentHash"`
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
- ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas,omitempty" toml:",omitempty"`
- BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty" toml:",omitempty"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
+ BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
}
var dec Genesis
if err := json.Unmarshal(input, &dec); err != nil {
diff --git a/core/genesis.go b/core/genesis.go
index bd565e7d3f..1070f470e6 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -37,6 +37,8 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/holiman/uint256"
)
//go:generate go run github.com/fjl/gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
@@ -62,9 +64,9 @@ type Genesis struct {
Number uint64 `json:"number"`
GasUsed uint64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
- BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
- ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
- BlobGasUsed *uint64 `json:"blobGasUsed,omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
+ BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
+ ExcessBlobGas *uint64 `json:"excessBlobGas"` // EIP-4844
+ BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844
}
func ReadGenesis(db ethdb.Database) (*Genesis, error) {
@@ -121,16 +123,28 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
}
// hash computes the state root according to the genesis specification.
-func (ga *GenesisAlloc) hash() (common.Hash, error) {
+func (ga *GenesisAlloc) hash(isVerkle bool) (common.Hash, error) {
+ // If a genesis-time verkle trie is requested, create a trie config
+ // with the verkle trie enabled so that the tree can be initialized
+ // as such.
+ var config *trie.Config
+ if isVerkle {
+ config = &trie.Config{
+ PathDB: pathdb.Defaults,
+ IsVerkle: true,
+ }
+ }
// Create an ephemeral in-memory database for computing hash,
// all the derived states will be discarded to not pollute disk.
- db := state.NewDatabase(rawdb.NewMemoryDatabase())
+ db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config)
statedb, err := state.New(types.EmptyRootHash, db, nil)
if err != nil {
return common.Hash{}, err
}
for addr, account := range *ga {
- statedb.AddBalance(addr, account.Balance)
+ if account.Balance != nil {
+ statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
+ }
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
for key, value := range account.Storage {
@@ -155,7 +169,9 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
return err
}
for addr, account := range *ga {
- statedb.AddBalance(addr, account.Balance)
+ if account.Balance != nil {
+ statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
+ }
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
for key, value := range account.Storage {
@@ -182,35 +198,6 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
return nil
}
-// CommitGenesisState loads the stored genesis state with the given block
-// hash and commits it into the provided trie database.
-func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
- var alloc GenesisAlloc
- blob := rawdb.ReadGenesisStateSpec(db, blockhash)
- if len(blob) != 0 {
- if err := alloc.UnmarshalJSON(blob); err != nil {
- return err
- }
- } else {
- // Genesis allocation is missing and there are several possibilities:
- // the node is legacy which doesn't persist the genesis allocation or
- // the persisted allocation is just lost.
- // - supported networks(mainnet, testnets), recover with defined allocations
- // - private network, can't recover
- var genesis *Genesis
- switch blockhash {
- case params.BSCGenesisHash:
- genesis = DefaultBSCGenesisBlock()
- }
- if genesis != nil {
- alloc = genesis.Alloc
- } else {
- return errors.New("not found")
- }
- }
- return alloc.flush(db, triedb, blockhash)
-}
-
// GenesisAccount is an account in the state of the genesis block.
type GenesisAccount struct {
Code []byte `json:"code,omitempty"`
@@ -280,6 +267,7 @@ type ChainOverrides struct {
OverrideKepler *uint64
OverrideCancun *uint64
OverrideVerkle *uint64
+ OverrideFeynman *uint64
}
// SetupGenesisBlock writes or updates the genesis block in db.
@@ -317,6 +305,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
if overrides != nil && overrides.OverrideVerkle != nil {
config.VerkleTime = overrides.OverrideVerkle
}
+ if overrides != nil && overrides.OverrideFeynman != nil {
+ config.FeynmanTime = overrides.OverrideFeynman
+ }
}
}
// Just commit the new block if there is no stored genesis block.
@@ -328,11 +319,11 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
} else {
log.Info("Writing custom genesis block")
}
+ applyOverrides(genesis.Config)
block, err := genesis.Commit(db, triedb)
if err != nil {
return genesis.Config, common.Hash{}, err
}
- applyOverrides(genesis.Config)
log.Info("genesis block hash", "hash", block.Hash())
return genesis.Config, block.Hash(), nil
}
@@ -345,6 +336,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
if genesis == nil {
genesis = DefaultBSCGenesisBlock()
}
+ applyOverrides(genesis.Config)
// Ensure the stored genesis matches with the given one.
hash := genesis.ToBlock().Hash()
if hash != stored {
@@ -354,11 +346,11 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
if err != nil {
return genesis.Config, hash, err
}
- applyOverrides(genesis.Config)
return genesis.Config, block.Hash(), nil
}
// Check whether the genesis block is already written.
if genesis != nil {
+ applyOverrides(genesis.Config)
hash := genesis.ToBlock().Hash()
if hash != stored {
return genesis.Config, hash, &GenesisMismatchError{stored, hash}
@@ -453,9 +445,15 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
return params.AllEthashProtocolChanges
}
+// IsVerkle indicates whether the state is already stored in a verkle
+// tree at genesis time.
+func (g *Genesis) IsVerkle() bool {
+ return g.Config.IsVerkle(new(big.Int).SetUint64(g.Number), g.Timestamp)
+}
+
// ToBlock returns the genesis block according to genesis specification.
func (g *Genesis) ToBlock() *types.Block {
- root, err := g.Alloc.hash()
+ root, err := g.Alloc.hash(g.IsVerkle())
if err != nil {
panic(err)
}
@@ -483,7 +481,11 @@ func (g *Genesis) ToBlock() *types.Block {
if g.BaseFee != nil {
head.BaseFee = g.BaseFee
} else {
- head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
+ if g.Config.Parlia != nil {
+ head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFeeForBSC)
+ } else {
+ head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
+ }
}
}
var withdrawals []*types.Withdrawal
@@ -494,6 +496,11 @@ func (g *Genesis) ToBlock() *types.Block {
withdrawals = make([]*types.Withdrawal, 0)
}
if conf.IsCancun(num, g.Timestamp) {
+ // EIP-4788: The parentBeaconBlockRoot of the genesis block is always
+ // the zero hash. This is because the genesis block does not have a parent
+ // by definition.
+ head.ParentBeaconRoot = new(common.Hash)
+ // EIP-4844 fields
head.ExcessBlobGas = g.ExcessBlobGas
head.BlobGasUsed = g.BlobGasUsed
if head.ExcessBlobGas == nil {
@@ -596,16 +603,16 @@ func DefaultChapelGenesisBlock() *Genesis {
}
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
-func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis {
+func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
// Override the default period to the user requested one
config := *params.AllDevChainProtocolChanges
// Assemble and return the genesis with the precompiles and faucet pre-funded
- return &Genesis{
+ genesis := &Genesis{
Config: &config,
GasLimit: gasLimit,
BaseFee: big.NewInt(params.InitialBaseFee),
- Difficulty: big.NewInt(0),
+ Difficulty: big.NewInt(1),
Alloc: map[common.Address]GenesisAccount{
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
@@ -616,9 +623,12 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet common.Address) *Genesis {
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
- faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
},
}
+ if faucet != nil {
+ genesis.Alloc[*faucet] = GenesisAccount{Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}
+ }
+ return genesis
}
func decodePrealloc(data string) GenesisAlloc {
diff --git a/core/genesis_test.go b/core/genesis_test.go
index a91d0ff3c2..aeaa1dd979 100644
--- a/core/genesis_test.go
+++ b/core/genesis_test.go
@@ -17,6 +17,7 @@
package core
import (
+ "bytes"
"encoding/json"
"math/big"
"reflect"
@@ -93,6 +94,17 @@ func testSetupGenesis(t *testing.T, scheme string) {
wantHash: customghash,
wantConfig: customg.Config,
},
+ {
+ name: "custom block in DB, genesis == chapel",
+ fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
+ tdb := trie.NewDatabase(db, newDbConfig(scheme))
+ customg.Commit(db, tdb)
+ return SetupGenesisBlock(db, tdb, DefaultChapelGenesisBlock())
+ },
+ wantErr: &GenesisMismatchError{Stored: customghash, New: params.ChapelGenesisHash},
+ wantHash: params.ChapelGenesisHash,
+ wantConfig: params.ChapelChainConfig,
+ },
{
name: "compatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
@@ -209,7 +221,7 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
{2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
}
- hash, _ = alloc.hash()
+ hash, _ = alloc.hash(false)
)
blob, _ := json.Marshal(alloc)
rawdb.WriteGenesisStateSpec(db, hash, blob)
@@ -264,3 +276,66 @@ func newDbConfig(scheme string) *trie.Config {
}
return &trie.Config{PathDB: pathdb.Defaults}
}
+
+func TestVerkleGenesisCommit(t *testing.T) {
+ var verkleTime uint64 = 0
+ verkleConfig := ¶ms.ChainConfig{
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: big.NewInt(0),
+ GrayGlacierBlock: big.NewInt(0),
+ MergeNetsplitBlock: nil,
+ ShanghaiTime: &verkleTime,
+ CancunTime: &verkleTime,
+ PragueTime: &verkleTime,
+ VerkleTime: &verkleTime,
+ TerminalTotalDifficulty: big.NewInt(0),
+ TerminalTotalDifficultyPassed: true,
+ Ethash: nil,
+ Clique: nil,
+ }
+
+ genesis := &Genesis{
+ BaseFee: big.NewInt(params.InitialBaseFee),
+ Config: verkleConfig,
+ Timestamp: verkleTime,
+ Difficulty: big.NewInt(0),
+ Alloc: GenesisAlloc{
+ {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
+ },
+ }
+
+ expected := common.Hex2Bytes("14398d42be3394ff8d50681816a4b7bf8d8283306f577faba2d5bc57498de23b")
+ got := genesis.ToBlock().Root().Bytes()
+ if !bytes.Equal(got, expected) {
+ t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got)
+ }
+
+ db := rawdb.NewMemoryDatabase()
+ triedb := trie.NewDatabase(db, &trie.Config{IsVerkle: true, PathDB: pathdb.Defaults})
+ block := genesis.MustCommit(db, triedb)
+ if !bytes.Equal(block.Root().Bytes(), expected) {
+ t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got)
+ }
+
+ // Test that the trie is verkle
+ if !triedb.IsVerkle() {
+ t.Fatalf("expected trie to be verkle")
+ }
+
+ if !rawdb.ExistsAccountTrieNode(db, nil) {
+ t.Fatal("could not find node")
+ }
+}
diff --git a/core/headerchain.go b/core/headerchain.go
index bdf99c2e5b..93aad2b56b 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -134,6 +134,10 @@ func (hc *HeaderChain) getFinalizedNumber(header *types.Header) uint64 {
return 0
}
+func (hc *HeaderChain) GenesisHeader() *types.Header {
+ panic("not supported")
+}
+
// GetBlockNumber retrieves the block number belonging to the given hash
// from the cache or database
func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 {
diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go
index 5555a7aa4c..1a7552d698 100644
--- a/core/rawdb/accessors_chain.go
+++ b/core/rawdb/accessors_chain.go
@@ -262,23 +262,6 @@ func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) {
}
}
-// ReadFastTxLookupLimit retrieves the tx lookup limit used in fast sync.
-func ReadFastTxLookupLimit(db ethdb.KeyValueReader) *uint64 {
- data, _ := db.Get(fastTxLookupLimitKey)
- if len(data) != 8 {
- return nil
- }
- number := binary.BigEndian.Uint64(data)
- return &number
-}
-
-// WriteFastTxLookupLimit stores the txlookup limit used in fast sync into database.
-func WriteFastTxLookupLimit(db ethdb.KeyValueWriter, number uint64) {
- if err := db.Put(fastTxLookupLimitKey, encodeBlockNumber(number)); err != nil {
- log.Crit("Failed to store transaction lookup limit for fast sync", "err", err)
- }
-}
-
// ReadHeaderRange returns the rlp-encoded headers, starting at 'number', and going
// backwards towards genesis. This method assumes that the caller already has
// placed a cap on count, to prevent DoS issues.
@@ -318,13 +301,18 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
return rlpHeaders
}
// read remaining from ancients
- max := count * 700 * 3
- data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, max)
- if err == nil && uint64(len(data)) == count {
- // the data is on the order [h, h+1, .., n] -- reordering needed
- for i := range data {
- rlpHeaders = append(rlpHeaders, data[len(data)-1-i])
- }
+ data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, 0)
+ if err != nil {
+ log.Error("Failed to read headers from freezer", "err", err)
+ return rlpHeaders
+ }
+ if uint64(len(data)) != count {
+ log.Warn("Incomplete read of headers from freezer", "wanted", count, "read", len(data))
+ return rlpHeaders
+ }
+ // The data is on the order [h, h+1, .., n] -- reordering needed
+ for i := range data {
+ rlpHeaders = append(rlpHeaders, data[len(data)-1-i])
}
return rlpHeaders
}
@@ -365,7 +353,7 @@ func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header
return nil
}
header := new(types.Header)
- if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
+ if err := rlp.DecodeBytes(data, header); err != nil {
log.Error("Invalid block header RLP", "hash", hash, "err", err)
return nil
}
@@ -482,7 +470,7 @@ func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body {
return nil
}
body := new(types.Body)
- if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
+ if err := rlp.DecodeBytes(data, body); err != nil {
log.Error("Invalid block body RLP", "hash", hash, "err", err)
return nil
}
@@ -566,7 +554,7 @@ func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int {
return nil
}
td := new(big.Int)
- if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
+ if err := rlp.DecodeBytes(data, td); err != nil {
log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err)
return nil
}
@@ -753,7 +741,7 @@ func deriveLogFields(receipts []*receiptLogs, hash common.Hash, number uint64, t
// ReadLogs retrieves the logs for all transactions in a block. In case
// receipts is not found, a nil is returned.
// Note: ReadLogs does not derive unstored log fields.
-func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) [][]*types.Log {
+func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log {
// Retrieve the flattened receipt slice
data := ReadReceiptsRLP(db, hash, number)
if len(data) == 0 {
diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go
index ae49932fc2..6b93e3d66e 100644
--- a/core/rawdb/accessors_chain_test.go
+++ b/core/rawdb/accessors_chain_test.go
@@ -736,7 +736,7 @@ func TestReadLogs(t *testing.T) {
// Insert the receipt slice into the database and check presence
WriteReceipts(db, hash, 0, receipts)
- logs := ReadLogs(db, hash, 0, params.TestChainConfig)
+ logs := ReadLogs(db, hash, 0)
if len(logs) == 0 {
t.Fatalf("no logs returned")
}
diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go
index 69679f2461..8a27579d60 100644
--- a/core/rawdb/accessors_metadata.go
+++ b/core/rawdb/accessors_metadata.go
@@ -118,10 +118,10 @@ const crashesToKeep = 10
func PushUncleanShutdownMarker(db ethdb.KeyValueStore) ([]uint64, uint64, error) {
var uncleanShutdowns crashList
// Read old data
- if data, err := db.Get(uncleanShutdownKey); err != nil {
- log.Warn("Error reading unclean shutdown markers", "error", err)
- } else if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil {
- return nil, 0, err
+ if data, err := db.Get(uncleanShutdownKey); err == nil {
+ if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil {
+ return nil, 0, err
+ }
}
var discarded = uncleanShutdowns.Discarded
var previous = make([]uint64, len(uncleanShutdowns.Recent))
diff --git a/core/rawdb/accessors_sync.go b/core/rawdb/accessors_sync.go
new file mode 100644
index 0000000000..54e5967d81
--- /dev/null
+++ b/core/rawdb/accessors_sync.go
@@ -0,0 +1,44 @@
+// Copyright 2022 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package rawdb
+
+import (
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+const (
+ StateSyncUnknown = uint8(0) // flags the state snap sync is unknown
+ StateSyncRunning = uint8(1) // flags the state snap sync is not completed yet
+ StateSyncFinished = uint8(2) // flags the state snap sync is completed
+)
+
+// ReadSnapSyncStatusFlag retrieves the state snap sync status flag.
+func ReadSnapSyncStatusFlag(db ethdb.KeyValueReader) uint8 {
+ blob, err := db.Get(snapSyncStatusFlagKey)
+ if err != nil || len(blob) != 1 {
+ return StateSyncUnknown
+ }
+ return blob[0]
+}
+
+// WriteSnapSyncStatusFlag stores the state snap sync status flag into database.
+func WriteSnapSyncStatusFlag(db ethdb.KeyValueWriter, flag uint8) {
+ if err := db.Put(snapSyncStatusFlagKey, []byte{flag}); err != nil {
+ log.Crit("Failed to store sync status flag", "err", err)
+ }
+}
diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go
index 5248fbecab..215d63bebb 100644
--- a/core/rawdb/accessors_trie.go
+++ b/core/rawdb/accessors_trie.go
@@ -292,6 +292,11 @@ func ReadStateScheme(db ethdb.Reader) string {
if len(blob) != 0 {
return PathScheme
}
+ // The root node might be deleted during the initial snap sync, check
+ // the persistent state id then.
+ if id := ReadPersistentStateID(db); id != 0 {
+ return PathScheme
+ }
// In a hash-based scheme, the genesis state is consistently stored
// on the disk. To assess the scheme of the persistent state, it
// suffices to inspect the scheme of the genesis state.
@@ -335,7 +340,7 @@ func ParseStateScheme(provided string, disk ethdb.Database) (string, error) {
if stored == "" {
// use default scheme for empty database, flip it when
// path mode is chosen as default
- log.Info("State schema set to default", "scheme", "hash")
+ log.Info("State scheme set to default", "scheme", "hash")
return HashScheme, nil
}
log.Info("State scheme set to already existing disk db", "scheme", stored)
diff --git a/core/rawdb/ancient_scheme.go b/core/rawdb/ancient_scheme.go
index 1f22a5c342..2dc1eae24f 100644
--- a/core/rawdb/ancient_scheme.go
+++ b/core/rawdb/ancient_scheme.go
@@ -68,14 +68,14 @@ var stateFreezerNoSnappy = map[string]bool{
// The list of identifiers of ancient stores.
var (
- chainFreezerName = "chain" // the folder name of chain segment ancient store.
- stateFreezerName = "state" // the folder name of reverse diff ancient store.
+ ChainFreezerName = "chain" // the folder name of chain segment ancient store.
+ StateFreezerName = "state" // the folder name of reverse diff ancient store.
)
// freezers the collections of all builtin freezers.
-var freezers = []string{chainFreezerName, stateFreezerName}
+var freezers = []string{ChainFreezerName, StateFreezerName}
// NewStateFreezer initializes the freezer for state history.
func NewStateFreezer(ancientDir string, readOnly bool, offset uint64) (*ResettableFreezer, error) {
- return NewResettableFreezer(filepath.Join(ancientDir, stateFreezerName), "eth/db/state", readOnly, offset, stateHistoryTableSize, stateFreezerNoSnappy)
+ return NewResettableFreezer(filepath.Join(ancientDir, StateFreezerName), "eth/db/state", readOnly, offset, stateHistoryTableSize, stateFreezerNoSnappy)
}
diff --git a/core/rawdb/ancient_utils.go b/core/rawdb/ancient_utils.go
index 392ac79631..a73e586192 100644
--- a/core/rawdb/ancient_utils.go
+++ b/core/rawdb/ancient_utils.go
@@ -83,14 +83,14 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
var infos []freezerInfo
for _, freezer := range freezers {
switch freezer {
- case chainFreezerName:
- info, err := inspect(chainFreezerName, chainFreezerNoSnappy, db)
+ case ChainFreezerName:
+ info, err := inspect(ChainFreezerName, chainFreezerNoSnappy, db)
if err != nil {
return nil, err
}
infos = append(infos, info)
- case stateFreezerName:
+ case StateFreezerName:
if ReadStateScheme(db) != PathScheme {
continue
}
@@ -104,7 +104,7 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
}
defer f.Close()
- info, err := inspect(stateFreezerName, stateFreezerNoSnappy, f)
+ info, err := inspect(StateFreezerName, stateFreezerNoSnappy, f)
if err != nil {
return nil, err
}
@@ -127,8 +127,10 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
tables map[string]bool
)
switch freezerName {
- case chainFreezerName:
+ case ChainFreezerName:
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
+ case StateFreezerName:
+ path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
default:
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
}
@@ -149,7 +151,7 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
}
func ResetStateFreezerTableOffset(ancient string, virtualTail uint64) error {
- path, tables := filepath.Join(ancient, stateFreezerName), stateFreezerNoSnappy
+ path, tables := filepath.Join(ancient, StateFreezerName), stateFreezerNoSnappy
for name, disableSnappy := range tables {
log.Info("Handle table", "name", name, "disableSnappy", disableSnappy)
diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go
index e3f63442de..c0bd64ef08 100644
--- a/core/rawdb/chain_freezer.go
+++ b/core/rawdb/chain_freezer.go
@@ -131,7 +131,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
continue
case *number < threshold:
- log.Debug("Current full block not old enough", "number", *number, "hash", hash, "delay", threshold)
+ log.Debug("Current full block not old enough to freeze", "number", *number, "hash", hash, "delay", threshold)
backoff = true
continue
@@ -200,7 +200,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
}
batch.Reset()
- // Step into the future and delete and dangling side chains
+ // Step into the future and delete any dangling side chains
if frozen > 0 {
tip := frozen
for len(dangling) > 0 {
diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go
index 256b71d4a9..90eb638506 100644
--- a/core/rawdb/chain_iterator.go
+++ b/core/rawdb/chain_iterator.go
@@ -185,7 +185,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
//
// There is a passed channel, the whole procedure will be interrupted if any
// signal received.
-func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
+func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
// short circuit for invalid range
if offset := db.AncientOffSet(); offset > from {
from = offset
@@ -198,13 +198,13 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
batch = db.NewBatch()
start = time.Now()
logged = start.Add(-7 * time.Second)
+
// Since we iterate in reverse, we expect the first number to come
// in to be [to-1]. Therefore, setting lastNum to means that the
- // prqueue gap-evaluation will work correctly
- lastNum = to
- queue = prque.New[int64, *blockTxHashes](nil)
- // for stats reporting
- blocks, txs = 0, 0
+ // queue gap-evaluation will work correctly
+ lastNum = to
+ queue = prque.New[int64, *blockTxHashes](nil)
+ blocks, txs = 0, 0 // for stats reporting
)
for chanDelivery := range hashesCh {
// Push the delivery into the queue and process contiguous ranges.
@@ -250,11 +250,15 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
log.Crit("Failed writing batch to db", "error", err)
return
}
+ logger := log.Debug
+ if report {
+ logger = log.Info
+ }
select {
case <-interrupt:
- log.Debug("Transaction indexing interrupted", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
+ logger("Transaction indexing interrupted", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
default:
- log.Debug("Indexed transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
+ logger("Indexed transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
}
}
@@ -267,20 +271,20 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
//
// There is a passed channel, the whole procedure will be interrupted if any
// signal received.
-func IndexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}) {
- indexTransactions(db, from, to, interrupt, nil)
+func IndexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) {
+ indexTransactions(db, from, to, interrupt, nil, report)
}
// indexTransactionsForTesting is the internal debug version with an additional hook.
func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
- indexTransactions(db, from, to, interrupt, hook)
+ indexTransactions(db, from, to, interrupt, hook, false)
}
// unindexTransactions removes txlookup indices of the specified block range.
//
// There is a passed channel, the whole procedure will be interrupted if any
// signal received.
-func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
+func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
// short circuit for invalid range
if offset := db.AncientOffSet(); offset > from {
from = offset
@@ -293,12 +297,12 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
batch = db.NewBatch()
start = time.Now()
logged = start.Add(-7 * time.Second)
+
// we expect the first number to come in to be [from]. Therefore, setting
- // nextNum to from means that the prqueue gap-evaluation will work correctly
- nextNum = from
- queue = prque.New[int64, *blockTxHashes](nil)
- // for stats reporting
- blocks, txs = 0, 0
+ // nextNum to from means that the queue gap-evaluation will work correctly
+ nextNum = from
+ queue = prque.New[int64, *blockTxHashes](nil)
+ blocks, txs = 0, 0 // for stats reporting
)
// Otherwise spin up the concurrent iterator and unindexer
for delivery := range hashesCh {
@@ -345,11 +349,15 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
log.Crit("Failed writing batch to db", "error", err)
return
}
+ logger := log.Debug
+ if report {
+ logger = log.Info
+ }
select {
case <-interrupt:
- log.Debug("Transaction unindexing interrupted", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
+ logger("Transaction unindexing interrupted", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
default:
- log.Debug("Unindexed transactions", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
+ logger("Unindexed transactions", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
}
}
@@ -358,11 +366,11 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
//
// There is a passed channel, the whole procedure will be interrupted if any
// signal received.
-func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}) {
- unindexTransactions(db, from, to, interrupt, nil)
+func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) {
+ unindexTransactions(db, from, to, interrupt, nil, report)
}
// unindexTransactionsForTesting is the internal debug version with an additional hook.
func unindexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
- unindexTransactions(db, from, to, interrupt, hook)
+ unindexTransactions(db, from, to, interrupt, hook, false)
}
diff --git a/core/rawdb/chain_iterator_test.go b/core/rawdb/chain_iterator_test.go
index 9580cd92a8..78b0a82e10 100644
--- a/core/rawdb/chain_iterator_test.go
+++ b/core/rawdb/chain_iterator_test.go
@@ -162,18 +162,18 @@ func TestIndexTransactions(t *testing.T) {
t.Fatalf("Transaction tail mismatch")
}
}
- IndexTransactions(chainDb, 5, 11, nil)
+ IndexTransactions(chainDb, 5, 11, nil, false)
verify(5, 11, true, 5)
verify(0, 5, false, 5)
- IndexTransactions(chainDb, 0, 5, nil)
+ IndexTransactions(chainDb, 0, 5, nil, false)
verify(0, 11, true, 0)
- UnindexTransactions(chainDb, 0, 5, nil)
+ UnindexTransactions(chainDb, 0, 5, nil, false)
verify(5, 11, true, 5)
verify(0, 5, false, 5)
- UnindexTransactions(chainDb, 5, 11, nil)
+ UnindexTransactions(chainDb, 5, 11, nil, false)
verify(0, 11, false, 11)
// Testing corner cases
@@ -190,7 +190,7 @@ func TestIndexTransactions(t *testing.T) {
})
verify(9, 11, true, 9)
verify(0, 9, false, 9)
- IndexTransactions(chainDb, 0, 9, nil)
+ IndexTransactions(chainDb, 0, 9, nil, false)
signal = make(chan struct{})
var once2 sync.Once
diff --git a/core/rawdb/database.go b/core/rawdb/database.go
index ea300d5fd9..e7e53947f6 100644
--- a/core/rawdb/database.go
+++ b/core/rawdb/database.go
@@ -36,7 +36,7 @@ import (
"github.com/ethereum/go-ethereum/log"
)
-// freezerdb is a database wrapper that enabled freezer data retrievals.
+// freezerdb is a database wrapper that enables freezer data retrievals.
type freezerdb struct {
ancientRoot string
ethdb.KeyValueStore
@@ -174,7 +174,7 @@ func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error)
// Unlike other ancient-related methods, this method does not return
// errNotSupported when invoked.
// The reason for this is that the caller might want to do several things:
- // 1. Check if something is in freezer,
+ // 1. Check if something is in the freezer,
// 2. If not, check leveldb.
//
// This will work, since the ancient-checks inside 'fn' will return errors,
@@ -228,8 +228,8 @@ func resolveChainFreezerDir(ancient string) string {
// sub folder, if not then two possibilities:
// - chain freezer is not initialized
// - chain freezer exists in legacy location (root ancient folder)
- chain := path.Join(ancient, chainFreezerName)
- state := path.Join(ancient, stateFreezerName)
+ chain := path.Join(ancient, ChainFreezerName)
+ state := path.Join(ancient, StateFreezerName)
if common.FileExist(chain) {
return chain
}
@@ -293,7 +293,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
// of the freezer and database. Ensure that we don't shoot ourselves in the foot
// by serving up conflicting data, leading to both datastores getting corrupted.
//
- // - If both the freezer and key-value store is empty (no genesis), we just
+ // - If both the freezer and key-value store are empty (no genesis), we just
// initialized a new empty freezer, so everything's fine.
// - If the key-value store is empty, but the freezer is not, we need to make
// sure the user's genesis matches the freezer. That will be checked in the
@@ -302,7 +302,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
// - If neither the key-value store nor the freezer is empty, cross validate
// the genesis hashes to make sure they are compatible. If they are, also
// ensure that there's no gap between the freezer and subsequently leveldb.
- // - If the key-value store is not empty, but the freezer is we might just be
+ // - If the key-value store is not empty, but the freezer is, we might just be
// upgrading to the freezer release, or we might have had a small chain and
// not frozen anything yet. Ensure that no blocks are missing yet from the
// key-value store, since that would mean we already had an old freezer.
@@ -340,7 +340,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
break
}
}
- // We are about to exit on error. Print database metdata before exiting
+ // We are about to exit on error. Print database metadata before exiting
printChainMetadata(db)
return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ",
frozen-1, number, head)
@@ -412,28 +412,10 @@ func NewLevelDBDatabase(file string, cache int, handles int, namespace string, r
return NewDatabase(db), nil
}
-// NewLevelDBDatabaseWithFreezer creates a persistent key-value database with a
-// freezer moving immutable chain segments into cold storage. The passed ancient
-// indicates the path of root ancient directory where the chain freezer can be
-// opened.
-// just used for test now
-func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient string, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData bool) (ethdb.Database, error) {
- kvdb, err := leveldb.New(file, cache, handles, namespace, readonly)
- if err != nil {
- return nil, err
- }
- frdb, err := NewDatabaseWithFreezer(kvdb, ancient, namespace, readonly, disableFreeze, isLastOffset, pruneAncientData)
- if err != nil {
- kvdb.Close()
- return nil, err
- }
- return frdb, nil
-}
-
// NewPebbleDBDatabase creates a persistent key-value database without a freezer
// moving immutable chain segments into cold storage.
-func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) {
- db, err := pebble.New(file, cache, handles, namespace, readonly)
+func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly, ephemeral bool) (ethdb.Database, error) {
+ db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral)
if err != nil {
return nil, err
}
@@ -445,10 +427,10 @@ const (
dbLeveldb = "leveldb"
)
-// hasPreexistingDb checks the given data directory whether a database is already
+// PreexistingDatabase checks the given data directory whether a database is already
// instantiated at that location, and if so, returns the type of database (or the
// empty string).
-func hasPreexistingDb(path string) string {
+func PreexistingDatabase(path string) string {
if _, err := os.Stat(filepath.Join(path, "CURRENT")); err != nil {
return "" // No pre-existing db
}
@@ -475,6 +457,9 @@ type OpenOptions struct {
DisableFreeze bool
IsLastOffset bool
PruneAncientData bool
+ // Ephemeral means that filesystem sync operations should be avoided: data integrity in the face of
+ // a crash is not important. This option should typically be used in tests.
+ Ephemeral bool
}
// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble.
@@ -490,13 +475,13 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
}
// Retrieve any pre-existing database's type and use that or the requested one
// as long as there's no conflict between the two types
- existingDb := hasPreexistingDb(o.Directory)
+ existingDb := PreexistingDatabase(o.Directory)
if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb {
return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb)
}
if o.Type == dbPebble || existingDb == dbPebble {
log.Info("Using pebble as the backing database")
- return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
+ return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral)
}
if o.Type == dbLeveldb || existingDb == dbLeveldb {
log.Info("Using leveldb as the backing database")
@@ -725,7 +710,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
lastPivotKey, fastTrieProgressKey, snapshotDisabledKey, SnapshotRootKey, snapshotJournalKey,
snapshotGeneratorKey, snapshotRecoveryKey, txIndexTailKey, fastTxLookupLimitKey,
uncleanShutdownKey, badBlockKey, transitionStatusKey, skeletonSyncStatusKey,
- persistentStateIDKey, trieJournalKey, snapshotSyncStatusKey,
+ persistentStateIDKey, trieJournalKey, snapshotSyncStatusKey, snapSyncStatusFlagKey,
} {
if bytes.Equal(key, meta) {
metadata.Add(size)
@@ -804,7 +789,7 @@ func printChainMetadata(db ethdb.KeyValueStore) {
fmt.Fprintf(os.Stderr, "\n\n")
}
-// ReadChainMetadata returns a set of key/value pairs that contains informatin
+// ReadChainMetadata returns a set of key/value pairs that contains information
// about the database chain status. This can be used for diagnostic purposes
// when investigating the state of the node.
func ReadChainMetadata(db ethdb.KeyValueStore) [][]string {
@@ -826,7 +811,6 @@ func ReadChainMetadata(db ethdb.KeyValueStore) [][]string {
{"snapshotRecoveryNumber", pp(ReadSnapshotRecoveryNumber(db))},
{"snapshotRoot", fmt.Sprintf("%v", ReadSnapshotRoot(db))},
{"txIndexTail", pp(ReadTxIndexTail(db))},
- {"fastTxLookupLimit", pp(ReadFastTxLookupLimit(db))},
}
return data
}
diff --git a/core/rawdb/freezer.go b/core/rawdb/freezer.go
index c9fb3a3ef4..89ad12ffa9 100644
--- a/core/rawdb/freezer.go
+++ b/core/rawdb/freezer.go
@@ -109,7 +109,11 @@ func NewFreezer(datadir string, namespace string, readonly bool, offset uint64,
// Leveldb uses LOCK as the filelock filename. To prevent the
// name collision, we use FLOCK as the lock name.
lock := flock.New(flockFile)
- if locked, err := lock.TryLock(); err != nil {
+ tryLock := lock.TryLock
+ if readonly {
+ tryLock = lock.TryRLock
+ }
+ if locked, err := tryLock(); err != nil {
return nil, err
} else if !locked {
return nil, errors.New("locking failed")
diff --git a/core/rawdb/freezer_batch.go b/core/rawdb/freezer_batch.go
index 07f0dc1c0c..3e1a8143a6 100644
--- a/core/rawdb/freezer_batch.go
+++ b/core/rawdb/freezer_batch.go
@@ -188,19 +188,27 @@ func (batch *freezerTableBatch) maybeCommit() error {
// commit writes the batched items to the backing freezerTable.
func (batch *freezerTableBatch) commit() error {
- // Write data.
+ // Write data. The head file is fsync'd after write to ensure the
+ // data is truly transferred to disk.
_, err := batch.t.head.Write(batch.dataBuffer)
if err != nil {
return err
}
+ if err := batch.t.head.Sync(); err != nil {
+ return err
+ }
dataSize := int64(len(batch.dataBuffer))
batch.dataBuffer = batch.dataBuffer[:0]
- // Write indices.
+ // Write indices. The index file is fsync'd after write to ensure the
+ // data indexes are truly transferred to disk.
_, err = batch.t.index.Write(batch.indexBuffer)
if err != nil {
return err
}
+ if err := batch.t.index.Sync(); err != nil {
+ return err
+ }
indexSize := int64(len(batch.indexBuffer))
batch.indexBuffer = batch.indexBuffer[:0]
diff --git a/core/rawdb/freezer_resettable.go b/core/rawdb/freezer_resettable.go
index 326ad5be96..67565530e1 100644
--- a/core/rawdb/freezer_resettable.go
+++ b/core/rawdb/freezer_resettable.go
@@ -119,9 +119,10 @@ func (f *ResettableFreezer) Ancient(kind string, number uint64) ([]byte, error)
// AncientRange retrieves multiple items in sequence, starting from the index 'start'.
// It will return
-// - at most 'max' items,
-// - at least 1 item (even if exceeding the maxByteSize), but will otherwise
-// return as many items as fit into maxByteSize
+// - at most 'count' items,
+// - if maxBytes is specified: at least 1 item (even if exceeding the maxByteSize),
+// but will otherwise return as many items as fit into maxByteSize.
+// - if maxBytes is not specified, 'count' items will be returned if they are present.
func (f *ResettableFreezer) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) {
f.lock.RLock()
defer f.lock.RUnlock()
diff --git a/core/rawdb/freezer_table.go b/core/rawdb/freezer_table.go
index 5f1fc7133e..daa594ec90 100644
--- a/core/rawdb/freezer_table.go
+++ b/core/rawdb/freezer_table.go
@@ -223,7 +223,9 @@ func (t *freezerTable) repair() error {
if t.readonly {
return fmt.Errorf("index file(path: %s, name: %s) size is not a multiple of %d", t.path, t.name, indexEntrySize)
}
- truncateFreezerFile(t.index, stat.Size()-overflow) // New file can't trigger this path
+ if err := truncateFreezerFile(t.index, stat.Size()-overflow); err != nil {
+ return err
+ } // New file can't trigger this path
}
// Retrieve the file sizes and prepare for truncation
if stat, err = t.index.Stat(); err != nil {
@@ -268,8 +270,8 @@ func (t *freezerTable) repair() error {
// Print an error log if the index is corrupted due to an incorrect
// last index item. While it is theoretically possible to have a zero offset
// by storing all zero-size items, it is highly unlikely to occur in practice.
- if lastIndex.offset == 0 && offsetsSize%indexEntrySize > 1 {
- log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "items", offsetsSize%indexEntrySize-1)
+ if lastIndex.offset == 0 && offsetsSize/indexEntrySize > 1 {
+ log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "indexes", offsetsSize/indexEntrySize)
}
if t.readonly {
t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly)
@@ -424,6 +426,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
if err := truncateFreezerFile(t.index, int64(length+1)*indexEntrySize); err != nil {
return err
}
+ if err := t.index.Sync(); err != nil {
+ return err
+ }
// Calculate the new expected size of the data file and truncate it
var expected indexEntry
if length == 0 {
@@ -446,6 +451,7 @@ func (t *freezerTable) truncateHead(items uint64) error {
// Release any files _after the current head -- both the previous head
// and any files which may have been opened for reading
t.releaseFilesAfter(expected.filenum, true)
+
// Set back the historic head
t.head = newHead
t.headId = expected.filenum
@@ -453,6 +459,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
if err := truncateFreezerFile(t.head, int64(expected.offset)); err != nil {
return err
}
+ if err := t.head.Sync(); err != nil {
+ return err
+ }
// All data files truncated, set internal counters and return
t.headBytes = int64(expected.offset)
t.items.Store(items)
@@ -466,6 +475,20 @@ func (t *freezerTable) truncateHead(items uint64) error {
return nil
}
+// sizeHidden returns the total data size of hidden items in the freezer table.
+// This function assumes the lock is already held.
+func (t *freezerTable) sizeHidden() (uint64, error) {
+ hidden, offset := t.itemHidden.Load(), t.itemOffset.Load()
+ if hidden <= offset {
+ return 0, nil
+ }
+ indices, err := t.getIndices(hidden-1, 1)
+ if err != nil {
+ return 0, err
+ }
+ return uint64(indices[1].offset), nil
+}
+
// truncateTail discards any recent data before the provided threshold number.
func (t *freezerTable) truncateTail(items uint64) error {
t.lock.Lock()
@@ -494,6 +517,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
newTail.unmarshalBinary(buffer)
newTailId = newTail.filenum
}
+ // Save the old size for metrics tracking. This needs to be done
+ // before any updates to either itemHidden or itemOffset.
+ oldSize, err := t.sizeNolock()
+ if err != nil {
+ return err
+ }
// Update the virtual tail marker and hidden these entries in table.
t.itemHidden.Store(items)
if err := writeMetadata(t.meta, newMetadata(items)); err != nil {
@@ -508,18 +537,12 @@ func (t *freezerTable) truncateTail(items uint64) error {
if t.tailId > newTailId {
return fmt.Errorf("invalid index, tail-file %d, item-file %d", t.tailId, newTailId)
}
- // Hidden items exceed the current tail file, drop the relevant
- // data files. We need to truncate, save the old size for metrics
- // tracking.
- oldSize, err := t.sizeNolock()
- if err != nil {
- return err
- }
// Count how many items can be deleted from the file.
var (
newDeleted = items
deleted = t.itemOffset.Load()
)
+ // Hidden items exceed the current tail file, drop the relevant data files.
for current := items - 1; current >= deleted; current -= 1 {
if _, err := t.index.ReadAt(buffer, int64((current-deleted+1)*indexEntrySize)); err != nil {
return err
@@ -597,10 +620,12 @@ func (t *freezerTable) Close() error {
// error on Windows.
doClose(t.index, true, true)
doClose(t.meta, true, true)
+
// The preopened non-head data-files are all opened in readonly.
// The head is opened in rw-mode, so we sync it here - but since it's also
// part of t.files, it will be closed in the loop below.
doClose(t.head, true, false) // sync but do not close
+
for _, f := range t.files {
doClose(f, false, true) // close but do not sync
}
@@ -677,6 +702,7 @@ func (t *freezerTable) releaseFilesBefore(num uint32, remove bool) {
func (t *freezerTable) getIndices(from, count uint64) ([]*indexEntry, error) {
// Apply the table-offset
from = from - t.itemOffset.Load()
+
// For reading N items, we need N+1 indices.
buffer := make([]byte, (count+1)*indexEntrySize)
if _, err := t.index.ReadAt(buffer, int64(from*indexEntrySize)); err != nil {
@@ -867,14 +893,18 @@ func (t *freezerTable) size() (uint64, error) {
return t.sizeNolock()
}
-// sizeNolock returns the total data size in the freezer table without obtaining
-// the mutex first.
+// sizeNolock returns the total data size in the freezer table. This function
+// assumes the lock is already held.
func (t *freezerTable) sizeNolock() (uint64, error) {
stat, err := t.index.Stat()
if err != nil {
return 0, err
}
- total := uint64(t.maxFileSize)*uint64(t.headId-t.tailId) + uint64(t.headBytes) + uint64(stat.Size())
+ hidden, err := t.sizeHidden()
+ if err != nil {
+ return 0, err
+ }
+ total := uint64(t.maxFileSize)*uint64(t.headId-t.tailId) + uint64(t.headBytes) + uint64(stat.Size()) - hidden
return total, nil
}
diff --git a/core/rawdb/freezer_table_test.go b/core/rawdb/freezer_table_test.go
index f2d3773dd9..d9a1aee595 100644
--- a/core/rawdb/freezer_table_test.go
+++ b/core/rawdb/freezer_table_test.go
@@ -661,6 +661,13 @@ func TestFreezerOffset(t *testing.T) {
}
}
+func assertTableSize(t *testing.T, f *freezerTable, size int) {
+ t.Helper()
+ if got, err := f.size(); got != uint64(size) {
+ t.Fatalf("expected size of %d bytes, got %d, err: %v", size, got, err)
+ }
+}
+
func TestTruncateTail(t *testing.T) {
t.Parallel()
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
@@ -695,6 +702,9 @@ func TestTruncateTail(t *testing.T) {
5: getChunk(20, 0xaa),
6: getChunk(20, 0x11),
})
+ // maxFileSize*fileCount + headBytes + indexFileSize - hiddenBytes
+ expected := 20*7 + 48 - 0
+ assertTableSize(t, f, expected)
// truncate single element( item 0 ), deletion is only supported at file level
f.truncateTail(1)
@@ -710,6 +720,8 @@ func TestTruncateTail(t *testing.T) {
5: getChunk(20, 0xaa),
6: getChunk(20, 0x11),
})
+ expected = 20*7 + 48 - 20
+ assertTableSize(t, f, expected)
// Reopen the table, the deletion information should be persisted as well
f.Close()
@@ -742,6 +754,8 @@ func TestTruncateTail(t *testing.T) {
5: getChunk(20, 0xaa),
6: getChunk(20, 0x11),
})
+ expected = 20*5 + 36 - 0
+ assertTableSize(t, f, expected)
// Reopen the table, the above testing should still pass
f.Close()
@@ -763,6 +777,23 @@ func TestTruncateTail(t *testing.T) {
6: getChunk(20, 0x11),
})
+ // truncate 3 more elements( item 2, 3, 4), the file 1 should be deleted
+ // file 2 should only contain item 5
+ f.truncateTail(5)
+ checkRetrieveError(t, f, map[uint64]error{
+ 0: errOutOfBounds,
+ 1: errOutOfBounds,
+ 2: errOutOfBounds,
+ 3: errOutOfBounds,
+ 4: errOutOfBounds,
+ })
+ checkRetrieve(t, f, map[uint64][]byte{
+ 5: getChunk(20, 0xaa),
+ 6: getChunk(20, 0x11),
+ })
+ expected = 20*3 + 24 - 20
+ assertTableSize(t, f, expected)
+
// truncate all, the entire freezer should be deleted
f.truncateTail(7)
checkRetrieveError(t, f, map[uint64]error{
@@ -774,6 +805,8 @@ func TestTruncateTail(t *testing.T) {
5: errOutOfBounds,
6: errOutOfBounds,
})
+ expected = 12
+ assertTableSize(t, f, expected)
}
func TestTruncateHead(t *testing.T) {
diff --git a/core/rawdb/freezer_test.go b/core/rawdb/freezer_test.go
index cf53c5d966..5be7f09330 100644
--- a/core/rawdb/freezer_test.go
+++ b/core/rawdb/freezer_test.go
@@ -283,6 +283,57 @@ func TestFreezerReadonlyValidate(t *testing.T) {
}
}
+func TestFreezerConcurrentReadonly(t *testing.T) {
+ t.Parallel()
+
+ tables := map[string]bool{"a": true}
+ dir := t.TempDir()
+
+ f, err := NewFreezer(dir, "", false, 0, 2049, tables)
+ if err != nil {
+ t.Fatal("can't open freezer", err)
+ }
+ var item = make([]byte, 1024)
+ batch := f.tables["a"].newBatch(0)
+ items := uint64(10)
+ for i := uint64(0); i < items; i++ {
+ require.NoError(t, batch.AppendRaw(i, item))
+ }
+ require.NoError(t, batch.commit())
+ if loaded := f.tables["a"].items.Load(); loaded != items {
+ t.Fatalf("unexpected number of items in table, want: %d, have: %d", items, loaded)
+ }
+ require.NoError(t, f.Close())
+
+ var (
+ wg sync.WaitGroup
+ fs = make([]*Freezer, 5)
+ errs = make([]error, 5)
+ )
+ for i := 0; i < 5; i++ {
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+
+ f, err := NewFreezer(dir, "", true, 0, 2049, tables)
+ if err == nil {
+ fs[i] = f
+ } else {
+ errs[i] = err
+ }
+ }(i)
+ }
+
+ wg.Wait()
+
+ for i := range fs {
+ if err := errs[i]; err != nil {
+ t.Fatal("failed to open freezer", err)
+ }
+ require.NoError(t, fs[i].Close())
+ }
+}
+
func newFreezerForTesting(t *testing.T, tables map[string]bool) (*Freezer, string) {
t.Helper()
diff --git a/core/rawdb/freezer_utils.go b/core/rawdb/freezer_utils.go
index 1bbb50c498..752e95ba6a 100644
--- a/core/rawdb/freezer_utils.go
+++ b/core/rawdb/freezer_utils.go
@@ -73,11 +73,7 @@ func copyFrom(srcPath, destPath string, offset uint64, before func(f *os.File) e
return err
}
f = nil
-
- if err := os.Rename(fname, destPath); err != nil {
- return err
- }
- return nil
+ return os.Rename(fname, destPath)
}
// openFreezerFileForAppend opens a freezer table file and seeks to the end
diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go
index 9e7f8500cb..02a41c6903 100644
--- a/core/rawdb/schema.go
+++ b/core/rawdb/schema.go
@@ -77,6 +77,8 @@ var (
txIndexTailKey = []byte("TransactionIndexTail")
// fastTxLookupLimitKey tracks the transaction lookup limit during fast sync.
+ // This flag is deprecated, it's kept to avoid reporting errors when inspect
+ // database.
fastTxLookupLimitKey = []byte("FastTransactionLookupLimit")
//offSet of new updated ancientDB.
@@ -103,6 +105,9 @@ var (
// transitionStatusKey tracks the eth2 transition status.
transitionStatusKey = []byte("eth2-transition")
+ // snapSyncStatusFlagKey flags that status of snap sync.
+ snapSyncStatusFlagKey = []byte("SnapSyncStatus")
+
// Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes).
headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header
headerTDSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + headerTDSuffix -> td
diff --git a/core/rawdb/table.go b/core/rawdb/table.go
index 23730aeb6a..509bdbc94e 100644
--- a/core/rawdb/table.go
+++ b/core/rawdb/table.go
@@ -237,7 +237,7 @@ func (b *tableBatch) Put(key, value []byte) error {
return b.batch.Put(append([]byte(b.prefix), key...), value)
}
-// Delete inserts the a key removal into the batch for later committing.
+// Delete inserts a key removal into the batch for later committing.
func (b *tableBatch) Delete(key []byte) error {
return b.batch.Delete(append([]byte(b.prefix), key...))
}
diff --git a/core/state/database.go b/core/state/database.go
index 071881b43e..4b6086b3cb 100644
--- a/core/state/database.go
+++ b/core/state/database.go
@@ -20,6 +20,7 @@ import (
"errors"
"fmt"
+ "github.com/crate-crypto/go-ipa/banderwagon"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core/rawdb"
@@ -28,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/trie/utils"
)
const (
@@ -36,6 +38,12 @@ const (
// Cache size granted for caching clean code.
codeCacheSize = 64 * 1024 * 1024
+
+ // commitmentSize is the size of commitment stored in cache.
+ commitmentSize = banderwagon.UncompressedSize
+
+ // Cache item granted for caching commitment results.
+ commitmentCacheItems = 64 * 1024 * 1024 / (commitmentSize + common.AddressLength)
)
// Database wraps access to tries and contract code.
@@ -44,7 +52,7 @@ type Database interface {
OpenTrie(root common.Hash) (Trie, error)
// OpenStorageTrie opens the storage trie of an account.
- OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error)
+ OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error)
// CopyTrie returns an independent copy of the given trie.
CopyTrie(Trie) Trie
@@ -73,11 +81,6 @@ type Trie interface {
// TODO(fjl): remove this when StateTrie is removed
GetKey([]byte) []byte
- // GetStorage returns the value for key stored in the trie. The value bytes
- // must not be modified by the caller. If a node was not found in the database,
- // a trie.MissingNodeError is returned.
- GetStorage(addr common.Address, key []byte) ([]byte, error)
-
// GetAccount abstracts an account read from the trie. It retrieves the
// account blob from the trie with provided account address and decodes it
// with associated decoding algorithm. If the specified account is not in
@@ -86,27 +89,32 @@ type Trie interface {
// be returned.
GetAccount(address common.Address) (*types.StateAccount, error)
- // UpdateStorage associates key with value in the trie. If value has length zero,
- // any existing value is deleted from the trie. The value bytes must not be modified
- // by the caller while they are stored in the trie. If a node was not found in the
- // database, a trie.MissingNodeError is returned.
- UpdateStorage(addr common.Address, key, value []byte) error
+ // GetStorage returns the value for key stored in the trie. The value bytes
+ // must not be modified by the caller. If a node was not found in the database,
+ // a trie.MissingNodeError is returned.
+ GetStorage(addr common.Address, key []byte) ([]byte, error)
// UpdateAccount abstracts an account write to the trie. It encodes the
// provided account object with associated algorithm and then updates it
// in the trie with provided address.
UpdateAccount(address common.Address, account *types.StateAccount) error
- // UpdateContractCode abstracts code write to the trie. It is expected
- // to be moved to the stateWriter interface when the latter is ready.
- UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error
+ // UpdateStorage associates key with value in the trie. If value has length zero,
+ // any existing value is deleted from the trie. The value bytes must not be modified
+ // by the caller while they are stored in the trie. If a node was not found in the
+ // database, a trie.MissingNodeError is returned.
+ UpdateStorage(addr common.Address, key, value []byte) error
+
+ // DeleteAccount abstracts an account deletion from the trie.
+ DeleteAccount(address common.Address) error
// DeleteStorage removes any existing value for key from the trie. If a node
// was not found in the database, a trie.MissingNodeError is returned.
DeleteStorage(addr common.Address, key []byte) error
- // DeleteAccount abstracts an account deletion from the trie.
- DeleteAccount(address common.Address) error
+ // UpdateContractCode abstracts code write to the trie. It is expected
+ // to be moved to the stateWriter interface when the latter is ready.
+ UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error
// Hash returns the root hash of the trie. It does not write to the database and
// can be used even if the trie doesn't have one.
@@ -183,6 +191,9 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
if db.noTries {
return trie.NewEmptyTrie(), nil
}
+ if db.triedb.IsVerkle() {
+ return trie.NewVerkleTrie(root, db.triedb, utils.NewPointCache(commitmentCacheItems))
+ }
tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
if err != nil {
return nil, err
@@ -191,11 +202,17 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
}
// OpenStorageTrie opens the storage trie of an account.
-func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error) {
+func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
if db.noTries {
return trie.NewEmptyTrie(), nil
}
+ // In the verkle case, there is only one tree. But the two-tree structure
+ // is hardcoded in the codebase. So we need to return the same trie in this
+ // case.
+ if db.triedb.IsVerkle() {
+ return self, nil
+ }
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb)
if err != nil {
return nil, err
diff --git a/core/state/dump.go b/core/state/dump.go
index cf206030b5..165a835369 100644
--- a/core/state/dump.go
+++ b/core/state/dump.go
@@ -51,20 +51,23 @@ type DumpCollector interface {
// DumpAccount represents an account in the state.
type DumpAccount struct {
- Balance string `json:"balance"`
- Nonce uint64 `json:"nonce"`
- Root hexutil.Bytes `json:"root"`
- CodeHash hexutil.Bytes `json:"codeHash"`
- Code hexutil.Bytes `json:"code,omitempty"`
- Storage map[common.Hash]string `json:"storage,omitempty"`
- Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode
- SecureKey hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key
+ Balance string `json:"balance"`
+ Nonce uint64 `json:"nonce"`
+ Root hexutil.Bytes `json:"root"`
+ CodeHash hexutil.Bytes `json:"codeHash"`
+ Code hexutil.Bytes `json:"code,omitempty"`
+ Storage map[common.Hash]string `json:"storage,omitempty"`
+ Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode
+ AddressHash hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key
}
// Dump represents the full dump in a collected format, as one large map.
type Dump struct {
- Root string `json:"root"`
- Accounts map[common.Address]DumpAccount `json:"accounts"`
+ Root string `json:"root"`
+ Accounts map[string]DumpAccount `json:"accounts"`
+ // Next can be set to represent that this dump is only partial, and Next
+ // is where an iterator should be positioned in order to continue the dump.
+ Next []byte `json:"next,omitempty"` // nil if no more accounts
}
// OnRoot implements DumpCollector interface
@@ -74,27 +77,11 @@ func (d *Dump) OnRoot(root common.Hash) {
// OnAccount implements DumpCollector interface
func (d *Dump) OnAccount(addr *common.Address, account DumpAccount) {
- if addr != nil {
- d.Accounts[*addr] = account
+ if addr == nil {
+ d.Accounts[fmt.Sprintf("pre(%s)", account.AddressHash)] = account
}
-}
-
-// IteratorDump is an implementation for iterating over data.
-type IteratorDump struct {
- Root string `json:"root"`
- Accounts map[common.Address]DumpAccount `json:"accounts"`
- Next []byte `json:"next,omitempty"` // nil if no more accounts
-}
-
-// OnRoot implements DumpCollector interface
-func (d *IteratorDump) OnRoot(root common.Hash) {
- d.Root = fmt.Sprintf("%x", root)
-}
-
-// OnAccount implements DumpCollector interface
-func (d *IteratorDump) OnAccount(addr *common.Address, account DumpAccount) {
if addr != nil {
- d.Accounts[*addr] = account
+ d.Accounts[(*addr).String()] = account
}
}
@@ -106,14 +93,14 @@ type iterativeDump struct {
// OnAccount implements DumpCollector interface
func (d iterativeDump) OnAccount(addr *common.Address, account DumpAccount) {
dumpAccount := &DumpAccount{
- Balance: account.Balance,
- Nonce: account.Nonce,
- Root: account.Root,
- CodeHash: account.CodeHash,
- Code: account.Code,
- Storage: account.Storage,
- SecureKey: account.SecureKey,
- Address: addr,
+ Balance: account.Balance,
+ Nonce: account.Nonce,
+ Root: account.Root,
+ CodeHash: account.CodeHash,
+ Code: account.Code,
+ Storage: account.Storage,
+ AddressHash: account.AddressHash,
+ Address: addr,
}
d.Encode(dumpAccount)
}
@@ -143,6 +130,7 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
trieIt, err := s.trie.NodeIterator(conf.Start)
if err != nil {
+ log.Error("Trie dumping error", "err", err)
return nil
}
it := trie.NewIterator(trieIt)
@@ -151,26 +139,27 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
panic(err)
}
- account := DumpAccount{
- Balance: data.Balance.String(),
- Nonce: data.Nonce,
- Root: data.Root[:],
- CodeHash: data.CodeHash,
- SecureKey: it.Key,
- }
var (
- addrBytes = s.trie.GetKey(it.Key)
- addr = common.BytesToAddress(addrBytes)
+ account = DumpAccount{
+ Balance: data.Balance.String(),
+ Nonce: data.Nonce,
+ Root: data.Root[:],
+ CodeHash: data.CodeHash,
+ AddressHash: it.Key,
+ }
address *common.Address
+ addr common.Address
+ addrBytes = s.trie.GetKey(it.Key)
)
if addrBytes == nil {
- // Preimage missing
missingPreimages++
if conf.OnlyWithAddresses {
continue
}
} else {
+ addr = common.BytesToAddress(addrBytes)
address = &addr
+ account.Address = address
}
obj := newObject(s, addr, &data)
if !conf.SkipCode {
@@ -227,12 +216,13 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
return nextKey
}
-// RawDump returns the entire state an a single large object
+// RawDump returns the state. If the processing is aborted e.g. due to options
+// reaching Max, the `Next` key is set on the returned Dump.
func (s *StateDB) RawDump(opts *DumpConfig) Dump {
dump := &Dump{
- Accounts: make(map[common.Address]DumpAccount),
+ Accounts: make(map[string]DumpAccount),
}
- s.DumpToCollector(dump, opts)
+ dump.Next = s.DumpToCollector(dump, opts)
return *dump
}
@@ -241,7 +231,7 @@ func (s *StateDB) Dump(opts *DumpConfig) []byte {
dump := s.RawDump(opts)
json, err := json.MarshalIndent(dump, "", " ")
if err != nil {
- fmt.Println("Dump err", err)
+ log.Error("Error dumping state", "err", err)
}
return json
}
@@ -250,12 +240,3 @@ func (s *StateDB) Dump(opts *DumpConfig) []byte {
func (s *StateDB) IterativeDump(opts *DumpConfig, output *json.Encoder) {
s.DumpToCollector(iterativeDump{output}, opts)
}
-
-// IteratorDump dumps out a batch of accounts starts with the given start key
-func (s *StateDB) IteratorDump(opts *DumpConfig) IteratorDump {
- iterator := &IteratorDump{
- Accounts: make(map[common.Address]DumpAccount),
- }
- iterator.Next = s.DumpToCollector(iterator, opts)
- return *iterator
-}
diff --git a/core/state/iterator.go b/core/state/iterator.go
index bb9af08206..dc84ce689b 100644
--- a/core/state/iterator.go
+++ b/core/state/iterator.go
@@ -112,7 +112,7 @@ func (it *nodeIterator) step() error {
}
// Otherwise we've reached an account node, initiate data iteration
var account types.StateAccount
- if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil {
+ if err := rlp.DecodeBytes(it.stateIt.LeafBlob(), &account); err != nil {
return err
}
// Lookup the preimage of account hash
@@ -123,7 +123,7 @@ func (it *nodeIterator) step() error {
address := common.BytesToAddress(preimage)
// Traverse the storage slots belong to the account
- dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, address, account.Root)
+ dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, address, account.Root, it.state.trie)
if err != nil {
return err
}
diff --git a/core/state/journal.go b/core/state/journal.go
index 4ae167657a..198c8da554 100644
--- a/core/state/journal.go
+++ b/core/state/journal.go
@@ -17,9 +17,8 @@
package state
import (
- "math/big"
-
"github.com/ethereum/go-ethereum/common"
+ "github.com/holiman/uint256"
)
// journalEntry is a modification entry in the state change journal that can be
@@ -104,13 +103,13 @@ type (
selfDestructChange struct {
account *common.Address
prev bool // whether account had already self-destructed
- prevbalance *big.Int
+ prevbalance *uint256.Int
}
// Changes to individual accounts.
balanceChange struct {
account *common.Address
- prev *big.Int
+ prev *uint256.Int
}
nonceChange struct {
account *common.Address
diff --git a/core/state/pruner/bloom.go b/core/state/pruner/bloom.go
index 9f068eaf2d..dad2b5b2a8 100644
--- a/core/state/pruner/bloom.go
+++ b/core/state/pruner/bloom.go
@@ -27,17 +27,10 @@ import (
bloomfilter "github.com/holiman/bloomfilter/v2"
)
-// stateBloomHasher is a wrapper around a byte blob to satisfy the interface API
-// requirements of the bloom library used. It's used to convert a trie hash or
-// contract code hash into a 64 bit mini hash.
-type stateBloomHasher []byte
-
-func (f stateBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
-func (f stateBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
-func (f stateBloomHasher) Reset() { panic("not implemented") }
-func (f stateBloomHasher) BlockSize() int { panic("not implemented") }
-func (f stateBloomHasher) Size() int { return 8 }
-func (f stateBloomHasher) Sum64() uint64 { return binary.BigEndian.Uint64(f) }
+// stateBloomHash is used to convert a trie hash or contract code hash into a 64 bit mini hash.
+func stateBloomHash(f []byte) uint64 {
+ return binary.BigEndian.Uint64(f)
+}
// stateBloom is a bloom filter used during the state conversion(snapshot->state).
// The keys of all generated entries will be recorded here so that in the pruning
@@ -113,10 +106,10 @@ func (bloom *stateBloom) Put(key []byte, value []byte) error {
if !isCode {
return errors.New("invalid entry")
}
- bloom.bloom.Add(stateBloomHasher(codeKey))
+ bloom.bloom.AddHash(stateBloomHash(codeKey))
return nil
}
- bloom.bloom.Add(stateBloomHasher(key))
+ bloom.bloom.AddHash(stateBloomHash(key))
return nil
}
@@ -128,5 +121,5 @@ func (bloom *stateBloom) Delete(key []byte) error { panic("not supported") }
// - If it says yes, the key may be contained
// - If it says no, the key is definitely not contained.
func (bloom *stateBloom) Contain(key []byte) bool {
- return bloom.bloom.Contains(stateBloomHasher(key))
+ return bloom.bloom.ContainsHash(stateBloomHash(key))
}
diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go
index f7f135ca46..3ba90f73de 100644
--- a/core/state/pruner/pruner.go
+++ b/core/state/pruner/pruner.go
@@ -27,6 +27,7 @@ import (
"strings"
"time"
+ "github.com/holiman/uint256"
"github.com/prometheus/tsdb/fileutil"
"github.com/ethereum/go-ethereum/common"
@@ -226,7 +227,7 @@ func pruneAll(maindb ethdb.Database, g *core.Genesis) error {
}
statedb, _ := state.New(common.Hash{}, state.NewDatabase(maindb), nil)
for addr, account := range g.Alloc {
- statedb.AddBalance(addr, account.Balance)
+ statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
for key, value := range account.Storage {
@@ -249,12 +250,12 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta
// dangling node is the state root is super low. So the dangling nodes in
// theory will never ever be visited again.
var (
- count int
- size common.StorageSize
- pstart = time.Now()
- logged = time.Now()
- batch = maindb.NewBatch()
- iter = maindb.NewIterator(nil, nil)
+ skipped, count int
+ size common.StorageSize
+ pstart = time.Now()
+ logged = time.Now()
+ batch = maindb.NewBatch()
+ iter = maindb.NewIterator(nil, nil)
)
for iter.Next() {
key := iter.Key()
@@ -273,6 +274,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta
log.Debug("Forcibly delete the middle state roots", "hash", common.BytesToHash(checkKey))
} else {
if stateBloom.Contain(checkKey) {
+ skipped += 1
continue
}
}
@@ -289,7 +291,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta
eta = time.Duration(left/speed) * time.Millisecond
}
if time.Since(logged) > 8*time.Second {
- log.Info("Pruning state data", "nodes", count, "size", size,
+ log.Info("Pruning state data", "nodes", count, "skipped", skipped, "size", size,
"elapsed", common.PrettyDuration(time.Since(pstart)), "eta", common.PrettyDuration(eta))
logged = time.Now()
}
diff --git a/core/state/snapshot/difflayer.go b/core/state/snapshot/difflayer.go
index d4155c26c7..fb01d9b4a5 100644
--- a/core/state/snapshot/difflayer.go
+++ b/core/state/snapshot/difflayer.go
@@ -127,47 +127,20 @@ type diffLayer struct {
lock sync.RWMutex
}
-// destructBloomHasher is a wrapper around a common.Hash to satisfy the interface
-// API requirements of the bloom library used. It's used to convert a destruct
-// event into a 64 bit mini hash.
-type destructBloomHasher common.Hash
-
-func (h destructBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
-func (h destructBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
-func (h destructBloomHasher) Reset() { panic("not implemented") }
-func (h destructBloomHasher) BlockSize() int { panic("not implemented") }
-func (h destructBloomHasher) Size() int { return 8 }
-func (h destructBloomHasher) Sum64() uint64 {
+// destructBloomHash is used to convert a destruct event into a 64 bit mini hash.
+func destructBloomHash(h common.Hash) uint64 {
return binary.BigEndian.Uint64(h[bloomDestructHasherOffset : bloomDestructHasherOffset+8])
}
-// accountBloomHasher is a wrapper around a common.Hash to satisfy the interface
-// API requirements of the bloom library used. It's used to convert an account
-// hash into a 64 bit mini hash.
-type accountBloomHasher common.Hash
-
-func (h accountBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
-func (h accountBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
-func (h accountBloomHasher) Reset() { panic("not implemented") }
-func (h accountBloomHasher) BlockSize() int { panic("not implemented") }
-func (h accountBloomHasher) Size() int { return 8 }
-func (h accountBloomHasher) Sum64() uint64 {
+// accountBloomHash is used to convert an account hash into a 64 bit mini hash.
+func accountBloomHash(h common.Hash) uint64 {
return binary.BigEndian.Uint64(h[bloomAccountHasherOffset : bloomAccountHasherOffset+8])
}
-// storageBloomHasher is a wrapper around a [2]common.Hash to satisfy the interface
-// API requirements of the bloom library used. It's used to convert an account
-// hash into a 64 bit mini hash.
-type storageBloomHasher [2]common.Hash
-
-func (h storageBloomHasher) Write(p []byte) (n int, err error) { panic("not implemented") }
-func (h storageBloomHasher) Sum(b []byte) []byte { panic("not implemented") }
-func (h storageBloomHasher) Reset() { panic("not implemented") }
-func (h storageBloomHasher) BlockSize() int { panic("not implemented") }
-func (h storageBloomHasher) Size() int { return 8 }
-func (h storageBloomHasher) Sum64() uint64 {
- return binary.BigEndian.Uint64(h[0][bloomStorageHasherOffset:bloomStorageHasherOffset+8]) ^
- binary.BigEndian.Uint64(h[1][bloomStorageHasherOffset:bloomStorageHasherOffset+8])
+// storageBloomHash is used to convert an account hash and a storage hash into a 64 bit mini hash.
+func storageBloomHash(h0, h1 common.Hash) uint64 {
+ return binary.BigEndian.Uint64(h0[bloomStorageHasherOffset:bloomStorageHasherOffset+8]) ^
+ binary.BigEndian.Uint64(h1[bloomStorageHasherOffset:bloomStorageHasherOffset+8])
}
// newDiffLayer creates a new diff on top of an existing snapshot, whether that's a low
@@ -239,14 +212,14 @@ func (dl *diffLayer) rebloom(origin *diskLayer) {
}
// Iterate over all the accounts and storage slots and index them
for hash := range dl.destructSet {
- dl.diffed.Add(destructBloomHasher(hash))
+ dl.diffed.AddHash(destructBloomHash(hash))
}
for hash := range dl.accountData {
- dl.diffed.Add(accountBloomHasher(hash))
+ dl.diffed.AddHash(accountBloomHash(hash))
}
for accountHash, slots := range dl.storageData {
for storageHash := range slots {
- dl.diffed.Add(storageBloomHasher{accountHash, storageHash})
+ dl.diffed.AddHash(storageBloomHash(accountHash, storageHash))
}
}
// Calculate the current false positive rate and update the error rate meter.
@@ -358,9 +331,9 @@ func (dl *diffLayer) AccountRLP(hash common.Hash) ([]byte, error) {
}
// Check the bloom filter first whether there's even a point in reaching into
// all the maps in all the layers below
- hit := dl.diffed.Contains(accountBloomHasher(hash))
+ hit := dl.diffed.ContainsHash(accountBloomHash(hash))
if !hit {
- hit = dl.diffed.Contains(destructBloomHasher(hash))
+ hit = dl.diffed.ContainsHash(destructBloomHash(hash))
}
var origin *diskLayer
if !hit {
@@ -429,9 +402,9 @@ func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
dl.lock.RUnlock()
return nil, ErrSnapshotStale
}
- hit := dl.diffed.Contains(storageBloomHasher{accountHash, storageHash})
+ hit := dl.diffed.ContainsHash(storageBloomHash(accountHash, storageHash))
if !hit {
- hit = dl.diffed.Contains(destructBloomHasher(accountHash))
+ hit = dl.diffed.ContainsHash(destructBloomHash(accountHash))
}
var origin *diskLayer
if !hit {
diff --git a/core/state/snapshot/disklayer.go b/core/state/snapshot/disklayer.go
index aafdf54917..646d84fc32 100644
--- a/core/state/snapshot/disklayer.go
+++ b/core/state/snapshot/disklayer.go
@@ -45,6 +45,16 @@ type diskLayer struct {
lock sync.RWMutex
}
+// Release releases underlying resources; specifically the fastcache requires
+// Reset() in order to not leak memory.
+// OBS: It does not invoke Close on the diskdb
+func (dl *diskLayer) Release() error {
+ if dl.cache != nil {
+ dl.cache.Reset()
+ }
+ return nil
+}
+
// Root returns root hash for which this snapshot was made.
func (dl *diskLayer) Root() common.Hash {
return dl.root
diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go
index fbd83e3b52..db2e1ad9fe 100644
--- a/core/state/snapshot/generate.go
+++ b/core/state/snapshot/generate.go
@@ -230,7 +230,9 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [
if origin == nil && !diskMore {
stackTr := trie.NewStackTrie(nil)
for i, key := range keys {
- stackTr.Update(key, vals[i])
+ if err := stackTr.Update(key, vals[i]); err != nil {
+ return nil, err
+ }
}
if gotRoot := stackTr.Hash(); gotRoot != root {
return &proofResult{
@@ -247,11 +249,6 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [
ctx.stats.Log("Trie missing, state snapshotting paused", dl.root, dl.genMarker)
return nil, errMissingTrie
}
- // Firstly find out the key of last iterated element.
- var last []byte
- if len(keys) > 0 {
- last = keys[len(keys)-1]
- }
// Generate the Merkle proofs for the first and last element
if origin == nil {
origin = common.Hash{}.Bytes()
@@ -266,9 +263,9 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [
tr: tr,
}, nil
}
- if last != nil {
- if err := tr.Prove(last, proof); err != nil {
- log.Debug("Failed to prove range", "kind", kind, "last", last, "err", err)
+ if len(keys) > 0 {
+ if err := tr.Prove(keys[len(keys)-1], proof); err != nil {
+ log.Debug("Failed to prove range", "kind", kind, "last", keys[len(keys)-1], "err", err)
return &proofResult{
keys: keys,
vals: vals,
@@ -280,7 +277,7 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [
}
// Verify the snapshot segment with range prover, ensure that all flat states
// in this range correspond to merkle trie.
- cont, err := trie.VerifyRangeProof(root, origin, last, keys, vals, proof)
+ cont, err := trie.VerifyRangeProof(root, origin, keys, vals, proof)
return &proofResult{
keys: keys,
vals: vals,
@@ -446,6 +443,10 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
internal += time.Since(istart)
}
if iter.Err != nil {
+ // Trie errors should never happen. Still, in case of a bug, expose the
+ // error here, as the outer code will presume errors are interrupts, not
+ // some deeper issues.
+ log.Error("State snapshotter failed to iterate trie", "err", iter.Err)
return false, nil, iter.Err
}
// Delete all stale snapshot states remaining
diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go
index 07016b675c..7d941f6285 100644
--- a/core/state/snapshot/generate_test.go
+++ b/core/state/snapshot/generate_test.go
@@ -18,7 +18,6 @@ package snapshot
import (
"fmt"
- "math/big"
"os"
"testing"
"time"
@@ -33,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
@@ -58,9 +58,9 @@ func testGeneration(t *testing.T, scheme string) {
var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
@@ -97,16 +97,16 @@ func testGenerateExistentState(t *testing.T, scheme string) {
var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
root, snap := helper.CommitAndGenerate()
@@ -259,28 +259,28 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
helper := newHelper(scheme)
// Account one, empty root but non-empty database
- helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
// Account two, non empty root but empty database
stRoot := helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
// Miss slots
{
// Account three, non empty root but misses slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
// Account four, non empty root but misses slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
// Account five, non empty root but misses slots in the end
helper.makeStorageTrie(hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-5", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
}
@@ -288,22 +288,22 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
{
// Account six, non empty root but wrong slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
// Account seven, non empty root but wrong slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-7", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
// Account eight, non empty root but wrong slots in the end
helper.makeStorageTrie(hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-8", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-8", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
// Account 9, non empty root but rotated slots
helper.makeStorageTrie(hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-9", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-9", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
}
@@ -311,17 +311,17 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) {
{
// Account 10, non empty root but extra slots in the beginning
helper.makeStorageTrie(hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-10", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-10", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
// Account 11, non empty root but extra slots in the middle
helper.makeStorageTrie(hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-11", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-11", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
// Account 12, non empty root but extra slots in the end
helper.makeStorageTrie(hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-12", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-12", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
}
@@ -366,25 +366,25 @@ func testGenerateExistentStateWithWrongAccounts(t *testing.T, scheme string) {
// Missing accounts, only in the trie
{
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning
- helper.addTrieAccount("acc-4", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle
- helper.addTrieAccount("acc-6", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning
+ helper.addTrieAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle
+ helper.addTrieAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
}
// Wrong accounts
{
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addSnapAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
}
// Extra accounts, only in the snap
{
- helper.addSnapAccount("acc-0", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning
- helper.addSnapAccount("acc-5", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle
- helper.addSnapAccount("acc-7", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end
+ helper.addSnapAccount("acc-0", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning
+ helper.addSnapAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle
+ helper.addSnapAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end
}
root, snap := helper.CommitAndGenerate()
@@ -418,9 +418,9 @@ func testGenerateCorruptAccountTrie(t *testing.T, scheme string) {
// without any storage slots to keep the test smaller.
helper := newHelper(scheme)
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
@@ -462,11 +462,11 @@ func testGenerateMissingStorageTrie(t *testing.T, scheme string) {
acc3 = hashData([]byte("acc-3"))
helper = newHelper(scheme)
)
- stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
+ stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
root := helper.Commit()
@@ -502,11 +502,11 @@ func testGenerateCorruptStorageTrie(t *testing.T, scheme string) {
// two of which also has the same 3-slot storage trie attached.
helper := newHelper(scheme)
- stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
+ stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
root := helper.Commit()
@@ -546,7 +546,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
true,
)
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
@@ -566,7 +566,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
true,
)
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
key := hashData([]byte("acc-2"))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@@ -601,7 +601,7 @@ func testGenerateWithExtraAccounts(t *testing.T, scheme string) {
}
func enableLogging() {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
}
// Tests that snapshot generation when an extra account with storage exists in the snap state.
@@ -622,7 +622,7 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) {
[]string{"val-1", "val-2", "val-3"},
true,
)
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
@@ -636,7 +636,7 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) {
{
// 100 accounts exist only in snapshot
for i := 0; i < 1000; i++ {
- acc := &types.StateAccount{Balance: big.NewInt(int64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@@ -678,7 +678,7 @@ func testGenerateWithExtraBeforeAndAfter(t *testing.T, scheme string) {
}
helper := newHelper(scheme)
{
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
helper.accTrie.MustUpdate(common.HexToHash("0x07").Bytes(), val)
@@ -720,7 +720,7 @@ func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) {
}
helper := newHelper(scheme)
{
- acc := &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
+ acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val)
@@ -764,7 +764,7 @@ func testGenerateFromEmptySnap(t *testing.T, scheme string) {
for i := 0; i < 400; i++ {
stRoot := helper.makeStorageTrie(hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
- &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
}
root, snap := helper.CommitAndGenerate()
t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
@@ -806,7 +806,7 @@ func testGenerateWithIncompleteStorage(t *testing.T, scheme string) {
for i := 0; i < 8; i++ {
accKey := fmt.Sprintf("acc-%d", i)
stRoot := helper.makeStorageTrie(hashData([]byte(accKey)), stKeys, stVals, true)
- helper.addAccount(accKey, &types.StateAccount{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount(accKey, &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
var moddedKeys []string
var moddedVals []string
for ii := 0; ii < 8; ii++ {
@@ -903,11 +903,11 @@ func testGenerateCompleteSnapshotWithDanglingStorage(t *testing.T, scheme string
var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addAccount("acc-2", &types.StateAccount{Balance: big.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addAccount("acc-3", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
@@ -943,11 +943,11 @@ func testGenerateBrokenSnapshotWithDanglingStorage(t *testing.T, scheme string)
var helper = newHelper(scheme)
stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-1", &types.StateAccount{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
- helper.addTrieAccount("acc-2", &types.StateAccount{Balance: big.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
- helper.addTrieAccount("acc-3", &types.StateAccount{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
+ helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
populateDangling(helper.diskdb)
diff --git a/core/state/snapshot/snapshot.go b/core/state/snapshot/snapshot.go
index f18b6faabe..99ef77a5c8 100644
--- a/core/state/snapshot/snapshot.go
+++ b/core/state/snapshot/snapshot.go
@@ -589,7 +589,7 @@ func diffToDisk(bottom *diffLayer) *diskLayer {
// Ensure we don't delete too much data blindly (contract can be
// huge). It's ok to flush, the root will go missing in case of a
// crash and we'll detect and regenerate the snapshot.
- if batch.ValueSize() > ethdb.IdealBatchSize {
+ if batch.ValueSize() > 64*1024*1024 {
if err := batch.Write(); err != nil {
log.Crit("Failed to write storage deletions", "err", err)
}
@@ -615,7 +615,7 @@ func diffToDisk(bottom *diffLayer) *diskLayer {
// Ensure we don't write too much data blindly. It's ok to flush, the
// root will go missing in case of a crash and we'll detect and regen
// the snapshot.
- if batch.ValueSize() > ethdb.IdealBatchSize {
+ if batch.ValueSize() > 64*1024*1024 {
if err := batch.Write(); err != nil {
log.Crit("Failed to write storage deletions", "err", err)
}
@@ -681,6 +681,13 @@ func diffToDisk(bottom *diffLayer) *diskLayer {
return res
}
+// Release releases resources
+func (t *Tree) Release() {
+ if dl := t.disklayer(); dl != nil {
+ dl.Release()
+ }
+}
+
// Journal commits an entire diff hierarchy to disk into a single journal entry.
// This is meant to be used during shutdown to persist the snapshot without
// flattening everything down (bad for reorgs).
@@ -882,3 +889,21 @@ func (t *Tree) DiskRoot() common.Hash {
return t.diskRoot()
}
+
+// Size returns the memory usage of the diff layers above the disk layer and the
+// dirty nodes buffered in the disk layer. Currently, the implementation uses a
+// special diff layer (the first) as an aggregator simulating a dirty buffer, so
+// the second return will always be 0. However, this will be made consistent with
+// the pathdb, which will require a second return.
+func (t *Tree) Size() (diffs common.StorageSize, buf common.StorageSize, preimages common.StorageSize) {
+ t.lock.RLock()
+ defer t.lock.RUnlock()
+
+ var size common.StorageSize
+ for _, layer := range t.layers {
+ if layer, ok := layer.(*diffLayer); ok {
+ size += common.StorageSize(layer.memory)
+ }
+ }
+ return size, 0, 0
+}
diff --git a/core/state/snapshot/snapshot_test.go b/core/state/snapshot/snapshot_test.go
index 69ef2e4e2d..57a1d9f1b4 100644
--- a/core/state/snapshot/snapshot_test.go
+++ b/core/state/snapshot/snapshot_test.go
@@ -20,7 +20,6 @@ import (
crand "crypto/rand"
"encoding/binary"
"fmt"
- "math/big"
"math/rand"
"testing"
"time"
@@ -30,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/holiman/uint256"
)
// randomHash generates a random blob of data and returns it as a hash.
@@ -44,7 +44,7 @@ func randomHash() common.Hash {
// randomAccount generates a random account and returns it RLP encoded.
func randomAccount() []byte {
a := &types.StateAccount{
- Balance: big.NewInt(rand.Int63()),
+ Balance: uint256.NewInt(rand.Uint64()),
Nonce: rand.Uint64(),
Root: randomHash(),
CodeHash: types.EmptyCodeHash[:],
diff --git a/core/state/state_object.go b/core/state/state_object.go
index 935620584b..524bdc47cd 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -20,7 +20,6 @@ import (
"bytes"
"fmt"
"io"
- "math/big"
"sync"
"time"
@@ -30,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/holiman/uint256"
)
type Code []byte
@@ -100,7 +100,10 @@ func (s *stateObject) empty() bool {
// newObject creates a state object.
func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *stateObject {
- origin := acct
+ var (
+ origin = acct
+ created = acct == nil // true if the account was not existent
+ )
if acct == nil {
acct = types.NewEmptyStateAccount()
}
@@ -120,6 +123,7 @@ func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *s
originStorage: make(Storage),
pendingStorage: make(Storage),
dirtyStorage: make(Storage),
+ created: created,
}
}
@@ -154,7 +158,7 @@ func (s *stateObject) getTrie() (Trie, error) {
// s.trie = s.db.prefetcher.trie(s.addrHash, s.data.Root)
// }
// if s.trie == nil {
- tr, err := s.db.db.OpenStorageTrie(s.db.originalRoot, s.address, s.data.Root)
+ tr, err := s.db.db.OpenStorageTrie(s.db.originalRoot, s.address, s.data.Root, s.db.trie)
if err != nil {
return nil, err
}
@@ -298,12 +302,17 @@ func (s *stateObject) finalise(prefetch bool) {
}
}
-// updateTrie writes cached storage modifications into the object's storage trie.
-// It will return nil if the trie has not been loaded and no changes have been
-// made. An error will be returned if the trie can't be loaded/updated correctly.
+// updateTrie is responsible for persisting cached storage changes into the
+// object's storage trie. In case the storage trie is not yet loaded, this
+// function will load the trie automatically. If any issues arise during the
+// loading or updating of the trie, an error will be returned. Furthermore,
+// this function will return the mutated storage trie, or nil if there is no
+// storage change at all.
func (s *stateObject) updateTrie() (Trie, error) {
// Make sure all dirty slots are finalized into the pending storage area
- s.finalise(false) // Don't prefetch anymore, pull directly if need be
+ s.finalise(false)
+
+ // Short circuit if nothing changed, don't bother with hashing anything
if len(s.pendingStorage) == 0 {
return s.trie, nil
}
@@ -326,7 +335,7 @@ func (s *stateObject) updateTrie() (Trie, error) {
s.db.setError(err)
return nil, err
}
- // Insert all the pending updates into the trie
+ // Insert all the pending storage updates into the trie
usedStorage := make([][]byte, 0, len(s.pendingStorage))
dirtyStorage := make(map[common.Hash][]byte)
for key, value := range s.pendingStorage {
@@ -383,11 +392,11 @@ func (s *stateObject) updateTrie() (Trie, error) {
khash := crypto.HashData(hasher, key[:])
// rlp-encoded value to be used by the snapshot
- var snapshotVal []byte
+ var encoded []byte
if len(value) != 0 {
- snapshotVal, _ = rlp.EncodeToBytes(value)
+ encoded, _ = rlp.EncodeToBytes(value)
}
- storage[khash] = snapshotVal // snapshotVal will be nil if it's deleted
+ storage[khash] = encoded // encoded will be nil if it's deleted
// Track the original value of slot only if it's mutated first time
prev := s.originStorage[key]
@@ -408,15 +417,12 @@ func (s *stateObject) updateTrie() (Trie, error) {
if s.db.prefetcher != nil {
s.db.prefetcher.used(s.addrHash, s.data.Root, usedStorage)
}
-
- if len(s.pendingStorage) > 0 {
- s.pendingStorage = make(Storage)
- }
+ s.pendingStorage = make(Storage) // reset pending map
return tr, nil
}
-// UpdateRoot sets the trie root to the current root hash of. An error
-// will be returned if trie root hash is not computed correctly.
+// updateRoot flushes all cached storage mutations to trie, recalculating the
+// new storage trie root.
func (s *stateObject) updateRoot() {
// If node runs in no trie mode, set root to empty.
defer func() {
@@ -425,12 +431,10 @@ func (s *stateObject) updateRoot() {
}
}()
+ // Flush cached storage mutations into trie, short circuit if any error
+ // is occurred or there is not change in the trie.
tr, err := s.updateTrie()
- if err != nil {
- return
- }
- // If nothing changed, don't bother with hashing anything
- if tr == nil {
+ if err != nil || tr == nil {
return
}
// Track the amount of time wasted on hashing the storage trie
@@ -444,14 +448,12 @@ func (s *stateObject) updateRoot() {
s.data.Root = tr.Hash()
}
-// commit returns the changes made in storage trie and updates the account data.
+// commit obtains a set of dirty storage trie nodes and updates the account data.
+// The returned set can be nil if nothing to commit. This function assumes all
+// storage mutations have already been flushed into trie by updateRoot.
func (s *stateObject) commit() (*trienode.NodeSet, error) {
- tr, err := s.updateTrie()
- if err != nil {
- return nil, err
- }
- // If nothing changed, don't bother with committing anything
- if tr == nil {
+ // Short circuit if trie is not even loaded, don't bother with committing anything
+ if s.trie == nil {
s.origin = s.data.Copy()
return nil, nil
}
@@ -459,7 +461,10 @@ func (s *stateObject) commit() (*trienode.NodeSet, error) {
if metrics.EnabledExpensive {
defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now())
}
- root, nodes, err := tr.Commit(false)
+ // The trie is currently in an open state and could potentially contain
+ // cached mutations. Call commit to acquire a set of nodes that have been
+ // modified, the set can be nil if nothing to commit.
+ root, nodes, err := s.trie.Commit(false)
if err != nil {
return nil, err
}
@@ -472,7 +477,7 @@ func (s *stateObject) commit() (*trienode.NodeSet, error) {
// AddBalance adds amount to s's balance.
// It is used to add funds to the destination account of a transfer.
-func (s *stateObject) AddBalance(amount *big.Int) {
+func (s *stateObject) AddBalance(amount *uint256.Int) {
// EIP161: We must check emptiness for the objects such that the account
// clearing (0,0,0 objects) can take effect.
if amount.Sign() == 0 {
@@ -481,27 +486,27 @@ func (s *stateObject) AddBalance(amount *big.Int) {
}
return
}
- s.SetBalance(new(big.Int).Add(s.Balance(), amount))
+ s.SetBalance(new(uint256.Int).Add(s.Balance(), amount))
}
// SubBalance removes amount from s's balance.
// It is used to remove funds from the origin account of a transfer.
-func (s *stateObject) SubBalance(amount *big.Int) {
+func (s *stateObject) SubBalance(amount *uint256.Int) {
if amount.Sign() == 0 {
return
}
- s.SetBalance(new(big.Int).Sub(s.Balance(), amount))
+ s.SetBalance(new(uint256.Int).Sub(s.Balance(), amount))
}
-func (s *stateObject) SetBalance(amount *big.Int) {
+func (s *stateObject) SetBalance(amount *uint256.Int) {
s.db.journal.append(balanceChange{
account: &s.address,
- prev: new(big.Int).Set(s.data.Balance),
+ prev: new(uint256.Int).Set(s.data.Balance),
})
s.setBalance(amount)
}
-func (s *stateObject) setBalance(amount *big.Int) {
+func (s *stateObject) setBalance(amount *uint256.Int) {
s.data.Balance = amount
}
@@ -600,10 +605,14 @@ func (s *stateObject) CodeHash() []byte {
return s.data.CodeHash
}
-func (s *stateObject) Balance() *big.Int {
+func (s *stateObject) Balance() *uint256.Int {
return s.data.Balance
}
func (s *stateObject) Nonce() uint64 {
return s.data.Nonce
}
+
+func (s *stateObject) Root() common.Hash {
+ return s.data.Root
+}
diff --git a/core/state/state_test.go b/core/state/state_test.go
index 5a28135f25..3534938fd4 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -19,7 +19,6 @@ package state
import (
"bytes"
"encoding/json"
- "math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -28,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
type stateEnv struct {
@@ -48,12 +48,12 @@ func TestDump(t *testing.T) {
s := &stateEnv{db: db, state: sdb}
// generate a few entries
- obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
- obj1.AddBalance(big.NewInt(22))
- obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
+ obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
+ obj1.AddBalance(uint256.NewInt(22))
+ obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
- obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
- obj3.SetBalance(big.NewInt(44))
+ obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02}))
+ obj3.SetBalance(uint256.NewInt(44))
// write some of them to the trie
s.state.updateStateObject(obj1)
@@ -73,6 +73,7 @@ func TestDump(t *testing.T) {
"nonce": 0,
"root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "address": "0x0000000000000000000000000000000000000001",
"key": "0x1468288056310c82aa4c01a7e12a10f8111a0560e72b700555479031b86c357d"
},
"0x0000000000000000000000000000000000000002": {
@@ -80,6 +81,7 @@ func TestDump(t *testing.T) {
"nonce": 0,
"root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "address": "0x0000000000000000000000000000000000000002",
"key": "0xd52688a8f926c816ca1e079067caba944f158e764817b83fc43594370ca9cf62"
},
"0x0000000000000000000000000000000000000102": {
@@ -88,6 +90,7 @@ func TestDump(t *testing.T) {
"root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"codeHash": "0x87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3",
"code": "0x03030303030303",
+ "address": "0x0000000000000000000000000000000000000102",
"key": "0xa17eacbc25cda025e81db9c5c62868822c73ce097cee2a63e33a2e41268358a1"
}
}
@@ -104,14 +107,14 @@ func TestIterativeDump(t *testing.T) {
s := &stateEnv{db: db, state: sdb}
// generate a few entries
- obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
- obj1.AddBalance(big.NewInt(22))
- obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
+ obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
+ obj1.AddBalance(uint256.NewInt(22))
+ obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
- obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
- obj3.SetBalance(big.NewInt(44))
- obj4 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x00}))
- obj4.AddBalance(big.NewInt(1337))
+ obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02}))
+ obj3.SetBalance(uint256.NewInt(44))
+ obj4 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x00}))
+ obj4.AddBalance(uint256.NewInt(1337))
// write some of them to the trie
s.state.updateStateObject(obj1)
@@ -211,7 +214,7 @@ func TestSnapshot2(t *testing.T) {
// db, trie are already non-empty values
so0 := state.getStateObject(stateobjaddr0)
- so0.SetBalance(big.NewInt(42))
+ so0.SetBalance(uint256.NewInt(42))
so0.SetNonce(43)
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
so0.selfDestructed = false
@@ -225,7 +228,7 @@ func TestSnapshot2(t *testing.T) {
// and one with deleted == true
so1 := state.getStateObject(stateobjaddr1)
- so1.SetBalance(big.NewInt(52))
+ so1.SetBalance(uint256.NewInt(52))
so1.SetNonce(53)
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
so1.selfDestructed = true
diff --git a/core/state/statedb.go b/core/state/statedb.go
index e9fff8791a..cb024661bd 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -18,9 +18,7 @@
package state
import (
- "errors"
"fmt"
- "math/big"
"runtime"
"sort"
"sync"
@@ -40,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/holiman/uint256"
)
const (
@@ -54,17 +53,6 @@ type revision struct {
journalIndex int
}
-type proofList [][]byte
-
-func (n *proofList) Put(key []byte, value []byte) error {
- *n = append(*n, value)
- return nil
-}
-
-func (n *proofList) Delete(key []byte) error {
- panic("not supported")
-}
-
// StateDB structs within the ethereum protocol are used to store anything
// within the merkle trie. StateDBs take care of caching and storing
// nested states. It's the general query interface to retrieve:
@@ -166,6 +154,9 @@ type StateDB struct {
StorageUpdated int
AccountDeleted int
StorageDeleted int
+
+ // Testing hooks
+ onCommit func(states *triestate.Set) // Hook invoked when commit is performed
}
// NewWithSharedPool creates a new state with sharedStorge on layer 1.5
@@ -433,14 +424,15 @@ func (s *StateDB) Empty(addr common.Address) bool {
}
// GetBalance retrieves the balance from the given address or 0 if object not found
-func (s *StateDB) GetBalance(addr common.Address) *big.Int {
+func (s *StateDB) GetBalance(addr common.Address) *uint256.Int {
stateObject := s.getStateObject(addr)
if stateObject != nil {
return stateObject.Balance()
}
- return common.Big0
+ return common.U2560
}
+// GetNonce retrieves the nonce from the given address or 0 if object not found
func (s *StateDB) GetNonce(addr common.Address) uint64 {
stateObject := s.getStateObject(addr)
if stateObject != nil {
@@ -450,6 +442,16 @@ func (s *StateDB) GetNonce(addr common.Address) uint64 {
return 0
}
+// GetStorageRoot retrieves the storage root from the given address or empty
+// if object not found.
+func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash {
+ stateObject := s.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.Root()
+ }
+ return common.Hash{}
+}
+
// TxIndex returns the current transaction index set by Prepare.
func (s *StateDB) TxIndex() int {
return s.txIndex
@@ -481,10 +483,10 @@ func (s *StateDB) GetCodeSize(addr common.Address) int {
func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
stateObject := s.getStateObject(addr)
- if stateObject == nil {
- return common.Hash{}
+ if stateObject != nil {
+ return common.BytesToHash(stateObject.CodeHash())
}
- return common.BytesToHash(stateObject.CodeHash())
+ return common.Hash{}
}
// GetState retrieves a value from the given account's storage trie.
@@ -496,38 +498,6 @@ func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
return common.Hash{}
}
-// GetProof returns the Merkle proof for a given account.
-func (s *StateDB) GetProof(addr common.Address) ([][]byte, error) {
- return s.GetProofByHash(crypto.Keccak256Hash(addr.Bytes()))
-}
-
-// GetProofByHash returns the Merkle proof for a given account.
-func (s *StateDB) GetProofByHash(addrHash common.Hash) ([][]byte, error) {
- var proof proofList
- if _, err := s.Trie(); err != nil {
- return nil, err
- }
- err := s.trie.Prove(addrHash[:], &proof)
- return proof, err
-}
-
-// GetStorageProof returns the Merkle proof for given storage slot.
-func (s *StateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte, error) {
- trie, err := s.StorageTrie(a)
- if err != nil {
- return nil, err
- }
- if trie == nil {
- return nil, errors.New("storage trie for requested address does not exist")
- }
- var proof proofList
- err = trie.Prove(crypto.Keccak256(key.Bytes()), &proof)
- if err != nil {
- return nil, err
- }
- return proof, nil
-}
-
// GetCommittedState retrieves a value from the given account's committed storage trie.
func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
stateObject := s.getStateObject(addr)
@@ -542,21 +512,6 @@ func (s *StateDB) Database() Database {
return s.db
}
-// StorageTrie returns the storage trie of an account. The return value is a copy
-// and is nil for non-existent accounts. An error will be returned if storage trie
-// is existent but can't be loaded correctly.
-func (s *StateDB) StorageTrie(addr common.Address) (Trie, error) {
- stateObject := s.getStateObject(addr)
- if stateObject == nil {
- return nil, nil
- }
- cpy := stateObject.deepCopy(s)
- if _, err := cpy.updateTrie(); err != nil {
- return nil, err
- }
- return cpy.getTrie()
-}
-
func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
stateObject := s.getStateObject(addr)
if stateObject != nil {
@@ -570,44 +525,44 @@ func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
*/
// AddBalance adds amount to the account associated with addr.
-func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) {
- stateObject := s.GetOrNewStateObject(addr)
+func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int) {
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject.AddBalance(amount)
}
}
// SubBalance subtracts amount from the account associated with addr.
-func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
- stateObject := s.GetOrNewStateObject(addr)
+func (s *StateDB) SubBalance(addr common.Address, amount *uint256.Int) {
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject.SubBalance(amount)
}
}
-func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) {
- stateObject := s.GetOrNewStateObject(addr)
+func (s *StateDB) SetBalance(addr common.Address, amount *uint256.Int) {
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetBalance(amount)
}
}
func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
- stateObject := s.GetOrNewStateObject(addr)
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetNonce(nonce)
}
}
func (s *StateDB) SetCode(addr common.Address, code []byte) {
- stateObject := s.GetOrNewStateObject(addr)
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetCode(crypto.Keccak256Hash(code), code)
}
}
func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
- stateObject := s.GetOrNewStateObject(addr)
+ stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetState(key, value)
}
@@ -628,7 +583,7 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
if _, ok := s.stateObjectsDestruct[addr]; !ok {
s.stateObjectsDestruct[addr] = nil
}
- stateObject := s.GetOrNewStateObject(addr)
+ stateObject := s.getOrNewStateObject(addr)
for k, v := range storage {
stateObject.SetState(k, v)
}
@@ -647,10 +602,10 @@ func (s *StateDB) SelfDestruct(addr common.Address) {
s.journal.append(selfDestructChange{
account: &addr,
prev: stateObject.selfDestructed,
- prevbalance: new(big.Int).Set(stateObject.Balance()),
+ prevbalance: new(uint256.Int).Set(stateObject.Balance()),
})
stateObject.markSelfdestructed()
- stateObject.data.Balance = new(big.Int)
+ stateObject.data.Balance = new(uint256.Int)
}
func (s *StateDB) Selfdestruct6780(addr common.Address) {
@@ -821,8 +776,8 @@ func (s *StateDB) setStateObject(object *stateObject) {
s.stateObjects[object.Address()] = object
}
-// GetOrNewStateObject retrieves a state object or create a new state object if nil.
-func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
+// getOrNewStateObject retrieves a state object or create a new state object if nil.
+func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject {
stateObject := s.getStateObject(addr)
if stateObject == nil {
stateObject, _ = s.createObject(addr)
@@ -865,9 +820,6 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject)
delete(s.accountsOrigin, prev.address)
delete(s.storagesOrigin, prev.address)
}
-
- newobj.created = true
-
s.setStateObject(newobj)
if prev != nil && !prev.deleted {
return newobj, prev
@@ -892,43 +844,6 @@ func (s *StateDB) CreateAccount(addr common.Address) {
}
}
-func (s *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error {
- so := s.getStateObject(addr)
- if so == nil {
- return nil
- }
- tr, err := so.getTrie()
- if err != nil {
- return err
- }
- trieIt, err := tr.NodeIterator(nil)
- if err != nil {
- return err
- }
- it := trie.NewIterator(trieIt)
-
- for it.Next() {
- key := common.BytesToHash(s.trie.GetKey(it.Key))
- if value, dirty := so.dirtyStorage[key]; dirty {
- if !cb(key, value) {
- return nil
- }
- continue
- }
-
- if len(it.Value) > 0 {
- _, content, _, err := rlp.Split(it.Value)
- if err != nil {
- return err
- }
- if !cb(key, common.BytesToHash(content)) {
- return nil
- }
- }
- }
- return nil
-}
-
// Copy creates a deep, independent copy of the state.
// Snapshots of the copied state cannot be applied to the copy.
func (s *StateDB) Copy() *StateDB {
@@ -1397,7 +1312,7 @@ func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (boo
// employed when the associated state snapshot is not available. It iterates the
// storage slots along with all internal trie nodes via trie directly.
func (s *StateDB) slowDeleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (bool, common.StorageSize, map[common.Hash][]byte, *trienode.NodeSet, error) {
- tr, err := s.db.OpenStorageTrie(s.originalRoot, addr, root)
+ tr, err := s.db.OpenStorageTrie(s.originalRoot, addr, root, s.trie)
if err != nil {
return false, 0, nil, nil, fmt.Errorf("failed to open storage trie, err: %w", err)
}
@@ -1466,12 +1381,10 @@ func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root
slotDeletionSkip.Inc(1)
}
n := int64(len(slots))
- if n > slotDeletionMaxCount.Value() {
- slotDeletionMaxCount.Update(n)
- }
- if int64(size) > slotDeletionMaxSize.Value() {
- slotDeletionMaxSize.Update(int64(size))
- }
+
+ slotDeletionMaxCount.UpdateIfGt(int64(len(slots)))
+ slotDeletionMaxSize.UpdateIfGt(int64(size))
+
slotDeletionTimer.UpdateSince(start)
slotDeletionCount.Mark(n)
slotDeletionSize.Mark(int64(size))
@@ -1701,13 +1614,17 @@ func (s *StateDB) Commit(block uint64, failPostCommitFunc func(), postCommitFunc
if root != origin {
start := time.Now()
- if err := s.db.TrieDB().Update(root, origin, block, nodes, triestate.New(s.accountsOrigin, s.storagesOrigin, incomplete)); err != nil {
+ set := triestate.New(s.accountsOrigin, s.storagesOrigin, incomplete)
+ if err := s.db.TrieDB().Update(root, origin, block, nodes, set); err != nil {
return err
}
s.originalRoot = root
if metrics.EnabledExpensive {
s.TrieDBCommits += time.Since(start)
}
+ if s.onCommit != nil {
+ s.onCommit(set)
+ }
}
}
@@ -1833,20 +1750,6 @@ func (s *StateDB) Commit(block uint64, failPostCommitFunc func(), postCommitFunc
if root == (common.Hash{}) {
root = types.EmptyRootHash
}
- //origin := s.originalRoot
- //if origin == (common.Hash{}) {
- // origin = types.EmptyRootHash
- //}
- //if root != origin {
- // start := time.Now()
- // if err := s.db.TrieDB().Update(root, origin, block, nodes, triestate.New(s.accountsOrigin, s.storagesOrigin, incomplete)); err != nil {
- // return common.Hash{}, nil, err
- // }
- // s.originalRoot = root
- // if metrics.EnabledExpensive {
- // s.TrieDBCommits += time.Since(start)
- // }
- //}
// Clear all internal flags at the end of commit operation.
s.accounts = make(map[common.Hash][]byte)
s.storages = make(map[common.Hash]map[common.Hash][]byte)
diff --git a/core/state/statedb_fuzz_test.go b/core/state/statedb_fuzz_test.go
index 26ca9b5e7d..856d3394f6 100644
--- a/core/state/statedb_fuzz_test.go
+++ b/core/state/statedb_fuzz_test.go
@@ -22,7 +22,6 @@ import (
"errors"
"fmt"
"math"
- "math/big"
"math/rand"
"reflect"
"strings"
@@ -38,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/holiman/uint256"
)
// A stateTest checks that the state changes are correctly captured. Instances
@@ -60,7 +60,7 @@ func newStateTestAction(addr common.Address, r *rand.Rand, index int) testAction
{
name: "SetBalance",
fn: func(a testAction, s *StateDB) {
- s.SetBalance(addr, big.NewInt(a.args[0]))
+ s.SetBalance(addr, uint256.NewInt(uint64(a.args[0])))
},
args: make([]int64, 1),
},
@@ -181,7 +181,7 @@ func (test *stateTest) run() bool {
storageList = append(storageList, copy2DSet(states.Storages))
}
disk = rawdb.NewMemoryDatabase()
- tdb = trie.NewDatabase(disk, &trie.Config{OnCommit: onCommit, PathDB: pathdb.Defaults})
+ tdb = trie.NewDatabase(disk, &trie.Config{PathDB: pathdb.Defaults})
sdb = NewDatabaseWithNodeDB(disk, tdb)
byzantium = rand.Intn(2) == 0
)
@@ -206,6 +206,8 @@ func (test *stateTest) run() bool {
if err != nil {
panic(err)
}
+ state.onCommit = onCommit
+
for i, action := range actions {
if i%test.chunk == 0 && i != 0 {
if byzantium {
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index eed905a87e..22e7d3aa43 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -21,7 +21,6 @@ import (
"encoding/binary"
"fmt"
"math"
- "math/big"
"math/rand"
"reflect"
"strings"
@@ -34,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
@@ -54,7 +54,7 @@ func TestUpdateLeaks(t *testing.T) {
// Update it with some accounts
for i := byte(0); i < 255; i++ {
addr := common.BytesToAddress([]byte{i})
- state.AddBalance(addr, big.NewInt(int64(11*i)))
+ state.AddBalance(addr, uint256.NewInt(uint64(11*i)))
state.SetNonce(addr, uint64(42*i))
if i%2 == 0 {
state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
@@ -89,7 +89,7 @@ func TestIntermediateLeaks(t *testing.T) {
finalState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(finalDb, finalNdb), nil)
modify := func(state *StateDB, addr common.Address, i, tweak byte) {
- state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak)))
+ state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)))
state.SetNonce(addr, uint64(42*i+tweak))
if i%2 == 0 {
state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{})
@@ -168,8 +168,8 @@ func TestCopy(t *testing.T) {
orig, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
for i := byte(0); i < 255; i++ {
- obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- obj.AddBalance(big.NewInt(int64(i)))
+ obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ obj.AddBalance(uint256.NewInt(uint64(i)))
orig.updateStateObject(obj)
}
orig.Finalise(false)
@@ -182,13 +182,13 @@ func TestCopy(t *testing.T) {
// modify all in memory
for i := byte(0); i < 255; i++ {
- origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
+ origObj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
- origObj.AddBalance(big.NewInt(2 * int64(i)))
- copyObj.AddBalance(big.NewInt(3 * int64(i)))
- ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
+ origObj.AddBalance(uint256.NewInt(2 * uint64(i)))
+ copyObj.AddBalance(uint256.NewInt(3 * uint64(i)))
+ ccopyObj.AddBalance(uint256.NewInt(4 * uint64(i)))
orig.updateStateObject(origObj)
copy.updateStateObject(copyObj)
@@ -210,17 +210,17 @@ func TestCopy(t *testing.T) {
// Verify that the three states have been updated independently
for i := byte(0); i < 255; i++ {
- origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
- ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
+ origObj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
- if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 {
+ if want := uint256.NewInt(3 * uint64(i)); origObj.Balance().Cmp(want) != 0 {
t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want)
}
- if want := big.NewInt(4 * int64(i)); copyObj.Balance().Cmp(want) != 0 {
+ if want := uint256.NewInt(4 * uint64(i)); copyObj.Balance().Cmp(want) != 0 {
t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want)
}
- if want := big.NewInt(5 * int64(i)); ccopyObj.Balance().Cmp(want) != 0 {
+ if want := uint256.NewInt(5 * uint64(i)); ccopyObj.Balance().Cmp(want) != 0 {
t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want)
}
}
@@ -268,14 +268,14 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
{
name: "SetBalance",
fn: func(a testAction, s *StateDB) {
- s.SetBalance(addr, big.NewInt(a.args[0]))
+ s.SetBalance(addr, uint256.NewInt(uint64(a.args[0])))
},
args: make([]int64, 1),
},
{
name: "AddBalance",
fn: func(a testAction, s *StateDB) {
- s.AddBalance(addr, big.NewInt(a.args[0]))
+ s.AddBalance(addr, uint256.NewInt(uint64(a.args[0])))
},
args: make([]int64, 1),
},
@@ -428,10 +428,12 @@ func (test *snapshotTest) run() bool {
state, _ = New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
snapshotRevs = make([]int, len(test.snapshots))
sindex = 0
+ checkstates = make([]*StateDB, len(test.snapshots))
)
for i, action := range test.actions {
if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
snapshotRevs[sindex] = state.Snapshot()
+ checkstates[sindex] = state.Copy()
sindex++
}
action.fn(action, state)
@@ -439,12 +441,8 @@ func (test *snapshotTest) run() bool {
// Revert all snapshots in reverse order. Each revert must yield a state
// that is equivalent to fresh state with all actions up the snapshot applied.
for sindex--; sindex >= 0; sindex-- {
- checkstate, _ := New(types.EmptyRootHash, state.Database(), nil)
- for _, action := range test.actions[:test.snapshots[sindex]] {
- action.fn(action, checkstate)
- }
state.RevertToSnapshot(snapshotRevs[sindex])
- if err := test.checkEqual(state, checkstate); err != nil {
+ if err := test.checkEqual(state, checkstates[sindex]); err != nil {
test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err)
return false
}
@@ -452,6 +450,43 @@ func (test *snapshotTest) run() bool {
return true
}
+func forEachStorage(s *StateDB, addr common.Address, cb func(key, value common.Hash) bool) error {
+ so := s.getStateObject(addr)
+ if so == nil {
+ return nil
+ }
+ tr, err := so.getTrie()
+ if err != nil {
+ return err
+ }
+ trieIt, err := tr.NodeIterator(nil)
+ if err != nil {
+ return err
+ }
+ it := trie.NewIterator(trieIt)
+
+ for it.Next() {
+ key := common.BytesToHash(s.trie.GetKey(it.Key))
+ if value, dirty := so.dirtyStorage[key]; dirty {
+ if !cb(key, value) {
+ return nil
+ }
+ continue
+ }
+
+ if len(it.Value) > 0 {
+ _, content, _, err := rlp.Split(it.Value)
+ if err != nil {
+ return err
+ }
+ if !cb(key, common.BytesToHash(content)) {
+ return nil
+ }
+ }
+ }
+ return nil
+}
+
// checkEqual checks that methods of state and checkstate return the same values.
func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
for _, addr := range test.addrs {
@@ -473,10 +508,10 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
// Check storage.
if obj := state.getStateObject(addr); obj != nil {
- state.ForEachStorage(addr, func(key, value common.Hash) bool {
+ forEachStorage(state, addr, func(key, value common.Hash) bool {
return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
})
- checkstate.ForEachStorage(addr, func(key, value common.Hash) bool {
+ forEachStorage(checkstate, addr, func(key, value common.Hash) bool {
return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
})
}
@@ -498,12 +533,14 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
func TestTouchDelete(t *testing.T) {
s := newStateEnv()
- s.state.GetOrNewStateObject(common.Address{})
+ s.state.getOrNewStateObject(common.Address{})
+ s.state.Finalise(false)
+ s.state.AccountsIntermediateRoot()
root, _, _ := s.state.Commit(0, nil)
s.state, _ = New(root, s.state.db, s.state.snaps)
snapshot := s.state.Snapshot()
- s.state.AddBalance(common.Address{}, new(big.Int))
+ s.state.AddBalance(common.Address{}, new(uint256.Int))
if len(s.state.journal.dirties) != 1 {
t.Fatal("expected one dirty state object")
@@ -519,7 +556,7 @@ func TestTouchDelete(t *testing.T) {
func TestCopyOfCopy(t *testing.T) {
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
addr := common.HexToAddress("aaaa")
- state.SetBalance(addr, big.NewInt(42))
+ state.SetBalance(addr, uint256.NewInt(42))
if got := state.Copy().GetBalance(addr).Uint64(); got != 42 {
t.Fatalf("1st copy fail, expected 42, got %v", got)
@@ -542,11 +579,11 @@ func TestCopyCommitCopy(t *testing.T) {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
- state.SetBalance(addr, big.NewInt(42)) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
- state.SetState(addr, skey, sval) // Change the storage trie
+ state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie
+ state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetState(addr, skey, sval) // Change the storage trie
- if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
}
if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -560,7 +597,7 @@ func TestCopyCommitCopy(t *testing.T) {
}
// Copy the non-committed state database and check pre/post commit balance
copyOne := state.Copy()
- if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyOne.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
}
if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -574,7 +611,7 @@ func TestCopyCommitCopy(t *testing.T) {
}
// Copy the copy and check the balance once more
copyTwo := copyOne.Copy()
- if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyTwo.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42)
}
if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -591,7 +628,7 @@ func TestCopyCommitCopy(t *testing.T) {
state.AccountsIntermediateRoot()
root, _, _ := state.Commit(0, nil)
state, _ = New(root, tdb, nil)
- if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("state post-commit balance mismatch: have %v, want %v", balance, 42)
}
if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -617,11 +654,11 @@ func TestCopyCopyCommitCopy(t *testing.T) {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
- state.SetBalance(addr, big.NewInt(42)) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
- state.SetState(addr, skey, sval) // Change the storage trie
+ state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie
+ state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetState(addr, skey, sval) // Change the storage trie
- if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
}
if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -635,7 +672,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
}
// Copy the non-committed state database and check pre/post commit balance
copyOne := state.Copy()
- if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyOne.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42)
}
if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -649,7 +686,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
}
// Copy the copy and check the balance once more
copyTwo := copyOne.Copy()
- if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyTwo.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
}
if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -663,7 +700,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
}
// Copy the copy-copy and check the balance once more
copyThree := copyTwo.Copy()
- if balance := copyThree.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := copyThree.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42)
}
if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -686,11 +723,11 @@ func TestCommitCopy(t *testing.T) {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
- state.SetBalance(addr, big.NewInt(42)) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
- state.SetState(addr, skey, sval) // Change the storage trie
+ state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie
+ state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetState(addr, skey, sval) // Change the storage trie
- if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
+ if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42)
}
if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) {
@@ -707,7 +744,7 @@ func TestCommitCopy(t *testing.T) {
state.AccountsIntermediateRoot()
state.Commit(0, nil)
copied := state.Copy()
- if balance := copied.GetBalance(addr); balance.Cmp(big.NewInt(0)) != 0 {
+ if balance := copied.GetBalance(addr); balance.Cmp(uint256.NewInt(0)) != 0 {
t.Fatalf("unexpected balance: have %v", balance)
}
if code := copied.GetCode(addr); code != nil {
@@ -734,7 +771,7 @@ func TestDeleteCreateRevert(t *testing.T) {
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
addr := common.BytesToAddress([]byte("so"))
- state.SetBalance(addr, big.NewInt(1))
+ state.SetBalance(addr, uint256.NewInt(1))
state.Finalise(false)
state.AccountsIntermediateRoot()
@@ -746,7 +783,7 @@ func TestDeleteCreateRevert(t *testing.T) {
state.Finalise(true)
id := state.Snapshot()
- state.SetBalance(addr, big.NewInt(2))
+ state.SetBalance(addr, uint256.NewInt(2))
state.RevertToSnapshot(id)
state.Finalise(true)
@@ -790,10 +827,10 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
state, _ := New(types.EmptyRootHash, db, nil)
addr := common.BytesToAddress([]byte("so"))
{
- state.SetBalance(addr, big.NewInt(1))
+ state.SetBalance(addr, uint256.NewInt(1))
state.SetCode(addr, []byte{1, 2, 3})
a2 := common.BytesToAddress([]byte("another"))
- state.SetBalance(a2, big.NewInt(100))
+ state.SetBalance(a2, uint256.NewInt(100))
state.SetCode(a2, []byte{1, 2, 4})
state.Finalise(false)
state.AccountsIntermediateRoot()
@@ -820,7 +857,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
t.Errorf("expected %d, got %d", exp, got)
}
// Modify the state
- state.SetBalance(addr, big.NewInt(2))
+ state.SetBalance(addr, uint256.NewInt(2))
state.Finalise(false)
state.AccountsIntermediateRoot()
root, _, err := state.Commit(0, nil)
@@ -1091,13 +1128,13 @@ func TestResetObject(t *testing.T) {
slotB = common.HexToHash("0x2")
)
// Initialize account with balance and storage in first transaction.
- state.SetBalance(addr, big.NewInt(1))
+ state.SetBalance(addr, uint256.NewInt(1))
state.SetState(addr, slotA, common.BytesToHash([]byte{0x1}))
state.IntermediateRoot(true)
// Reset account and mutate balance and storages
state.CreateAccount(addr)
- state.SetBalance(addr, big.NewInt(2))
+ state.SetBalance(addr, uint256.NewInt(2))
state.SetState(addr, slotB, common.BytesToHash([]byte{0x2}))
root := state.IntermediateRoot(true)
state.SetExpectedStateRoot(root)
@@ -1125,7 +1162,7 @@ func TestDeleteStorage(t *testing.T) {
addr = common.HexToAddress("0x1")
)
// Initialize account and populate storage
- state.SetBalance(addr, big.NewInt(1))
+ state.SetBalance(addr, uint256.NewInt(1))
state.CreateAccount(addr)
for i := 0; i < 1000; i++ {
slot := common.Hash(uint256.NewInt(uint64(i)).Bytes32())
@@ -1137,7 +1174,7 @@ func TestDeleteStorage(t *testing.T) {
fastState, _ := New(root, db, snaps)
slowState, _ := New(root, db, nil)
- obj := fastState.GetOrNewStateObject(addr)
+ obj := fastState.getOrNewStateObject(addr)
storageRoot := obj.data.Root
_, _, fastNodes, err := fastState.deleteStorage(addr, crypto.Keccak256Hash(addr[:]), storageRoot)
diff --git a/core/state/sync.go b/core/state/sync.go
index 61097c6462..d6775e8896 100644
--- a/core/state/sync.go
+++ b/core/state/sync.go
@@ -17,8 +17,6 @@
package state
import (
- "bytes"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
@@ -45,7 +43,7 @@ func NewStateSync(root common.Hash, database ethdb.KeyValueReader, onLeaf func(k
}
}
var obj types.StateAccount
- if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil {
+ if err := rlp.DecodeBytes(leaf, &obj); err != nil {
return err
}
syncer.AddSubTrie(obj.Root, path, parent, parentPath, onSlot)
diff --git a/core/state/sync_test.go b/core/state/sync_test.go
index c935c02ae4..70cd8fcb6d 100644
--- a/core/state/sync_test.go
+++ b/core/state/sync_test.go
@@ -18,7 +18,6 @@ package state
import (
"bytes"
- "math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -30,12 +29,13 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/holiman/uint256"
)
// testAccount is the data associated with an account used by the state tests.
type testAccount struct {
address common.Address
- balance *big.Int
+ balance *uint256.Int
nonce uint64
code []byte
}
@@ -57,11 +57,11 @@ func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, com
// Fill it with some arbitrary data
var accounts []*testAccount
for i := byte(0); i < 96; i++ {
- obj := state.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
+ obj := state.getOrNewStateObject(common.BytesToAddress([]byte{i}))
acc := &testAccount{address: common.BytesToAddress([]byte{i})}
- obj.AddBalance(big.NewInt(int64(11 * i)))
- acc.balance = big.NewInt(int64(11 * i))
+ obj.AddBalance(uint256.NewInt(uint64(11 * i)))
+ acc.balance = uint256.NewInt(uint64(11 * i))
obj.SetNonce(uint64(42 * i))
acc.nonce = uint64(42 * i)
diff --git a/core/state/trie_prefetcher.go b/core/state/trie_prefetcher.go
index 4184369d9c..91e6ca40b1 100644
--- a/core/state/trie_prefetcher.go
+++ b/core/state/trie_prefetcher.go
@@ -53,7 +53,7 @@ type triePrefetcher struct {
db Database // Database to fetch trie nodes through
root common.Hash // Root hash of the account trie for metrics
rootParent common.Hash // Root has of the account trie from block before the prvious one, designed for pipecommit mode
- fetches map[string]Trie // Partially or fully fetcher tries
+ fetches map[string]Trie // Partially or fully fetched tries. Only populated for inactive copies
fetchers map[string]*subfetcher // Subfetchers for each trie
abortChan chan *subfetcher // to abort a single subfetcher and its children
@@ -339,7 +339,10 @@ func (p *triePrefetcher) used(owner common.Hash, root common.Hash, used [][]byte
// trieID returns an unique trie identifier consists the trie owner and root hash.
func (p *triePrefetcher) trieID(owner common.Hash, root common.Hash) string {
- return string(append(owner.Bytes(), root.Bytes()...))
+ trieID := make([]byte, common.HashLength*2)
+ copy(trieID, owner.Bytes())
+ copy(trieID[common.HashLength:], root.Bytes())
+ return string(trieID)
}
// subfetcher is a trie fetcher goroutine responsible for pulling entries for a
@@ -483,7 +486,7 @@ func (sf *subfetcher) loop() {
if sf.owner == (common.Hash{}) {
trie, err = sf.db.OpenTrie(sf.root)
} else {
- trie, err = sf.db.OpenStorageTrie(sf.state, sf.addr, sf.root)
+ trie, err = sf.db.OpenStorageTrie(sf.state, sf.addr, sf.root, nil)
}
if err != nil {
log.Debug("Trie prefetcher failed opening trie", "root", sf.root, "err", err)
@@ -501,7 +504,7 @@ func (sf *subfetcher) loop() {
sf.trie, err = sf.db.OpenTrie(sf.root)
} else {
// address is useless
- sf.trie, err = sf.db.OpenStorageTrie(sf.state, sf.addr, sf.root)
+ sf.trie, err = sf.db.OpenStorageTrie(sf.state, sf.addr, sf.root, nil)
}
if err != nil {
continue
diff --git a/core/state/trie_prefetcher_test.go b/core/state/trie_prefetcher_test.go
index 35545d283e..4ef450dbfb 100644
--- a/core/state/trie_prefetcher_test.go
+++ b/core/state/trie_prefetcher_test.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/holiman/uint256"
)
func filledStateDB() *StateDB {
@@ -34,9 +35,9 @@ func filledStateDB() *StateDB {
skey := common.HexToHash("aaa")
sval := common.HexToHash("bbb")
- state.SetBalance(addr, big.NewInt(42)) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
- state.SetState(addr, skey, sval) // Change the storage trie
+ state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie
+ state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetState(addr, skey, sval) // Change the storage trie
for i := 0; i < 100; i++ {
sk := common.BigToHash(big.NewInt(int64(i)))
state.SetState(addr, sk, sk) // Change the storage trie
diff --git a/core/state_processor.go b/core/state_processor.go
index 25cb7df409..f7d8f2c08b 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -73,12 +73,15 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb)
}
- // Handle upgrade build-in system contract code
+
lastBlock := p.bc.GetBlockByHash(block.ParentHash())
if lastBlock == nil {
return statedb, nil, nil, 0, fmt.Errorf("could not get parent block")
}
- systemcontracts.UpgradeBuildInSystemContract(p.config, blockNumber, lastBlock.Time(), block.Time(), statedb)
+ if !p.config.IsFeynman(block.Number(), block.Time()) {
+ // Handle upgrade build-in system contract code
+ systemcontracts.UpgradeBuildInSystemContract(p.config, blockNumber, lastBlock.Time(), block.Time(), statedb)
+ }
var (
context = NewEVMBlockContext(header, p.bc, nil)
@@ -86,6 +89,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
signer = types.MakeSigner(p.config, header.Number, header.Time)
txNum = len(block.Transactions())
)
+ if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
+ ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
+ }
// Iterate over and process the individual transactions
posa, isPoSA := p.engine.(consensus.PoSA)
commonTxs := make([]*types.Transaction, 0, txNum)
@@ -174,6 +180,11 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
receipt.TxHash = tx.Hash()
receipt.GasUsed = result.UsedGas
+ if tx.Type() == types.BlobTxType {
+ receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob)
+ receipt.BlobGasPrice = evm.Context.BlobBaseFee
+ }
+
// If the transaction created a contract, store the creation address in the receipt.
if msg.To == nil {
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
@@ -201,7 +212,8 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
}
// Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author)
- vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.BlobHashes()}, statedb, config, cfg)
+ txContext := NewEVMTxContext(msg)
+ vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg)
defer func() {
ite := vmenv.Interpreter()
vm.EVMInterpreterPool.Put(ite)
@@ -209,3 +221,23 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
}()
return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, receiptProcessors...)
}
+
+// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
+// contract. This method is exported to be used in tests.
+func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) {
+ // If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with
+ // the new root
+ msg := &Message{
+ From: params.SystemAddress,
+ GasLimit: 30_000_000,
+ GasPrice: common.Big0,
+ GasFeeCap: common.Big0,
+ GasTipCap: common.Big0,
+ To: ¶ms.BeaconRootsStorageAddress,
+ Data: beaconRoot[:],
+ }
+ vmenv.Reset(NewEVMTxContext(msg), statedb)
+ statedb.AddAddressToAccessList(params.BeaconRootsStorageAddress)
+ _, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
+ statedb.Finalise(true)
+}
diff --git a/core/state_processor_test.go b/core/state_processor_test.go
index 53b24c101a..dd4919c950 100644
--- a/core/state_processor_test.go
+++ b/core/state_processor_test.go
@@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
@@ -99,23 +100,22 @@ func TestStateProcessorErrors(t *testing.T) {
}), signer, key1)
return tx
}
- /*
- var mkBlobTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, hashes []common.Hash) *types.Transaction {
- tx, err := types.SignTx(types.NewTx(&types.BlobTx{
- Nonce: nonce,
- GasTipCap: uint256.MustFromBig(gasTipCap),
- GasFeeCap: uint256.MustFromBig(gasFeeCap),
- Gas: gasLimit,
- To: to,
- BlobHashes: hashes,
- Value: new(uint256.Int),
- }), signer, key1)
- if err != nil {
- t.Fatal(err)
- }
- return tx
+ var mkBlobTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap, blobGasFeeCap *big.Int, hashes []common.Hash) *types.Transaction {
+ tx, err := types.SignTx(types.NewTx(&types.BlobTx{
+ Nonce: nonce,
+ GasTipCap: uint256.MustFromBig(gasTipCap),
+ GasFeeCap: uint256.MustFromBig(gasFeeCap),
+ Gas: gasLimit,
+ To: to,
+ BlobHashes: hashes,
+ BlobFeeCap: uint256.MustFromBig(blobGasFeeCap),
+ Value: new(uint256.Int),
+ }), signer, key1)
+ if err != nil {
+ t.Fatal(err)
}
- */
+ return tx
+ }
{ // Tests against a 'recent' chain definition
var (
@@ -202,7 +202,7 @@ func TestStateProcessorErrors(t *testing.T) {
txs: []*types.Transaction{
mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(0), big.NewInt(0)),
},
- want: "invalid gas used (remote: 0 local: 21000)",
+ want: "could not apply tx 0 [0xc4ab868fef0c82ae0387b742aee87907f2d0fc528fc6ea0a021459fb0fc4a4a8]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 0, baseFee: 875000000",
},
{ // ErrTipVeryHigh
txs: []*types.Transaction{
@@ -237,29 +237,26 @@ func TestStateProcessorErrors(t *testing.T) {
txs: []*types.Transaction{
mkDynamicTx(0, common.Address{}, params.TxGas, bigNumber, bigNumber),
},
- want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 2431633873983640103894990685182446064918669677978451844828609264166175722438635000",
+ want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 required balance exceeds 256 bits",
},
{ // ErrMaxInitCodeSizeExceeded
txs: []*types.Transaction{
- mkDynamicCreationTx(0, 500000, common.Big0, big.NewInt(params.InitialBaseFeeForEthMainnet), tooBigInitCode[:]),
+ mkDynamicCreationTx(0, 500000, common.Big0, big.NewInt(params.InitialBaseFee), tooBigInitCode[:]),
},
want: "could not apply tx 0 [0xd491405f06c92d118dd3208376fcee18a57c54bc52063ee4a26b1cf296857c25]: max initcode size exceeded: code size 49153 limit 49152",
},
{ // ErrIntrinsicGas: Not enough gas to cover init code
txs: []*types.Transaction{
- mkDynamicCreationTx(0, 54299, common.Big0, big.NewInt(params.InitialBaseFeeForEthMainnet), make([]byte, 320)),
+ mkDynamicCreationTx(0, 54299, common.Big0, big.NewInt(params.InitialBaseFee), make([]byte, 320)),
},
want: "could not apply tx 0 [0xfd49536a9b323769d8472fcb3ebb3689b707a349379baee3e2ee3fe7baae06a1]: intrinsic gas too low: have 54299, want 54300",
},
- // TODO(Nathan), blobtx disable now
- /*
- { // ErrBlobFeeCapTooLow
- txs: []*types.Transaction{
- mkBlobTx(0, common.Address{}, params.TxGas, big.NewInt(1), big.NewInt(1), []common.Hash{(common.Hash{1})}),
- },
- want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1 baseFee: 875000000",
+ { // ErrBlobFeeCapTooLow
+ txs: []*types.Transaction{
+ mkBlobTx(0, common.Address{}, params.TxGas, big.NewInt(1), big.NewInt(1), big.NewInt(0), []common.Hash{(common.Hash{1})}),
},
- */
+ want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1, baseFee: 875000000",
+ },
} {
block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config)
_, err := blockchain.InsertChain(types.Blocks{block})
@@ -368,7 +365,8 @@ func TestStateProcessorErrors(t *testing.T) {
func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig) *types.Block {
difficulty := big.NewInt(0)
if !config.TerminalTotalDifficultyPassed {
- difficulty = engine.CalcDifficulty(&fakeChainReader{config}, parent.Time()+10, &types.Header{
+ fakeChainReader := newChainMaker(nil, config, engine)
+ difficulty = engine.CalcDifficulty(fakeChainReader, parent.Time()+10, &types.Header{
Number: parent.Number(),
Time: parent.Time(),
Difficulty: parent.Difficulty(),
@@ -419,6 +417,9 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)
header.ExcessBlobGas = &excess
header.BlobGasUsed = &used
+
+ beaconRoot := common.HexToHash("0xbeac00")
+ header.ParentBeaconRoot = &beaconRoot
}
// Assemble and return the final block for sealing
if config.IsShanghai(header.Number, header.Time) {
diff --git a/core/state_transition.go b/core/state_transition.go
index 2a40eff663..3b165f9ee8 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -17,7 +17,6 @@
package core
import (
- "errors"
"fmt"
"math"
"math/big"
@@ -25,18 +24,20 @@ import (
"github.com/ethereum/go-ethereum/common"
cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
- "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
// ExecutionResult includes all output after executing given evm
// message no matter the execution itself is successful or not.
type ExecutionResult struct {
- UsedGas uint64 // Total used gas but include the refunded gas
- Err error // Any error encountered during the execution(listed in core/vm/errors.go)
- ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode)
+ UsedGas uint64 // Total used gas, not including the refunded gas
+ RefundedGas uint64 // Total gas refunded after execution
+ Err error // Any error encountered during the execution(listed in core/vm/errors.go)
+ ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode)
}
// Unwrap returns the internal evm error which allows us for further
@@ -249,11 +250,15 @@ func (st *StateTransition) buyGas() error {
balanceCheck.Add(balanceCheck, blobBalanceCheck)
// Pay for blobGasUsed * actual blob fee
blobFee := new(big.Int).SetUint64(blobGas)
- blobFee.Mul(blobFee, eip4844.CalcBlobFee(*st.evm.Context.ExcessBlobGas))
+ blobFee.Mul(blobFee, st.evm.Context.BlobBaseFee)
mgval.Add(mgval, blobFee)
}
}
- if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 {
+ balanceCheckU256, overflow := uint256.FromBig(balanceCheck)
+ if overflow {
+ return fmt.Errorf("%w: address %v required balance exceeds 256 bits", ErrInsufficientFunds, st.msg.From.Hex())
+ }
+ if have, want := st.state.GetBalance(st.msg.From), balanceCheckU256; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want)
}
if err := st.gp.SubGas(st.msg.GasLimit); err != nil {
@@ -262,7 +267,8 @@ func (st *StateTransition) buyGas() error {
st.gasRemaining += st.msg.GasLimit
st.initialGas = st.msg.GasLimit
- st.state.SubBalance(st.msg.From, mgval)
+ mgvalU256, _ := uint256.FromBig(mgval)
+ st.state.SubBalance(st.msg.From, mgvalU256)
return nil
}
@@ -289,11 +295,11 @@ func (st *StateTransition) preCheck() error {
msg.From.Hex(), codeHash)
}
}
-
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
- if !st.evm.Config.NoBaseFee || msg.GasFeeCap.BitLen() > 0 || msg.GasTipCap.BitLen() > 0 {
+ skipCheck := st.evm.Config.NoBaseFee && msg.GasFeeCap.BitLen() == 0 && msg.GasTipCap.BitLen() == 0
+ if !skipCheck {
if l := msg.GasFeeCap.BitLen(); l > 256 {
return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh,
msg.From.Hex(), l)
@@ -309,34 +315,43 @@ func (st *StateTransition) preCheck() error {
// This will panic if baseFee is nil, but basefee presence is verified
// as part of header validation.
if msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 {
- return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow,
+ return fmt.Errorf("%w: address %v, maxFeePerGas: %s, baseFee: %s", ErrFeeCapTooLow,
msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee)
}
}
}
// Check the blob version validity
if msg.BlobHashes != nil {
+ // The to field of a blob tx type is mandatory, and a `BlobTx` transaction internally
+ // has it as a non-nillable value, so any msg derived from blob transaction has it non-nil.
+ // However, messages created through RPC (eth_call) don't have this restriction.
+ if msg.To == nil {
+ return ErrBlobTxCreate
+ }
if len(msg.BlobHashes) == 0 {
- return errors.New("blob transaction missing blob hashes")
+ return ErrMissingBlobHashes
}
for i, hash := range msg.BlobHashes {
- if hash[0] != params.BlobTxHashVersion {
- return fmt.Errorf("blob %d hash version mismatch (have %d, supported %d)",
- i, hash[0], params.BlobTxHashVersion)
+ if !kzg4844.IsValidVersionedHash(hash[:]) {
+ return fmt.Errorf("blob %d has invalid hash version", i)
}
}
}
-
+ // Check that the user is paying at least the current blob fee
if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) {
if st.blobGasUsed() > 0 {
- // Check that the user is paying at least the current blob fee
- blobFee := eip4844.CalcBlobFee(*st.evm.Context.ExcessBlobGas)
- if st.msg.BlobGasFeeCap.Cmp(blobFee) < 0 {
- return fmt.Errorf("%w: address %v have %v want %v", ErrBlobFeeCapTooLow, st.msg.From.Hex(), st.msg.BlobGasFeeCap, blobFee)
+ // Skip the checks if gas fields are zero and blobBaseFee was explicitly disabled (eth_call)
+ skipCheck := st.evm.Config.NoBaseFee && msg.BlobGasFeeCap.BitLen() == 0
+ if !skipCheck {
+ // This will panic if blobBaseFee is nil, but blobBaseFee presence
+ // is verified as part of header validation.
+ if msg.BlobGasFeeCap.Cmp(st.evm.Context.BlobBaseFee) < 0 {
+ return fmt.Errorf("%w: address %v blobGasFeeCap: %v, blobBaseFee: %v", ErrBlobFeeCapTooLow,
+ msg.From.Hex(), msg.BlobGasFeeCap, st.evm.Context.BlobBaseFee)
+ }
}
}
}
-
return st.buyGas()
}
@@ -400,7 +415,11 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
st.gasRemaining -= gas
// Check clause 6
- if msg.Value.Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From, msg.Value) {
+ value, overflow := uint256.FromBig(msg.Value)
+ if overflow {
+ return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex())
+ }
+ if !value.IsZero() && !st.evm.Context.CanTransfer(st.state, msg.From, value) {
return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex())
}
@@ -419,40 +438,45 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
vmerr error // vm errors do not effect consensus and are therefore not assigned to err
)
if contractCreation {
- ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, msg.Value)
+ ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value)
} else {
// Increment the nonce for the next transaction
st.state.SetNonce(msg.From, st.state.GetNonce(sender.Address())+1)
- ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value)
+ ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value)
}
+ var gasRefund uint64
if !rules.IsLondon {
// Before EIP-3529: refunds were capped to gasUsed / 2
- st.refundGas(params.RefundQuotient)
+ gasRefund = st.refundGas(params.RefundQuotient)
} else {
// After EIP-3529: refunds are capped to gasUsed / 5
- st.refundGas(params.RefundQuotientEIP3529)
+ gasRefund = st.refundGas(params.RefundQuotientEIP3529)
}
effectiveTip := msg.GasPrice
if rules.IsLondon {
effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee))
}
+ effectiveTipU256, _ := uint256.FromBig(effectiveTip)
+ fee := new(uint256.Int).SetUint64(st.gasUsed())
+ fee.Mul(fee, effectiveTipU256)
// consensus engine is parlia
if st.evm.ChainConfig().Parlia != nil {
- st.state.AddBalance(consensus.SystemAddress, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip))
+ st.state.AddBalance(consensus.SystemAddress, fee)
} else {
- st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip))
+ st.state.AddBalance(st.evm.Context.Coinbase, fee)
}
return &ExecutionResult{
- UsedGas: st.gasUsed(),
- Err: vmerr,
- ReturnData: ret,
+ UsedGas: st.gasUsed(),
+ RefundedGas: gasRefund,
+ Err: vmerr,
+ ReturnData: ret,
}, nil
}
-func (st *StateTransition) refundGas(refundQuotient uint64) {
+func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {
// Apply refund counter, capped to a refund quotient
refund := st.gasUsed() / refundQuotient
if refund > st.state.GetRefund() {
@@ -461,12 +485,15 @@ func (st *StateTransition) refundGas(refundQuotient uint64) {
st.gasRemaining += refund
// Return ETH for remaining gas, exchanged at the original rate.
- remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gasRemaining), st.msg.GasPrice)
+ remaining := uint256.NewInt(st.gasRemaining)
+ remaining = remaining.Mul(remaining, uint256.MustFromBig(st.msg.GasPrice))
st.state.AddBalance(st.msg.From, remaining)
// Also return remaining gas to the block gas counter so it is
// available for the next transaction.
st.gp.AddGas(st.gasRemaining)
+
+ return refund
}
// gasUsed returns the amount of gas used up by the state transition.
diff --git a/core/systemcontracts/const.go b/core/systemcontracts/const.go
index a5a74905e0..430000e415 100644
--- a/core/systemcontracts/const.go
+++ b/core/systemcontracts/const.go
@@ -13,4 +13,10 @@ const (
TokenManagerContract = "0x0000000000000000000000000000000000001008"
CrossChainContract = "0x0000000000000000000000000000000000002000"
StakingContract = "0x0000000000000000000000000000000000002001"
+ StakeHubContract = "0x0000000000000000000000000000000000002002"
+ StakeCreditContract = "0x0000000000000000000000000000000000002003"
+ GovernorContract = "0x0000000000000000000000000000000000002004"
+ GovTokenContract = "0x0000000000000000000000000000000000002005"
+ TimelockContract = "0x0000000000000000000000000000000000002006"
+ TokenRecoverPortalContract = "0x0000000000000000000000000000000000003000"
)
diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go
index 26650673b8..973c023e16 100644
--- a/core/systemcontracts/upgrade.go
+++ b/core/systemcontracts/upgrade.go
@@ -57,6 +57,8 @@ var (
platoUpgrade = make(map[string]*Upgrade)
keplerUpgrade = make(map[string]*Upgrade)
+
+ feynmanUpgrade = make(map[string]*Upgrade)
)
func init() {
@@ -530,23 +532,135 @@ func init() {
},
}
- keplerUpgrade[rialtoNet] = &Upgrade{
- UpgradeName: "kepler",
+ // TODO: update mainNet and chapelNet to latest version
+ feynmanUpgrade[chapelNet] = &Upgrade{
+ UpgradeName: "feynman",
Configs: []*UpgradeConfig{
{
ContractAddr: common.HexToAddress(ValidatorContract),
- CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/b3a5c1fa8882c0e546dc5ba913ce4db77ec9befe",
- Code: "6080604052600436106104a35760003560e01c806388b32f1111610260578063c6d3394511610144578063e40716a1116100c1578063f92eb86b11610085578063f92eb86b14610c02578063f9a2bbc714610c17578063fc3e590814610c2c578063fccc281314610c41578063fd4ad81f14610c56578063fd6a687914610c85576104aa565b8063e40716a114610b85578063ea321e4914610b9a578063eb57e20214610bba578063eda5868c14610bda578063f340fa0114610bef576104aa565b8063d86222d511610108578063d86222d514610b1c578063daacdb6614610b31578063dc927faf14610b46578063e086c7b114610b5b578063e1c7392a14610b70576104aa565b8063c6d3394514610abd578063c81b166214610ad2578063c8509d81146108b6578063ce910b0c14610ae7578063d68fb56a14610b07576104aa565b8063a5422d5c116101dd578063ad3c9da6116101a1578063ad3c9da614610a3c578063aef198a914610a5c578063b7ab4db514610a71578063b8cf4ef114610a93578063bf9f499514610666578063c466689d14610aa8576104aa565b8063a5422d5c146109c8578063a78abc16146109dd578063aaf5eb68146109f2578063ab51bb9614610a07578063ac43175114610a1c576104aa565b806396713da91161022457806396713da91461095f5780639dc09262146109745780639fe0f81614610989578063a0dc27581461099e578063a1a11bf5146109b3576104aa565b806388b32f11146108eb5780638a7beb01146109005780638b5ad0c9146109155780638d19a4101461092a5780639369d7de1461094a576104aa565b806351e80672116103875780636e47b482116103045780637942fd05116102c85780637942fd05146108775780637a84ca2a1461088c57806381650b62146108a1578063831d65d1146108b6578063853230aa1461086257806386249882146108d6576104aa565b80636e47b4821461080e57806370fd5bad14610823578063718a8aa81461083857806375d47a0a1461084d57806378dfed4a14610862576104aa565b80635de1e22c1161034b5780635de1e22c14610792578063603d86d31461065157806360eba4fe146107a757806362b72cf5146107c75780636969a25c146107dc576104aa565b806351e806721461071357806355614fcc14610728578063565c56b3146107485780635667515a146107685780635d77156c1461077d576104aa565b80633365af3a1161042057806343756e5c116103e457806343756e5c1461068857806345cf9daf1461069d578063493279b1146106b25780634bf6c882146106d45780634df6e0c3146106e95780635192c82c146106fe576104aa565b80633365af3a146105ee57806335409f7f1461060e5780633b071dcc1461062e5780633de0f0d8146106515780633dffc38714610666576104aa565b8063152ad3b811610467578063152ad3b8146105625780631ff1806914610584578063219f22d514610599578063300c3567146105ae578063321d398a146105ce576104aa565b806304c4fec6146104af57806307a56847146104c65780630bee7a67146104f15780630e2374a5146105135780631182b87514610535576104aa565b366104aa57005b600080fd5b3480156104bb57600080fd5b506104c4610c9a565b005b3480156104d257600080fd5b506104db610d0c565b6040516104e89190617692565b60405180910390f35b3480156104fd57600080fd5b50610506610d12565b6040516104e891906176bc565b34801561051f57600080fd5b50610528610d17565b6040516104e89190616a61565b34801561054157600080fd5b50610555610550366004616947565b610d1d565b6040516104e89190616bd8565b34801561056e57600080fd5b50610577610f55565b6040516104e89190616bcd565b34801561059057600080fd5b506104db610f5e565b3480156105a557600080fd5b50610506610f64565b3480156105ba57600080fd5b506104c46105c93660046167d1565b610f69565b3480156105da57600080fd5b506105776105e93660046168f4565b6112b0565b3480156105fa57600080fd5b506105776106093660046168f4565b61137f565b34801561061a57600080fd5b506104c46106293660046167aa565b611430565b34801561063a57600080fd5b50610643611589565b6040516104e8929190616ae3565b34801561065d57600080fd5b506104db611865565b34801561067257600080fd5b5061067b61186b565b6040516104e891906176cd565b34801561069457600080fd5b50610528611870565b3480156106a957600080fd5b506104db611876565b3480156106be57600080fd5b506106c761187c565b6040516104e89190617683565b3480156106e057600080fd5b5061067b611882565b3480156106f557600080fd5b50610643611887565b34801561070a57600080fd5b506104db611a05565b34801561071f57600080fd5b50610528611a0b565b34801561073457600080fd5b506105776107433660046167aa565b611a11565b34801561075457600080fd5b506104db6107633660046167aa565b611a46565b34801561077457600080fd5b5061067b611a97565b34801561078957600080fd5b50610506611a9c565b34801561079e57600080fd5b506104db611aa1565b3480156107b357600080fd5b506105556107c23660046168f4565b611aa7565b3480156107d357600080fd5b506104db611b4d565b3480156107e857600080fd5b506107fc6107f73660046168f4565b611b53565b6040516104e896959493929190616a8e565b34801561081a57600080fd5b50610528611bb7565b34801561082f57600080fd5b5061067b611bbd565b34801561084457600080fd5b5061067b611bc2565b34801561085957600080fd5b50610528611bc7565b34801561086e57600080fd5b506104db611bcd565b34801561088357600080fd5b5061067b611bd3565b34801561089857600080fd5b506104db611bd8565b3480156108ad57600080fd5b50610506611bde565b3480156108c257600080fd5b506104c46108d1366004616947565b611be3565b3480156108e257600080fd5b506104db611c44565b3480156108f757600080fd5b506104db611c4a565b34801561090c57600080fd5b50610577611c50565b34801561092157600080fd5b506104db611c59565b34801561093657600080fd5b506104db6109453660046167aa565b611c5f565b34801561095657600080fd5b506104c4611c9f565b34801561096b57600080fd5b5061067b611db3565b34801561098057600080fd5b50610528611db8565b34801561099557600080fd5b506104db611dbe565b3480156109aa57600080fd5b506104db611dc3565b3480156109bf57600080fd5b50610528611dc8565b3480156109d457600080fd5b50610555611dce565b3480156109e957600080fd5b50610577611ded565b3480156109fe57600080fd5b506104db611df6565b348015610a1357600080fd5b50610506611a97565b348015610a2857600080fd5b506104c4610a37366004616898565b611dff565b348015610a4857600080fd5b506104db610a573660046167aa565b61269d565b348015610a6857600080fd5b506104db6126af565b348015610a7d57600080fd5b50610a866126bc565b6040516104e89190616ad0565b348015610a9f57600080fd5b506104db6127a8565b348015610ab457600080fd5b506104db6127ad565b348015610ac957600080fd5b506104db611bbd565b348015610ade57600080fd5b506105286127b3565b348015610af357600080fd5b50610555610b023660046168f4565b6127b9565b348015610b1357600080fd5b506104db6127c6565b348015610b2857600080fd5b506104db612805565b348015610b3d57600080fd5b506104db612811565b348015610b5257600080fd5b50610528612817565b348015610b6757600080fd5b506104db610d12565b348015610b7c57600080fd5b506104c461281d565b348015610b9157600080fd5b506104db6129cc565b348015610ba657600080fd5b50610577610bb5366004616859565b6129d2565b348015610bc657600080fd5b506104c4610bd53660046167aa565b612b58565b348015610be657600080fd5b50610506612c60565b6104c4610bfd3660046167aa565b612c65565b348015610c0e57600080fd5b506104db612fcd565b348015610c2357600080fd5b50610528612fd3565b348015610c3857600080fd5b5061067b611dbe565b348015610c4d57600080fd5b50610528612fd9565b348015610c6257600080fd5b50610c76610c713660046168f4565b612fdf565b6040516104e89392919061769b565b348015610c9157600080fd5b506105286130a1565b6000610ca533611c5f565b9050600b8181548110610cb457fe5b600091825260209091206001601690920201015460ff16610cf05760405162461bcd60e51b8152600401610ce79061733d565b60405180910390fd5b6000610cfa6127c6565b9050610d073383836130a7565b505050565b60095481565b606481565b61200181565b60005460609060ff16610d425760405162461bcd60e51b8152600401610ce790616d97565b3361200014610d635760405162461bcd60e51b8152600401610ce7906174d6565b600b54610e2157610d72616496565b60015460005b81811015610e1d57600b805460018101825560009190915283516000805160206178f083398151915260169092029182019081556020808601516000805160206179308339815191528401805460ff1916911515919091179055604086015180518794610df9936000805160206179108339815191529091019201906164c5565b506060820151610e0f906003830190601361653f565b505050806001019050610d78565b5050505b610e2961656c565b6000610e6a85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061329392505050565b9150915080610e8657610e7d606461344f565b92505050610f4e565b815160009060ff16610eab57610ea4836020015184604001516134b0565b9050610f1a565b825160ff1660011415610f1657826020015151600114610ef0576000805160206178d0833981519152604051610ee0906171f6565b60405180910390a1506067610f11565b610ea48360200151600081518110610f0457fe5b6020026020010151614104565b610f1a565b5060655b63ffffffff8116610f3f5750506040805160008152602081019091529150610f4e9050565b610f488161344f565b93505050505b9392505050565b60075460ff1681565b60035481565b606881565b334114610f885760405162461bcd60e51b8152600401610ce790617525565b6010544311610fa95760405162461bcd60e51b8152600401610ce790616ef3565b3a15610fc75760405162461bcd60e51b8152600401610ce79061727c565b60005460ff16610fe95760405162461bcd60e51b8152600401610ce790616d97565b60006110023168056bc75e2d63100000811115611020576110198168056bc75e2d6310000063ffffffff61427b16565b9150611027565b50506112a6565b6040516213929d60e11b8152611002906227253a9061104c9030908690600401616a75565b602060405180830381600087803b15801561106657600080fd5b505af115801561107a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109e919061690c565b9150816110ac5750506112a6565b6000805b848110156110da578585828181106110c457fe5b90506020020135820191508060010190506110b0565b50806110e8575050506112a6565b6000806000805b8981101561129e578489898381811061110457fe5b9050602002013588028161111457fe5b0493508a8a8281811061112357fe5b905060200201602081019061113891906167aa565b6001600160a01b0381166000908152600460205260409020549093509150811561125457600060018084038154811061116d57fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff16156111da57836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85866040516111cd9190617692565b60405180910390a261124e565b6003546111ed908663ffffffff6142bd16565b6003908155810154611205908663ffffffff6142bd16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b290611245908890617692565b60405180910390a25b50611296565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d858560405161128d9190617692565b60405180910390a25b6001016110ef565b505050505050505b5050436010555050565b60015460009082106112c45750600061137a565b60006001600160a01b0316600183815481106112dc57fe5b60009182526020909120600490910201546001600160a01b0316148061130c5750600854158061130c5750600a54155b8061131b575060085460095410155b8061132c575061132a8261137f565b155b8061135557506000600b838154811061134157fe5b906000526020600020906016020160000154115b80611369575060016113656126bc565b5111155b156113765750600061137a565b5060015b919050565b60015460009082106113935750600061137a565b600b5482106113d057600182815481106113a957fe5b9060005260206000209060040201600201601c9054906101000a900460ff1615905061137a565b600182815481106113dd57fe5b9060005260206000209060040201600201601c9054906101000a900460ff1615801561142a5750600b828154811061141157fe5b600091825260209091206001601690920201015460ff16155b92915050565b33611001146114515760405162461bcd60e51b8152600401610ce79061763a565b600b5461150f57611460616496565b60015460005b8181101561150b57600b805460018101825560009190915283516000805160206178f083398151915260169092029182019081556020808601516000805160206179308339815191528401805460ff19169115159190911790556040860151805187946114e7936000805160206179108339815191529091019201906164c5565b5060608201516114fd906003830190601361653f565b505050806001019050611466565b5050505b6001600160a01b038116600090815260046020526040902054806115335750611586565b6001810390506000600b828154811061154857fe5b600091825260209091206001601690920201015460ff16905061156b83836142e2565b80156115745750805b15610d07576009805460001901905550505b50565b60015460609081906000805b828110156115dc57600181815481106115aa57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166115d4576001909101905b600101611595565b50606081604051908082528060200260200182016040528015611609578160200160208202803683370190505b50905060608260405190808252806020026020018201604052801561164257816020015b606081526020019060019003908161162d5790505b50600b54600094509091508414156117bd5760005b848110156117b7576001818154811061166c57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166117af576001818154811061169c57fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106116c757fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b81815481106116f457fe5b600091825260209182902060026016909202018101805460408051601f60001961010060018616150201909316949094049182018590048502840185019052808352919290919083018282801561178c5780601f106117615761010080835404028352916020019161178c565b820191906000526020600020905b81548152906001019060200180831161176f57829003601f168201915b505050505082858151811061179d57fe5b60209081029190910101526001909301925b600101611657565b50611859565b60005b8481101561185757600181815481106117d557fe5b9060005260206000209060040201600201601c9054906101000a900460ff1661184f576001818154811061180557fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061183057fe5b6001600160a01b03909216602092830291909101909101526001909301925b6001016117c0565b505b909450925050505b9091565b61271081565b600181565b61100181565b60085481565b6102ca81565b600881565b600e54600c5460609182918061189b575060155b60606118a56126bc565b905060606118b282614695565b9050828251116118c9579094509250611861915050565b838383510310156118db578282510393505b83156119115760c843046118f783838388880360008a8a614803565b61190f8383838888038989038a8b8b8b510301614803565b505b60608360405190808252806020026020018201604052801561193d578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561197657816020015b60608152602001906001900390816119615790505b50905060005b858110156119f75784818151811061199057fe5b60200260200101518382815181106119a457fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508381815181106119d057fe5b60200260200101518282815181106119e457fe5b602090810291909101015260010161197c565b509096509450505050509091565b60065481565b61200081565b6001600160a01b03811660009081526004602052604081205480611a3957600091505061137a565b60001901610f4e8161137f565b6001600160a01b03811660009081526004602052604081205480611a6e57600091505061137a565b600180820381548110611a7d57fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b600f5481565b60128181548110611ab457fe5b600091825260209182902001805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815293509091830182828015611b455780601f10611b1a57610100808354040283529160200191611b45565b820191906000526020600020905b815481529060010190602001808311611b2857829003601f168201915b505050505081565b60105481565b60018181548110611b6057fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b606681565b3361200014611c045760405162461bcd60e51b8152600401610ce7906174d6565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051611c37939291906176db565b60405180910390a1505050565b60025481565b60115481565b60145460ff1681565b600a5481565b6001600160a01b03811660009081526004602052604081205480611c955760405162461bcd60e51b8152600401610ce79061745e565b6000190192915050565b600b54611d5d57611cae616496565b60015460005b81811015611d5957600b805460018101825560009190915283516000805160206178f083398151915260169092029182019081556020808601516000805160206179308339815191528401805460ff1916911515919091179055604086015180518794611d35936000805160206179108339815191529091019201906164c5565b506060820151611d4b906003830190601361653f565b505050806001019050611cb4565b5050505b600854611d6a5760036008555b600a54611d77576002600a555b6000611d8233611c5f565b9050611d8d816112b0565b611da95760405162461bcd60e51b8152600401610ce7906171b3565b611586338261495a565b600981565b61100781565b600381565b60c881565b61100681565b604051806101e001604052806101ab81526020016177256101ab913981565b60005460ff1681565b6402540be40081565b60005460ff16611e215760405162461bcd60e51b8152600401610ce790616d97565b3361100714611e425760405162461bcd60e51b8152600401610ce7906172aa565b611eac84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506149f29050565b15611f495760208114611ed15760405162461bcd60e51b8152600401610ce790617418565b604080516020601f8401819004810282018101909252828152600091611f0f91858580838501838280828437600092019190915250614a4b92505050565b905060648110158015611f255750620186a08111155b611f415760405162461bcd60e51b8152600401610ce7906170a3565b60025561265a565b611fa984848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506149f29050565b156120385760208114611fce5760405162461bcd60e51b8152600401610ce790616c1d565b604080516020601f840181900481028201810190925282815260009161200c91858580838501838280828437600092019190915250614a4b92505050565b90506127108111156120305760405162461bcd60e51b8152600401610ce790616f35565b60065561265a565b6120a284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506149f29050565b1561213c57602081146120c75760405162461bcd60e51b8152600401610ce790616c54565b604080516020601f840181900481028201810190925282815260009161210591858580838501838280828437600092019190915250614a4b92505050565b600c5490915080612114575060155b8082106121335760405162461bcd60e51b8152600401610ce790616fa8565b5060085561265a565b6121a584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506149f29050565b1561223e57602081146121ca5760405162461bcd60e51b8152600401610ce790616d1d565b604080516020601f840181900481028201810190925282815260009161220891858580838501838280828437600092019190915250614a4b92505050565b905060008111801561221a5750600a81105b6122365760405162461bcd60e51b8152600401610ce7906175b6565b600a5561265a565b6122b284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506149f29050565b1561234157602081146122d75760405162461bcd60e51b8152600401610ce790616cd1565b604080516020601f840181900481028201810190925282815260009161231591858580838501838280828437600092019190915250614a4b92505050565b9050600d548111156123395760405162461bcd60e51b8152600401610ce790617119565b600e5561265a565b6123aa84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506149f29050565b1561242c57602081146123cf5760405162461bcd60e51b8152600401610ce7906172f8565b604080516020601f840181900481028201810190925282815260009161240d91858580838501838280828437600092019190915250614a4b92505050565b600d819055600e5490915081101561242657600d54600e555b5061265a565b61249084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506149f29050565b1561253e57602081146124b55760405162461bcd60e51b8152600401610ce790616d62565b604080516020601f84018190048102820181019092528281526000916124f391858580838501838280828437600092019190915250614a4b92505050565b9050600081116125155760405162461bcd60e51b8152600401610ce790616e05565b60648111156125365760405162461bcd60e51b8152600401610ce790616e4d565b600c5561265a565b6125a684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601181527073797374656d526577617264526174696f60781b602082015291506149f29050565b1561264257602081146125cb5760405162461bcd60e51b8152600401610ce790617572565b604080516020601f840181900481028201810190925282815260009161260991858580838501838280828437600092019190915250614a4b92505050565b90506001811015801561261e57506127108111155b61263a5760405162461bcd60e51b8152600401610ce790617050565b600f5561265a565b60405162461bcd60e51b8152600401610ce790617613565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a8484848460405161268f9493929190616beb565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156126eb576126d78161137f565b156126e3578160010191505b6001016126c6565b50606081604051908082528060200260200182016040528015612718578160200160208202803683370190505b5090506000915060005b8381101561279f576127338161137f565b15612797576001818154811061274557fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061277057fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101612722565b50925050505b90565b601581565b61027181565b61100281565b60138181548110611ab457fe5b60006127d06126bc565b519050600080600c54116127e55760156127e9565b600c545b9050808211156127f7578091505b8161280157600191505b5090565b67016345785d8a000081565b60055481565b61100381565b60005460ff16156128405760405162461bcd60e51b8152600401610ce7906173aa565b61284861656c565b600061286e604051806101e001604052806101ab81526020016177256101ab9139613293565b915091508061288f5760405162461bcd60e51b8152600401610ce790617495565b60005b8260200151518110156129b4576001836020015182815181106128b157fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061298757fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101612892565b50506103e8600255506000805460ff19166001179055565b600d5481565b601354600090815b81811015612adb57612ac385858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050601380549092508591508110612a2b57fe5b600091825260209182902001805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015612ab95780601f10612a8e57610100808354040283529160200191612ab9565b820191906000526020600020905b815481529060010190602001808311612a9c57829003601f168201915b5050505050614a50565b15612ad35760019250505061142a565b6001016129da565b5060125460005b81811015612b4c57612b3386868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050601280549092508591508110612a2b57fe5b15612b44576001935050505061142a565b600101612ae2565b50600095945050505050565b3361100114612b795760405162461bcd60e51b8152600401610ce79061763a565b600b54612c3757612b88616496565b60015460005b81811015612c3357600b805460018101825560009190915283516000805160206178f083398151915260169092029182019081556020808601516000805160206179308339815191528401805460ff1916911515919091179055604086015180518794612c0f936000805160206179108339815191529091019201906164c5565b506060820151612c25906003830190601361653f565b505050806001019050612b8e565b5050505b6000612c4282614ab4565b9050612c4d816112b0565b15612c5c57612c5c828261495a565b5050565b606581565b334114612c845760405162461bcd60e51b8152600401610ce790617525565b60005460ff16612ca65760405162461bcd60e51b8152600401610ce790616d97565b60003411612cc65760405162461bcd60e51b8152600401610ce7906170ea565b3a15612ce45760405162461bcd60e51b8152600401610ce79061727c565b6001600160a01b03811660009081526004602052604090205460145434919060ff16612d2457610271600f556103e86006556014805460ff191660011790555b6000612d4d612710612d41600f5486614c5790919063ffffffff16565b9063ffffffff614c9116565b90508015612dbd576040516110029082156108fc029083906000818181858888f19350505050158015612d84573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d81604051612db49190617692565b60405180910390a15b600083118015612dcf57506000600654115b15612e75576000612df1612710612d4160065487614c5790919063ffffffff16565b90508015612e735760405161dead9082156108fc029083906000818181858888f19350505050158015612e28573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee581604051612e589190617692565b60405180910390a1612e70848263ffffffff61427b16565b93505b505b612e85838263ffffffff61427b16565b92508115612f85576000600180840381548110612e9e57fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615612f0b57846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b485604051612efe9190617692565b60405180910390a2612f7f565b600354612f1e908563ffffffff6142bd16565b6003908155810154612f36908563ffffffff6142bd16565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc05590612f76908790617692565b60405180910390a25b50612fc7565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b484604051612fbe9190617692565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b8181548110612fec57fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff909116949192918301828280156130975780601f1061306c57610100808354040283529160200191613097565b820191906000526020600020905b81548152906001019060200180831161307a57829003601f168201915b5050505050905083565b61100481565b6000600a54600014806130b8575081155b806130c35750600954155b156130d057506000610f4e565b6009600081546001900391905081905550600061311b600a54612d4185612d41600b89815481106130fd57fe5b6000918252602090912060169091020154439063ffffffff61427b16565b90506000600b858154811061312c57fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b15801561319157600080fd5b505afa1580156131a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131c99190616924565b9150915060009350808310613243576131e287876142e2565b506040516305bfb49960e41b815261100190635bfb499090613208908a90600401616a61565b600060405180830381600087803b15801561322257600080fd5b505af1158015613236573d6000803e3d6000fd5b5050505060019350613255565b8183106132555761325387614ab4565b505b6040516001600160a01b038816907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050509392505050565b61329b61656c565b60006132a561656c565b6132ad616590565b6132be6132b986614cd3565b614cf8565b90506000805b6132cd83614d42565b1561344157806132f2576132e86132e384614d63565b614db1565b60ff168452613439565b806001141561343457606061330e61330985614d63565b614e31565b9050805160405190808252806020026020018201604052801561334b57816020015b6133386165b0565b8152602001906001900390816133305790505b508560200181905250805160405190808252806020026020018201604052801561338957816020015b60608152602001906001900390816133745790505b50604086015260005b8151811015613429576133a36165b0565b606060006133c38585815181106133b657fe5b6020026020010151614f02565b925092509250806133e3578860009a509a5050505050505050505061344a565b82896020015185815181106133f457fe5b6020026020010181905250818960400151858151811061341057fe5b6020026020010181905250505050806001019050613392565b506001925050613439565b613441565b6001016132c4565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b606081526020019060019003908161346957905050905061348f8363ffffffff1661501c565b8160008151811061349c57fe5b6020026020010181905250610f4e8161502f565b60006064835111156134e7576000805160206178d08339815191526040516134d790616eaa565b60405180910390a150606661142a565b60005b83518110156135855760005b8181101561357c5784818151811061350a57fe5b6020026020010151600001516001600160a01b031685838151811061352b57fe5b6020026020010151600001516001600160a01b03161415613574576000805160206178d083398151915260405161356190617005565b60405180910390a160669250505061142a565b6001016134f6565b506001016134ea565b5060608061359385856150b9565b60015491935091506000908190815b818110156136185767016345785d8a0000600182815481106135c057fe5b906000526020600020906004020160030154106135e257836001019350613610565b6000600182815481106135f157fe5b9060005260206000209060040201600301541115613610578260010192505b6001016135a2565b50606083604051908082528060200260200182016040528015613645578160200160208202803683370190505b509050606084604051908082528060200260200182016040528015613674578160200160208202803683370190505b5090506060856040519080825280602002602001820160405280156136a3578160200160208202803683370190505b5090506060866040519080825280602002602001820160405280156136d2578160200160208202803683370190505b5090506000606087604051908082528060200260200182016040528015613703578160200160208202803683370190505b509050606088604051908082528060200260200182016040528015613732578160200160208202803683370190505b509050600099506000985060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561377a57600080fd5b505afa15801561378e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137b2919061690c565b905067016345785d8a00008111156137fd576000805160206178d08339815191526040516137df90617369565b60405180910390a160689d505050505050505050505050505061142a565b60005b89811015613a6e5767016345785d8a00006001828154811061381e57fe5b906000526020600020906004020160030154106139a3576001818154811061384257fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898d8151811061387357fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be400600183815481106138a857fe5b906000526020600020906004020160030154816138c157fe5b06600183815481106138cf57fe5b9060005260206000209060040201600301540390506138f7838261427b90919063ffffffff16565b898e8151811061390357fe5b6020026020010181815250506001828154811061391c57fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316878e8151811061394d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888e8151811061397a57fe5b6020908102919091010152613995868263ffffffff6142bd16565b95508c6001019c5050613a66565b6000600182815481106139b257fe5b9060005260206000209060040201600301541115613a6657600181815481106139d757fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848c81518110613a0857fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060018181548110613a3557fe5b906000526020600020906004020160030154838c81518110613a5357fe5b6020026020010181815250508a6001019a505b600101613800565b5060008415613ce4576002546040516303702b2960e51b815261100491636e056520918891613aa8918e918e918d91420190600401616b53565b6020604051808303818588803b158015613ac157600080fd5b505af193505050508015613af2575060408051601f3d908101601f19168201909252613aef91810190616839565b60015b613c69576040516000815260443d1015613b0e57506000613ba9565b60046000803e60005160e01c6308c379a08114613b2f576000915050613ba9565b60043d036004833e81513d60248201116001600160401b0382111715613b5a57600092505050613ba9565b80830180516001600160401b03811115613b7b576000945050505050613ba9565b8060208301013d8601811115613b9957600095505050505050613ba9565b601f01601f191660405250925050505b80613bb45750613bf6565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051613be89190616bd8565b60405180910390a250613c64565b3d808015613c20576040519150601f19603f3d011682016040523d82523d6000602084013e613c25565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a4582604051613c5a9190616bd8565b60405180910390a2505b613ce4565b8015613cab577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b7086604051613c9e9190617692565b60405180910390a1613ce2565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280604051613cd990616c9a565b60405180910390a25b505b8015613e9a5760005b8751811015613e98576000888281518110613d0457fe5b60200260200101519050600060018281548110613d1d57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc9185908110613d4e57fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015613e0a5760018281548110613d8f57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110613dde57fe5b906000526020600020906004020160030154604051613dfd9190617692565b60405180910390a2613e8e565b60018281548110613e1757fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110613e6657fe5b906000526020600020906004020160030154604051613e859190617692565b60405180910390a25b5050600101613ced565b505b835115613fe45760005b8451811015613fe2576000858281518110613ebb57fe5b60200260200101516001600160a01b03166108fc868481518110613edb57fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015613f7157858281518110613f1157fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110613f4f57fe5b6020026020010151604051613f649190617692565b60405180910390a2613fd9565b858281518110613f7d57fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110613fbb57fe5b6020026020010151604051613fd09190617692565b60405180910390a25b50600101613ea4565b505b5050505050505050505050506000471115614060577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516140289190617692565b60405180910390a1604051611002904780156108fc02916000818181858888f1935050505015801561405e573d6000803e3d6000fd5b505b6000600381905560055581511561407b5761407b82826152f2565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156140b857600080fd5b505af11580156140cc573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b80516001600160a01b0316600090815260046020526040812054801580614155575060018082038154811061413557fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b1561419b5782516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a2600091505061137a565b6001546005546000198201118015906141f15784516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a26000935050505061137a565b60058054600190810190915580548190600019860190811061420f57fe5b6000918252602082206002600490920201018054921515600160e01b0260ff60e01b199093169290921790915585516040516001600160a01b03909116917ff226e7d8f547ff903d9d419cf5f54e0d7d07efa9584135a53a057c5f1f27f49a91a2506000949350505050565b6000610f4e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615aac565b600082820183811015610f4e5760405162461bcd60e51b8152600401610ce790616dce565b600080600183815481106142f257fe5b9060005260206000209060040201600301549050600060018080549050039050600161431c6126bc565b51116143515760006001858154811061433157fe5b90600052602060002090600402016003018190555060009250505061142a565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a708360405161438a9190617692565b60405180910390a26001600160a01b038516600090815260046020526040812055835b6001546000190181101561457757600181600101815481106143cb57fe5b9060005260206000209060040201600182815481106143e657fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b8054909183019081106144a757fe5b9060005260206000209060160201600b82815481106144c257fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff19909216919091179055600280840180546145199383860193908216156101000260001901909116046165e5565b5061452c6003828101908401601361665a565b5090505080600101600460006001848154811061454557fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020556001016143ad565b50600180548061458357fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b8054806145d657fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906146086002830182616684565b6146166003830160006166c8565b50509055600081838161462557fe5b04905080156146895760015460005b8181101561468657826001828154811061464a57fe5b906000526020600020906004020160030154016001828154811061466a57fe5b6000918252602090912060036004909202010155600101614634565b50505b50600195945050505050565b6001548151604080518281526020808402820101909152606092919083908280156146d457816020015b60608152602001906001900390816146bf5790505b50600b5490915083146146eb57925061137a915050565b60005b828110156147fa57600b60016004600089858151811061470a57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054038154811061473e57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156147d65780601f106147ab576101008083540402835291602001916147d6565b820191906000526020600020905b8154815290600101906020018083116147b957829003601f168201915b50505050508282815181106147e757fe5b60209081029190910101526001016146ee565b50949350505050565b60005b828110156149505760008287838801604051602001614826929190616a53565b6040516020818303038152906040528051906020012060001c8161484657fe5b06905080850182870114614947576000898388018151811061486457fe5b602002602001015190506060898489018151811061487e57fe5b602002602001015190508a8388018151811061489657fe5b60200260200101518b858a01815181106148ac57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b848901815181106148db57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061490957fe5b60200260200101518a858a018151811061491f57fe5b6020026020010181905250808a8489018151811061493957fe5b602002602001018190525050505b50600101614806565b5050505050505050565b600980546001908101909155600b80548390811061497457fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b82815481106149aa57fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b600081604051602001614a059190616a37565b6040516020818303038152906040528051906020012083604051602001614a2c9190616a37565b6040516020818303038152906040528051906020012014905092915050565b015190565b815181516000916001918114808314614a6c5760009250614aaa565b600160208701838101602088015b600284838510011415614aa5578051835114614a995760009650600093505b60209283019201614a7a565b505050505b5090949350505050565b6001600160a01b03811660009081526004602052604081205480614add5750600019905061137a565b600181039050600060018281548110614af257fe5b9060005260206000209060040201600301549050600060018381548110614b1557fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90614b6e908590617692565b60405180910390a280614b865782935050505061137a565b6000818381614b9157fe5b0490508015614c4d5760005b84811015614bef578160018281548110614bb357fe5b9060005260206000209060040201600301540160018281548110614bd357fe5b6000918252602090912060036004909202010155600101614b9d565b50600180549085015b81811015614c4a578260018281548110614c0e57fe5b9060005260206000209060040201600301540160018281548110614c2e57fe5b6000918252602090912060036004909202010155600101614bf8565b50505b5091949350505050565b600082614c665750600061142a565b82820282848281614c7357fe5b0414610f4e5760405162461bcd60e51b8152600401610ce79061723b565b6000610f4e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250615ad8565b614cdb6166d7565b506040805180820190915281518152602082810190820152919050565b614d00616590565b614d0982615b0f565b614d1257600080fd5b6000614d218360200151615b49565b60208085015160408051808201909152868152920190820152915050919050565b6000614d4c6166d7565b505080518051602091820151919092015191011190565b614d6b6166d7565b614d7482614d42565b614d7d57600080fd5b60208201516000614d8d82615bac565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590614dc657508151602110155b614dcf57600080fd5b6000614dde8360200151615b49565b90508083600001511015614e045760405162461bcd60e51b8152600401610ce7906173e1565b8251602080850151830180519284900392918310156147fa57506020919091036101000a90049392505050565b6060614e3c82615b0f565b614e4557600080fd5b6000614e5083615c8d565b9050606081604051908082528060200260200182016040528015614e8e57816020015b614e7b6166d7565b815260200190600190039081614e735790505b5090506000614ea08560200151615b49565b60208601510190506000805b84811015614ef757614ebd83615bac565b9150604051806040016040528083815260200184815250848281518110614ee057fe5b602090810291909101015291810191600101614eac565b509195945050505050565b614f0a6165b0565b60606000614f166165b0565b6060614f20616590565b614f2987614cf8565b90506000805b614f3883614d42565b1561500d5780614f6357614f53614f4e84614d63565b615ce9565b6001600160a01b03168552615005565b8060011415614f8b57614f78614f4e84614d63565b6001600160a01b03166020860152615005565b8060021415614fb357614fa0614f4e84614d63565b6001600160a01b03166040860152615005565b8060031415614fdf57614fc86132e384614d63565b6001600160401b0316606086015260019150615005565b806004141561500057614ff9614ff484614d63565b615d03565b9350615005565b61500d565b600101614f2f565b50929791965091945092505050565b606061142a61502a83615d73565b615e59565b6060815160001415615050575060408051600081526020810190915261137a565b60608260008151811061505f57fe5b602002602001015190506000600190505b83518110156150a0576150968285838151811061508957fe5b6020026020010151615eab565b9150600101615070565b50610f4e6150b3825160c060ff16615f28565b82615eab565b6060806000808080806150ca6127c6565b6001549091505b80156151d857600181039250600b83815481106150ea57fe5b600091825260209091206001601690920201015460ff1661510a576151cf565b6001838154811061511757fe5b60009182526020909120600490910201546001600160a01b0316945061513e8584846130a7565b9350831580615151575060018a51038610155b1561515b576151cf565b60005b8a518110156151cd57856001600160a01b03168b828151811061517d57fe5b6020026020010151600001516001600160a01b031614156151c55760018b82815181106151a657fe5b60209081029190910101519015156080909101526001909601956151cd565b60010161515e565b505b600019016150d1565b508489510360405190808252806020026020018201604052801561521657816020015b6152036165b0565b8152602001906001900390816151fb5790505b5096508489510360405190808252806020026020018201604052801561525057816020015b606081526020019060019003908161523b5790505b5095506000915060005b89518110156152e45789818151811061526f57fe5b6020026020010151608001516152dc5789818151811061528b57fe5b602002602001015188848151811061529f57fe5b60200260200101819052508881815181106152b657fe5b60200260200101518784815181106152ca57fe5b60200260200101819052508260010192505b60010161525a565b5050505050505b9250929050565b600154825160005b8281101561540f57600161530c6165b0565b6001838154811061531957fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b848110156153e3578781815181106153a957fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b031614156153db57600092506153e3565b600101615395565b5081156154055780516001600160a01b03166000908152600460205260408120555b50506001016152fa565b50808211156154ce57805b828110156154cc57600180548061542d57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061548057fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906154b26002830182616684565b6154c06003830160006166c8565b5050905560010161541a565b505b60008183106154dd57816154df565b825b905060005b8181101561584e576155918682815181106154fb57fe5b60200260200101516001838154811061551057fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152615ffa565b6157455780600101600460008884815181106155a957fe5b6020026020010151600001516001600160a01b03166001600160a01b03168152602001908152602001600020819055508581815181106155e557fe5b6020026020010151600182815481106155fa57fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015584518590829081106156b557fe5b6020026020010151600b82815481106156ca57fe5b906000526020600020906016020160020190805190602001906156ee9291906164c5565b506000600b82815481106156fe57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061572f57fe5b6000918252602090912060169091020155615846565b6157d685828151811061575457fe5b6020026020010151600b838154811061576957fe5b600091825260209182902060026016909202018101805460408051601f600019610100600186161502019093169490940491820185900485028401850190528083529192909190830182828015612ab95780601f10612a8e57610100808354040283529160200191612ab9565b615821578481815181106157e657fe5b6020026020010151600b82815481106157fb57fe5b9060005260206000209060160201600201908051906020019061581f9291906164c5565b505b60006001828154811061583057fe5b9060005260206000209060040201600301819055505b6001016154e4565b5082821115615a265761585f616496565b835b83811015615a235785818151811061587557fe5b60200260200101518260400181905250600187828151811061589357fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b80549283018155909352845160169091026000805160206178f08339815191528101918255858301516000805160206179308339815191528201805491151560ff19909216919091179055928501518051869492936159c993600080516020617910833981519152019201906164c5565b5060608201516159df906003830190601361653f565b50505080600101600460008984815181106159f657fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101615861565b50505b615a2e61607b565b615a3661625d565b6000600981905560015493505b83811015615aa4576000600b8281548110615a5a57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110615a8b57fe5b6000918252602090912060169091020155600101615a43565b505050505050565b60008184841115615ad05760405162461bcd60e51b8152600401610ce79190616bd8565b505050900390565b60008183615af95760405162461bcd60e51b8152600401610ce79190616bd8565b506000838581615b0557fe5b0495945050505050565b8051600090615b205750600061137a565b6020820151805160001a9060c0821015615b3f5760009250505061137a565b5060019392505050565b8051600090811a6080811015615b6357600091505061137a565b60b8811080615b7e575060c08110801590615b7e575060f881105b15615b8d57600191505061137a565b60c0811015615ba15760b51901905061137a565b60f51901905061137a565b80516000908190811a6080811015615bc75760019150615c86565b60b8811015615bdc57607e1981019150615c86565b60c0811015615c2d57600060b78203600186019550806020036101000a865104915060018101820193505080831015615c275760405162461bcd60e51b8152600401610ce790617188565b50615c86565b60f8811015615c425760be1981019150615c86565b600060f78203600186019550806020036101000a865104915060018101820193505080831015615c845760405162461bcd60e51b8152600401610ce790617188565b505b5092915050565b8051600090615c9e5750600061137a565b60008090506000615cb28460200151615b49565b602085015185519181019250015b80821015615ce057615cd182615bac565b82019150826001019250615cc0565b50909392505050565b8051600090601514615cfa57600080fd5b61142a82614db1565b8051606090615d1157600080fd5b6000615d208360200151615b49565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015615d57576020820181803683370190505b50905060008160200190506147fa84876020015101828561644b565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416615db757506018615ddb565b6fffffffffffffffffffffffffffffffff198416615dd757506010615ddb565b5060005b6020811015615e1157818181518110615df057fe5b01602001516001600160f81b03191615615e0957615e11565b600101615ddb565b60008160200390506060816040519080825280601f01601f191660200182016040528015615e46576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015615e8b5750607f60f81b82600081518110615e7957fe5b01602001516001600160f81b03191611155b15615e9757508061137a565b61142a615ea98351608060ff16615f28565b835b6060806040519050835180825260208201818101602087015b81831015615edc578051835260209283019201615ec4565b50855184518101855292509050808201602086015b81831015615f09578051835260209283019201615ef1565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310615f525760405162461bcd60e51b8152600401610ce790616f80565b60408051600180825281830190925260609160208201818036833701905050905060378411615fac5782840160f81b81600081518110615f8e57fe5b60200101906001600160f81b031916908160001a905350905061142a565b6060615fb785615d73565b90508381510160370160f81b82600081518110615fd057fe5b60200101906001600160f81b031916908160001a905350615ff18282615eab565b95945050505050565b805182516000916001600160a01b039182169116148015616034575081602001516001600160a01b031683602001516001600160a01b0316145b8015616059575081604001516001600160a01b031683604001516001600160a01b0316145b8015610f4e5750506060908101519101516001600160401b0390811691161490565b601254601354808211156160c657805b828110156160c457601280548061609e57fe5b6001900381819060005260206000200160006160ba9190616684565b905560010161608b565b505b60008183106160d557816160d7565b825b905060005b818110156161ef57616194601282815481106160f457fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156161825780601f1061615757610100808354040283529160200191616182565b820191906000526020600020905b81548152906001019060200180831161616557829003601f168201915b505050505060138381548110612a2b57fe5b6161e757601381815481106161a557fe5b90600052602060002001601282815481106161bc57fe5b9060005260206000200190805460018160011615610100020316600290046161e59291906165e5565b505b6001016160dc565b5082821115610d0757825b82811015612fc75760126013828154811061621157fe5b60009182526020808320845460018181018755958552919093209290910180546162549493909201929091600261010092821615929092026000190116046165e5565b506001016161fa565b601354600b54808211156162a857805b828110156162a657601380548061628057fe5b60019003818190600052602060002001600061629c9190616684565b905560010161626d565b505b60008183106162b757816162b9565b825b905060005b818110156163d857616376601382815481106162d657fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156163645780601f1061633957610100808354040283529160200191616364565b820191906000526020600020905b81548152906001019060200180831161634757829003601f168201915b5050505050600b838154811061576957fe5b6163d057600b818154811061638757fe5b9060005260206000209060160201600201601382815481106163a557fe5b9060005260206000200190805460018160011615610100020316600290046163ce9291906165e5565b505b6001016162be565b5082821115610d0757825b82811015612fc7576013600b82815481106163fa57fe5b600091825260208083208454600180820187559585529190932060169290920290920160029081018054616442959390940193909260001990821615610100020116046165e5565b506001016163e3565b8061645557610d07565b5b60208110616475578251825260209283019290910190601f1901616456565b915181516020939093036101000a6000190180199091169216919091179052565b604051806080016040528060008152602001600015158152602001606081526020016164c06166f1565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061650657805160ff1916838001178555616533565b82800160010185558215616533579182015b82811115616533578251825591602001919060010190616518565b50612801929150616710565b82601381019282156165335791602002820182811115616533578251825591602001919060010190616518565b6040518060600160405280600060ff16815260200160608152602001606081525090565b60405180604001604052806165a36166d7565b8152602001600081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061661e5780548555616533565b8280016001018555821561653357600052602060002091601f016020900482015b8281111561653357825482559160010191906001019061663f565b8260138101928215616533579182018281111561653357825482559160010191906001019061663f565b50805460018160011615610100020316600290046000825580601f106166aa5750611586565b601f0160209004906000526020600020908101906115869190616710565b50611586906013810190616710565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b6127a591905b808211156128015760008155600101616716565b60008083601f84011261673b578182fd5b5081356001600160401b03811115616751578182fd5b60208301915083602080830285010111156152eb57600080fd5b60008083601f84011261677c578182fd5b5081356001600160401b03811115616792578182fd5b6020830191508360208285010111156152eb57600080fd5b6000602082840312156167bb578081fd5b81356001600160a01b0381168114610f4e578182fd5b600080600080604085870312156167e6578283fd5b84356001600160401b03808211156167fc578485fd5b6168088883890161672a565b90965094506020870135915080821115616820578384fd5b5061682d8782880161672a565b95989497509550505050565b60006020828403121561684a578081fd5b81518015158114610f4e578182fd5b6000806020838503121561686b578182fd5b82356001600160401b03811115616880578283fd5b61688c8582860161676b565b90969095509350505050565b600080600080604085870312156168ad578384fd5b84356001600160401b03808211156168c3578586fd5b6168cf8883890161676b565b909650945060208701359150808211156168e7578384fd5b5061682d8782880161676b565b600060208284031215616905578081fd5b5035919050565b60006020828403121561691d578081fd5b5051919050565b60008060408385031215616936578182fd5b505080516020909101519092909150565b60008060006040848603121561695b578283fd5b833560ff8116811461696b578384fd5b925060208401356001600160401b03811115616985578283fd5b6169918682870161676b565b9497909650939450505050565b6000815180845260208085019450808401835b838110156169d65781516001600160a01b0316875295820195908201906001016169b1565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452616a238160208601602086016176f8565b601f01601f19169290920160200192915050565b60008251616a498184602087016176f8565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b600060208252610f4e602083018461699e565b600060408252616af6604083018561699e565b602083820381850152818551808452828401915082838202850101838801865b83811015616b4457601f19878403018552616b32838351616a0b565b94860194925090850190600101616b16565b50909998505050505050505050565b600060808252616b66608083018761699e565b828103602084810191909152865180835287820192820190845b81811015616b9c57845183529383019391830191600101616b80565b50508481036040860152616bb0818861699e565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b600060208252610f4e6020830184616a0b565b600060408252616bff6040830186886169e1565b8281036020840152616c128185876169e1565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252602b908201527f746865206275726e526174696f206d757374206265206e6f206772656174657260408201526a0207468616e2031303030360ac1b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526033908201527f7468652073797374656d526577617264526174696f206d757374206265206e6f60408201527202067726561746572207468616e20313030303606c1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526024908201527f6c656e677468206f662073797374656d526577617264526174696f206d69736d6040820152630c2e8c6d60e31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152615ff16060830184616a0b565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260406020830152615ff16040830184866169e1565b60005b838110156177135781810151838201526020016176fb565b83811115612fc7575050600091015256fef901a880f901a4f844941284214b9b9c85549ab3d2b972df0deef66ac2c9946ddf42a51534fc98d0c0a3b42c963cace8441ddf946ddf42a51534fc98d0c0a3b42c963cace8441ddf8410000000f84494a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0948081ef03f1d9e0bb4a5bf38f16285c879299f07f948081ef03f1d9e0bb4a5bf38f16285c879299f07f8410000000f8449435552c16704d214347f29fa77f77da6d75d7c75294dc4973e838e3949c77aced16ac2315dc2d7ab11194dc4973e838e3949c77aced16ac2315dc2d7ab1118410000000f84494980a75ecd1309ea12fa2ed87a8744fbfc9b863d594cc6ac05c95a99c1f7b5f88de0e3486c82293b27094cc6ac05c95a99c1f7b5f88de0e3486c82293b2708410000000f84494f474cf03cceff28abc65c9cbae594f725c80e12d94e61a183325a18a173319dd8e19c8d069459e217594e61a183325a18a173319dd8e19c8d069459e21758410000000f84494b71b214cb885500844365e95cd9942c7276e7fd894d22ca3ba2141d23adab65ce4940eb7665ea2b6a794d22ca3ba2141d23adab65ce4940eb7665ea2b6a7841000000070e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a",
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106104fb5760003560e01c806388b32f111161028c578063c6d339451161015a578063e40716a1116100cc578063f92eb86b11610085578063f92eb86b14610d2d578063f9a2bbc714610d42578063fc3e590814610d57578063fccc281314610d6c578063fd4ad81f14610d81578063fd6a687914610db057610502565b8063e40716a114610c9b578063ea321e4914610cb0578063eb57e20214610cd0578063eda5868c14610cf0578063f1fad10414610d05578063f340fa0114610d1a57610502565b8063d86222d51161011e578063d86222d514610c1d578063daacdb6614610c32578063dc927faf14610c47578063df8079e914610c5c578063e086c7b114610c71578063e1c7392a14610c8657610502565b8063c6d3394514610bbe578063c81b166214610bd3578063c8509d811461098d578063ce910b0c14610be8578063d68fb56a14610c0857610502565b8063a78abc16116101fe578063ad3c9da6116101b7578063ad3c9da614610b3d578063aef198a914610b5d578063b7ab4db514610b72578063b8cf4ef114610b94578063bf9f4995146106fe578063c466689d14610ba957610502565b8063a78abc1614610ab4578063aa82dce114610ac9578063aad5606314610ade578063aaf5eb6814610af3578063ab51bb9614610b08578063ac43175114610b1d57610502565b806396713da91161025057806396713da914610a365780639dc0926214610a4b5780639fe0f81614610a60578063a0dc275814610a75578063a1a11bf514610a8a578063a5422d5c14610a9f57610502565b806388b32f11146109c25780638a7beb01146109d75780638b5ad0c9146109ec5780638d19a41014610a015780639369d7de14610a2157610502565b806351b4dce3116103c957806370fd5bad1161033b5780637e434d54116102f45780637e434d541461094e57806381650b6214610963578063820dcaa814610978578063831d65d11461098d578063853230aa1461090f57806386249882146109ad57610502565b806370fd5bad146108d0578063718a8aa8146108e557806375d47a0a146108fa57806378dfed4a1461090f5780637942fd05146109245780637a84ca2a1461093957610502565b80635d77156c1161038d5780635d77156c1461082a5780635de1e22c1461083f57806360eba4fe1461085457806362b72cf5146108745780636969a25c146108895780636e47b482146108bb57610502565b806351b4dce3146107ab57806351e80672146107c057806355614fcc146107d5578063565c56b3146107f55780635667515a1461081557610502565b8063300c35671161046d57806343756e5c1161042657806343756e5c1461072057806345cf9daf14610735578063493279b11461074a5780634bf6c8821461076c5780634df6e0c3146107815780635192c82c1461079657610502565b8063300c35671461065b578063321d398a1461067b5780633365af3a1461069b57806335409f7f146106bb5780633b071dcc146106db5780633dffc387146106fe57610502565b8063152ad3b8116104bf578063152ad3b8146105ba5780631e4c1524146105dc5780631ff18069146105fc578063219f22d51461061157806328087028146106265780632a0ffb6e1461063b57610502565b806304c4fec61461050757806307a568471461051e5780630bee7a67146105495780630e2374a51461056b5780631182b8751461058d57610502565b3661050257005b600080fd5b34801561051357600080fd5b5061051c610dc5565b005b34801561052a57600080fd5b50610533610e37565b6040516105409190618ee4565b60405180910390f35b34801561055557600080fd5b5061055e610e3d565b6040516105409190618f0e565b34801561057757600080fd5b50610580610e42565b60405161054091906181f7565b34801561059957600080fd5b506105ad6105a83660046180dd565b610e48565b604051610540919061838a565b3480156105c657600080fd5b506105cf611165565b604051610540919061837f565b3480156105e857600080fd5b5061051c6105f7366004617eeb565b61116e565b34801561060857600080fd5b50610533611844565b34801561061d57600080fd5b5061055e61184a565b34801561063257600080fd5b5061058061184f565b34801561064757600080fd5b5061051c610656366004617e4b565b611855565b34801561066757600080fd5b5061051c610676366004617e83565b611902565b34801561068757600080fd5b506105cf61069636600461808a565b611c4b565b3480156106a757600080fd5b506105cf6106b636600461808a565b611d1a565b3480156106c757600080fd5b5061051c6106d6366004617e4b565b611dcb565b3480156106e757600080fd5b506106f0611f30565b604051610540929190618295565b34801561070a57600080fd5b5061071361220c565b6040516105409190618f1f565b34801561072c57600080fd5b50610580612211565b34801561074157600080fd5b50610533612217565b34801561075657600080fd5b5061075f61221d565b6040516105409190618ed5565b34801561077857600080fd5b50610713612222565b34801561078d57600080fd5b506106f0612227565b3480156107a257600080fd5b506105336123b3565b3480156107b757600080fd5b506105806123b9565b3480156107cc57600080fd5b506105806123bf565b3480156107e157600080fd5b506105cf6107f0366004617e4b565b6123c5565b34801561080157600080fd5b50610533610810366004617e4b565b6123fa565b34801561082157600080fd5b5061071361244b565b34801561083657600080fd5b5061055e612450565b34801561084b57600080fd5b50610533612455565b34801561086057600080fd5b506105ad61086f36600461808a565b61245b565b34801561088057600080fd5b50610533612501565b34801561089557600080fd5b506108a96108a436600461808a565b612507565b60405161054096959493929190618224565b3480156108c757600080fd5b5061058061256b565b3480156108dc57600080fd5b50610713612571565b3480156108f157600080fd5b50610713612576565b34801561090657600080fd5b5061058061257b565b34801561091b57600080fd5b50610533612581565b34801561093057600080fd5b50610713612587565b34801561094557600080fd5b5061053361258c565b34801561095a57600080fd5b50610580612592565b34801561096f57600080fd5b5061055e612598565b34801561098457600080fd5b5061053361259d565b34801561099957600080fd5b5061051c6109a83660046180dd565b6125a3565b3480156109b957600080fd5b50610533612604565b3480156109ce57600080fd5b5061053361260a565b3480156109e357600080fd5b506105cf612610565b3480156109f857600080fd5b50610533612619565b348015610a0d57600080fd5b50610533610a1c366004617e4b565b61261f565b348015610a2d57600080fd5b5061051c61265f565b348015610a4257600080fd5b50610713612773565b348015610a5757600080fd5b50610580612778565b348015610a6c57600080fd5b5061053361277e565b348015610a8157600080fd5b50610533612783565b348015610a9657600080fd5b50610580612788565b348015610aab57600080fd5b506105ad61278e565b348015610ac057600080fd5b506105cf6127ad565b348015610ad557600080fd5b506105806127b6565b348015610aea57600080fd5b506105806127bc565b348015610aff57600080fd5b506105336127c2565b348015610b1457600080fd5b5061055e61244b565b348015610b2957600080fd5b5061051c610b3836600461802e565b6127cb565b348015610b4957600080fd5b50610533610b58366004617e4b565b613084565b348015610b6957600080fd5b50610533613096565b348015610b7e57600080fd5b50610b876130a3565b6040516105409190618282565b348015610ba057600080fd5b5061053361318f565b348015610bb557600080fd5b50610533613194565b348015610bca57600080fd5b50610533612571565b348015610bdf57600080fd5b5061058061319a565b348015610bf457600080fd5b506105ad610c0336600461808a565b6131a0565b348015610c1457600080fd5b506105336131ad565b348015610c2957600080fd5b506105336131ec565b348015610c3e57600080fd5b506105336131f8565b348015610c5357600080fd5b506105806131fe565b348015610c6857600080fd5b50610580613204565b348015610c7d57600080fd5b50610533610e3d565b348015610c9257600080fd5b5061051c61320a565b348015610ca757600080fd5b506105336133b9565b348015610cbc57600080fd5b506105cf610ccb366004617fef565b6133bf565b348015610cdc57600080fd5b5061051c610ceb366004617e4b565b613545565b348015610cfc57600080fd5b5061055e613649565b348015610d1157600080fd5b5061071361364e565b61051c610d28366004617e4b565b613653565b348015610d3957600080fd5b506105336139d2565b348015610d4e57600080fd5b506105806139d8565b348015610d6357600080fd5b5061071361277e565b348015610d7857600080fd5b506105806139de565b348015610d8d57600080fd5b50610da1610d9c36600461808a565b6139e4565b60405161054093929190618eed565b348015610dbc57600080fd5b50610580613aa6565b6000610dd03361261f565b9050600b8181548110610ddf57fe5b600091825260209091206001601690920201015460ff16610e1b5760405162461bcd60e51b8152600401610e1290618af0565b60405180910390fd5b6000610e256131ad565b9050610e32338383613aac565b505050565b60095481565b606481565b61200181565b60005460609060ff16610e6d5760405162461bcd60e51b8152600401610e12906185b1565b3361200014610e8e5760405162461bcd60e51b8152600401610e1290618cf1565b600b54610f4c57610e9d6179f7565b60015460005b81811015610f4857600b8054600181018255600091909152835160008051602061919c83398151915260169092029182019081556020808601516000805160206191dc8339815191528401805460ff1916911515919091179055604086015180518794610f24936000805160206191bc833981519152909101920190617a26565b506060820151610f3a9060038301906013617aa0565b505050806001019050610ea3565b5050505b610f54617acd565b6000610f9585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d7d92505050565b9150915080610fb157610fa86064613f39565b9250505061115e565b815160009060ff16610fd657610fcf83602001518460400151613f9a565b905061112a565b825160ff16600114156111265782602001515160011461101b5760008051602061917c83398151915260405161100b906189a9565b60405180910390a1506067611121565b6000836020015160008151811061102e57fe5b602090810291909101810151516001600160a01b0381166000908152600490925260409091205490915080158061108f575060018082038154811061106f57fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b156110cd576040516001600160a01b038316907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a261111a565b60006110dc836001840361515c565b905080611118576040516001600160a01b038416907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a25b505b6000925050505b61112a565b5060655b63ffffffff811661114f575050604080516000815260208101909152915061115e9050565b61115881613f39565b93505050505b9392505050565b60075460ff1681565b33411461118d5760405162461bcd60e51b8152600401610e1290618d40565b3a156111ab5760405162461bcd60e51b8152600401610e1290618a2f565b82516040805182815260208084028201019091526060908280156111e957816020015b6111d6617af1565b8152602001906001900390816111ce5790505b50905060005b82811015611293576040518060c0016040528087838151811061120e57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200186838151811061125057fe5b60200260200101516001600160401b03168152602001600015158152602001600081525082828151811061128057fe5b60209081029190910101526001016111ef565b5060405163d31f968d60e01b81526120009063d31f968d906112be9061100090600890600401618266565b60206040518083038186803b1580156112d657600080fd5b505afa1580156112ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130e9190617fcf565b15611631578051601554818111156113b057815b818110156113ae57601580548061133557fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055601680548061138857fe5b6001900381819060005260206000200160006113a49190617b26565b9055600101611322565b505b60005b828110156115f0578181106114d85760158482815181106113d057fe5b602090810291909101810151825460018181018555600094855293839020825160049092020180546001600160a01b039283166001600160a01b0319918216178255938301519481018054958316958516959095179094556040820151600285018054606085015160808601511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590961692909716919091179290921692909217169290921790915560a0015160039091015585516016908790839081106114a057fe5b602090810291909101810151825460018101845560009384529282902081516114d29491909101929190910190617a26565b506115e8565b8381815181106114e457fe5b6020026020010151601582815481106114f957fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015585518690829081106115b457fe5b6020026020010151601682815481106115c957fe5b9060005260206000200190805190602001906115e6929190617a26565b505b6001016113b3565b507fb8e726330a0dad1cf3d04e925663b17e391f1ed547d79b7f4e5f344119b44246826040516116209190618ee4565b60405180910390a150505050610e32565b60608061163e838661551f565b9150915060005b6001548110156117345760006001828154811061165e57fe5b90600052602060002090600402016003015490508060001461172b5760006001838154811061168957fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab82600185815481106116bd57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b1681526116f8926001600160a01b0390921691016181f7565b6000604051808303818588803b15801561171157600080fd5b505af1158015611725573d6000803e3d6000fd5b50505050505b50600101611645565b5047156117a2577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d4760405161176a9190618ee4565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156117a0573d6000803e3d6000fd5b505b600060038190556005558151156117bd576117bd8282615a06565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117fa57600080fd5b505af115801561180e573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b606881565b61200581565b33612002146118765760405162461bcd60e51b8152600401610e1290618e9e565b60005b6015548110156118fe57816001600160a01b03166015828154811061189a57fe5b60009182526020909120600490910201546001600160a01b031614156118f6576001601582815481106118c957fe5b9060005260206000209060040201600201601c6101000a81548160ff0219169083151502179055506118fe565b600101611879565b5050565b3341146119215760405162461bcd60e51b8152600401610e1290618d40565b60105443116119425760405162461bcd60e51b8152600401610e1290618744565b3a156119605760405162461bcd60e51b8152600401610e1290618a2f565b60005460ff166119825760405162461bcd60e51b8152600401610e12906185b1565b60006110023168056bc75e2d631000008111156119b9576119b28168056bc75e2d6310000063ffffffff6161f516565b91506119c0565b5050611c41565b6040516309a99b4f60e41b815261100290639a99b4f0906119e7903090869060040161820b565b602060405180830381600087803b158015611a0157600080fd5b505af1158015611a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3991906180a2565b915081611a47575050611c41565b6000805b84811015611a7557858582818110611a5f57fe5b9050602002013582019150806001019050611a4b565b5080611a8357505050611c41565b6000806000805b89811015611c395784898983818110611a9f57fe5b90506020020135880281611aaf57fe5b0493508a8a82818110611abe57fe5b9050602002016020810190611ad39190617e4b565b6001600160a01b03811660009081526004602052604090205490935091508115611bef576000600180840381548110611b0857fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611b7557836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8586604051611b689190618ee4565b60405180910390a2611be9565b600354611b88908663ffffffff61623716565b6003908155810154611ba0908663ffffffff61623716565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b290611be0908890618ee4565b60405180910390a25b50611c31565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8585604051611c289190618ee4565b60405180910390a25b600101611a8a565b505050505050505b5050436010555050565b6001546000908210611c5f57506000611d15565b60006001600160a01b031660018381548110611c7757fe5b60009182526020909120600490910201546001600160a01b03161480611ca757506008541580611ca75750600a54155b80611cb6575060085460095410155b80611cc75750611cc582611d1a565b155b80611cf057506000600b8381548110611cdc57fe5b906000526020600020906016020160000154115b80611d0457506001611d006130a3565b5111155b15611d1157506000611d15565b5060015b919050565b6001546000908210611d2e57506000611d15565b600b548210611d6b5760018281548110611d4457fe5b9060005260206000209060040201600201601c9054906101000a900460ff16159050611d15565b60018281548110611d7857fe5b9060005260206000209060040201600201601c9054906101000a900460ff16158015611dc55750600b8281548110611dac57fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611e8957611dda6179f7565b60015460005b81811015611e8557600b8054600181018255600091909152835160008051602061919c83398151915260169092029182019081556020808601516000805160206191dc8339815191528401805460ff1916911515919091179055604086015180518794611e61936000805160206191bc833981519152909101920190617a26565b506060820151611e779060038301906013617aa0565b505050806001019050611de0565b5050505b336110011480611e9a575033612002145b611eb65760405162461bcd60e51b8152600401610e12906185e8565b6001600160a01b03811660009081526004602052604090205480611eda5750611f2d565b6001810390506000600b8281548110611eef57fe5b600091825260209091206001601690920201015460ff169050611f12838361515c565b8015611f1b5750805b15610e32576009805460001901905550505b50565b60015460609081906000805b82811015611f835760018181548110611f5157fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611f7b576001909101905b600101611f3c565b50606081604051908082528060200260200182016040528015611fb0578160200160208202803683370190505b509050606082604051908082528060200260200182016040528015611fe957816020015b6060815260200190600190039081611fd45790505b50600b54600094509091508414156121645760005b8481101561215e576001818154811061201357fe5b9060005260206000209060040201600201601c9054906101000a900460ff16612156576001818154811061204357fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061206e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061209b57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156121335780601f1061210857610100808354040283529160200191612133565b820191906000526020600020905b81548152906001019060200180831161211657829003601f168201915b505050505082858151811061214457fe5b60209081029190910101526001909301925b600101611ffe565b50612200565b60005b848110156121fe576001818154811061217c57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166121f657600181815481106121ac57fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106121d757fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101612167565b505b909450925050505b9091565b600181565b61100181565b60085481565b606181565b600881565b6060806000600e549050600080600c5411612243576015612247565b600c545b905060606122536130a3565b905060606122608261625c565b905082825111612277579094509250612208915050565b83838351031015612289578282510393505b83156122bf5760c843046122a583838388880360008a8a6163ca565b6122bd8383838888038989038a8b8b8b5103016163ca565b505b6060836040519080825280602002602001820160405280156122eb578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561232457816020015b606081526020019060019003908161230f5790505b50905060005b858110156123a55784818151811061233e57fe5b602002602001015183828151811061235257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083818151811061237e57fe5b602002602001015182828151811061239257fe5b602090810291909101015260010161232a565b509096509450505050509091565b60065481565b61200681565b61200081565b6001600160a01b038116600090815260046020526040812054806123ed576000915050611d15565b6000190161115e81611d1a565b6001600160a01b03811660009081526004602052604081205480612422576000915050611d15565b60018082038154811061243157fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b600f5481565b6012818154811061246857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156124f95780601f106124ce576101008083540402835291602001916124f9565b820191906000526020600020905b8154815290600101906020018083116124dc57829003601f168201915b505050505081565b60105481565b6001818154811061251457fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b61200381565b606681565b61271081565b33612000146125c45760405162461bcd60e51b8152600401610e1290618cf1565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f389021016058383836040516125f793929190618f2d565b60405180910390a1505050565b60025481565b60115481565b60145460ff1681565b600a5481565b6001600160a01b038116600090815260046020526040812054806126555760405162461bcd60e51b8152600401610e1290618c79565b6000190192915050565b600b5461271d5761266e6179f7565b60015460005b8181101561271957600b8054600181018255600091909152835160008051602061919c83398151915260169092029182019081556020808601516000805160206191dc8339815191528401805460ff19169115159190911790556040860151805187946126f5936000805160206191bc833981519152909101920190617a26565b50606082015161270b9060038301906013617aa0565b505050806001019050612674565b5050505b60085461272a5760036008555b600a54612737576002600a555b60006127423361261f565b905061274d81611c4b565b6127695760405162461bcd60e51b8152600401610e1290618966565b611f2d3382616521565b600981565b61100781565b600381565b60c881565b61100681565b604051806101e001604052806101ab8152602001618fd16101ab913981565b60005460ff1681565b61200281565b61300081565b6402540be40081565b60005460ff166127ed5760405162461bcd60e51b8152600401610e12906185b1565b336110071461280e5760405162461bcd60e51b8152600401610e1290618a5d565b61287884848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506165b99050565b15612915576020811461289d5760405162461bcd60e51b8152600401610e1290618c33565b604080516020601f84018190048102820181019092528281526000916128db9185858083850183828082843760009201919091525061661292505050565b9050606481101580156128f15750620186a08111155b61290d5760405162461bcd60e51b8152600401610e1290618856565b600255613041565b61297584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506165b99050565b15612a18576020811461299a5760405162461bcd60e51b8152600401610e12906183cf565b604080516020601f84018190048102820181019092528281526000916129d89185858083850183828082843760009201919091525061661292505050565b90506127106129f2600f548361623790919063ffffffff16565b1115612a105760405162461bcd60e51b8152600401610e1290618406565b600655613041565b612a8284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506165b99050565b15612b1c5760208114612aa75760405162461bcd60e51b8152600401610e129061846e565b604080516020601f8401819004810282018101909252828152600091612ae59185858083850183828082843760009201919091525061661292505050565b600c5490915080612af4575060155b808210612b135760405162461bcd60e51b8152600401610e12906187ae565b50600855613041565b612b8584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506165b99050565b15612c1e5760208114612baa5760405162461bcd60e51b8152600401610e1290618537565b604080516020601f8401819004810282018101909252828152600091612be89185858083850183828082843760009201919091525061661292505050565b9050600081118015612bfa5750600a81105b612c165760405162461bcd60e51b8152600401610e1290618dd1565b600a55613041565b612c9284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506165b99050565b15612d215760208114612cb75760405162461bcd60e51b8152600401610e12906184eb565b604080516020601f8401819004810282018101909252828152600091612cf59185858083850183828082843760009201919091525061661292505050565b9050600d54811115612d195760405162461bcd60e51b8152600401610e12906188cc565b600e55613041565b612d8a84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506165b99050565b15612e0c5760208114612daf5760405162461bcd60e51b8152600401610e1290618aab565b604080516020601f8401819004810282018101909252828152600091612ded9185858083850183828082843760009201919091525061661292505050565b600d819055600e54909150811015612e0657600d54600e555b50613041565b612e7084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506165b99050565b15612f1e5760208114612e955760405162461bcd60e51b8152600401610e129061857c565b604080516020601f8401819004810282018101909252828152600091612ed39185858083850183828082843760009201919091525061661292505050565b905060008111612ef55760405162461bcd60e51b8152600401610e1290618656565b6064811115612f165760405162461bcd60e51b8152600401610e129061869e565b600c55613041565b612f8684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601181527073797374656d526577617264526174696f60781b602082015291506165b99050565b156130295760208114612fab5760405162461bcd60e51b8152600401610e1290618d8d565b604080516020601f8401819004810282018101909252828152600091612fe99185858083850183828082843760009201919091525061661292505050565b90506127106130036006548361623790919063ffffffff16565b11156130215760405162461bcd60e51b8152600401610e1290618b94565b600f55613041565b60405162461bcd60e51b8152600401610e1290618e2e565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a84848484604051613076949392919061839d565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156130d2576130be81611d1a565b156130ca578160010191505b6001016130ad565b506060816040519080825280602002602001820160405280156130ff578160200160208202803683370190505b5090506000915060005b838110156131865761311a81611d1a565b1561317e576001818154811061312c57fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061315757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101613109565b50925050505b90565b601581565b61027181565b61100281565b6013818154811061246857fe5b60006131b76130a3565b519050600080600c54116131cc5760156131d0565b600c545b9050808211156131de578091505b816131e857600191505b5090565b67016345785d8a000081565b60055481565b61100381565b61200481565b60005460ff161561322d5760405162461bcd60e51b8152600401610e1290618b5d565b613235617acd565b600061325b604051806101e001604052806101ab8152602001618fd16101ab9139613d7d565b915091508061327c5760405162461bcd60e51b8152600401610e1290618cb0565b60005b8260200151518110156133a15760018360200151828151811061329e57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061337457fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161327f565b50506103e8600255506000805460ff19166001179055565b600d5481565b601354600090815b818110156134c8576134b085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060138054909250859150811061341857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156134a65780601f1061347b576101008083540402835291602001916134a6565b820191906000526020600020905b81548152906001019060200180831161348957829003601f168201915b5050505050616617565b156134c057600192505050611dc5565b6001016133c7565b5060125460005b818110156135395761352086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060128054909250859150811061341857fe5b156135315760019350505050611dc5565b6001016134cf565b50600095945050505050565b33611001146135665760405162461bcd60e51b8152600401610e1290618e55565b600b54613624576135756179f7565b60015460005b8181101561362057600b8054600181018255600091909152835160008051602061919c83398151915260169092029182019081556020808601516000805160206191dc8339815191528401805460ff19169115159190911790556040860151805187946135fc936000805160206191bc833981519152909101920190617a26565b5060608201516136129060038301906013617aa0565b50505080600101905061357b565b5050505b600061362f8261667b565b905061363a81611c4b565b156118fe576118fe8282616521565b606581565b601181565b3341146136725760405162461bcd60e51b8152600401610e1290618d40565b60005460ff166136945760405162461bcd60e51b8152600401610e12906185b1565b600034116136b45760405162461bcd60e51b8152600401610e129061889d565b3a156136d25760405162461bcd60e51b8152600401610e1290618a2f565b6001600160a01b03811660009081526004602052604090205460145434919060ff1661371257610271600f556103e86006556014805460ff191660011790555b60008211801561372457506000600f54115b156137d6576000613752612710613746600f54346167fe90919063ffffffff16565b9063ffffffff61683816565b905080156137d4576040516110029082156108fc029083906000818181858888f19350505050158015613789573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d816040516137b99190618ee4565b60405180910390a16137d1838263ffffffff6161f516565b92505b505b6000821180156137e857506000600654115b1561388e57600061380a612710613746600654346167fe90919063ffffffff16565b9050801561388c5760405161dead9082156108fc029083906000818181858888f19350505050158015613841573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee5816040516138719190618ee4565b60405180910390a1613889838263ffffffff6161f516565b92505b505b801561398c5760006001808303815481106138a557fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561391257836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4846040516139059190618ee4565b60405180910390a2613986565b600354613925908463ffffffff61623716565b600390815581015461393d908463ffffffff61623716565b60038201556040516001600160a01b038516907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc0559061397d908690618ee4565b60405180910390a25b50610e32565b826001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4836040516139c59190618ee4565b60405180910390a2505050565b600e5481565b61100081565b61dead81565b600b81815481106139f157fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015613a9c5780601f10613a7157610100808354040283529160200191613a9c565b820191906000526020600020905b815481529060010190602001808311613a7f57829003601f168201915b5050505050905083565b61100481565b6000600a5460001480613abd575081155b80613ac85750600954155b15613ad55750600061115e565b60096000815460019003919050819055506000613b20600a5461374685613746600b8981548110613b0257fe5b6000918252602090912060169091020154439063ffffffff6161f516565b90506000600b8581548110613b3157fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015613b9657600080fd5b505afa158015613baa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bce91906180ba565b9150915060009350808310613d2d57613be7878761515c565b5060405163436aa28360e11b8152600090612002906386d5450690613c10908b906004016181f7565b60206040518083038186803b158015613c2857600080fd5b505afa158015613c3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c609190617e67565b6001600160a01b031614613ccc576040516313d13bdb60e31b815261100190639e89ded890613c95908a90879060040161820b565b600060405180830381600087803b158015613caf57600080fd5b505af1158015613cc3573d6000803e3d6000fd5b50505050613d24565b6040516305bfb49960e41b815261100190635bfb499090613cf1908a906004016181f7565b600060405180830381600087803b158015613d0b57600080fd5b505af1158015613d1f573d6000803e3d6000fd5b505050505b60019350613d3f565b818310613d3f57613d3d8761667b565b505b6040516001600160a01b038816907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050509392505050565b613d85617acd565b6000613d8f617acd565b613d97617b6a565b613da8613da38661687a565b61689f565b90506000805b613db7836168e9565b15613f2b5780613ddc57613dd2613dcd8461690a565b616958565b60ff168452613f23565b8060011415613f1e576060613df8613df38561690a565b6169d8565b90508051604051908082528060200260200182016040528015613e3557816020015b613e22617af1565b815260200190600190039081613e1a5790505b5085602001819052508051604051908082528060200260200182016040528015613e7357816020015b6060815260200190600190039081613e5e5790505b50604086015260005b8151811015613f1357613e8d617af1565b60606000613ead858581518110613ea057fe5b6020026020010151616aa9565b92509250925080613ecd578860009a509a50505050505050505050613f34565b8289602001518581518110613ede57fe5b60200260200101819052508189604001518581518110613efa57fe5b6020026020010181905250505050806001019050613e7c565b506001925050613f23565b613f2b565b600101613dae565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081613f53579050509050613f798363ffffffff16616bc3565b81600081518110613f8657fe5b602002602001018190525061115e81616bd6565b6000606483511115613fd15760008051602061917c833981519152604051613fc1906186fb565b60405180910390a1506066611dc5565b60005b835181101561406f5760005b8181101561406657848181518110613ff457fe5b6020026020010151600001516001600160a01b031685838151811061401557fe5b6020026020010151600001516001600160a01b0316141561405e5760008051602061917c83398151915260405161404b9061880b565b60405180910390a1606692505050611dc5565b600101613fe0565b50600101613fd4565b5060608060606015805480602002602001604051908101604052809291908181526020016000905b828210156141215760008481526020908190206040805160c0810182526004860290920180546001600160a01b039081168452600180830154821685870152600283015491821693850193909352600160a01b81046001600160401b03166060850152600160e01b900460ff16151560808401526003015460a08301529083529092019101614097565b50505050905060606016805480602002602001604051908101604052809291908181526020016000905b828210156141f65760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156141e25780601f106141b7576101008083540402835291602001916141e2565b820191906000526020600020905b8154815290600101906020018083116141c557829003601f168201915b50505050508152602001906001019061414b565b50505050905060005b82518110156142535782818151811061421457fe5b60200260200101516060015160030283828151811061422f57fe5b60209081029190910101516001600160401b039091166060909101526001016141ff565b5060608061426389898686616c60565b91509150614271828261551f565b600154604080518281526020808402820101909152929850909650600095508594509250606091508280156142b0578160200160208202803683370190505b50905060005b828110156144415760006001600160a01b03166120026001600160a01b03166386d54506600184815481106142e757fe5b60009182526020909120600491820201546040516001600160e01b031960e085901b168152614322926001600160a01b0390921691016181f7565b60206040518083038186803b15801561433a57600080fd5b505afa15801561434e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143729190617e67565b6001600160a01b0316146143d457600182828151811061438e57fe5b602002602001019060ff16908160ff1681525050600181815481106143af57fe5b9060005260206000209060040201600301546000146143cf578360010193505b614439565b67016345785d8a0000600182815481106143ea57fe5b9060005260206000209060040201600301541061440c57846001019450614439565b6001818154811061441957fe5b906000526020600020906004020160030154600014614439578360010193505b6001016142b6565b5060608460405190808252806020026020018201604052801561446e578160200160208202803683370190505b50905060608560405190808252806020026020018201604052801561449d578160200160208202803683370190505b5090506060866040519080825280602002602001820160405280156144cc578160200160208202803683370190505b5090506060876040519080825280602002602001820160405280156144fb578160200160208202803683370190505b509050600060608860405190808252806020026020018201604052801561452c578160200160208202803683370190505b50905060608960405190808252806020026020018201604052801561455b578160200160208202803683370190505b50905060009a506000995060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b1580156145a357600080fd5b505afa1580156145b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145db91906180a2565b905067016345785d8a00008111156146275760008051602061917c83398151915260405161460890618b1c565b60405180910390a160689e505050505050505050505050505050611dc5565b60005b8a8110156149bb5789818151811061463e57fe5b602002602001015160ff1660011415614734576001818154811061465e57fe5b90600052602060002090600402016003015460001461472f576001818154811061468457fe5b600091825260209091206004909102015484516001600160a01b039091169085908e9081106146af57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600181815481106146dc57fe5b906000526020600020906004020160030154838d815181106146fa57fe5b60200260200101818152505060018a8d8151811061471457fe5b602002602001019060ff16908160ff16815250508b6001019b505b6149b3565b67016345785d8a00006001828154811061474a57fe5b906000526020600020906004020160030154106148cf576001818154811061476e57fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898e8151811061479f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be400600183815481106147d457fe5b906000526020600020906004020160030154816147ed57fe5b06600183815481106147fb57fe5b90600052602060002090600402016003015403905061482383826161f590919063ffffffff16565b898f8151811061482f57fe5b6020026020010181815250506001828154811061484857fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316878f8151811061487957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888f815181106148a657fe5b60209081029190910101526148c1868263ffffffff61623716565b95508d6001019d50506149b3565b600181815481106148dc57fe5b9060005260206000209060040201600301546000146149b3576001818154811061490257fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848d8151811061493357fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001818154811061496057fe5b906000526020600020906004020160030154838d8151811061497e57fe5b60200260200101818152505060008a8d8151811061499857fe5b602002602001019060ff16908160ff16815250508b6001019b505b60010161462a565b5060008415614c31576002546040516303702b2960e51b815261100491636e0565209188916149f5918e918e918d91420190600401618305565b6020604051808303818588803b158015614a0e57600080fd5b505af193505050508015614a3f575060408051601f3d908101601f19168201909252614a3c91810190617fcf565b60015b614bb6576040516000815260443d1015614a5b57506000614af6565b60046000803e60005160e01c6308c379a08114614a7c576000915050614af6565b60043d036004833e81513d60248201116001600160401b0382111715614aa757600092505050614af6565b80830180516001600160401b03811115614ac8576000945050505050614af6565b8060208301013d8601811115614ae657600095505050505050614af6565b601f01601f191660405250925050505b80614b015750614b43565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051614b35919061838a565b60405180910390a250614bb1565b3d808015614b6d576040519150601f19603f3d011682016040523d82523d6000602084013e614b72565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a4582604051614ba7919061838a565b60405180910390a2505b614c31565b8015614bf8577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b7086604051614beb9190618ee4565b60405180910390a1614c2f565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280604051614c26906184b4565b60405180910390a25b505b8015614de75760005b8751811015614de5576000888281518110614c5157fe5b60200260200101519050600060018281548110614c6a57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc9185908110614c9b57fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015614d575760018281548110614cdc57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110614d2b57fe5b906000526020600020906004020160030154604051614d4a9190618ee4565b60405180910390a2614ddb565b60018281548110614d6457fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110614db357fe5b906000526020600020906004020160030154604051614dd29190618ee4565b60405180910390a25b5050600101614c3a565b505b835115614fdd5760005b8451811015614fdb578a8181518110614e0657fe5b602002602001015160ff1660011415614ea5576120026001600160a01b031663092193ab858381518110614e3657fe5b6020026020010151878481518110614e4a57fe5b60200260200101516040518363ffffffff1660e01b8152600401614e6e91906181f7565b6000604051808303818588803b158015614e8757600080fd5b505af1158015614e9b573d6000803e3d6000fd5b5050505050614fd3565b6000858281518110614eb357fe5b60200260200101516001600160a01b03166108fc868481518110614ed357fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015614f6957858281518110614f0957fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110614f4757fe5b6020026020010151604051614f5c9190618ee4565b60405180910390a2614fd1565b858281518110614f7557fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110614fb357fe5b6020026020010151604051614fc89190618ee4565b60405180910390a25b505b600101614df1565b505b5050505050505050505050505060005b60015481101561504a576001818154811061500457fe5b9060005260206000209060040201600301546000146150425760006001828154811061502c57fe5b9060005260206000209060040201600301819055505b600101614fed565b5047156150b8577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516150809190618ee4565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156150b6573d6000803e3d6000fd5b505b600060038190556005558151156150d3576150d38282615a06565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561511057600080fd5b505af1158015615124573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b6000806001838154811061516c57fe5b906000526020600020906004020160030154905060006001808054905003905060016151966130a3565b51116151cb576000600185815481106151ab57fe5b906000526020600020906004020160030181905550600092505050611dc5565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516152049190618ee4565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156153f1576001816001018154811061524557fe5b90600052602060002090600402016001828154811061526057fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b80549091830190811061532157fe5b9060005260206000209060160201600b828154811061533c57fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054615393938386019390821615610100026000190190911604617b8a565b506153a660038281019084016013617bff565b509050508060010160046000600184815481106153bf57fe5b600091825260208083206004909202909101546001600160a01b03168352820192909252604001902055600101615227565b5060018054806153fd57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061545057fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906154826002830182617b26565b615490600383016000617c29565b50509055600081838161549f57fe5b04905080156155135760015460005b81811015615510576154e783600183815481106154c757fe5b90600052602060002090600402016003015461623790919063ffffffff16565b600182815481106154f457fe5b60009182526020909120600360049092020101556001016154ae565b50505b50600195945050505050565b6060806000808080806155306131ad565b6001549091505b801561575f57600181039250600b838154811061555057fe5b600091825260209091206001601690920201015460ff1661557057615756565b6001838154811061557d57fe5b60009182526020909120600490910201546001600160a01b031694506155a4858484613aac565b9350836155b057615756565b60405163436aa28360e11b81526000908190612002906386d54506906155da908a906004016181f7565b60206040518083038186803b1580156155f257600080fd5b505afa158015615606573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061562a9190617e67565b90506001600160a01b038116156156b3576040516302ceee9160e11b81526120029063059ddd22906156609084906004016181f7565b60206040518083038186803b15801561567857600080fd5b505afa15801561568c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906156b09190617e67565b91505b60005b8c5181101561575257876001600160a01b03168d82815181106156d557fe5b6020026020010151600001516001600160a01b0316148061571e5750826001600160a01b03168d828151811061570757fe5b6020026020010151600001516001600160a01b0316145b1561574a5760018d828151811061573157fe5b6020908102919091010151901515608090910152615752565b6001016156b6565b5050505b60001901615537565b5060005b89518110156157cc5789818151811061577857fe5b602002602001015160800151806157b8575060006001600160a01b03168a82815181106157a157fe5b6020026020010151600001516001600160a01b0316145b156157c4578560010195505b600101615763565b50885185106158b45760408051600180825281830190925290816020015b6157f2617af1565b8152602001906001900390816157ea575050604080516001808252818301909252919850602082015b606081526020019060019003908161581b5790505095508860008151811061583f57fe5b60200260200101518760008151811061585457fe5b60200260200101819052508760008151811061586c57fe5b60200260200101518660008151811061588157fe5b602002602001018190525060008760008151811061589b57fe5b60209081029190910101519015156080909101526159f9565b848951036040519080825280602002602001820160405280156158f157816020015b6158de617af1565b8152602001906001900390816158d65790505b5096508489510360405190808252806020026020018201604052801561592b57816020015b60608152602001906001900390816159165790505b5095506000915060005b89518110156159f75789818151811061594a57fe5b60200260200101516080015115801561598d575060006001600160a01b03168a828151811061597557fe5b6020026020010151600001516001600160a01b031614155b156159ef5789818151811061599e57fe5b60200260200101518884815181106159b257fe5b60200260200101819052508881815181106159c957fe5b60200260200101518784815181106159dd57fe5b60200260200101819052508260010192505b600101615935565b505b50505050505b9250929050565b600154825160005b82811015615b23576001615a20617af1565b60018381548110615a2d57fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015615af757878181518110615abd57fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415615aef5760009250615af7565b600101615aa9565b508115615b195780516001600160a01b03166000908152600460205260408120555b5050600101615a0e565b5080821115615be257805b82811015615be0576001805480615b4157fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480615b9457fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590615bc66002830182617b26565b615bd4600383016000617c29565b50509055600101615b2e565b505b6000818310615bf15781615bf3565b825b905060005b81811015615f9757615ca5868281518110615c0f57fe5b602002602001015160018381548110615c2457fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a082015261702c565b615e59578060010160046000888481518110615cbd57fe5b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550858181518110615cf957fe5b602002602001015160018281548110615d0e57fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101558451859082908110615dc957fe5b6020026020010151600b8281548110615dde57fe5b90600052602060002090601602016002019080519060200190615e02929190617a26565b506000600b8281548110615e1257fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110615e4357fe5b6000918252602090912060169091020155615f8f565b858181518110615e6557fe5b60200260200101516060015160018281548110615e7e57fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b03160217905550615f44858281518110615ec257fe5b6020026020010151600b8381548110615ed757fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156134a65780601f1061347b576101008083540402835291602001916134a6565b615f8f57848181518110615f5457fe5b6020026020010151600b8281548110615f6957fe5b90600052602060002090601602016002019080519060200190615f8d929190617a26565b505b600101615bf8565b508282111561616f57615fa86179f7565b835b8381101561616c57858181518110615fbe57fe5b602002602001015182604001819052506001878281518110615fdc57fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b805492830181559093528451601690910260008051602061919c8339815191528101918255858301516000805160206191dc8339815191528201805491151560ff1990921691909117905592850151805186949293616112936000805160206191bc83398151915201920190617a26565b5060608201516161289060038301906013617aa0565b505050806001016004600089848151811061613f57fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101615faa565b50505b616177617088565b61617f617270565b6000600981905560015493505b838110156161ed576000600b82815481106161a357fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106161d457fe5b600091825260209091206016909102015560010161618c565b505050505050565b600061115e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061745e565b60008282018381101561115e5760405162461bcd60e51b8152600401610e129061861f565b60015481516040805182815260208084028201019091526060929190839082801561629b57816020015b60608152602001906001900390816162865790505b50600b5490915083146162b2579250611d15915050565b60005b828110156163c157600b6001600460008985815181106162d157fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054038154811061630557fe5b600091825260209182902060026016909202018101805460408051601f60001961010060018616150201909316949094049182018590048502840185019052808352919290919083018282801561639d5780601f106163725761010080835404028352916020019161639d565b820191906000526020600020905b81548152906001019060200180831161638057829003601f168201915b50505050508282815181106163ae57fe5b60209081029190910101526001016162b5565b50949350505050565b60005b8281101561651757600082878388016040516020016163ed9291906181e9565b6040516020818303038152906040528051906020012060001c8161640d57fe5b0690508085018287011461650e576000898388018151811061642b57fe5b602002602001015190506060898489018151811061644557fe5b602002602001015190508a8388018151811061645d57fe5b60200260200101518b858a018151811061647357fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b848901815181106164a257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505089838801815181106164d057fe5b60200260200101518a858a01815181106164e657fe5b6020026020010181905250808a8489018151811061650057fe5b602002602001018190525050505b506001016163cd565b5050505050505050565b600980546001908101909155600b80548390811061653b57fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b828154811061657157fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b6000816040516020016165cc91906181cd565b60405160208183030381529060405280519060200120836040516020016165f391906181cd565b6040516020818303038152906040528051906020012014905092915050565b015190565b8151815160009160019181148083146166335760009250616671565b600160208701838101602088015b60028483851001141561666c5780518351146166605760009650600093505b60209283019201616641565b505050505b5090949350505050565b6001600160a01b038116600090815260046020526040812054806166a457506000199050611d15565b6001810390506000600182815481106166b957fe5b90600052602060002090600402016003015490506000600183815481106166dc57fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90616735908590618ee4565b60405180910390a28061674d57829350505050611d15565b600081838161675857fe5b04905080156167f45760005b848110156167a65761677d82600183815481106154c757fe5b6001828154811061678a57fe5b6000918252602090912060036004909202010155600101616764565b50600180549085015b818110156167f1576167c883600183815481106154c757fe5b600182815481106167d557fe5b60009182526020909120600360049092020101556001016167af565b50505b5091949350505050565b60008261680d57506000611dc5565b8282028284828161681a57fe5b041461115e5760405162461bcd60e51b8152600401610e12906189ee565b600061115e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061748a565b616882617c38565b506040805180820190915281518152602082810190820152919050565b6168a7617b6a565b6168b0826174c1565b6168b957600080fd5b60006168c883602001516174fb565b60208085015160408051808201909152868152920190820152915050919050565b60006168f3617c38565b505080518051602091820151919092015191011190565b616912617c38565b61691b826168e9565b61692457600080fd5b602082015160006169348261755e565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061696d57508151602110155b61697657600080fd5b600061698583602001516174fb565b905080836000015110156169ab5760405162461bcd60e51b8152600401610e1290618bfc565b8251602080850151830180519284900392918310156163c157506020919091036101000a90049392505050565b60606169e3826174c1565b6169ec57600080fd5b60006169f78361763f565b9050606081604051908082528060200260200182016040528015616a3557816020015b616a22617c38565b815260200190600190039081616a1a5790505b5090506000616a4785602001516174fb565b60208601510190506000805b84811015616a9e57616a648361755e565b9150604051806040016040528083815260200184815250848281518110616a8757fe5b602090810291909101015291810191600101616a53565b509195945050505050565b616ab1617af1565b60606000616abd617af1565b6060616ac7617b6a565b616ad08761689f565b90506000805b616adf836168e9565b15616bb45780616b0a57616afa616af58461690a565b61769b565b6001600160a01b03168552616bac565b8060011415616b3257616b1f616af58461690a565b6001600160a01b03166020860152616bac565b8060021415616b5a57616b47616af58461690a565b6001600160a01b03166040860152616bac565b8060031415616b8657616b6f613dcd8461690a565b6001600160401b0316606086015260019150616bac565b8060041415616ba757616ba0616b9b8461690a565b6176b5565b9350616bac565b616bb4565b600101616ad6565b50929791965091945092505050565b6060611dc5616bd183617725565b61780b565b6060815160001415616bf75750604080516000815260208101909152611d15565b606082600081518110616c0657fe5b602002602001015190506000600190505b8351811015616c4757616c3d82858381518110616c3057fe5b602002602001015161785d565b9150600101616c17565b5061115e616c5a825160c060ff166178da565b8261785d565b60608060006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b158015616ca057600080fd5b505afa158015616cb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616cd891906180a2565b90508085518851011015616ced575083518651015b606081604051908082528060200260200182016040528015616d2957816020015b616d16617af1565b815260200190600190039081616d0e5790505b509050606082604051908082528060200260200182016040528015616d6257816020015b6060815260200190600190039081616d4d5790505b50905060008060005b8b51831080616d7a5750895182105b8015616d8557508581105b1561701a578b51831415616df557898281518110616d9f57fe5b6020026020010151858281518110616db357fe5b6020026020010181905250888281518110616dca57fe5b6020026020010151848281518110616dde57fe5b602090810291909101015260019182019101616d6b565b8951821415616e60578b8381518110616e0a57fe5b6020026020010151858281518110616e1e57fe5b60200260200101819052508a8381518110616e3557fe5b6020026020010151848281518110616e4957fe5b602090810291909101015260019283019201616d6b565b898281518110616e6c57fe5b6020026020010151606001516001600160401b03168c8481518110616e8d57fe5b6020026020010151606001516001600160401b03161115616f09578b8381518110616eb457fe5b6020026020010151858281518110616ec857fe5b60200260200101819052508a8381518110616edf57fe5b6020026020010151848281518110616ef357fe5b6020026020010181905250826001019250617012565b898281518110616f1557fe5b6020026020010151606001516001600160401b03168c8481518110616f3657fe5b6020026020010151606001516001600160401b03161015616fb257898281518110616f5d57fe5b6020026020010151858281518110616f7157fe5b6020026020010181905250888281518110616f8857fe5b6020026020010151848281518110616f9c57fe5b6020026020010181905250816001019150617012565b898281518110616fbe57fe5b6020026020010151600001516001600160a01b03168c8481518110616fdf57fe5b6020026020010151600001516001600160a01b03161015617006578b8381518110616eb457fe5b898281518110616d9f57fe5b600101616d6b565b50929a91995090975050505050505050565b805182516000916001600160a01b039182169116148015617066575081602001516001600160a01b031683602001516001600160a01b0316145b801561115e5750506040908101519101516001600160a01b0390811691161490565b601254601354808211156170d357805b828110156170d15760128054806170ab57fe5b6001900381819060005260206000200160006170c79190617b26565b9055600101617098565b505b60008183106170e257816170e4565b825b905060005b818110156171fc576171a16012828154811061710157fe5b600091825260209182902001805460408051601f600260001961010060018716150201909416939093049283018590048502810185019091528181529283018282801561718f5780601f106171645761010080835404028352916020019161718f565b820191906000526020600020905b81548152906001019060200180831161717257829003601f168201915b50505050506013838154811061341857fe5b6171f457601381815481106171b257fe5b90600052602060002001601282815481106171c957fe5b9060005260206000200190805460018160011615610100020316600290046171f2929190617b8a565b505b6001016170e9565b5082821115610e3257825b8281101561726a5760126013828154811061721e57fe5b6000918252602080832084546001818101875595855291909320929091018054617261949390920192909160026101009282161592909202600019011604617b8a565b50600101617207565b50505050565b601354600b54808211156172bb57805b828110156172b957601380548061729357fe5b6001900381819060005260206000200160006172af9190617b26565b9055600101617280565b505b60008183106172ca57816172cc565b825b905060005b818110156173eb57617389601382815481106172e957fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156173775780601f1061734c57610100808354040283529160200191617377565b820191906000526020600020905b81548152906001019060200180831161735a57829003601f168201915b5050505050600b8381548110615ed757fe5b6173e357600b818154811061739a57fe5b9060005260206000209060160201600201601382815481106173b857fe5b9060005260206000200190805460018160011615610100020316600290046173e1929190617b8a565b505b6001016172d1565b5082821115610e3257825b8281101561726a576013600b828154811061740d57fe5b60009182526020808320845460018082018755958552919093206016929092029092016002908101805461745595939094019390926000199082161561010002011604617b8a565b506001016173f6565b600081848411156174825760405162461bcd60e51b8152600401610e12919061838a565b505050900390565b600081836174ab5760405162461bcd60e51b8152600401610e12919061838a565b5060008385816174b757fe5b0495945050505050565b80516000906174d257506000611d15565b6020820151805160001a9060c08210156174f157600092505050611d15565b5060019392505050565b8051600090811a6080811015617515576000915050611d15565b60b8811080617530575060c08110801590617530575060f881105b1561753f576001915050611d15565b60c08110156175535760b519019050611d15565b60f519019050611d15565b80516000908190811a60808110156175795760019150617638565b60b881101561758e57607e1981019150617638565b60c08110156175df57600060b78203600186019550806020036101000a8651049150600181018201935050808310156175d95760405162461bcd60e51b8152600401610e129061893b565b50617638565b60f88110156175f45760be1981019150617638565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156176365760405162461bcd60e51b8152600401610e129061893b565b505b5092915050565b805160009061765057506000611d15565b6000809050600061766484602001516174fb565b602085015185519181019250015b80821015617692576176838261755e565b82019150826001019250617672565b50909392505050565b80516000906015146176ac57600080fd5b611dc582616958565b80516060906176c357600080fd5b60006176d283602001516174fb565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015617709576020820181803683370190505b50905060008160200190506163c18487602001510182856179ac565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166177695750601861778d565b6fffffffffffffffffffffffffffffffff1984166177895750601061778d565b5060005b60208110156177c3578181815181106177a257fe5b01602001516001600160f81b031916156177bb576177c3565b60010161778d565b60008160200390506060816040519080825280601f01601f1916602001820160405280156177f8576020820181803683370190505b5080830196909652508452509192915050565b60608151600114801561783d5750607f60f81b8260008151811061782b57fe5b01602001516001600160f81b03191611155b15617849575080611d15565b611dc561785b8351608060ff166178da565b835b6060806040519050835180825260208201818101602087015b8183101561788e578051835260209283019201617876565b50855184518101855292509050808201602086015b818310156178bb5780518352602092830192016178a3565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106179045760405162461bcd60e51b8152600401610e1290618786565b6040805160018082528183019092526060916020820181803683370190505090506037841161795e5782840160f81b8160008151811061794057fe5b60200101906001600160f81b031916908160001a9053509050611dc5565b606061796985617725565b90508381510160370160f81b8260008151811061798257fe5b60200101906001600160f81b031916908160001a9053506179a3828261785d565b95945050505050565b806179b657610e32565b5b602081106179d6578251825260209283019290910190601f19016179b7565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001617a21617c52565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617a6757805160ff1916838001178555617a94565b82800160010185558215617a94579182015b82811115617a94578251825591602001919060010190617a79565b506131e8929150617c71565b8260138101928215617a945791602002820182811115617a94578251825591602001919060010190617a79565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b50805460018160011615610100020316600290046000825580601f10617b4c5750611f2d565b601f016020900490600052602060002090810190611f2d9190617c71565b6040518060400160405280617b7d617c38565b8152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617bc35780548555617a94565b82800160010185558215617a9457600052602060002091601f016020900482015b82811115617a94578254825591600101919060010190617be4565b8260138101928215617a945791820182811115617a94578254825591600101919060010190617be4565b50611f2d906013810190617c71565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b61318c91905b808211156131e85760008155600101617c77565b8035611dc581618fbb565b60008083601f840112617ca7578182fd5b5081356001600160401b03811115617cbd578182fd5b60208301915083602080830285010111156159ff57600080fd5b6000601f8381840112617ce8578182fd5b8235617cfb617cf682618f70565b618f4a565b818152925060208084019085810160005b84811015617d8d578135880189603f820112617d2757600080fd5b838101356001600160401b03811115617d3f57600080fd5b617d50818901601f19168601618f4a565b81815260408c81848601011115617d6657600080fd5b82818501888401375060009181018601919091528552509282019290820190600101617d0c565b50505050505092915050565b600082601f830112617da9578081fd5b8135617db7617cf682618f70565b818152915060208083019084810181840286018201871015617dd857600080fd5b6000805b85811015617d8d5782356001600160401b0381168114617dfa578283fd5b85529383019391830191600101617ddc565b60008083601f840112617e1d578182fd5b5081356001600160401b03811115617e33578182fd5b6020830191508360208285010111156159ff57600080fd5b600060208284031215617e5c578081fd5b813561115e81618fbb565b600060208284031215617e78578081fd5b815161115e81618fbb565b60008060008060408587031215617e98578283fd5b84356001600160401b0380821115617eae578485fd5b617eba88838901617c96565b90965094506020870135915080821115617ed2578384fd5b50617edf87828801617c96565b95989497509550505050565b600080600060608486031215617eff578283fd5b83356001600160401b0380821115617f15578485fd5b81860187601f820112617f26578586fd5b80359250617f36617cf684618f70565b80848252602080830192508084018b828389028701011115617f5657898afd5b8994505b86851015617f8057617f6c8c82617c8b565b845260019490940193928101928101617f5a565b509097508801359350505080821115617f97578384fd5b617fa387838801617d99565b93506040860135915080821115617fb8578283fd5b50617fc586828701617cd7565b9150509250925092565b600060208284031215617fe0578081fd5b8151801515811461115e578182fd5b60008060208385031215618001578182fd5b82356001600160401b03811115618016578283fd5b61802285828601617e0c565b90969095509350505050565b60008060008060408587031215618043578384fd5b84356001600160401b0380821115618059578586fd5b61806588838901617e0c565b9096509450602087013591508082111561807d578384fd5b50617edf87828801617e0c565b60006020828403121561809b578081fd5b5035919050565b6000602082840312156180b3578081fd5b5051919050565b600080604083850312156180cc578182fd5b505080516020909101519092909150565b6000806000604084860312156180f1578081fd5b833560ff81168114618101578182fd5b925060208401356001600160401b0381111561811b578182fd5b61812786828701617e0c565b9497909650939450505050565b6000815180845260208085019450808401835b8381101561816c5781516001600160a01b031687529582019590820190600101618147565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526181b9816020860160208601618f8f565b601f01601f19169290920160200192915050565b600082516181df818460208701618f8f565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0392909216825260ff16602082015260400190565b60006020825261115e6020830184618134565b6000604082526182a86040830185618134565b602083820381850152818551808452828401915082838202850101838801865b838110156182f657601f198784030185526182e48383516181a1565b948601949250908501906001016182c8565b50909998505050505050505050565b6000608082526183186080830187618134565b828103602084810191909152865180835287820192820190845b8181101561834e57845183529383019391830191600101618332565b505084810360408601526183628188618134565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b60006020825261115e60208301846181a1565b6000604082526183b1604083018688618177565b82810360208401526183c4818587618177565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526042908201527f746865206275726e526174696f20706c75732073797374656d5265776172645260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b60208082526042908201527f7468652073797374656d526577617264526174696f20706c7573206275726e5260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526024908201527f6c656e677468206f662073797374656d526577617264526174696f206d69736d6040820152630c2e8c6d60e31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b60008482528315156020830152606060408301526179a360608301846181a1565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff85168252604060208301526179a3604083018486618177565b6040518181016001600160401b0381118282101715618f6857600080fd5b604052919050565b60006001600160401b03821115618f85578081fd5b5060209081020190565b60005b83811015618faa578181015183820152602001618f92565b8381111561726a5750506000910152565b6001600160a01b0381168114611f2d57600080fdfef901a880f901a4f844941284214b9b9c85549ab3d2b972df0deef66ac2c9946ddf42a51534fc98d0c0a3b42c963cace8441ddf946ddf42a51534fc98d0c0a3b42c963cace8441ddf8410000000f84494a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0948081ef03f1d9e0bb4a5bf38f16285c879299f07f948081ef03f1d9e0bb4a5bf38f16285c879299f07f8410000000f8449435552c16704d214347f29fa77f77da6d75d7c75294dc4973e838e3949c77aced16ac2315dc2d7ab11194dc4973e838e3949c77aced16ac2315dc2d7ab1118410000000f84494980a75ecd1309ea12fa2ed87a8744fbfc9b863d594cc6ac05c95a99c1f7b5f88de0e3486c82293b27094cc6ac05c95a99c1f7b5f88de0e3486c82293b2708410000000f84494f474cf03cceff28abc65c9cbae594f725c80e12d94e61a183325a18a173319dd8e19c8d069459e217594e61a183325a18a173319dd8e19c8d069459e21758410000000f84494b71b214cb885500844365e95cd9942c7276e7fd894d22ca3ba2141d23adab65ce4940eb7665ea2b6a794d22ca3ba2141d23adab65ce4940eb7665ea2b6a7841000000070e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a",
},
{
ContractAddr: common.HexToAddress(SlashContract),
- CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/b3a5c1fa8882c0e546dc5ba913ce4db77ec9befe",
- Code: "608060405234801561001057600080fd5b50600436106102955760003560e01c80638256ace611610167578063c81b1662116100ce578063e1c7392a11610087578063e1c7392a146104d3578063eb57bff7146104db578063f9a2bbc7146104e3578063fc3e5908146104eb578063fc4333cd146104f3578063fd6a6879146104fb57610295565b8063c81b166214610482578063c8509d811461048a578063c96be4cb1461049d578063cc844b73146104b0578063d2a42e4b146104c3578063dc927faf146104cb57610295565b8063a78abc1611610120578063a78abc1614610447578063ab51bb961461044f578063ac0af62914610457578063ac4317511461045f578063ae61dc3b14610472578063c80d4b8f1461047a57610295565b80638256ace61461040c578063831d65d11461041457806396713da9146104275780639bc8e4f21461042f5780639dc0926214610437578063a1a11bf51461043f57610295565b8063493279b11161020b5780636e47b482116101c45780636e47b482146103dc57806370fd5bad146103e4578063718a8aa8146103ec57806375d47a0a146103f45780637912a65d146103fc5780637942fd051461040457610295565b8063493279b1146103925780634bf6c882146103a757806351e80672146103af578063567a372d146103b75780635bfb4990146103bf57806362b72cf5146103d457610295565b806335aa2e441161025d57806335aa2e441461032457806337c8dab914610337578063389f4f71146103585780633a63f4b11461036d5780633dffc3871461037557806343756e5c1461038a57610295565b80630bee7a671461029a5780630e2374a5146102b85780631182b875146102cd57806322d1e80b146102ed57806323bac5a214610302575b600080fd5b6102a2610503565b6040516102af9190613550565b60405180910390f35b6102c0610508565b6040516102af9190612d6c565b6102e06102db366004612ca2565b61050e565b6040516102af9190612da4565b6102f5610574565b6040516102af9190612d99565b610315610310366004612a50565b61057d565b6040516102af93929190613538565b6102c0610332366004612c72565b6105a0565b61034a610345366004612a50565b6105c7565b6040516102af92919061352a565b61036061061e565b6040516102af9190613500565b610360610624565b61037d61062a565b6040516102af9190613561565b6102c061062f565b61039a610635565b6040516102af91906134f1565b61037d61063b565b6102c0610640565b610360610646565b6103d26103cd366004612a50565b61064c565b005b6103606106f7565b6102c06106fd565b61037d610703565b61037d610708565b6102c061070d565b610360610713565b61037d610718565b61034a61071d565b6103d2610422366004612ca2565b610727565b61037d610839565b61036061083e565b6102c0610849565b6102c061084f565b6102f5610855565b6102a261085e565b610360610863565b6103d261046d366004612b56565b610868565b610360610e18565b610360610e1f565b6102c0610e24565b6103d2610498366004612ca2565b610e2a565b6103d26104ab366004612a50565b610e9b565b6103d26104be366004612bbf565b61128c565b61036061187d565b6102c0611882565b6103d2611888565b6103606118c4565b6102c06118ca565b61037d6118d0565b6103d26118d5565b6102c0611d1e565b606481565b61200181565b6060336120001461053a5760405162461bcd60e51b815260040161053190613349565b60405180910390fd5b60005460ff1661055c5760405162461bcd60e51b815260040161053190612e9f565b60405162461bcd60e51b81526004016105319061343a565b60075460ff1681565b600260208190526000918252604090912080546001820154919092015460ff1683565b600181815481106105ad57fe5b6000918252602090912001546001600160a01b0316905081565b6000806105d2612837565b5050506001600160a01b0316600090815260026020818152604092839020835160608101855281548082526001830154938201849052919093015460ff16151592909301919091529091565b60055481565b60065481565b600181565b61100181565b6102ca81565b600881565b61200081565b60045481565b336110001461066d5760405162461bcd60e51b81526004016105319061312e565b60005460ff1661068f5760405162461bcd60e51b815260040161053190612e9f565b61200063f7a251d7600b6106a284611d24565b60006040518463ffffffff1660e01b81526004016106c29392919061356f565b600060405180830381600087803b1580156106dc57600080fd5b505af11580156106f0573d6000803e3d6000fd5b5050505050565b60035481565b61100581565b600281565b601081565b61100881565b603281565b600b81565b6004546005549091565b33612000146107485760405162461bcd60e51b815260040161053190613349565b60005460ff1661076a5760405162461bcd60e51b815260040161053190612e9f565b61077261285a565b60006107b384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611df792505050565b9150915080156107fa5781516040517f7f0956d47419b9525356e7111652b653b530ec6f5096dccc04589bc38e629967916107ed91613550565b60405180910390a16106f0565b81516040517f7d45f62d17443dd4547bca8a8112c60e2385669318dc300ec61a5d2492f262e79161082a91613550565b60405180910390a15050505050565b600981565b662386f26fc1000081565b61100781565b61100681565b60005460ff1681565b600081565b600481565b60005460ff1661088a5760405162461bcd60e51b815260040161053190612e9f565b33611007146108ab5760405162461bcd60e51b815260040161053190613206565b61091684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260148152731b5a5cd9195b59585b9bdc951a1c995cda1bdb1960621b60208201529150611e779050565b156109b1576020811461093b5760405162461bcd60e51b8152600401610531906130ba565b604080516020601f840181900481028201810190925282815260009161097991858580838501838280828437600092019190915250611ed192505050565b90506001811015801561098d575060055481105b6109a95760405162461bcd60e51b815260040161053190613304565b600455610dd5565b610a1784848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e19995b1bdb9e551a1c995cda1bdb19608a1b60208201529150611e779050565b15610ab35760208114610a3c5760405162461bcd60e51b815260040161053190613254565b604080516020601f8401819004810282018101909252828152600091610a7a91858580838501838280828437600092019190915250611ed192505050565b90506103e88111158015610a8f575060045481115b610aab5760405162461bcd60e51b815260040161053190612f58565b600555610dd5565b610b2784848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f66696e616c697479536c617368526577617264526174696f000000000000000060208201529150611e779050565b15610bc15760208114610b4c5760405162461bcd60e51b815260040161053190613471565b604080516020601f8401819004810282018101909252828152600091610b8a91858580838501838280828437600092019190915250611ed192505050565b9050600a8110158015610b9d5750606481105b610bb95760405162461bcd60e51b81526004016105319061306e565b600655610dd5565b610c3584848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f656e61626c654d616c6963696f7573566f7465536c617368000000000000000060208201529150611e779050565b15610cac5760208114610c5a5760405162461bcd60e51b815260040161053190612f8d565b604080516020601f8401819004810282018101909252828152610c969190848480838501838280828437600092019190915250611ed692505050565b6007805460ff1916911515919091179055610dd5565b610d2084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f6d616c6963696f7573566f7465536c61736853636f706500000000000000000060208201529150611e779050565b15610dbd5760208114610d455760405162461bcd60e51b815260040161053190612de9565b604080516020601f8401819004810282018101909252828152600091610d8391858580838501838280828437600092019190915250611ed192505050565b90506170808110158015610d995750620d2f0081105b610db55760405162461bcd60e51b815260040161053190612ed6565b600855610dd5565b60405162461bcd60e51b8152600401610531906133e5565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a84848484604051610e0a9493929190612db7565b60405180910390a150505050565b6201518081565b609681565b61100281565b3361200014610e4b5760405162461bcd60e51b815260040161053190613349565b60005460ff16610e6d5760405162461bcd60e51b815260040161053190612e9f565b6040517f07db600eebe2ac176be8dcebad61858c245a4961bb32ca2aa3d159b09aa0810e90600090a1505050565b334114610eba5760405162461bcd60e51b815260040161053190613398565b60005460ff16610edc5760405162461bcd60e51b815260040161053190612e9f565b6003544311610efd5760405162461bcd60e51b8152600401610531906134bc565b3a15610f1b5760405162461bcd60e51b8152600401610531906131a9565b60405163155853f360e21b8152611000906355614fcc90610f40908490600401612d6c565b60206040518083038186803b158015610f5857600080fd5b505afa158015610f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f909190612b36565b610f9957611285565b610fa1612837565b506001600160a01b0381166000908152600260208181526040928390208351606081018552815481526001820154928101929092529091015460ff161580159282019290925290610ffc576020810180516001019052611055565b60016040820181905260208201819052805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0384161790555b43815260055460208201518161106757fe5b066111b357600060208201526040516335409f7f60e01b8152611000906335409f7f90611098908590600401612d6c565b600060405180830381600087803b1580156110b257600080fd5b505af11580156110c6573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b6110e685611d24565b60006040518463ffffffff1660e01b81526004016111069392919061356f565b600060405180830381600087803b15801561112057600080fd5b505af1925050508015611131575060015b6111ae573d80801561115f576040519150601f19603f3d011682016040523d82523d6000602084013e611164565b606091505b50826001600160a01b03167fd7bc86ff5d08c8ab043edec743302aba2520e6635172a428bc956721db9e2d1c8360200151836040516111a4929190613509565b60405180910390a2505b61121f565b6004548160200151816111c257fe5b0661121f576040516375abf10160e11b81526110009063eb57e202906111ec908590600401612d6c565b600060405180830381600087803b15801561120657600080fd5b505af115801561121a573d6000803e3d6000fd5b505050505b6001600160a01b0382166000818152600260208181526040808420865181559186015160018301558581015191909201805460ff1916911515919091179055517fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9190a2505b5043600355565b60005460ff166112ae5760405162461bcd60e51b815260040161053190612e9f565b604051630a83aaa960e31b81526110069063541d5548906112d3903390600401612d6c565b60206040518083038186803b1580156112eb57600080fd5b505afa1580156112ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113239190612b36565b61133f5760405162461bcd60e51b815260040161053190612e33565b60075460ff166113615760405162461bcd60e51b815260040161053190612e6a565b60065461136e5760146006555b60085461137d57620151806008555b6008548151604001514391011180156113a157504360085482602001516040015101115b6113bd5760405162461bcd60e51b81526004016105319061340c565b8060200151602001518160000151602001511480156113eb5750806020015160600151816000015160600151145b156114085760405162461bcd60e51b815260040161053190613101565b8051604081015190511080156114275750602081015160408101519051105b6114435760405162461bcd60e51b815260040161053190613037565b6020810151518151511080156114685750806000015160400151816020015160400151105b8061149357508051516020820151511080156114935750806020015160400151816000015160400151105b806114ad5750806020015160400151816000015160400151145b6114c95760405162461bcd60e51b815260040161053190612f21565b604080820151905163ea321e4960e01b81526110009163ea321e49916114f29190600401612da4565b60206040518083038186803b15801561150a57600080fd5b505afa15801561151e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115429190612b36565b61155e5760405162461bcd60e51b8152600401610531906131d7565b61157081600001518260400151611efe565b8015611589575061158981602001518260400151611efe565b6115a55760405162461bcd60e51b815260040161053190612fd8565b6060806110006001600160a01b0316633b071dcc6040518163ffffffff1660e01b815260040160006040518083038186803b1580156115e357600080fd5b505afa1580156115f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261161f9190810190612a73565b9150915060005b815181101561175a5761165082828151811061163e57fe5b602002602001015185604001516120d6565b15611752576006546040516213929d60e11b8152606461100280319093020491906227253a906116869033908590600401612d80565b602060405180830381600087803b1580156116a057600080fd5b505af11580156116b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d89190612c8a565b506110006001600160a01b03166335409f7f8584815181106116f657fe5b60200260200101516040518263ffffffff1660e01b815260040161171a9190612d6c565b600060405180830381600087803b15801561173457600080fd5b505af1158015611748573d6000803e3d6000fd5b505050505061175a565b600101611626565b50600061176c8460400151600061213a565b90506120006001600160a01b031663f7a251d7600b61178e8760400151612156565b60006040518463ffffffff1660e01b81526004016117ae9392919061356f565b600060405180830381600087803b1580156117c857600080fd5b505af19250505080156117d9575060015b61184b573d808015611807576040519150601f19603f3d011682016040523d82523d6000602084013e61180c565b606091505b50817fd58d1183100bd0932c0588f31c4205d6bc6168909765a96c41adbed3115f36288260405161183d9190612da4565b60405180910390a250611877565b60405181907f7b78aadacff901d8b63d0dba4f86283d4db8aef27f9ed70413dd860f1c9532b690600090a25b50505050565b601481565b61100381565b60005460ff16156118ab5760405162461bcd60e51b815260040161053190613296565b603260045560966005556000805460ff19166001179055565b60085481565b61100081565b600381565b33611000146118f65760405162461bcd60e51b81526004016105319061312e565b60005460ff166119185760405162461bcd60e51b815260040161053190612e9f565b60015461192457611d1c565b600154600090600019015b808211611cf0576000805b82841015611a535761194a612837565b600260006001878154811061195b57fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff161515908201526005549091506004900481602001511115611a3d576004600554816119c857fe5b048160200151038160200181815250508060026000600188815481106119ea57fe5b6000918252602080832091909101546001600160a01b0316835282810193909352604091820190208351815591830151600183015591909101516002909101805460ff1916911515919091179055611a47565b6001925050611a53565b5083600101935061193a565b828411611bea57611a62612837565b6002600060018681548110611a7357fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff161515908201526005549091506004900481602001511115611b5b57600460055481611ae057fe5b04816020015103816020018181525050806002600060018781548110611b0257fe5b6000918252602080832091909101546001600160a01b03168352828101939093526040918201902083518155918301516001808401919091559201516002909101805460ff19169115159190911790559150611bea9050565b6002600060018681548110611b6c57fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff19169055805480611bb057fe5b600082815260209020810160001990810180546001600160a01b031916905501905583611bdd5750611bea565b5060001990920191611a53565b818015611bf45750805b15611cd3576002600060018681548110611c0a57fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff19169055805484908110611c5157fe5b600091825260209091200154600180546001600160a01b039092169186908110611c7757fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506001805480611cb057fe5b600082815260209020810160001990810180546001600160a01b03191690550190555b82611cdf575050611cf0565b50506001909101906000190161192f565b6040517fcfdb3b6ccaeccbdc68be3c59c840e3b3c90f0a7c491f5fff1cf56cfda200dd9c90600090a150505b565b61100481565b60408051600480825260a08201909252606091829190816020015b6060815260200190600190039081611d3f579050509050611d68836001600160a01b0316612191565b81600081518110611d7557fe5b6020026020010181905250611d89436121b4565b81600181518110611d9657fe5b6020908102919091010152611dac6102ca6121b4565b81600281518110611db957fe5b6020026020010181905250611dcd426121b4565b81600381518110611dda57fe5b6020026020010181905250611dee816121c7565b9150505b919050565b611dff61285a565b6000611e0961285a565b611e1161286c565b611e22611e1d86612251565b612276565b90506000805b611e31836122c0565b15611e6a5780611e5d57611e4c611e47846122e1565b61232f565b63ffffffff16845260019150611e62565b611e6a565b600101611e28565b5091935090915050915091565b600081604051602001611e8a9190612d50565b6040516020818303038152906040528051906020012083604051602001611eb19190612d50565b604051602081830303815290604052805190602001201490505b92915050565b015190565b8082015160009060ff811615611ef0576001915081611ef6565b60009150815b505092915050565b60408051600480825260a0820190925260009160609190816020015b6060815260200190600190039081611f1a575050604080516020808252818301909252919250606091908082018180368337019050509050611f5f85600001516121b4565b82600081518110611f6c57fe5b6020026020010181905250611f8760208660200151836123b1565b611f90816123c1565b82600181518110611f9d57fe5b6020026020010181905250611fb585604001516121b4565b82600281518110611fc257fe5b6020026020010181905250611fdd60208660600151836123b1565b611fe6816123c1565b82600381518110611ff357fe5b6020026020010181905250612019602061200c846121c7565b80519060200120836123b1565b6040805160b080825260e08201909252606091602082018180368337019050509050612049818360006020612417565b61205b81876080015160206060612417565b612069818660806030612417565b604080516001808252818301909252606091602082018180368337019050509050815160016020830182602086016066600019fa6120a657600080fd5b5060016120b482600061246a565b60ff16146120c9576000945050505050611ecb565b5060019695505050505050565b8151815160009160019181148083146120f25760009250612130565b600160208701838101602088015b60028483851001141561212b57805183511461211f5760009650600093505b60209283019201612100565b505050505b5090949350505050565b6000816020018351101561214d57600080fd5b50016020015190565b60408051600480825260a08201909252606091829190816020015b6060815260200190600190039081612171579050509050611d68836123c1565b60408051600560a21b8318601482015260348101909152606090611dee816123c1565b6060611ecb6121c283612486565b6123c1565b60608151600014156121e85750604080516000815260208101909152611df2565b6060826000815181106121f757fe5b602002602001015190506000600190505b83518110156122385761222e8285838151811061222157fe5b602002602001015161256c565b9150600101612208565b50611dee61224b825160c060ff166125e9565b8261256c565b61225961288c565b506040805180820190915281518152602082810190820152919050565b61227e61286c565b612287826126bb565b61229057600080fd5b600061229f83602001516126f5565b60208085015160408051808201909152868152920190820152915050919050565b60006122ca61288c565b505080518051602091820151919092015191011190565b6122e961288c565b6122f2826122c0565b6122fb57600080fd5b6020820151600061230b82612758565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061234457508151602110155b61234d57600080fd5b600061235c83602001516126f5565b905080836000015110156123825760405162461bcd60e51b8152600401610531906132cd565b8251602080850151830180519284900392918310156123a857826020036101000a820491505b50949350505050565b9091018181526020918201910152565b6060815160011480156123f35750607f60f81b826000815181106123e157fe5b01602001516001600160f81b03191611155b156123ff575080611df2565b611ecb6124118351608060ff166125e9565b8361256c565b60005b818110156106f05783818151811061242e57fe5b602001015160f81c60f81b85848060010195508151811061244b57fe5b60200101906001600160f81b031916908160001a90535060010161241a565b6000816001018351101561247d57600080fd5b50016001015190565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166124ca575060186124ee565b6fffffffffffffffffffffffffffffffff1984166124ea575060106124ee565b5060005b60208110156125245781818151811061250357fe5b01602001516001600160f81b0319161561251c57612524565b6001016124ee565b60008160200390506060816040519080825280601f01601f191660200182016040528015612559576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b8183101561259d578051835260209283019201612585565b50855184518101855292509050808201602086015b818310156125ca5780518352602092830192016125b2565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106126135760405162461bcd60e51b81526004016105319061300f565b6040805160018082528183019092526060916020820181803683370190505090506037841161266d5782840160f81b8160008151811061264f57fe5b60200101906001600160f81b031916908160001a9053509050611ecb565b606061267885612486565b90508381510160370160f81b8260008151811061269157fe5b60200101906001600160f81b031916908160001a9053506126b2828261256c565b95945050505050565b80516000906126cc57506000611df2565b6020820151805160001a9060c08210156126eb57600092505050611df2565b5060019392505050565b8051600090811a608081101561270f576000915050611df2565b60b881108061272a575060c0811080159061272a575060f881105b15612739576001915050611df2565b60c081101561274d5760b519019050611df2565b60f519019050611df2565b80516000908190811a60808110156127735760019150612830565b60b881101561278857607e1981019150612830565b60c08110156127d957600060b78203600186019550806020036101000a8651049150600181018201935050808310156127d35760405162461bcd60e51b81526004016105319061317e565b50612830565b60f88110156127ee5760be1981019150612830565b600060f78203600186019550806020036101000a865104915060018101820193505080831015611ef65760405162461bcd60e51b81526004016105319061317e565b5092915050565b604051806060016040528060008152602001600081526020016000151581525090565b60408051602081019091526000815290565b604051806040016040528061287f61288c565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b600082601f8301126128b6578081fd5b81516128c96128c4826135c2565b61359b565b818152915060208083019084810160005b8481101561293f578151870188603f8201126128f557600080fd5b838101516129056128c4826135e2565b81815260408b8184860101111561291b57600080fd5b61292a83888401838701613606565b508652505092820192908201906001016128da565b505050505092915050565b60008083601f84011261295b578182fd5b50813567ffffffffffffffff811115612972578182fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600082601f8301126129a1578081fd5b81356129af6128c4826135e2565b91508082528360208285010111156129c657600080fd5b8060208401602084013760009082016020015292915050565b600060a082840312156129f0578081fd5b6129fa60a061359b565b905081358152602082013560208201526040820135604082015260608201356060820152608082013567ffffffffffffffff811115612a3857600080fd5b612a4484828501612991565b60808301525092915050565b600060208284031215612a61578081fd5b8135612a6c81613632565b9392505050565b60008060408385031215612a85578081fd5b825167ffffffffffffffff80821115612a9c578283fd5b81850186601f820112612aad578384fd5b80519250612abd6128c4846135c2565b80848252602080830192508084018a828389028701011115612add578788fd5b8794505b86851015612b08578051612af481613632565b845260019490940193928101928101612ae1565b508801519096509350505080821115612b1f578283fd5b50612b2c858286016128a6565b9150509250929050565b600060208284031215612b47578081fd5b81518015158114612a6c578182fd5b60008060008060408587031215612b6b578182fd5b843567ffffffffffffffff80821115612b82578384fd5b612b8e8883890161294a565b90965094506020870135915080821115612ba6578384fd5b50612bb38782880161294a565b95989497509550505050565b600060208284031215612bd0578081fd5b813567ffffffffffffffff80821115612be7578283fd5b81840160608187031215612bf9578384fd5b612c03606061359b565b9250803582811115612c13578485fd5b612c1f878284016129df565b845250602081013582811115612c33578485fd5b612c3f878284016129df565b602085015250604081013582811115612c56578485fd5b612c6287828401612991565b6040850152509195945050505050565b600060208284031215612c83578081fd5b5035919050565b600060208284031215612c9b578081fd5b5051919050565b600080600060408486031215612cb6578283fd5b833560ff81168114612cc6578384fd5b9250602084013567ffffffffffffffff811115612ce1578283fd5b612ced8682870161294a565b9497909650939450505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452612d3c816020860160208601613606565b601f01601f19169290920160200192915050565b60008251612d62818460208701613606565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b600060208252612a6c6020830184612d24565b600060408252612dcb604083018688612cfa565b8281036020840152612dde818587612cfa565b979650505050505050565b6020808252602a908201527f6c656e677468206f66206d616c6963696f7573566f7465536c61736853636f706040820152690ca40dad2e6dac2e8c6d60b31b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604082015260600190565b6020808252818101527f6d616c6963696f757320766f746520736c617368206e6f7420656e61626c6564604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252602b908201527f746865206d616c6963696f757320766f746520736c6173682073636f7065206f60408201526a7574206f662072616e676560a81b606082015260800190565b6020808252601a908201527f6e6f2076696f6c6174696f6e206f6620766f74652072756c6573000000000000604082015260600190565b6020808252818101527f7468652066656c6f6e795468726573686f6c64206f7574206f662072616e6765604082015260600190565b6020808252602b908201527f6c656e677468206f6620656e61626c654d616c6963696f7573566f7465536c6160408201526a0e6d040dad2e6dac2e8c6d60ab1b606082015260800190565b60208082526017908201527f766572696679207369676e6174757265206661696c6564000000000000000000604082015260600190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526019908201527f7372634e756d20626967676572207468616e207461724e756d00000000000000604082015260600190565b6020808252602c908201527f7468652066696e616c69747920736c6173682072657761726420726174696f2060408201526b6f7574206f662072616e676560a01b606082015260800190565b60208082526027908201527f6c656e677468206f66206d697364656d65616e6f725468726573686f6c64206d6040820152660d2e6dac2e8c6d60cb1b606082015260800190565b60208082526013908201527274776f206964656e746963616c20766f74657360681b604082015260600190565b60208082526030908201527f746865206d6573736167652073656e646572206d7573742062652076616c696460408201526f185d1bdc94d95d0818dbdb9d1c9858dd60821b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252601590820152741d9bdd195059191c881a5cc81b9bdd08199bdd5b99605a1b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526022908201527f6c656e677468206f662066656c6f6e795468726573686f6c64206d69736d61746040820152610c6d60f31b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526025908201527f746865206d697364656d65616e6f725468726573686f6c64206f7574206f662060408201526472616e676560d81b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b6020808252601490820152731d185c99d95d08189b1bd8dac81d1bdbc81bdb1960621b604082015260600190565b6020808252601e908201527f7265636569766520756e65787065637465642073796e207061636b6167650000604082015260600190565b6020808252602b908201527f6c656e677468206f662066696e616c697479536c61736852657761726452617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b6020808252818101527f63616e206e6f7420736c61736820747769636520696e206f6e6520626c6f636b604082015260600190565b61ffff91909116815260200190565b90815260200190565b6000838252604060208301526135226040830184612d24565b949350505050565b918252602082015260400190565b92835260208301919091521515604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff851682526060602083015261358b6060830185612d24565b9050826040830152949350505050565b60405181810167ffffffffffffffff811182821017156135ba57600080fd5b604052919050565b600067ffffffffffffffff8211156135d8578081fd5b5060209081020190565b600067ffffffffffffffff8211156135f8578081fd5b50601f01601f191660200190565b60005b83811015613621578181015183820152602001613609565b838111156118775750506000910152565b6001600160a01b038116811461364757600080fd5b5056fea164736f6c6343000604000a",
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b506004361061035d5760003560e01c80637e434d54116101d3578063c80d4b8f11610104578063df8079e9116100a2578063f9a2bbc71161007c578063f9a2bbc714610601578063fc3e590814610609578063fc4333cd14610611578063fd6a6879146106195761035d565b8063df8079e9146105e9578063e1c7392a146105f1578063f1fad104146105f95761035d565b8063c96be4cb116100de578063c96be4cb146105b3578063cc844b73146105c6578063dc927faf146105d9578063dcc6f156146105e15761035d565b8063c80d4b8f14610590578063c81b166214610598578063c8509d81146105a05761035d565b8063a1a11bf511610171578063aad560631161014b578063aad5606314610565578063ab51bb961461056d578063ac0af62914610575578063ac4317511461057d5761035d565b8063a1a11bf51461054d578063a78abc1614610555578063aa82dce11461055d5761035d565b806396713da9116101ad57806396713da9146105225780639dc092621461052a5780639e89ded8146105325780639f804f5f146105455761035d565b80637e434d54146104ff5780638256ace614610507578063831d65d11461050f5761035d565b8063493279b1116102ad57806362b72cf51161024b578063718a8aa811610225578063718a8aa8146104df57806375d47a0a146104e75780637912a65d146104ef5780637942fd05146104f75761035d565b806362b72cf5146104c75780636e47b482146104cf57806370fd5bad146104d75761035d565b806351b4dce31161028757806351b4dce31461049c57806351e80672146104a4578063567a372d146104ac5780635bfb4990146104b45761035d565b8063493279b1146104775780634bf6c8821461048c57806350055f90146104945761035d565b8063280870281161031a57806337c8dab9116102f457806337c8dab914610431578063389f4f71146104525780633dffc3871461045a57806343756e5c1461046f5761035d565b806328087028146104015780633306ccca1461040957806335aa2e441461041e5761035d565b80630bee7a67146103625780630e2374a5146103805780631182b8751461039557806322d1e80b146103b557806323bac5a2146103ca57806327962118146103ec575b600080fd5b61036a610621565b6040516103779190613d56565b60405180910390f35b610388610626565b6040516103779190613534565b6103a86103a336600461346a565b61062c565b604051610377919061356c565b6103bd610692565b6040516103779190613561565b6103dd6103d8366004613181565b61069b565b60405161037793929190613d3e565b6103ff6103fa3660046132c7565b6106be565b005b610388610a13565b610411610a19565b6040516103779190613d27565b61038861042c36600461343a565b610a1f565b61044461043f366004613181565b610a46565b604051610377929190613d30565b610411610a9d565b610462610aa3565b6040516103779190613d67565b610388610aa8565b61047f610aae565b6040516103779190613d18565b610462610ab3565b610411610ab8565b610388610abe565b610388610ac4565b610411610aca565b6103ff6104c2366004613181565b610ad0565b610411610bdc565b610388610be2565b610462610be8565b610462610bed565b610388610bf2565b610411610bf8565b610462610bfd565b610388610c02565b610444610c08565b6103ff61051d36600461346a565b610c12565b610462610d26565b610388610d2b565b6103ff6105403660046131b9565b610d31565b610411610d60565b610388610d66565b6103bd610d6c565b610388610d75565b610388610d7b565b61036a610d81565b610411610d86565b6103ff61058b36600461331e565b610d8b565b610411611327565b61038861132c565b6103ff6105ae36600461346a565b611332565b6103ff6105c1366004613181565b6113a3565b6103ff6105d4366004613387565b611812565b610388611df1565b610411611df7565b610388611dfc565b6103ff611e02565b610462611e3e565b610388611e43565b610462611e49565b6103ff611e4e565b610388612297565b606481565b61200181565b606033612000146106585760405162461bcd60e51b815260040161064f90613bbb565b60405180910390fd5b60005460ff1661067a5760405162461bcd60e51b815260040161064f90613661565b60405162461bcd60e51b815260040161064f90613cac565b60075460ff1681565b600260208190526000918252604090912080546001820154919092015460ff1683565b60005460ff166106e05760405162461bcd60e51b815260040161064f90613661565b6006546106ed5760146006555b6008546106fb576170806008555b81511580159061070b5750805115155b6107275760405162461bcd60e51b815260040161064f90613b19565b60408051600380825260808201909252606091816020015b606081526020019060019003908161073f579050509050610760606161229d565b8160008151811061076d57fe5b6020026020010181905250610781836122b8565b8160018151811061078e57fe5b60200260200101819052506107a2826122b8565b816002815181106107af57fe5b602002602001018190525060606107c58261230e565b60408051603480825260608281019093529293509091602082018180368337019050509050815160346020830182602086016068600019fa61080657600080fd5b506014810151603482015160405163436aa28360e11b8152600090612002906386d5450690610839908690600401613534565b60206040518083038186803b15801561085157600080fd5b505afa158015610865573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610889919061319d565b6001600160a01b031614156108b05760405162461bcd60e51b815260040161064f90613631565b43600854820110156108d45760405162461bcd60e51b815260040161064f906135d2565b604051631871f7d960e31b81526120029063c38fbec8906108f9908590600401613534565b600060405180830381600087803b15801561091357600080fd5b505af1158015610927573d6000803e3d6000fd5b50506040516335409f7f60e01b815261100092506335409f7f9150610950908590600401613534565b600060405180830381600087803b15801561096a57600080fd5b505af115801561097e573d6000803e3d6000fd5b50506006546040516309a99b4f60e41b815260646110028031909302049350909150639a99b4f0906109b69033908590600401613548565b602060405180830381600087803b1580156109d057600080fd5b505af11580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a089190613452565b505050505050505050565b61200581565b61708081565b60018181548110610a2c57fe5b6000918252602090912001546001600160a01b0316905081565b600080610a51612f68565b5050506001600160a01b0316600090815260026020818152604092839020835160608101855281548082526001830154938201849052919093015460ff16151592909301919091529091565b60055481565b600181565b61100181565b606181565b600881565b60065481565b61200681565b61200081565b60045481565b3361100014610af15760405162461bcd60e51b815260040161064f906138a4565b60005460ff16610b135760405162461bcd60e51b815260040161064f90613661565b61200063f7a251d7600b610b268461239f565b60006040518463ffffffff1660e01b8152600401610b4693929190613d75565b600060405180830381600087803b158015610b6057600080fd5b505af1925050508015610b71575060015b610bd9573d808015610b9f576040519150601f19603f3d011682016040523d82523d6000602084013e610ba4565b606091505b50816001600160a01b0316600080516020613e52833981519152600083604051610bcf92919061357f565b60405180910390a2505b50565b60035481565b61100581565b600281565b601081565b61100881565b603281565b600b81565b61200381565b6004546005549091565b3361200014610c335760405162461bcd60e51b815260040161064f90613bbb565b60005460ff16610c555760405162461bcd60e51b815260040161064f90613661565b610c5d612f8b565b6000610c9e84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061246892505050565b915091508015610ce55781516040517f7f0956d47419b9525356e7111652b653b530ec6f5096dccc04589bc38e62996791610cd891613d56565b60405180910390a1610d1e565b81516040517f7d45f62d17443dd4547bca8a8112c60e2385669318dc300ec61a5d2492f262e791610d1591613d56565b60405180910390a15b50505b505050565b600981565b61100781565b3361100014610d525760405162461bcd60e51b815260040161064f906138a4565b610d5c82826124e8565b5050565b60085481565b61100681565b60005460ff1681565b61200281565b61300081565b600081565b600481565b60005460ff16610dad5760405162461bcd60e51b815260040161064f90613661565b3361100714610dce5760405162461bcd60e51b815260040161064f90613a08565b610e3984848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260148152731b5a5cd9195b59585b9bdc951a1c995cda1bdb1960621b6020820152915061269b9050565b15610ed45760208114610e5e5760405162461bcd60e51b815260040161064f90613830565b604080516020601f8401819004810282018101909252828152600091610e9c918585808385018382808284376000920191909152506126f592505050565b905060018110158015610eb0575060055481105b610ecc5760405162461bcd60e51b815260040161064f90613b76565b6004556112e4565b610f3a84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e19995b1bdb9e551a1c995cda1bdb19608a1b6020820152915061269b9050565b15610fd65760208114610f5f5760405162461bcd60e51b815260040161064f90613a56565b604080516020601f8401819004810282018101909252828152600091610f9d918585808385018382808284376000920191909152506126f592505050565b90506103e88111158015610fb2575060045481115b610fce5760405162461bcd60e51b815260040161064f9061371a565b6005556112e4565b61104384848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601681527566656c6f6e79536c617368526577617264526174696f60501b6020820152915061269b9050565b156110dd57602081146110685760405162461bcd60e51b815260040161064f90613990565b604080516020601f84018190048102820181019092528281526000916110a6918585808385018382808284376000920191909152506126f592505050565b9050600a81101580156110b95750606481105b6110d55760405162461bcd60e51b815260040161064f90613a98565b6006556112e4565b61115184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f656e61626c654d616c6963696f7573566f7465536c61736800000000000000006020820152915061269b9050565b156111c857602081146111765760405162461bcd60e51b815260040161064f9061374f565b604080516020601f84018190048102820181019092528281526111b291908484808385018382808284376000920191909152506126fa92505050565b6007805460ff19169115159190911790556112e4565b61122f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601081526f66656c6f6e79536c61736853636f706560801b6020820152915061269b9050565b156112cc57602081146112545760405162461bcd60e51b815260040161064f9061391f565b604080516020601f8401819004810282018101909252828152600091611292918585808385018382808284376000920191909152506126f592505050565b905061708081101580156112a85750620d2f0081105b6112c45760405162461bcd60e51b815260040161064f90613698565b6008556112e4565b60405162461bcd60e51b815260040161064f90613c57565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a8484848460405161131994939291906135a0565b60405180910390a150505050565b609681565b61100281565b33612000146113535760405162461bcd60e51b815260040161064f90613bbb565b60005460ff166113755760405162461bcd60e51b815260040161064f90613661565b6040517f07db600eebe2ac176be8dcebad61858c245a4961bb32ca2aa3d159b09aa0810e90600090a1505050565b3341146113c25760405162461bcd60e51b815260040161064f90613c0a565b60005460ff166113e45760405162461bcd60e51b815260040161064f90613661565b60035443116114055760405162461bcd60e51b815260040161064f90613ce3565b3a156114235760405162461bcd60e51b815260040161064f90613962565b60405163155853f360e21b8152611000906355614fcc90611448908490600401613534565b60206040518083038186803b15801561146057600080fd5b505afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149891906132a7565b6114a15761180b565b6114a9612f68565b506001600160a01b0381166000908152600260208181526040928390208351606081018552815481526001820154928101929092529091015460ff16158015928201929092529061150457602081018051600101905261155d565b60016040820181905260208201819052805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0384161790555b43815260055460208201518161156f57fe5b0661173957600060208201526040516335409f7f60e01b8152611000906335409f7f906115a0908590600401613534565b600060405180830381600087803b1580156115ba57600080fd5b505af11580156115ce573d6000803e3d6000fd5b505060405163436aa28360e11b81526000925061200291506386d54506906115fa908690600401613534565b60206040518083038186803b15801561161257600080fd5b505afa158015611626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164a919061319d565b6001600160a01b03161461166b576116668282602001516124e8565b611734565b61200063f7a251d7600b61167e8561239f565b60006040518463ffffffff1660e01b815260040161169e93929190613d75565b600060405180830381600087803b1580156116b857600080fd5b505af19250505080156116c9575060015b611734573d8080156116f7576040519150601f19603f3d011682016040523d82523d6000602084013e6116fc565b606091505b50826001600160a01b0316600080516020613e5283398151915283602001518360405161172a92919061357f565b60405180910390a2505b6117a5565b60045481602001518161174857fe5b066117a5576040516375abf10160e11b81526110009063eb57e20290611772908590600401613534565b600060405180830381600087803b15801561178c57600080fd5b505af11580156117a0573d6000803e3d6000fd5b505050505b6001600160a01b0382166000818152600260208181526040808420865181559186015160018301558581015191909201805460ff1916911515919091179055517fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9190a2505b5043600355565b60005460ff166118345760405162461bcd60e51b815260040161064f90613661565b60075460ff166118565760405162461bcd60e51b815260040161064f906135fc565b6006546118635760146006555b600854611871576170806008555b60085481516040015143910111801561189557504360085482602001516040015101115b6118b15760405162461bcd60e51b815260040161064f90613c7e565b8060200151602001518160000151602001511480156118df5750806020015160600151816000015160600151145b156118fc5760405162461bcd60e51b815260040161064f90613877565b80516040810151905110801561191b5750602081015160408101519051105b6119375760405162461bcd60e51b815260040161064f906137f9565b60208101515181515110801561195c5750806000015160400151816020015160400151105b8061198757508051516020820151511080156119875750806020015160400151816000015160400151105b806119a15750806020015160400151816000015160400151145b6119bd5760405162461bcd60e51b815260040161064f906136e3565b604080820151905163ea321e4960e01b81526110009163ea321e49916119e6919060040161356c565b60206040518083038186803b1580156119fe57600080fd5b505afa158015611a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3691906132a7565b611a525760405162461bcd60e51b815260040161064f906139d9565b611a6481600001518260400151612722565b8015611a7d5750611a7d81602001518260400151612722565b611a995760405162461bcd60e51b815260040161064f9061379a565b6060806110006001600160a01b0316633b071dcc6040518163ffffffff1660e01b815260040160006040518083038186803b158015611ad757600080fd5b505afa158015611aeb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b1391908101906131e4565b9150915060005b8151811015611c5057611b44828281518110611b3257fe5b602002602001015185604001516128fa565b15611c48576006546040516309a99b4f60e41b815260646110028031909302049190639a99b4f090611b7c9033908590600401613548565b602060405180830381600087803b158015611b9657600080fd5b505af1158015611baa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bce9190613452565b506110006001600160a01b03166335409f7f858481518110611bec57fe5b60200260200101516040518263ffffffff1660e01b8152600401611c109190613534565b600060405180830381600087803b158015611c2a57600080fd5b505af1158015611c3e573d6000803e3d6000fd5b5050505050611c50565b600101611b1a565b5060408084015190516317b4f35360e01b8152600091612002916317b4f35391611c7c9160040161356c565b60206040518083038186803b158015611c9457600080fd5b505afa158015611ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ccc919061319d565b6001600160a01b031614611d3a576040808401519051630e9fbf5160e01b815261200291630e9fbf5191611d03919060040161356c565b600060405180830381600087803b158015611d1d57600080fd5b505af1158015611d31573d6000803e3d6000fd5b50505050610d21565b6120006001600160a01b031663f7a251d7600b611d5a866040015161295e565b60006040518463ffffffff1660e01b8152600401611d7a93929190613d75565b600060405180830381600087803b158015611d9457600080fd5b505af1158015611da8573d6000803e3d6000fd5b505050506000611dbd84604001516000612999565b60405190915081907f7b78aadacff901d8b63d0dba4f86283d4db8aef27f9ed70413dd860f1c9532b690600090a250505050565b61100381565b601481565b61200481565b60005460ff1615611e255760405162461bcd60e51b815260040161064f90613ae2565b603260045560966005556000805460ff19166001179055565b601181565b61100081565b600381565b3361100014611e6f5760405162461bcd60e51b815260040161064f906138a4565b60005460ff16611e915760405162461bcd60e51b815260040161064f90613661565b600154611e9d57612295565b600154600090600019015b808211612269576000805b82841015611fcc57611ec3612f68565b6002600060018781548110611ed457fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff161515908201526005549091506004900481602001511115611fb657600460055481611f4157fe5b04816020015103816020018181525050806002600060018881548110611f6357fe5b6000918252602080832091909101546001600160a01b0316835282810193909352604091820190208351815591830151600183015591909101516002909101805460ff1916911515919091179055611fc0565b6001925050611fcc565b50836001019350611eb3565b82841161216357611fdb612f68565b6002600060018681548110611fec57fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156120d45760046005548161205957fe5b0481602001510381602001818152505080600260006001878154811061207b57fe5b6000918252602080832091909101546001600160a01b03168352828101939093526040918201902083518155918301516001808401919091559201516002909101805460ff191691151591909117905591506121639050565b60026000600186815481106120e557fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff1916905580548061212957fe5b600082815260209020810160001990810180546001600160a01b0319169055019055836121565750612163565b5060001990920191611fcc565b81801561216d5750805b1561224c57600260006001868154811061218357fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff191690558054849081106121ca57fe5b600091825260209091200154600180546001600160a01b0390921691869081106121f057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600180548061222957fe5b600082815260209020810160001990810180546001600160a01b03191690550190555b82612258575050612269565b505060019091019060001901611ea8565b6040517fcfdb3b6ccaeccbdc68be3c59c840e3b3c90f0a7c491f5fff1cf56cfda200dd9c90600090a150505b565b61100481565b60606122b06122ab836129b5565b6122b8565b90505b919050565b6060815160011480156122ea5750607f60f81b826000815181106122d857fe5b01602001516001600160f81b03191611155b156122f65750806122b3565b6122b06123088351608060ff16612a9b565b83612b6d565b606081516000141561232f57506040805160008152602081019091526122b3565b60608260008151811061233e57fe5b602002602001015190506000600190505b835181101561237f576123758285838151811061236857fe5b6020026020010151612b6d565b915060010161234f565b50612398612392825160c060ff16612a9b565b82612b6d565b9392505050565b60408051600480825260a08201909252606091829190816020015b60608152602001906001900390816123ba5790505090506123e3836001600160a01b0316612bea565b816000815181106123f057fe5b60200260200101819052506124044361229d565b8160018151811061241157fe5b6020908102919091010152612426606161229d565b8160028151811061243357fe5b60200260200101819052506124474261229d565b8160038151811061245457fe5b60200260200101819052506123988161230e565b612470612f8b565b600061247a612f8b565b612482612f9d565b61249361248e86612c0d565b612c32565b90506000805b6124a283612c7c565b156124db57806124ce576124bd6124b884612c9d565b612ceb565b63ffffffff168452600191506124d3565b6124db565b600101612499565b5091935090915050915091565b6040516375cc7d8960e01b8152612002906375cc7d899061250d908590600401613534565b600060405180830381600087803b15801561252757600080fd5b505af1925050508015612538575060015b610d5c576040516000815260443d1015612554575060006125f1565b60046000803e60005160e01c6308c379a081146125755760009150506125f1565b60043d036004833e81513d602482011167ffffffffffffffff821117156125a1576000925050506125f1565b808301805167ffffffffffffffff8111156125c35760009450505050506125f1565b8060208301013d86018111156125e1576000955050505050506125f1565b601f01601f191660405250925050505b806125fc5750612633565b826001600160a01b0316600080516020613e52833981519152838360405161262592919061357f565b60405180910390a250612696565b3d80801561265d576040519150601f19603f3d011682016040523d82523d6000602084013e612662565b606091505b50826001600160a01b0316600080516020613e52833981519152838360405161268c92919061357f565b60405180910390a2505b610d5c565b6000816040516020016126ae9190613518565b60405160208183030381529060405280519060200120836040516020016126d59190613518565b604051602081830303815290604052805190602001201490505b92915050565b015190565b8082015160009060ff81161561271457600191508161271a565b60009150815b505092915050565b60408051600480825260a0820190925260009160609190816020015b606081526020019060019003908161273e575050604080516020808252818301909252919250606091908082018180368337019050509050612783856000015161229d565b8260008151811061279057fe5b60200260200101819052506127ab6020866020015183612d6d565b6127b4816122b8565b826001815181106127c157fe5b60200260200101819052506127d9856040015161229d565b826002815181106127e657fe5b60200260200101819052506128016020866060015183612d6d565b61280a816122b8565b8260038151811061281757fe5b602002602001018190525061283d60206128308461230e565b8051906020012083612d6d565b6040805160b080825260e0820190925260609160208201818036833701905050905061286d818360006020612d7d565b61287f81876080015160206060612d7d565b61288d818660806030612d7d565b604080516001808252818301909252606091602082018180368337019050509050815160016020830182602086016066600019fa6128ca57600080fd5b5060016128d8826000612dd0565b60ff16146128ed5760009450505050506126ef565b5060019695505050505050565b8151815160009160019181148083146129165760009250612954565b600160208701838101602088015b60028483851001141561294f5780518351146129435760009650600093505b60209283019201612924565b505050505b5090949350505050565b60408051600480825260a08201909252606091829190816020015b60608152602001906001900390816129795790505090506123e3836122b8565b600081602001835110156129ac57600080fd5b50016020015190565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166129f957506018612a1d565b6fffffffffffffffffffffffffffffffff198416612a1957506010612a1d565b5060005b6020811015612a5357818181518110612a3257fe5b01602001516001600160f81b03191615612a4b57612a53565b600101612a1d565b60008160200390506060816040519080825280601f01601f191660200182016040528015612a88576020820181803683370190505b5080830196909652508452509192915050565b6060680100000000000000008310612ac55760405162461bcd60e51b815260040161064f906137d1565b60408051600180825281830190925260609160208201818036833701905050905060378411612b1f5782840160f81b81600081518110612b0157fe5b60200101906001600160f81b031916908160001a90535090506126ef565b6060612b2a856129b5565b90508381510160370160f81b82600081518110612b4357fe5b60200101906001600160f81b031916908160001a905350612b648282612b6d565b95945050505050565b6060806040519050835180825260208201818101602087015b81831015612b9e578051835260209283019201612b86565b50855184518101855292509050808201602086015b81831015612bcb578051835260209283019201612bb3565b508651929092011591909101601f01601f191660405250905092915050565b60408051600560a21b8318601482015260348101909152606090612398816122b8565b612c15612fbd565b506040805180820190915281518152602082810190820152919050565b612c3a612f9d565b612c4382612dec565b612c4c57600080fd5b6000612c5b8360200151612e26565b60208085015160408051808201909152868152920190820152915050919050565b6000612c86612fbd565b505080518051602091820151919092015191011190565b612ca5612fbd565b612cae82612c7c565b612cb757600080fd5b60208201516000612cc782612e89565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590612d0057508151602110155b612d0957600080fd5b6000612d188360200151612e26565b90508083600001511015612d3e5760405162461bcd60e51b815260040161064f90613b3f565b825160208085015183018051928490039291831015612d6457826020036101000a820491505b50949350505050565b9091018181526020918201910152565b60005b81811015610d1e57838181518110612d9457fe5b602001015160f81c60f81b858480600101955081518110612db157fe5b60200101906001600160f81b031916908160001a905350600101612d80565b60008160010183511015612de357600080fd5b50016001015190565b8051600090612dfd575060006122b3565b6020820151805160001a9060c0821015612e1c576000925050506122b3565b5060019392505050565b8051600090811a6080811015612e405760009150506122b3565b60b8811080612e5b575060c08110801590612e5b575060f881105b15612e6a5760019150506122b3565b60c0811015612e7e5760b5190190506122b3565b60f5190190506122b3565b80516000908190811a6080811015612ea45760019150612f61565b60b8811015612eb957607e1981019150612f61565b60c0811015612f0a57600060b78203600186019550806020036101000a865104915060018101820193505080831015612f045760405162461bcd60e51b815260040161064f906138f4565b50612f61565b60f8811015612f1f5760be1981019150612f61565b600060f78203600186019550806020036101000a86510491506001810182019350508083101561271a5760405162461bcd60e51b815260040161064f906138f4565b5092915050565b604051806060016040528060008152602001600081526020016000151581525090565b60408051602081019091526000815290565b6040518060400160405280612fb0612fbd565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b600082601f830112612fe7578081fd5b8151612ffa612ff582613dc8565b613da1565b818152915060208083019084810160005b84811015613070578151870188603f82011261302657600080fd5b83810151613036612ff582613de8565b81815260408b8184860101111561304c57600080fd5b61305b83888401838701613e0c565b5086525050928201929082019060010161300b565b505050505092915050565b60008083601f84011261308c578182fd5b50813567ffffffffffffffff8111156130a3578182fd5b6020830191508360208285010111156130bb57600080fd5b9250929050565b600082601f8301126130d2578081fd5b81356130e0612ff582613de8565b91508082528360208285010111156130f757600080fd5b8060208401602084013760009082016020015292915050565b600060a08284031215613121578081fd5b61312b60a0613da1565b905081358152602082013560208201526040820135604082015260608201356060820152608082013567ffffffffffffffff81111561316957600080fd5b613175848285016130c2565b60808301525092915050565b600060208284031215613192578081fd5b813561239881613e3c565b6000602082840312156131ae578081fd5b815161239881613e3c565b600080604083850312156131cb578081fd5b82356131d681613e3c565b946020939093013593505050565b600080604083850312156131f6578182fd5b825167ffffffffffffffff8082111561320d578384fd5b81850186601f82011261321e578485fd5b8051925061322e612ff584613dc8565b80848252602080830192508084018a82838902870101111561324e578889fd5b8894505b8685101561327957805161326581613e3c565b845260019490940193928101928101613252565b508801519096509350505080821115613290578283fd5b5061329d85828601612fd7565b9150509250929050565b6000602082840312156132b8578081fd5b81518015158114612398578182fd5b600080604083850312156132d9578182fd5b823567ffffffffffffffff808211156132f0578384fd5b6132fc868387016130c2565b93506020850135915080821115613311578283fd5b5061329d858286016130c2565b60008060008060408587031215613333578182fd5b843567ffffffffffffffff8082111561334a578384fd5b6133568883890161307b565b9096509450602087013591508082111561336e578384fd5b5061337b8782880161307b565b95989497509550505050565b600060208284031215613398578081fd5b813567ffffffffffffffff808211156133af578283fd5b818401606081870312156133c1578384fd5b6133cb6060613da1565b92508035828111156133db578485fd5b6133e787828401613110565b8452506020810135828111156133fb578485fd5b61340787828401613110565b60208501525060408101358281111561341e578485fd5b61342a878284016130c2565b6040850152509195945050505050565b60006020828403121561344b578081fd5b5035919050565b600060208284031215613463578081fd5b5051919050565b60008060006040848603121561347e578081fd5b833560ff8116811461348e578182fd5b9250602084013567ffffffffffffffff8111156134a9578182fd5b6134b58682870161307b565b9497909650939450505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452613504816020860160208601613e0c565b601f01601f19169290920160200192915050565b6000825161352a818460208701613e0c565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b60006020825261239860208301846134ec565b60008382526040602083015261359860408301846134ec565b949350505050565b6000604082526135b46040830186886134c2565b82810360208401526135c78185876134c2565b979650505050505050565b60208082526010908201526f195d9a59195b98d9481d1bdbc81bdb1960821b604082015260600190565b6020808252818101527f6d616c6963696f757320766f746520736c617368206e6f7420656e61626c6564604082015260600190565b6020808252601690820152751d985b1a59185d1bdc881b9bdd081b5a59dc985d195960521b604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252602b908201527f746865206d616c6963696f757320766f746520736c6173682073636f7065206f60408201526a7574206f662072616e676560a81b606082015260800190565b6020808252601a908201527f6e6f2076696f6c6174696f6e206f6620766f74652072756c6573000000000000604082015260600190565b6020808252818101527f7468652066656c6f6e795468726573686f6c64206f7574206f662072616e6765604082015260600190565b6020808252602b908201527f6c656e677468206f6620656e61626c654d616c6963696f7573566f7465536c6160408201526a0e6d040dad2e6dac2e8c6d60ab1b606082015260800190565b60208082526017908201527f766572696679207369676e6174757265206661696c6564000000000000000000604082015260600190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526019908201527f7372634e756d20626967676572207468616e207461724e756d00000000000000604082015260600190565b60208082526027908201527f6c656e677468206f66206d697364656d65616e6f725468726573686f6c64206d6040820152660d2e6dac2e8c6d60cb1b606082015260800190565b60208082526013908201527274776f206964656e746963616c20766f74657360681b604082015260600190565b60208082526030908201527f746865206d6573736167652073656e646572206d7573742062652076616c696460408201526f185d1bdc94d95d0818dbdb9d1c9858dd60821b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f6c656e677468206f662066656c6f6e79536c61736853636f7065206d69736d616040820152620e8c6d60eb1b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b60208082526029908201527f6c656e677468206f662066656c6f6e79536c617368526577617264526174696f604082015268040dad2e6dac2e8c6d60bb1b606082015260800190565b6020808252601590820152741d9bdd195059191c881a5cc81b9bdd08199bdd5b99605a1b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526022908201527f6c656e677468206f662066656c6f6e795468726573686f6c64206d69736d61746040820152610c6d60f31b606082015260800190565b6020808252602a908201527f7468652066656c6f6e7920736c6173682072657761726420726174696f206f7560408201526974206f662072616e676560b01b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252600c908201526b32b6b83a3c903432b0b232b960a11b604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526025908201527f746865206d697364656d65616e6f725468726573686f6c64206f7574206f662060408201526472616e676560d81b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b6020808252601490820152731d185c99d95d08189b1bd8dac81d1bdbc81bdb1960621b604082015260600190565b6020808252601e908201527f7265636569766520756e65787065637465642073796e207061636b6167650000604082015260600190565b6020808252818101527f63616e206e6f7420736c61736820747769636520696e206f6e6520626c6f636b604082015260600190565b61ffff91909116815260200190565b90815260200190565b918252602082015260400190565b92835260208301919091521515604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260606020830152613d9160608301856134ec565b9050826040830152949350505050565b60405181810167ffffffffffffffff81118282101715613dc057600080fd5b604052919050565b600067ffffffffffffffff821115613dde578081fd5b5060209081020190565b600067ffffffffffffffff821115613dfe578081fd5b50601f01601f191660200190565b60005b83811015613e27578181015183820152602001613e0f565b83811115613e36576000848401525b50505050565b6001600160a01b0381168114610bd957600080fdfed7bc86ff5d08c8ab043edec743302aba2520e6635172a428bc956721db9e2d1ca164736f6c6343000604000a",
},
{
- ContractAddr: common.HexToAddress(SystemRewardContract),
- CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/b3a5c1fa8882c0e546dc5ba913ce4db77ec9befe",
- Code: "6080604052600436106101c55760003560e01c806375d47a0a116100f7578063ab51bb9611610095578063f9a2bbc711610064578063f9a2bbc7146105c3578063fb5478b3146105d8578063fc3e5908146105ed578063fd6a68791461060257610209565b8063ab51bb96146104b5578063ac431751146104ca578063c81b166214610599578063dc927faf146105ae57610209565b80639a99b4f0116100d15780639a99b4f01461043d5780639dc0926214610476578063a1a11bf51461048b578063a78abc16146104a057610209565b806375d47a0a146103fe5780637942fd051461041357806396713da91461042857610209565b8063493279b1116101645780636d70f7ae1161013e5780636d70f7ae146103785780636e47b482146103bf57806370fd5bad146103d4578063718a8aa8146103e957610209565b8063493279b1146103225780634bf6c8821461034e57806351e806721461036357610209565b806331b6d4a5116101a057806331b6d4a5146102b85780633a0b0eff146102cd5780633dffc387146102e257806343756e5c1461030d57610209565b806227253a1461020e5780630bee7a67146102595780630e2374a51461028757610209565b366102095734156102075760408051348152905133917f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db919081900360200190a25b005b600080fd5b34801561021a57600080fd5b506102476004803603604081101561023157600080fd5b506001600160a01b038135169060200135610617565b60408051918252519081900360200190f35b34801561026557600080fd5b5061026e6107c2565b6040805163ffffffff9092168252519081900360200190f35b34801561029357600080fd5b5061029c6107c7565b604080516001600160a01b039092168252519081900360200190f35b3480156102c457600080fd5b506102476107cd565b3480156102d957600080fd5b506102476107d9565b3480156102ee57600080fd5b506102f76107df565b6040805160ff9092168252519081900360200190f35b34801561031957600080fd5b5061029c6107e4565b34801561032e57600080fd5b506103376107ea565b6040805161ffff9092168252519081900360200190f35b34801561035a57600080fd5b506102f76107f0565b34801561036f57600080fd5b5061029c6107f5565b34801561038457600080fd5b506103ab6004803603602081101561039b57600080fd5b50356001600160a01b03166107fb565b604080519115158252519081900360200190f35b3480156103cb57600080fd5b5061029c610819565b3480156103e057600080fd5b506102f761081f565b3480156103f557600080fd5b506102f7610824565b34801561040a57600080fd5b5061029c610829565b34801561041f57600080fd5b506102f761082f565b34801561043457600080fd5b506102f7610834565b34801561044957600080fd5b506102476004803603604081101561046057600080fd5b506001600160a01b038135169060200135610839565b34801561048257600080fd5b5061029c610963565b34801561049757600080fd5b5061029c610969565b3480156104ac57600080fd5b506103ab61096f565b3480156104c157600080fd5b5061026e610978565b3480156104d657600080fd5b50610207600480360360408110156104ed57600080fd5b81019060208101813564010000000081111561050857600080fd5b82018360208201111561051a57600080fd5b8035906020019184600183028401116401000000008311171561053c57600080fd5b91939092909160208101903564010000000081111561055a57600080fd5b82018360208201111561056c57600080fd5b8035906020019184600183028401116401000000008311171561058e57600080fd5b50909250905061097d565b3480156105a557600080fd5b5061029c610d00565b3480156105ba57600080fd5b5061029c610d06565b3480156105cf57600080fd5b5061029c610d0c565b3480156105e457600080fd5b50610247610d12565b3480156105f957600080fd5b506102f7610d1e565b34801561060e57600080fd5b5061029c610d23565b6000805460ff1661069457600260208190527fe57bda0a954a7c7381b17b2c763e646ba2c60f67292d287ba583603e2c1c41668054600160ff19918216811790925561100560009081527fe25235fc0de9d7165652bef0846fefda506174abb9a190f03d0f7bcc6146dbce80548316841790559282558254161790555b3360009081526002602052604090205460ff166106e25760405162461bcd60e51b815260040180806020018281038252602b815260200180610e11602b913960400191505060405180910390fd5b60004783106106f157476106f3565b825b9050674563918244f400008111156107105750674563918244f400005b8015610791576040516001600160a01b0385169082156108fc029083906000818181858888f1935050505015801561074c573d6000803e3d6000fd5b506040805182815290516001600160a01b038616917ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0919081900360200190a26107bb565b6040517fe589651933c2457488cc0d8e0941518abf748e799435e4e396d9c4d0b2db2d4d90600090a15b9392505050565b606481565b61200181565b674563918244f4000081565b60015481565b600181565b61100181565b6102ca81565b600881565b61200081565b6001600160a01b031660009081526002602052604090205460ff1690565b61100581565b600281565b601081565b61100881565b600b81565b600981565b6000805460ff166108b657600260208190527fe57bda0a954a7c7381b17b2c763e646ba2c60f67292d287ba583603e2c1c41668054600160ff19918216811790925561100560009081527fe25235fc0de9d7165652bef0846fefda506174abb9a190f03d0f7bcc6146dbce80548316841790559282558254161790555b3360009081526002602052604090205460ff166109045760405162461bcd60e51b815260040180806020018281038252602b815260200180610e11602b913960400191505060405180910390fd5b60004783106109135747610915565b825b9050670de0b6b3a76400008111156107105750604051670de0b6b3a7640000906001600160a01b03851690600090839082818181858883f1935050505015801561074c573d6000803e3d6000fd5b61100781565b61100681565b60005460ff1681565b600081565b33611007146109bd5760405162461bcd60e51b815260040180806020018281038252602e815260200180610e6b602e913960400191505060405180910390fd5b610a1f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600b81526a30b23227b832b930ba37b960a91b60208201529150610d299050565b15610af757606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060149091149050610aa25760405162461bcd60e51b815260040180806020018281038252602c815260200180610e99602c913960400191505060405180910390fd5b60148101516001600160a01b038116600081815260026020526040808220805460ff19166001179055517f9870d7fe5d112134c55844951dedf365363006d9c588db07c4c85af6322a06199190a25050610c6e565b610b5c84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600e81526d3232b632ba32a7b832b930ba37b960911b60208201529150610d299050565b15610c3157606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060149091149050610bdf5760405162461bcd60e51b815260040180806020018281038252602f815260200180610e3c602f913960400191505060405180910390fd5b60148101516001600160a01b038116600081815260026020526040808220805460ff19169055517fb40992a19dba61ea600e87fce607102bf5908dc89076217b6ca6ae195224f7029190a25050610c6e565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b61100281565b61100381565b61100081565b670de0b6b3a764000081565b600381565b61100481565b6000816040516020018082805190602001908083835b60208310610d5e5780518252601f199092019160209182019101610d3f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310610dcc5780518252601f199092019160209182019101610dad565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201490509291505056fe6f6e6c79206f70657261746f7220697320616c6c6f77656420746f2063616c6c20746865206d6574686f646c656e677468206f662076616c756520666f722064656c6574654f70657261746f722073686f756c64206265203230746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662076616c756520666f72206164644f70657261746f722073686f756c64206265203230a164736f6c6343000604000a",
+ ContractAddr: common.HexToAddress(TokenHubContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106104405760003560e01c80639509b98011610234578063c81b16621161012e578063ebf71d53116100b6578063fb063e8f1161007a578063fb063e8f146110d3578063fc1a598f146110e8578063fc3e590814610cca578063fd6a68791461111b578063ff9c0027146108a057610488565b8063ebf71d531461106a578063f01484721461107f578063f1fad10414611094578063f9a2bbc7146110a9578063fa9e9159146110be57610488565b8063dc927faf116100fd578063dc927faf14610fce578063df8079e914610fe3578063e04c83a714610ff8578063e1c7392a14611022578063e8f35cea1461103757610488565b8063c81b166214610ef9578063c8509d8114610f0e578063cf41984414610f93578063d9e6dae91461080d57610488565b8063aa7415f5116101bc578063b99328c511610180578063b99328c514610e30578063b9fd21e314610e69578063ba35ead614610e7e578063bbface1f14610e93578063bd46646114610ec657610488565b8063aa7415f514610cdf578063aa82dce114610d26578063aad5606314610d3b578063ab51bb9614610d50578063ac43175114610d6557610488565b80639dc09262116102035780639dc0926214610c76578063a1a11bf514610c8b578063a496fba214610ca0578063a78abc1614610cb5578063a7c9f02d14610cca57610488565b80639509b98014610bda57806396713da914610c135780639a854bbd14610c285780639a99b4f014610c3d57610488565b806359b9278911610345578063727be1f8116102cd578063831d65d111610291578063831d65d114610ac85780638525db0314610b4d5780638b87b21f146107625780638eff336c14610b8657806393ab703f14610bc557610488565b8063727be1f814610a2057806375d47a0a14610a4a5780637942fd0514610a5f578063799758b914610a745780637e434d5414610ab357610488565b80636e056520116103145780636e056520146108b55780636e47b482146109e157806370fd5bad146108a0578063718a8aa8146109f657806371d3086314610a0b57610488565b806359b92789146108615780635d499b1b1461088b578063613684751461080d57806366dea52a146108a057610488565b80633fd8b02f116103c85780634a3acdf4116103975780634a3acdf4146107f85780634bf6c8821461080d57806350432d321461082257806351b4dce31461083757806351e806721461084c57610488565b80633fd8b02f1461078d57806343756e5c146107a257806343a368b9146107b7578063493279b1146107cc57610488565b8063149d14d91161040f578063149d14d91461062157806328087028146106485780632ae454831461065d5780633d713223146106b15780633dffc3871461076257610488565b80630bee7a671461048d5780630e2374a5146104bb5780631182b875146104ec57806312234582146105e657610488565b36610488573415610486576040805133815234602082015281517f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db929181900390910190a15b005b600080fd5b34801561049957600080fd5b506104a2611130565b6040805163ffffffff9092168252519081900360200190f35b3480156104c757600080fd5b506104d0611135565b604080516001600160a01b039092168252519081900360200190f35b3480156104f857600080fd5b506105716004803603604081101561050f57600080fd5b60ff8235169190810190604081016020820135600160201b81111561053357600080fd5b82018360208201111561054557600080fd5b803590602001918460018302840111600160201b8311171561056657600080fd5b50909250905061113b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105ab578181015183820152602001610593565b50505050905090810190601f1680156105d85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156105f257600080fd5b506104866004803603604081101561060957600080fd5b506001600160a01b0381358116916020013516611269565b34801561062d57600080fd5b50610636611363565b60408051918252519081900360200190f35b34801561065457600080fd5b506104d0611369565b34801561066957600080fd5b506106986004803603604081101561068057600080fd5b506001600160a01b038135811691602001351661136f565b6040805192835260208301919091528051918290030190f35b3480156106bd57600080fd5b506104d0600480360360208110156106d457600080fd5b810190602081018135600160201b8111156106ee57600080fd5b82018360208201111561070057600080fd5b803590602001918460018302840111600160201b8311171561072157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611393945050505050565b34801561076e57600080fd5b506107776113b7565b6040805160ff9092168252519081900360200190f35b34801561079957600080fd5b506106366113bc565b3480156107ae57600080fd5b506104d06113c2565b3480156107c357600080fd5b506106366113c8565b3480156107d857600080fd5b506107e16113d4565b6040805161ffff9092168252519081900360200190f35b34801561080457600080fd5b506106366113d9565b34801561081957600080fd5b506107776113df565b34801561082e57600080fd5b506106366113e4565b34801561084357600080fd5b506104d06113ef565b34801561085857600080fd5b506104d06113f5565b34801561086d57600080fd5b506104d06004803603602081101561088457600080fd5b50356113fb565b34801561089757600080fd5b50610636611416565b3480156108ac57600080fd5b5061077761141f565b6109cd600480360360808110156108cb57600080fd5b810190602081018135600160201b8111156108e557600080fd5b8201836020820111156108f757600080fd5b803590602001918460208302840111600160201b8311171561091857600080fd5b919390929091602081019035600160201b81111561093557600080fd5b82018360208201111561094757600080fd5b803590602001918460208302840111600160201b8311171561096857600080fd5b919390929091602081019035600160201b81111561098557600080fd5b82018360208201111561099757600080fd5b803590602001918460208302840111600160201b831117156109b857600080fd5b91935091503567ffffffffffffffff16611424565b604080519115158252519081900360200190f35b3480156109ed57600080fd5b506104d06118f9565b348015610a0257600080fd5b506107776118ff565b348015610a1757600080fd5b50610636611904565b348015610a2c57600080fd5b506109cd60048036036020811015610a4357600080fd5b503561190a565b348015610a5657600080fd5b506104d061198b565b348015610a6b57600080fd5b50610777611991565b348015610a8057600080fd5b5061048660048036036060811015610a9757600080fd5b508035906001600160a01b036020820135169060400135611996565b348015610abf57600080fd5b506104d0611c46565b348015610ad457600080fd5b5061048660048036036040811015610aeb57600080fd5b60ff8235169190810190604081016020820135600160201b811115610b0f57600080fd5b820183602082011115610b2157600080fd5b803590602001918460018302840111600160201b83111715610b4257600080fd5b509092509050611c4c565b348015610b5957600080fd5b5061048660048036036040811015610b7057600080fd5b50803590602001356001600160a01b0316611d94565b348015610b9257600080fd5b5061048660048036036060811015610ba957600080fd5b508035906001600160a01b036020820135169060400135611efd565b348015610bd157600080fd5b50610636611f83565b348015610be657600080fd5b5061048660048036036040811015610bfd57600080fd5b506001600160a01b038135169060200135611f8a565b348015610c1f57600080fd5b50610777612147565b348015610c3457600080fd5b5061063661214c565b348015610c4957600080fd5b5061063660048036036040811015610c6057600080fd5b506001600160a01b038135169060200135612158565b348015610c8257600080fd5b506104d0612296565b348015610c9757600080fd5b506104d061229c565b348015610cac57600080fd5b506107776122a2565b348015610cc157600080fd5b506109cd6122a7565b348015610cd657600080fd5b506107776122b0565b6109cd60048036036080811015610cf557600080fd5b5080356001600160a01b03908116916020810135909116906040810135906060013567ffffffffffffffff166122b5565b348015610d3257600080fd5b506104d0612335565b348015610d4757600080fd5b506104d061233b565b348015610d5c57600080fd5b506104a26122a2565b348015610d7157600080fd5b5061048660048036036040811015610d8857600080fd5b810190602081018135600160201b811115610da257600080fd5b820183602082011115610db457600080fd5b803590602001918460018302840111600160201b83111715610dd557600080fd5b919390929091602081019035600160201b811115610df257600080fd5b820183602082011115610e0457600080fd5b803590602001918460018302840111600160201b83111715610e2557600080fd5b509092509050612341565b348015610e3c57600080fd5b5061048660048036036040811015610e5357600080fd5b50803590602001356001600160a01b03166127e9565b348015610e7557600080fd5b50610636612869565b348015610e8a57600080fd5b50610636612873565b348015610e9f57600080fd5b5061063660048036036020811015610eb657600080fd5b50356001600160a01b0316612879565b348015610ed257600080fd5b5061063660048036036020811015610ee957600080fd5b50356001600160a01b031661288b565b348015610f0557600080fd5b506104d06128a6565b348015610f1a57600080fd5b5061048660048036036040811015610f3157600080fd5b60ff8235169190810190604081016020820135600160201b811115610f5557600080fd5b820183602082011115610f6757600080fd5b803590602001918460018302840111600160201b83111715610f8857600080fd5b5090925090506128ac565b348015610f9f57600080fd5b5061048660048036036040811015610fb657600080fd5b506001600160a01b038135811691602001351661297c565b348015610fda57600080fd5b506104d0612c50565b348015610fef57600080fd5b506104d0612c56565b34801561100457600080fd5b506109cd6004803603602081101561101b57600080fd5b5035612c5c565b34801561102e57600080fd5b50610486612cfc565b34801561104357600080fd5b506106366004803603602081101561105a57600080fd5b50356001600160a01b0316612d9c565b34801561107657600080fd5b50610777612dae565b34801561108b57600080fd5b50610777612db3565b3480156110a057600080fd5b50610777612db8565b3480156110b557600080fd5b506104d0612dbd565b3480156110ca57600080fd5b50610636612dc3565b3480156110df57600080fd5b50610636612dc9565b3480156110f457600080fd5b506105716004803603602081101561110b57600080fd5b50356001600160a01b0316612dd7565b34801561112757600080fd5b506104d0612efe565b606481565b61200181565b60005460609060ff16611183576040805162461bcd60e51b815260206004820152601960248201526000805160206153e4833981519152604482015290519081900360640190fd5b33612000146111c35760405162461bcd60e51b815260040180806020018281038252602f815260200180615392602f913960400191505060405180910390fd5b60ff8416600214156112155761120e83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f0492505050565b9050611262565b6040805162461bcd60e51b815260206004820152601860248201527f756e7265636f676e697a65642073796e207061636b6167650000000000000000604482015290519081900360640190fd5b9392505050565b33612000146112a95760405162461bcd60e51b815260040180806020018281038252602f815260200180615392602f913960400191505060405180910390fd5b6001600160a01b0380831660009081526007602090815260408083209385168352929052208054611314576040805162461bcd60e51b815260206004820152601060248201526f1b9bc81b1bd8dad95908185b5bdd5b9d60821b604482015290519081900360640190fd5b8054600082556040805182815290516001600160a01b0380861692908716917f152fb15aa5d80f843e1e4bd5f2fc9161714f169945024decec7e84fb910fdd519181900360200190a350505050565b60015490565b61200581565b60076020908152600092835260408084209091529082529020805460019091015482565b6020818101516000908152600490915260409020546001600160a01b03165b919050565b600181565b60055481565b61100181565b670de0b6b3a764000081565b606181565b61a8c081565b600881565b66071afd498d000081565b61200681565b61200081565b6000908152600460205260409020546001600160a01b031690565b6402540be40081565b600281565b6000805460ff1661146a576040805162461bcd60e51b815260206004820152601960248201526000805160206153e4833981519152604482015290519081900360640190fd5b8685146114a85760405162461bcd60e51b815260040180806020018281038252603b815260200180615357603b913960400191505060405180910390fd5b8683146114e65760405162461bcd60e51b815260040180806020018281038252603f815260200180615269603f913960400191505060405180910390fd5b426078018267ffffffffffffffff1610156115325760405162461bcd60e51b81526004018080602001828103825260248152602001806151e56024913960400191505060405180910390fd5b6402540be4003406156115765760405162461bcd60e51b815260040180806020018281038252604081526020018061545a6040913960400191505060405180910390fd5b604080518681526020808802820101909152859060009081906060908480156115a9578160200160208202803683370190505b50905060005b84811015611684576402540be4008b8b838181106115c957fe5b90506020020135816115d757fe5b06156116145760405162461bcd60e51b815260040180806020018281038252603c8152602001806152a8603c913960400191505060405180910390fd5b6116398b8b8381811061162357fe5b905060200201358561302890919063ffffffff16565b93506116656402540be4008c8c8481811061165057fe5b9050602002013561308290919063ffffffff16565b82828151811061167157fe5b60209081029190910101526001016115af565b506001546116a99061169c908663ffffffff6130c416565b849063ffffffff61302816565b3410156116e75760405162461bcd60e51b81526004018080602001828103825260568152602001806154046056913960600191505060405180910390fd5b6116f7348463ffffffff61311d16565b9150611701615023565b6040518060c001604052806221272160e91b60001b815260200160006001600160a01b031681526020018381526020018e8e808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208c810282810182019093528c82529283019290918d918d91829185019084908082843760009201919091525050509082525067ffffffffffffffff8916602090910152905061200063f7a251d760036117c58461315f565b6117da876402540be40063ffffffff61308216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611838578181015183820152602001611820565b50505050905090810190601f1680156118655780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561188657600080fd5b505af115801561189a573d6000803e3d6000fd5b505060408051600081523360208201528082018890526060810187905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a15060019c9b505050505050505050505050565b61100581565b601081565b60015481565b6000336120011461194c5760405162461bcd60e51b815260040180806020018281038252603381526020018061513d6033913960400191505060405180910390fd5b8115611983576040516120019083156108fc029084906000818181858888f19350505050158015611981573d6000803e3d6000fd5b505b506001919050565b61100881565b600b81565b60005460ff166119db576040805162461bcd60e51b815260206004820152601960248201526000805160206153e4833981519152604482015290519081900360640190fd5b3361300014611a1b5760405162461bcd60e51b815260040180806020018281038252602b81526020018061523e602b913960400191505060405180910390fd5b677ce66c50e2840000811115611a625760405162461bcd60e51b81526004018080602001828103825260358152602001806152096035913960400191505060405180910390fd5b60006221272160e91b8414611bcc576000848152600460205260409020546001600160a01b031680611ad5576040805184815290516001600160a01b0386169187917fc16ee9013bf67c846d37735983debb0acc5b2d1419cb5931c9843ad4689505499181900360200190a35050611c41565b6001600160a01b038116600090815260026020526040902054611af8848261341a565b604080516370a0823160e01b8152306004820152905191945084916001600160a01b038516916370a08231916024808301926020929190829003018186803b158015611b4357600080fd5b505afa158015611b57573d6000803e3d6000fd5b505050506040513d6020811015611b6d57600080fd5b50511015611bb9576040805162461bcd60e51b8152602060048201526014602482015273696e73756666696369656e742062616c616e636560601b604482015290519081900360640190fd5b611bc58683858861345a565b5050611c3f565b611be1826402540be40063ffffffff6130c416565b905080471015611c2f576040805162461bcd60e51b8152602060048201526014602482015273696e73756666696369656e742062616c616e636560601b604482015290519081900360640190fd5b6000611c3d8582848761345a565b505b505b505050565b61200381565b60005460ff16611c91576040805162461bcd60e51b815260206004820152601960248201526000805160206153e4833981519152604482015290519081900360640190fd5b3361200014611cd15760405162461bcd60e51b815260040180806020018281038252602f815260200180615392602f913960400191505060405180910390fd5b60ff831660031415611d2157611d1c82828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506134f492505050565b611c41565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1505050565b3361300014611dd45760405162461bcd60e51b815260040180806020018281038252602b81526020018061523e602b913960400191505060405180910390fd5b60006221272160e91b8314611e3f57506000828152600460205260409020546001600160a01b031680611e3f576040805162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081cde5b589bdb60921b604482015290519081900360640190fd5b6001600160a01b0380821660009081526007602090815260408083209386168352929052208054611eaa576040805162461bcd60e51b815260206004820152601060248201526f1b9bc81b1bd8dad95908185b5bdd5b9d60821b604482015290519081900360640190fd5b8054600082556040805182815290516001600160a01b03808716929086169188917f8041a9a8704332594e2884f5e0f942281cdd7611854c365b4d0aa70b2295d6b6919081900360200190a45050505050565b3361100814611f3d5760405162461bcd60e51b81526004018080602001828103825260238152602001806153c16023913960400191505060405180910390fd5b600083815260046020908152604080832080546001600160a01b039096166001600160a01b03199096168617905593825260038152838220949094556002909352912055565b6201518081565b81806001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b158015611fc457600080fd5b505afa158015611fd8573d6000803e3d6000fd5b505050506040513d6020811015611fee57600080fd5b50516001600160a01b0316331461204c576040805162461bcd60e51b815260206004820152601860248201527f6e6f74206f776e6572206f6620424550323020746f6b656e0000000000000000604482015290519081900360640190fd5b6000821161209a576040805162461bcd60e51b81526020600482015260166024820152751e995c9bc81b1a5b5a5d081b9bdd08185b1b1bddd95960521b604482015290519081900360640190fd5b6001600160a01b0383166000908152600360205260409020546120f0576040805162461bcd60e51b81526020600482015260096024820152681b9bdd08189bdd5b9960ba1b604482015290519081900360640190fd5b6001600160a01b038316600081815260066020908152604091829020859055815185815291513393927f9df3a90730dbf23b5cc18dbbd5f4af3fa94a0dffb6ff6841f98a9a9a6ac626a892908290030190a3505050565b600981565b677ce66c50e284000081565b6000805460ff1661219e576040805162461bcd60e51b815260206004820152601960248201526000805160206153e4833981519152604482015290519081900360640190fd5b33611005146121de5760405162461bcd60e51b815260040180806020018281038252602f815260200180615170602f913960400191505060405180910390fd5b60004783106121ed57476121ef565b825b9050670de0b6b3a764000081111561220b576000915050612290565b801561228d576040516001600160a01b0385169082156108fc029083906000818181858888f19350505050158015612247573d6000803e3d6000fd5b50604080516001600160a01b03861681526020810183905281517ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0929181900390910190a15b90505b92915050565b61100781565b61100681565b600081565b60005460ff1681565b600381565b6000805460ff166122fb576040805162461bcd60e51b815260206004820152601960248201526000805160206153e4833981519152604482015290519081900360640190fd5b6040805162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b604482015290519081900360640190fd5b61200281565b61300081565b33611007146123815760405162461bcd60e51b815260040180806020018281038252602e815260200180615305602e913960400191505060405180910390fd5b602081146123d6576040805162461bcd60e51b815260206004820152601b60248201527f65787065637465642076616c7565206c656e6774682069732033320000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152939450606093925086915085908190840183828082843760009201919091525050505060208301519091506772656c617946656560c01b8114156124de576020820151670de0b6b3a7640000811180159061248557506402540be4008106155b6124d6576040805162461bcd60e51b815260206004820152601960248201527f7468652072656c6179466565206f7574206f662072616e676500000000000000604482015290519081900360640190fd5b600155612754565b61255287878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f6c617267655472616e736665724c6f636b506572696f64000000000000000000602082015291506135509050565b156125ee57604080516020601f87018190048102820181019092528581526000916125959188888083850183828082843760009201919091525061363792505050565b905062093a808111156125e6576040805162461bcd60e51b81526020600482015260146024820152736c6f636b20706572696f6420746f6f206c6f6e6760601b604482015290519081900360640190fd5b600555612754565b61265a87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526015815274189b9893185c99d9551c985b9cd9995c931a5b5a5d605a1b602082015291506135509050565b1561271757604080516020601f870181900481028201810190925285815260009161269d9188888083850183828082843760009201919091525061363792505050565b905068056bc75e2d631000008110156126e75760405162461bcd60e51b815260040180806020018281038252602281526020018061519f6022913960400191505060405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f855612754565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b33611008146128295760405162461bcd60e51b81526004018080602001828103825260238152602001806153c16023913960400191505060405180910390fd5b600091825260046020908152604080842080546001600160a01b03191690556001600160a01b039290921683526003815281832083905560029052812055565b6221272160e91b81565b61c35081565b60026020526000908152604090205481565b6001600160a01b031660009081526003602052604090205490565b61100281565b60005460ff166128f1576040805162461bcd60e51b815260206004820152601960248201526000805160206153e4833981519152604482015290519081900360640190fd5b33612000146129315760405162461bcd60e51b815260040180806020018281038252602f815260200180615392602f913960400191505060405180910390fd5b60ff831660031415611d2157611d1c82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061363c92505050565b60085460ff16600214156129c8576040805162461bcd60e51b815260206004820152600e60248201526d4e6f2072652d656e7472616e637960901b604482015290519081900360640190fd5b6008805460ff191660021790556001600160a01b0380831660009081526007602090815260408083209385168352929052208054612a40576040805162461bcd60e51b815260206004820152601060248201526f1b9bc81b1bd8dad95908185b5bdd5b9d60821b604482015290519081900360640190fd5b8060010154421015612a99576040805162461bcd60e51b815260206004820152601760248201527f7374696c6c206f6e206c6f636b696e6720706572696f64000000000000000000604482015290519081900360640190fd5b805460008083556001600160a01b038516612b0c576040516001600160a01b038516906127109084906000818181858888f193505050503d8060008114612afc576040519150601f19603f3d011682016040523d82523d6000602084013e612b01565b606091505b505080915050612b9f565b846001600160a01b031663a9059cbb61c35086856040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015612b6f57600080fd5b5087f1158015612b83573d6000803e3d6000fd5b50505050506040513d6020811015612b9a57600080fd5b505190505b80612bf1576040805162461bcd60e51b815260206004820152601e60248201527f776974686472617720756e6c6f636b656420746f6b656e206661696c65640000604482015290519081900360640190fd5b836001600160a01b0316856001600160a01b03167f832fc3e25f2b3e6fb0eb59419a73cba405f2a249fce75f7e31ea5a457a0323f1846040518082815260200191505060405180910390a350506008805460ff19166001179055505050565b61100381565b61200481565b60003361200214612cb4576040805162461bcd60e51b815260206004820152601f60248201527f746865206d73672073656e646572206d757374206265207374616b6548756200604482015290519081900360640190fd5b814710612cf4576040516120029083156108fc029084906000818181858888f19350505050158015612cea573d6000803e3d6000fd5b50600190506113b2565b506000919050565b60005460ff1615612d54576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b66071afd498d000060019081556000808052600260205260127fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b55805460ff19169091179055565b60066020526000908152604090205481565b600481565b600581565b601181565b61100081565b61271081565b69021e19e0c9bab240000081565b6001600160a01b03811660009081526003602090815260409182902054825182815280840190935260609290918391906020820181803683375050506020810183905290506000805b60208160ff161015612e6757828160ff1681518110612e3b57fe5b01602001516001600160f81b03191615612e5a57816001019150612e5f565b612e67565b600101612e20565b5060608160ff166040519080825280601f01601f191660200182016040528015612e98576020820181803683370190505b50905060005b8260ff168160ff161015612ef457838160ff1681518110612ebb57fe5b602001015160f81c60f81b828260ff1681518110612ed557fe5b60200101906001600160f81b031916908160001a905350600101612e9e565b5095945050505050565b61100481565b6060612f0e61506f565b6000612f1984613733565b9150915080612f6f576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b6000612f7a83613872565b905063ffffffff81161561300e576040808401516020808601516001600160a01b03166000908152600290915291822054612fb59190613bd8565b9050612fbf6150a4565b60405180608001604052808660000151815260200183815260200186608001516001600160a01b031681526020018463ffffffff16815250905061300281613c11565b955050505050506113b2565b505060408051600081526020810190915291506113b29050565b60008282018381101561228d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061228d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613ced565b6000826130d357506000612290565b828202828482816130e057fe5b041461228d5760405162461bcd60e51b81526004018080602001828103825260218152602001806152e46021913960400191505060405180910390fd5b600061228d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613d8f565b60408051600680825260e08201909252606091829190816020015b606081526020019060019003908161317a575050835190915061319c90613de9565b816000815181106131a957fe5b60200260200101819052506131ca83602001516001600160a01b0316613dfc565b816001815181106131d757fe5b60200260200101819052506000836040015151905060608160405190808252806020026020018201604052801561322257816020015b606081526020019060019003908161320d5790505b50905060005b8281101561326f576132508660400151828151811061324357fe5b6020026020010151613de9565b82828151811061325c57fe5b6020908102919091010152600101613228565b5061327981613e1f565b8360028151811061328657fe5b60200260200101819052506060826040519080825280602002602001820160405280156132c757816020015b60608152602001906001900390816132b25790505b50905060005b8381101561331d576132fe876060015182815181106132e857fe5b60200260200101516001600160a01b0316613dfc565b82828151811061330a57fe5b60209081029190910101526001016132cd565b5061332781613e1f565b8460038151811061333457fe5b602002602001018190525060608360405190808252806020026020018201604052801561337557816020015b60608152602001906001900390816133605790505b50905060005b848110156133b557613396886080015182815181106132e857fe5b8282815181106133a257fe5b602090810291909101015260010161337b565b506133bf81613e1f565b856004815181106133cc57fe5b60200260200101819052506133ee8760a0015167ffffffffffffffff16613de9565b856005815181106133fb57fe5b602002602001018190525061340f85613e1f565b979650505050505050565b600060088211156134435761343c836007198401600a0a63ffffffff6130c416565b9050612290565b61228d836008849003600a0a63ffffffff61308216565b6001600160a01b0380841660009081526007602090815260408083209385168352929052208054613491908463ffffffff61302816565b81554262015180016001820181905560408051858152602081019290925280516001600160a01b03808616939088169289927f446d1aa056e7b903901f49880e9f252762c1b81dc4301cf28db6dae526497eaa9281900390910190a45050505050565b6134fc6150cb565b600061350783613ea9565b91509150806135475760405162461bcd60e51b81526004018080602001828103825260248152602001806153336024913960400191505060405180910390fd5b611c4182614074565b6000816040516020018082805190602001908083835b602083106135855780518252601f199092019160209182019101613566565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106135f35780518252601f1990920191602091820191016135d4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b613644615023565b600061364f836144f8565b915091508061368f5760405162461bcd60e51b81526004018080602001828103825260248152602001806151c16024913960400191505060405180910390fd5b6136976150cb565b602080840180516001600160a01b0390811684526040808701518585015291511660009081526002909252812054905b846040015151811015613718576136f5856040015182815181106136e757fe5b60200260200101518361341a565b8560400151828151811061370557fe5b60209081029190910101526001016136c7565b506080840151604083015260056060830152611c3d82614074565b61373b61506f565b600061374561506f565b61374d615102565b61375e6137598661475c565b614781565b90506000805b61376d836147cb565b15613865578061378f57613788613783846147ec565b61483a565b845261385d565b80600114156137bc576137a96137a4846147ec565b6148f1565b6001600160a01b0316602085015261385d565b80600214156137db576137d1613783846147ec565b604085015261385d565b8060031415613803576137f06137a4846147ec565b6001600160a01b0316606085015261385d565b806004141561382b576138186137a4846147ec565b6001600160a01b0316608085015261385d565b806005141561385857613840613783846147ec565b67ffffffffffffffff1660a08501526001915061385d565b613865565b600101613764565b5091935090915050915091565b60208101516000906001600160a01b03166139b6578160a0015167ffffffffffffffff164211156138a5575060016113b2565b81604001514710156138b9575060036113b2565b6138c28261490b565b61393757606082015160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d806000811461391d576040519150601f19603f3d011682016040523d82523d6000602084013e613922565b606091505b50509050806139355750600490506113b2565b505b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5982602001518360600151846040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060006113b2565b8160a0015167ffffffffffffffff164211156139d4575060016113b2565b81516020808401516001600160a01b031660009081526003909152604090205414613a01575060026113b2565b602080830151604080516370a0823160e01b815230600482015290516000936001600160a01b03909316926370a082319261c3509260248083019392829003018187803b158015613a5157600080fd5b5086fa158015613a65573d6000803e3d6000fd5b50505050506040513d6020811015613a7c57600080fd5b50516040840151909150811015613a975750600390506113b2565b613aa08361490b565b613b5757600083602001516001600160a01b031663a9059cbb61c350866060015187604001516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015613b1557600080fd5b5087f1158015613b29573d6000803e3d6000fd5b50505050506040513d6020811015613b4057600080fd5b5051905080613b555750600591506113b29050565b505b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5983602001518460600151856040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a150600090506113b2565b60006008821115613bfa5761343c836007198401600a0a63ffffffff61308216565b61228d836008849003600a0a63ffffffff6130c416565b60408051600480825260a08201909252606091829190816020015b6060815260200190600190039081613c2c5750508351909150613c4e90613de9565b81600081518110613c5b57fe5b6020026020010181905250613c738360200151613de9565b81600181518110613c8057fe5b6020026020010181905250613ca183604001516001600160a01b0316613dfc565b81600281518110613cae57fe5b6020026020010181905250613ccc836060015163ffffffff16613de9565b81600381518110613cd957fe5b602002602001018190525061126281613e1f565b60008183613d795760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613d3e578181015183820152602001613d26565b50505050905090810190601f168015613d6b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613d8557fe5b0495945050505050565b60008184841115613de15760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613d3e578181015183820152602001613d26565b505050900390565b6060612290613df783614a79565b614b5f565b60408051600560a21b831860148201526034810190915260609061126281614b5f565b6060815160001415613e4057506040805160008152602081019091526113b2565b606082600081518110613e4f57fe5b602002602001015190506000600190505b8351811015613e9057613e8682858381518110613e7957fe5b6020026020010151614bb1565b9150600101613e60565b50611262613ea3825160c060ff16614c2e565b82614bb1565b613eb16150cb565b6000613ebb6150cb565b613ec3615102565b613ecf6137598661475c565b90506000805b613ede836147cb565b156138655780613f0457613ef46137a4846147ec565b6001600160a01b0316845261406c565b8060011415613fa5576060613f20613f1b856147ec565b614d26565b90508051604051908082528060200260200182016040528015613f4d578160200160208202803683370190505b50602086015260005b8151811015613f9e57613f7b828281518110613f6e57fe5b602002602001015161483a565b86602001518281518110613f8b57fe5b6020908102919091010152600101613f56565b505061406c565b8060021415614047576060613fbc613f1b856147ec565b90508051604051908082528060200260200182016040528015613fe9578160200160208202803683370190505b50604086015260005b8151811015613f9e5761401782828151811061400a57fe5b60200260200101516148f1565b8660400151828151811061402757fe5b6001600160a01b0390921660209283029190910190910152600101613ff2565b80600314156138585761405c613783846147ec565b63ffffffff166060850152600191505b600101613ed5565b80516001600160a01b031661429e5760005b816020015151811015614298576000826040015182815181106140a557fe5b60200260200101516001600160a01b0316612710846020015184815181106140c957fe5b60209081029190910101516040516000818181858888f193505050503d8060008114614111576040519150601f19603f3d011682016040523d82523d6000602084013e614116565b606091505b50509050806141d9577f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061415557fe5b60200260200101518560200151858151811061416d57fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a161428f565b7fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a83600001518460400151848151811061420f57fe5b60200260200101518560200151858151811061422757fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101614086565b506144f5565b60005b8160200151518110156144f357600082600001516001600160a01b031663a9059cbb61c350856040015185815181106142d657fe5b6020026020010151866020015186815181106142ee57fe5b60200260200101516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b15801561434557600080fd5b5087f1158015614359573d6000803e3d6000fd5b50505050506040513d602081101561437057600080fd5b505190508015614434577fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a8360000151846040015184815181106143b057fe5b6020026020010151856020015185815181106143c857fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a16144ea565b7f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061446a57fe5b60200260200101518560200151858151811061448257fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b506001016142a1565b505b50565b614500615023565b600061450a615023565b614512615102565b61451e6137598661475c565b90506000805b61452d836147cb565b15613865578061454a57614543613783846147ec565b8452614754565b80600114156145725761455f6137a4846147ec565b6001600160a01b03166020850152614754565b8060021415614601576060614589613f1b856147ec565b905080516040519080825280602002602001820160405280156145b6578160200160208202803683370190505b50604086015260005b81518110156145fa576145d7828281518110613f6e57fe5b866040015182815181106145e757fe5b60209081029190910101526001016145bf565b5050614754565b8060031415614696576060614618613f1b856147ec565b90508051604051908082528060200260200182016040528015614645578160200160208202803683370190505b50606086015260005b81518110156145fa5761466682828151811061400a57fe5b8660600151828151811061467657fe5b6001600160a01b039092166020928302919091019091015260010161464e565b806004141561472b5760606146ad613f1b856147ec565b905080516040519080825280602002602001820160405280156146da578160200160208202803683370190505b50608086015260005b81518110156145fa576146fb82828151811061400a57fe5b8660800151828151811061470b57fe5b6001600160a01b03909216602092830291909101909101526001016146e3565b806005141561385857614740613783846147ec565b67ffffffffffffffff1660a0850152600191505b600101614524565b614764615122565b506040805180820190915281518152602082810190820152919050565b614789615102565b61479282614df7565b61479b57600080fd5b60006147aa8360200151614e31565b60208085015160408051808201909152868152920190820152915050919050565b60006147d5615122565b505080518051602091820151919092015191011190565b6147f4615122565b6147fd826147cb565b61480657600080fd5b6020820151600061481682614e94565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061484f57508151602110155b61485857600080fd5b60006148678360200151614e31565b905080836000015110156148c2576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b8251602080850151830180519284900392918310156148e857826020036101000a820491505b50949350505050565b805160009060151461490257600080fd5b6122908261483a565b600080805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8541580156149445750600554155b156149865760008052600660205269021e19e0c9bab24000007f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85561a8c06005555b6020808301516001600160a01b03166000908152600690915260409020548015806149b45750808360400151105b156149c35760009150506113b2565b6020808401516001600160a01b039081166000908152600783526040808220606088015190931682529190925290819020908401518154614a099163ffffffff61302816565b8155600554420160018201819055606085015160208087015160408089015181519081529283019490945283516001600160a01b039384169493909116927f3fb83143cd331170da18fb1e8564d97e8ec39264b6ecb1ba248ea7596ab07258928290030190a35060019392505050565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416614abd57506018614ae1565b6fffffffffffffffffffffffffffffffff198416614add57506010614ae1565b5060005b6020811015614b1757818181518110614af657fe5b01602001516001600160f81b03191615614b0f57614b17565b600101614ae1565b60008160200390506060816040519080825280601f01601f191660200182016040528015614b4c576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015614b915750607f60f81b82600081518110614b7f57fe5b01602001516001600160f81b03191611155b15614b9d5750806113b2565b612290614baf8351608060ff16614c2e565b835b6060806040519050835180825260208201818101602087015b81831015614be2578051835260209283019201614bca565b50855184518101855292509050808201602086015b81831015614c0f578051835260209283019201614bf7565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310614c7e576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b60408051600180825281830190925260609160208201818036833701905050905060378411614cd85782840160f81b81600081518110614cba57fe5b60200101906001600160f81b031916908160001a9053509050612290565b6060614ce385614a79565b90508381510160370160f81b82600081518110614cfc57fe5b60200101906001600160f81b031916908160001a905350614d1d8282614bb1565b95945050505050565b6060614d3182614df7565b614d3a57600080fd5b6000614d4583614fc7565b9050606081604051908082528060200260200182016040528015614d8357816020015b614d70615122565b815260200190600190039081614d685790505b5090506000614d958560200151614e31565b60208601510190506000805b84811015614dec57614db283614e94565b9150604051806040016040528083815260200184815250848281518110614dd557fe5b602090810291909101015291810191600101614da1565b509195945050505050565b8051600090614e08575060006113b2565b6020820151805160001a9060c0821015614e27576000925050506113b2565b5060019392505050565b8051600090811a6080811015614e4b5760009150506113b2565b60b8811080614e66575060c08110801590614e66575060f881105b15614e755760019150506113b2565b60c0811015614e895760b5190190506113b2565b60f5190190506113b2565b80516000908190811a6080811015614eaf5760019150614fc0565b60b8811015614ec457607e1981019150614fc0565b60c0811015614f3e57600060b78203600186019550806020036101000a865104915060018101820193505080831015614f38576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50614fc0565b60f8811015614f535760be1981019150614fc0565b600060f78203600186019550806020036101000a865104915060018101820193505080831015614fbe576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b8051600090614fd8575060006113b2565b60008090506000614fec8460200151614e31565b602085015185519181019250015b8082101561501a5761500b82614e94565b82019150826001019250614ffa565b50909392505050565b6040518060c001604052806000801916815260200160006001600160a01b03168152602001606081526020016060815260200160608152602001600067ffffffffffffffff1681525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806080016040528060006001600160a01b031681526020016060815260200160608152602001600063ffffffff1681525090565b6040518060400160405280615115615122565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe6f6e6c79207374616b696e672073797374656d20636f6e74726163742063616e2063616c6c20746869732066756e6374696f6e746865206d6573736167652073656e646572206d75737420626520696e63656e746976697a6520636f6e7472616374626e62206c61726765207472616e73666572206c696d697420746f6f20736d616c6c756e7265636f676e697a6564207472616e736665724f75742073796e207061636b61676565787069726554696d65206d7573742062652074776f206d696e75746573206c61746572616d6f756e7420697320746f6f206c617267652c20657863656564206d6178696d756d206265703220746f6b656e20616d6f756e74746865206d73672073656e646572206d75737420626520746f6b656e207265636f76657220706f7274616c4c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620726566756e644164647273696e76616c6964207472616e7366657220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374756e7265636f676e697a6564207472616e736665724f75742061636b207061636b6167654c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620616d6f756e7473746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d73672073656e646572206d75737420626520746f6b656e4d616e6167657274686520636f6e7472616374206e6f7420696e69742079657400000000000000726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e7366657220424e4220616d6f756e7420616e642072656c6179466565696e76616c696420726563656976656420424e4220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6ea164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(GovHubContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b506004361061021c5760003560e01c8063831d65d111610125578063ab51bb96116100ad578063df8079e91161007c578063df8079e914610615578063f1fad1041461061d578063f9a2bbc714610625578063fc3e59081461062d578063fd6a6879146106355761021c565b8063ab51bb9614610585578063c81b16621461058d578063c8509d8114610595578063dc927faf1461060d5761021c565b80639dc09262116100f45780639dc0926214610549578063a1a11bf514610551578063a78abc1614610559578063aa82dce114610575578063aad560631461057d5761021c565b8063831d65d1146103f857806388e4194e1461047257806396713da9146105395780639ab1a373146105415761021c565b80634bf6c882116101a857806370fd5bad1161017757806370fd5bad146103d0578063718a8aa8146103d857806375d47a0a146103e05780637942fd05146103e85780637e434d54146103f05761021c565b80634bf6c882146103b057806351b4dce3146103b857806351e80672146103c05780636e47b482146103c85761021c565b80633a21baae116101ef5780633a21baae1461035b5780633dffc3871461036357806343756e5c146103815780634900c4ea14610389578063493279b1146103915761021c565b80630bee7a67146102215780630e2374a5146102425780631182b875146102665780632808702814610353575b600080fd5b61022961063d565b6040805163ffffffff9092168252519081900360200190f35b61024a610642565b604080516001600160a01b039092168252519081900360200190f35b6102de6004803603604081101561027c57600080fd5b60ff8235169190810190604081016020820135600160201b8111156102a057600080fd5b8201836020820111156102b257600080fd5b803590602001918460018302840111600160201b831117156102d357600080fd5b509092509050610648565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610318578181015183820152602001610300565b50505050905090810190601f1680156103455780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61024a610737565b61022961073d565b61036b610742565b6040805160ff9092168252519081900360200190f35b61024a610747565b61036b61074d565b610399610752565b6040805161ffff9092168252519081900360200190f35b61036b610757565b61024a61075c565b61024a610762565b61024a610768565b61036b61076e565b61036b610773565b61024a610778565b61036b61077e565b61024a610783565b6104706004803603604081101561040e57600080fd5b60ff8235169190810190604081016020820135600160201b81111561043257600080fd5b82018360208201111561044457600080fd5b803590602001918460018302840111600160201b8311171561046557600080fd5b509092509050610789565b005b6104706004803603606081101561048857600080fd5b810190602081018135600160201b8111156104a257600080fd5b8201836020820111156104b457600080fd5b803590602001918460018302840111600160201b831117156104d557600080fd5b919390929091602081019035600160201b8111156104f257600080fd5b82018360208201111561050457600080fd5b803590602001918460018302840111600160201b8311171561052557600080fd5b9193509150356001600160a01b031661081b565b61036b610906565b61022961090b565b61024a610910565b61024a610916565b61056161091c565b604080519115158252519081900360200190f35b61024a610925565b61024a61092b565b61022961074d565b61024a610931565b610470600480360360408110156105ab57600080fd5b60ff8235169190810190604081016020820135600160201b8111156105cf57600080fd5b8201836020820111156105e157600080fd5b803590602001918460018302840111600160201b8311171561060257600080fd5b509092509050610937565b61024a6109ae565b61024a6109b4565b61036b6109ba565b61024a6109bf565b61036b6109c5565b61024a6109ca565b606481565b61200181565b6060336120001461068a5760405162461bcd60e51b815260040180806020018281038252602f81526020018061169d602f913960400191505060405180910390fd5b610692611638565b60006106d385858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109d092505050565b91509150806106ef576106e66064610a96565b92505050610730565b60006106fa83610b00565b905063ffffffff811661072157505060408051600081526020810190915291506107309050565b61072a81610a96565b93505050505b9392505050565b61200581565b606681565b600181565b61100181565b600081565b606181565b600881565b61200681565b61200081565b61100581565b600281565b601081565b61100881565b600b81565b61200381565b33612000146107c95760405162461bcd60e51b815260040180806020018281038252602f81526020018061169d602f913960400191505060405180910390fd5b6040805162461bcd60e51b815260206004820152601e60248201527f7265636569766520756e65787065637465642061636b207061636b6167650000604482015290519081900360640190fd5b505050565b336120061461085b5760405162461bcd60e51b81526004018080602001828103825260318152602001806116cc6031913960400191505060405180910390fd5b610863611638565b604051806060016040528087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f8801819004810282018101909252868152918101919087908790819084018382808284376000920191909152505050908252506001600160a01b03841660209091015290506108fd81610b00565b50505050505050565b600981565b606581565b61100781565b61100681565b60005460ff1681565b61200281565b61300081565b61100281565b33612000146109775760405162461bcd60e51b815260040180806020018281038252602f81526020018061169d602f913960400191505060405180910390fd5b60405162461bcd60e51b81526004018080602001828103825260238152602001806116fd6023913960400191505060405180910390fd5b61100381565b61200481565b601181565b61100081565b600381565b61100481565b6109d8611638565b60006109e2611638565b6109ea611662565b6109fb6109f686610ea1565b610ec6565b90506000805b610a0a83610f10565b15610a895780610a2c57610a25610a2084610f31565b610f7f565b8452610a81565b8060011415610a4b57610a41610a2084610f31565b6020850152610a81565b8060021415610a7c57610a65610a6084610f31565b610ff8565b6001600160a01b0316604085015260019150610a81565b610a89565b600101610a01565b5091935090915050915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081610ab0579050509050610ad68363ffffffff16611018565b81600081518110610ae357fe5b6020026020010181905250610af78161102b565b9150505b919050565b6000610b0f82604001516110b5565b610b7b57604080516020808252601c908201527f74686520746172676574206973206e6f74206120636f6e7472616374000000008183015290517f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb29181900360600190a1506065610afb565b81604001516001600160a01b031663ac431751836000015184602001516040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015610be8578181015183820152602001610bd0565b50505050905090810190601f168015610c155780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610c48578181015183820152602001610c30565b50505050905090810190601f168015610c755780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015610c9657600080fd5b505af1925050508015610ca7575060015b610e99576040516000815260443d1015610cc357506000610d60565b60046000803e60005160e01c6308c379a08114610ce4576000915050610d60565b60043d036004833e81513d602482011167ffffffffffffffff82111715610d1057600092505050610d60565b808301805167ffffffffffffffff811115610d32576000945050505050610d60565b8060208301013d8601811115610d5057600095505050505050610d60565b601f01601f191660405250925050505b80610d6b5750610e0e565b7f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2816040518080602001828103825283818151815260200191508051906020019080838360005b83811015610dca578181015183820152602001610db2565b50505050905090810190601f168015610df75780820380516001836020036101000a031916815260200191505b509250505060405180910390a16066915050610afb565b3d808015610e38576040519150601f19603f3d011682016040523d82523d6000602084013e610e3d565b606091505b5060408051602080825283518183015283517f1279f84165b4fd69c35e1f338ff107231b036c655cd1688851e011ce617c4e8d938593928392918301919085019080838360008315610dca578181015183820152602001610db2565b506000919050565b610ea9611682565b506040805180820190915281518152602082810190820152919050565b610ece611662565b610ed7826110bb565b610ee057600080fd5b6000610eef83602001516110f5565b60208085015160408051808201909152868152920190820152915050919050565b6000610f1a611682565b505080518051602091820151919092015191011190565b610f39611682565b610f4282610f10565b610f4b57600080fd5b60208201516000610f5b82611158565b80830160209586015260408051808201909152908152938401919091525090919050565b8051606090610f8d57600080fd5b6000610f9c83602001516110f5565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015610fd3576020820181803683370190505b5090506000816020019050610fef84876020015101828561128b565b50949350505050565b805160009060151461100957600080fd5b611012826112d6565b92915050565b60606110126110268361138b565b611471565b606081516000141561104c5750604080516000815260208101909152610afb565b60608260008151811061105b57fe5b602002602001015190506000600190505b835181101561109c576110928285838151811061108557fe5b60200260200101516114c3565b915060010161106c565b50610af76110af825160c060ff16611540565b826114c3565b3b151590565b80516000906110cc57506000610afb565b6020820151805160001a9060c08210156110eb57600092505050610afb565b5060019392505050565b8051600090811a608081101561110f576000915050610afb565b60b881108061112a575060c0811080159061112a575060f881105b15611139576001915050610afb565b60c081101561114d5760b519019050610afb565b60f519019050610afb565b80516000908190811a60808110156111735760019150611284565b60b881101561118857607e1981019150611284565b60c081101561120257600060b78203600186019550806020036101000a8651049150600181018201935050808310156111fc576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50611284565b60f88110156112175760be1981019150611284565b600060f78203600186019550806020036101000a865104915060018101820193505080831015611282576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b8061129557610816565b5b602081106112b5578251825260209283019290910190601f1901611296565b915181516020939093036101000a6000190180199091169216919091179052565b8051600090158015906112eb57508151602110155b6112f457600080fd5b600061130383602001516110f5565b9050808360000151101561135e576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015610fef57506020919091036101000a90049392505050565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166113cf575060186113f3565b6fffffffffffffffffffffffffffffffff1984166113ef575060106113f3565b5060005b60208110156114295781818151811061140857fe5b01602001516001600160f81b0319161561142157611429565b6001016113f3565b60008160200390506060816040519080825280601f01601f19166020018201604052801561145e576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156114a35750607f60f81b8260008151811061149157fe5b01602001516001600160f81b03191611155b156114af575080610afb565b6110126114c18351608060ff16611540565b835b6060806040519050835180825260208201818101602087015b818310156114f45780518352602092830192016114dc565b50855184518101855292509050808201602086015b81831015611521578051835260209283019201611509565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310611590576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116115ea5782840160f81b816000815181106115cc57fe5b60200101906001600160f81b031916908160001a9053509050611012565b60606115f58561138b565b90508381510160370160f81b8260008151811061160e57fe5b60200101906001600160f81b031916908160001a90535061162f82826114c3565b95945050505050565b6040518060600160405280606081526020016060815260200160006001600160a01b031681525090565b6040518060400160405280611675611682565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d73672073656e646572206d75737420626520676f7665726e6f722074696d656c6f636b20636f6e74726163747265636569766520756e6578706563746564206661696c2061636b207061636b616765a164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(CrossChainContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b50600436106103e65760003560e01c806374f079b81161020a578063c27cdcfb11610125578063df8079e9116100b8578063f1fad10411610087578063f1fad10414610bac578063f7a251d714610bb4578063f9a2bbc714610c2c578063fc3e590814610c34578063fd6a687914610c3c576103e6565b8063df8079e914610b74578063e1c7392a14610b7c578063e3b0480514610b84578063e6400bbe14610ba4576103e6565b8063d31f968d116100f4578063d31f968d14610b2d578063d76a867514610b5c578063dc40433114610b64578063dc927faf14610b6c576103e6565b8063c27cdcfb14610af5578063c780e9de14610b15578063c81b166214610b1d578063ccc108d714610b25576103e6565b80639dc092621161019d578063aad560631161016c578063aad5606314610a27578063ab51bb9614610a2f578063ac43175114610a37578063b0355f5b146107d6576103e6565b80639dc0926214610a07578063a1a11bf514610a0f578063a78abc1614610a17578063aa82dce114610a1f576103e6565b806384013b6a116101d957806384013b6a1461091c578063863fe4ab146109f75780638cc8f561146108e457806396713da9146109ff576103e6565b806374f079b8146108fc57806375d47a0a146109045780637942fd051461090c5780637e434d5414610914576103e6565b806343756e5c116103055780636a3cb34d116102985780636e47a51a116102675780636e47a51a146108bc5780636e47b482146108dc57806370fd5bad146108e4578063718a8aa8146108ec578063719482d5146108f4576103e6565b80636a3cb34d146108645780636bacff2c1461086c5780636c46aa68146108645780636de380bd146108b4576103e6565b806351e80672116102d457806351e806721461081e5780635692ddd3146108265780635f8321771461082e57806363e1394e1461085c576103e6565b806343756e5c146107fe578063493279b1146108065780634bf6c8821461080e57806351b4dce314610816576103e6565b8063299b533d1161037d5780633a648b151161034c5780633a648b15146106725780633bdc47a6146106ae5780633dffc387146107d6578063422f9050146107de576103e6565b8063299b533d146105f85780632af6f3991461062c5780632ff32aea14610649578063308325f41461066a576103e6565b80631d130935116103b95780631d130935146104685780631e275ae11461048457806322556cdc146105e857806328087028146105f0576103e6565b806305e68258146103eb5780630bee7a67146104095780630e2374a51461042a57806314b3023b1461044e575b600080fd5b6103f3610c44565b6040805160ff9092168252519081900360200190f35b610411610c49565b6040805163ffffffff9092168252519081900360200190f35b610432610c4e565b604080516001600160a01b039092168252519081900360200190f35b610456610c54565b60408051918252519081900360200190f35b610470610c5a565b604080519115158252519081900360200190f35b6105e6600480360361010081101561049b57600080fd5b81018160a081016080820135600160201b8111156104b857600080fd5b8201836020820111156104ca57600080fd5b803590602001918460018302840111600160201b831117156104eb57600080fd5b919390929091602081019035600160201b81111561050857600080fd5b82018360208201111561051a57600080fd5b803590602001918460018302840111600160201b8311171561053b57600080fd5b919390929091602081019035600160201b81111561055857600080fd5b82018360208201111561056a57600080fd5b803590602001918460018302840111600160201b8311171561058b57600080fd5b919390929091602081019035600160201b8111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111600160201b831117156105db57600080fd5b509092509050610c63565b005b610456611347565b61043261134c565b6106156004803603602081101561060e57600080fd5b5035611352565b6040805161ffff9092168252519081900360200190f35b6104706004803603602081101561064257600080fd5b5035611368565b61065161137d565b60408051600792830b90920b8252519081900360200190f35b610456611386565b6106926004803603602081101561068857600080fd5b503560ff1661138c565b604080516001600160401b039092168252519081900360200190f35b610761600480360360608110156106c457600080fd5b60ff82351691602081013591810190606081016040820135600160201b8111156106ed57600080fd5b8201836020820111156106ff57600080fd5b803590602001918460018302840111600160201b8311171561072057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506113a7945050505050565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561079b578181015183820152602001610783565b50505050905090810190601f1680156107c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103f361141d565b610470600480360360208110156107f457600080fd5b503560ff16611422565b610432611437565b61061561143d565b6103f3611442565b610432611447565b61043261144d565b610456611453565b6105e66004803603604081101561084457600080fd5b506001600160a01b0381358116916020013516611483565b6104566116e3565b61061561170b565b6108896004803603602081101561088257600080fd5b5035611710565b6040805161ffff90941684526001600160801b03909216602084015282820152519081900360600190f35b61045661173f565b610432600480360360208110156108d257600080fd5b503560ff16611766565b610432611781565b6103f361170b565b6103f3611787565b61061561141d565b61045661178c565b610432611792565b6103f3611798565b61043261179d565b6105e6600480360360a081101561093257600080fd5b810190602081018135600160201b81111561094c57600080fd5b82018360208201111561095e57600080fd5b803590602001918460018302840111600160201b8311171561097f57600080fd5b919390929091602081019035600160201b81111561099c57600080fd5b8201836020820111156109ae57600080fd5b803590602001918460018302840111600160201b831117156109cf57600080fd5b919350915080356001600160401b03908116916020810135909116906040013560ff166117a3565b610456612a5d565b6103f3612a65565b610432612a6a565b610432612a70565b610470612a76565b610432612a7f565b610432612a85565b610411610c44565b6105e660048036036040811015610a4d57600080fd5b810190602081018135600160201b811115610a6757600080fd5b820183602082011115610a7957600080fd5b803590602001918460018302840111600160201b83111715610a9a57600080fd5b919390929091602081019035600160201b811115610ab757600080fd5b820183602082011115610ac957600080fd5b803590602001918460018302840111600160201b83111715610aea57600080fd5b509092509050612a8b565b61069260048036036020811015610b0b57600080fd5b503560ff1661354f565b61045661356a565b61043261358e565b6105e6613594565b61047060048036036040811015610b4357600080fd5b5080356001600160a01b0316906020013560ff166137e8565b610761613808565b610456613827565b61043261382d565b610432613833565b6105e6613839565b61069260048036036020811015610b9a57600080fd5b503560ff16613bf0565b6105e6613c0b565b6103f3613e2a565b6105e660048036036060811015610bca57600080fd5b60ff8235169190810190604081016020820135600160201b811115610bee57600080fd5b820183602082011115610c0057600080fd5b803590602001918460018302840111600160201b83111715610c2157600080fd5b919350915035613e2f565b610432613f72565b6103f3613f78565b610432613f7d565b600081565b606481565b61200181565b60015481565b600b5460ff1681565b60005460ff16610ca8576040805162461bcd60e51b81526020600482015260196024820152600080516020614a60833981519152604482015290519081900360640190fd5b604080516337d7f9c160e21b81526001600160401b038b35166004820181905291516110039163df5fe704916024808301926020929190829003018186803b158015610cf357600080fd5b505afa158015610d07573d6000803e3d6000fd5b505050506040513d6020811015610d1d57600080fd5b5051610d5a5760405162461bcd60e51b8152600401808060200182810382526023815260200180614a806023913960400191505060405180910390fd5b604080516337d7f9c160e21b815260208c8101356001600160401b03166004830181905292516110039263df5fe704926024808301939192829003018186803b158015610da657600080fd5b505afa158015610dba573d6000803e3d6000fd5b505050506040513d6020811015610dd057600080fd5b5051610e0d5760405162461bcd60e51b8152600401808060200182810382526023815260200180614a806023913960400191505060405180910390fd5b60608b013560ff81166000908152600560205260409020546001600160401b03909116906001600160a01b0316610e86576040805162461bcd60e51b815260206004820152601860248201527718da185b9b995b081a5cc81b9bdd081cdd5c1c1bdc9d195960421b604482015290519081900360640190fd5b600b5460ff1615610eca576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b8888604051808383808284376040519201829003822094508f93508e9250819050838380828437808301925050509250505060405180910390201415610f46576040805162461bcd60e51b815260206004820152600c60248201526b1cd85b59481c185e5b1bd85960a21b604482015290519081900360640190fd5b60606001600160401b0360408e01358116908e83013516610f678282613f83565b80516020808301919091206000818152600e9092526040909120549194509060ff1615610fd0576040805162461bcd60e51b8152602060048201526012602482015271185b1c9958591e4818da185b1b195b99d95960721b604482015290519081900360640190fd5b6000908152600e60205260408120805460ff191660011790558f8160200201356001600160401b0316905060608f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060608c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805163cba510a960e01b81526001600160401b038a16600482015290519596509094611003945063cba510a9935060248083019350602092829003018186803b1580156110c657600080fd5b505afa1580156110da573d6000803e3d6000fd5b505050506040513d60208110156110f057600080fd5b505160408051808201909152600381526269626360e81b602082015290915061111d908290898686613fcb565b611166576040805162461bcd60e51b81526020600482015260156024820152740696e76616c6964206d65726b6c652070726f6f663605c1b604482015290519081900360640190fd5b5050505060008f60016004811061117957fe5b60200201356001600160401b0316905060608d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815293945060609392508d91508c908190840183828082843760009201829052506040805163cba510a960e01b81526001600160401b038a16600482015290519596509094611003945063cba510a9935060248083019350602092829003018186803b15801561124557600080fd5b505afa158015611259573d6000803e3d6000fd5b505050506040513d602081101561126f57600080fd5b505160408051808201909152600381526269626360e81b602082015290915061129c908290898686613fcb565b6112e5576040805162461bcd60e51b8152602060048201526015602482015274696e76616c6964206d65726b6c652070726f6f663160581b604482015290519081900360640190fd5b505050506112f16140c8565b604080516001600160401b038416815260ff83166020820152815133927f039eb91179ffd7d3b6e97f8ea106e748e827f910b872375dbc9c14a362319c3c928290030190a2505050505050505050505050505050565b603281565b61200581565b600d6020526000908152604090205461ffff1681565b600e6020526000908152604090205460ff1681565b60045460070b81565b60025481565b600a602052600090815260409020546001600160401b031681565b60606000825160210190506060816040519080825280601f01601f1916602001820160405280156113df576020820181803683370190505b506021810186905260018101879052828152905060418101600061140286614146565b50905061141181838851614150565b50909695505050505050565b600181565b60096020526000908152604090205460ff1681565b61100181565b606181565b600881565b61200681565b61200081565b604080517710d05390d15317d514905394d1915497d41493d413d4d05360421b8152905190819003601801902081565b60005460ff166114c8576040805162461bcd60e51b81526020600482015260196024820152600080516020614a60833981519152604482015290519081900360640190fd5b6040805163569e4ed360e11b815233600482015290516000916110009163ad3c9da691602480820192602092909190829003018186803b15801561150b57600080fd5b505afa15801561151f573d6000803e3d6000fd5b505050506040513d602081101561153557600080fd5b505160408051633d42651560e11b8152905191925060009161100091637a84ca2a916004808301926020929190829003018186803b15801561157657600080fd5b505afa15801561158a573d6000803e3d6000fd5b505050506040513d60208110156115a057600080fd5b50519050806115ad575060155b6000821180156115bd5750808211155b6115fc576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd0818d8589a5b995d60aa1b604482015290519081900360640190fd5b604080516001600160a01b038087166020808401919091529086168284015282518083038401815260608301808552815191909201207710d05390d15317d514905394d1915497d41493d413d4d05360421b90915291519081900360780190206000906116699083614191565b905080156116db5760408051630911a2c160e11b81526001600160a01b03888116600483015287166024820152905161100491631223458291604480830192600092919082900301818387803b1580156116c257600080fd5b505af11580156116d6573d6000803e3d6000fd5b505050505b505050505050565b604080516f14d554d411539117d41493d413d4d05360821b8152905190819003601001902081565b600281565b600c602052600090815260409020805460019091015461ffff8216916201000090046001600160801b03169083565b604080516e149153d4115397d41493d413d4d053608a1b8152905190819003600f01902081565b6005602052600090815260409020546001600160a01b031681565b61100581565b601081565b60035481565b61100881565b600b81565b61200381565b60005460ff166117e8576040805162461bcd60e51b81526020600482015260196024820152600080516020614a60833981519152604482015290519081900360640190fd5b60408051630a83aaa960e31b815233600482015290516110069163541d5548916024808301926020929190829003018186803b15801561182757600080fd5b505afa15801561183b573d6000803e3d6000fd5b505050506040513d602081101561185157600080fd5b50516118a4576040805162461bcd60e51b815260206004820152601f60248201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604482015290519081900360640190fd5b60ff8116600090815260086020526040902054829082906001600160401b039081169083168114611914576040805162461bcd60e51b815260206004820152601560248201527439b2b8bab2b731b2903737ba1034b71037b93232b960591b604482015290519081900360640190fd5b60ff8216600090815260086020908152604091829020805467ffffffffffffffff1916600185016001600160401b039081169190911790915582516337d7f9c160e21b81529089166004820152915188926110039263df5fe70492602480840193829003018186803b15801561198957600080fd5b505afa15801561199d573d6000803e3d6000fd5b505050506040513d60208110156119b357600080fd5b50516119f05760405162461bcd60e51b8152600401808060200182810382526023815260200180614a806023913960400191505060405180910390fd5b60ff851660009081526005602052604090205485906001600160a01b0316611a5a576040805162461bcd60e51b815260206004820152601860248201527718da185b9b995b081a5cc81b9bdd081cdd5c1c1bdc9d195960421b604482015290519081900360640190fd5b60ff86166000908152600a6020526040902054889087906001600160401b039081169083161015611ac3576040805162461bcd60e51b815260206004820152600e60248201526d3a37b79037b632103432b0b232b960911b604482015290519081900360640190fd5b60ff81166000908152600a60205260409020546001600160401b03838116911614611b155760ff81166000908152600a60205260409020805467ffffffffffffffff19166001600160401b0384161790555b600b5460ff1615611b59576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b60608e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060608d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509050611c9d6110036001600160a01b031663cba510a98e6040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060206040518083038186803b158015611c4657600080fd5b505afa158015611c5a573d6000803e3d6000fd5b505050506040513d6020811015611c7057600080fd5b505160408051808201909152600381526269626360e81b6020820152611c968e8e613f83565b8585613fcb565b611ce5576040805162461bcd60e51b815260206004820152601460248201527334b73b30b634b21036b2b935b63290383937b7b360611b604482015290519081900360640190fd5b60408051631bb5062960e31b81526001600160401b038e16600482015290516000916110039163dda8314891602480820192602092909190829003018186803b158015611d3157600080fd5b505afa158015611d45573d6000803e3d6000fd5b505050506040513d6020811015611d5b57600080fd5b505190508b8b600080806060611d7089614476565b935093509350935083611e32578460ff16866001600160401b03167ff7b2e42d694eb1100184aae86d4245d9e46966100b1dc7e723275b98326854ac8b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611dea578181015183820152602001611dd2565b50505050905090810190601f168015611e175780820380516001836020036101000a031916815260200191505b509250505060405180910390a3505050505050505050612a4d565b6040805160ff85811682529151918716916001600160401b038916917f36afdaf439a8f43fe72135135d804ae620b37a474f0943b5b85f6788312cad40919081900360200190a360ff83166123b75760ff85166000818152600560209081526040808320548151631182b87560e01b815260048101958652602481019283528651604482015286516001600160a01b03909216958695631182b875958d958a9593949093606490910192918601918190849084905b83811015611eff578181015183820152602001611ee7565b50505050905090810190601f168015611f2c5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611f4c57600080fd5b505af192505050801561203057506040513d6000823e601f3d908101601f191682016040526020811015611f7f57600080fd5b8101908080516040519392919084600160201b821115611f9e57600080fd5b908301906020820185811115611fb357600080fd5b8251600160201b811182820188101715611fcc57600080fd5b82525081516020918201929091019080838360005b83811015611ff9578181015183820152602001611fe1565b50505050905090810190601f1680156120265780820380516001836020036101000a031916815260200191505b5060405250505060015b612342576040516000815260443d101561204c575060006120e7565b60046000803e60005160e01c6308c379a0811461206d5760009150506120e7565b60043d036004833e81513d60248201116001600160401b0382111715612098576000925050506120e7565b80830180516001600160401b038111156120b95760009450505050506120e7565b8060208301013d86018111156120d7576000955050505050506120e7565b601f01601f191660405250925050505b806120f25750612204565b60ff8716600090815260076020526040812054612129916001600160401b0390911690899061212490600290886113a7565b614526565b60ff8716600090815260076020908152604080832080546001600160401b038082166001011667ffffffffffffffff19909116179055805182815284518184015284516001600160a01b038716947ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf948794849390840192918601918190849084905b838110156121c45781810151838201526020016121ac565b50505050905090810190601f1680156121f15780820380516001836020036101000a031916815260200191505b509250505060405180910390a25061233d565b3d80801561222e576040519150601f19603f3d011682016040523d82523d6000602084013e612233565b606091505b5060ff8716600090815260076020526040812054612266916001600160401b0390911690899061212490600290886113a7565b60ff8716600090815260076020908152604080832080546001600160401b038082166001011667ffffffffffffffff19909116179055805182815284518184015284516001600160a01b038716947f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351948794849390840192918601918190849084905b838110156123015781810151838201526020016122e9565b50505050905090810190601f16801561232e5780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b6123b1565b8051156123af5760ff871660009081526007602052604081205461237b916001600160401b0390911690899061212490600190866113a7565b60ff8716600090815260076020526040902080546001600160401b038082166001011667ffffffffffffffff199091161790555b505b50612985565b60ff83166001141561265b5760ff8516600081815260056020908152604080832054815163831d65d160e01b815260048101958652602481019283528651604482015286516001600160a01b0390921695869563831d65d1958d958a9593949093606490910192918601918190849084905b83811015612441578181015183820152602001612429565b50505050905090810190601f16801561246e5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561248e57600080fd5b505af192505050801561249f575060015b6123b1576040516000815260443d10156124bb57506000612556565b60046000803e60005160e01c6308c379a081146124dc576000915050612556565b60043d036004833e81513d60248201116001600160401b038211171561250757600092505050612556565b80830180516001600160401b03811115612528576000945050505050612556565b8060208301013d860181111561254657600095505050505050612556565b601f01601f191660405250925050505b8061256157506125c6565b60408051602080825283518183015283516001600160a01b038616937ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf93869390928392830191850190808383600083156121c45781810151838201526020016121ac565b3d8080156125f0576040519150601f19603f3d011682016040523d82523d6000602084013e6125f5565b606091505b5060408051602080825283518183015283516001600160a01b038616937f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd297735193869390928392830191850190808383600083156123015781810151838201526020016122e9565b60ff8316600214156129855760ff8516600081815260056020908152604080832054815163c8509d8160e01b815260048101958652602481019283528651604482015286516001600160a01b0390921695869563c8509d81958d958a9593949093606490910192918601918190849084905b838110156126e55781810151838201526020016126cd565b50505050905090810190601f1680156127125780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561273257600080fd5b505af1925050508015612743575060015b612983576040516000815260443d101561275f575060006127fa565b60046000803e60005160e01c6308c379a081146127805760009150506127fa565b60043d036004833e81513d60248201116001600160401b03821117156127ab576000925050506127fa565b80830180516001600160401b038111156127cc5760009450505050506127fa565b8060208301013d86018111156127ea576000955050505050506127fa565b601f01601f191660405250925050505b8061280557506128ae565b816001600160a01b03167ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf826040518080602001828103825283818151815260200191508051906020019080838360005b8381101561286e578181015183820152602001612856565b50505050905090810190601f16801561289b5780820380516001836020036101000a031916815260200191505b509250505060405180910390a250612983565b3d8080156128d8576040519150601f19603f3d011682016040523d82523d6000602084013e6128dd565b606091505b50816001600160a01b03167f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351826040518080602001828103825283818151815260200191508051906020019080838360005b8381101561294757818101518382015260200161292f565b50505050905090810190601f1680156129745780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b505b60ff80861660009081526009602052604090205461100591636f93d2e6918a913391879116806129b7575060ff881615155b604080516001600160e01b031960e088901b1681526001600160a01b039586166004820152939094166024840152604483019190915215156064820152905160848083019260209291908290030181600087803b158015612a1757600080fd5b505af1158015612a2b573d6000803e3d6000fd5b505050506040513d6020811015612a4157600080fd5b50505050505050505050505b5050505050505050505050505050565b630100610081565b600981565b61100781565b61100681565b60005460ff1681565b61200281565b61300081565b3361100714612acb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806149b6602e913960400191505060405180910390fd5b600b5460ff1615612b0f576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b612b7884848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526012815271626174636853697a65466f724f7261636c6560701b602082015291506146c09050565b15612c1357604080516020601f8401819004810282018101909252828152600091612bbb918585808385018382808284376000920191909152506147a792505050565b90506127108111158015612bd05750600a8110155b612c0b5760405162461bcd60e51b8152600401808060200182810382526032815260200180614a2e6032913960400191505060405180910390fd5b6001556134bd565b612c7c84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601281527118591913dc955c19185d1950da185b9b995b60721b602082015291506146c09050565b15612e0457606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060169091149050612cff5760405162461bcd60e51b815260040180806020018281038252605a8152602001806148cf605a913960600191505060405180910390fd5b60018101516002820151601683015160ff82161590612d1d816147ac565b612d6e576040805162461bcd60e51b815260206004820152601960248201527f61646472657373206973206e6f74206120636f6e747261637400000000000000604482015290519081900360640190fd5b60ff8416600081815260056020908152604080832080546001600160a01b0319166001600160a01b038716908117909155808452600683528184208585528352818420805460ff199081166001179091556009909352818420805490931687151517909255519092917f7e3b6af43092577ee20e60eaa1d9b114a7031305c895ee7dd3ffe17196d2e1e091a350505050506134bd565b612e7184848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526016815275195b98589b1953dc911a5cd8589b1950da185b9b995b60521b602082015291506146c09050565b15612fa257606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060029091149050612ef45760405162461bcd60e51b815260040180806020018281038252604a8152602001806149e4604a913960600191505060405180910390fd5b600181810151600283015160ff80831660009081526005602052604090205492939192908316909114906001600160a01b03168015612f98576001600160a01b038116600090815260066020908152604080832060ff881680855290835292819020805460ff1916861515908117909155815190815290517fa3132e3f9819fbddc7f0ed6d38d7feef59aa95112090b7c592f5cb5bc4aa4adc929181900390910190a25b50505050506134bd565b61300684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c73757370656e6451756f72756d60981b602082015291506146c09050565b1561313b576002811461304a5760405162461bcd60e51b815260040180806020018281038252602d81526020018061495d602d913960400191505060405180910390fd5b600061308d600284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147a792505050565b905060008161ffff161180156130a7575060648161ffff16105b6130f1576040805162461bcd60e51b8152602060048201526016602482015275696e76616c69642073757370656e642071756f72756d60501b604482015290519081900360640190fd5b604080516f14d554d411539117d41493d413d4d05360821b815281519081900360100190206000908152600d60205220805461ffff90921661ffff199092169190911790556134bd565b61319e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600c81526b72656f70656e51756f72756d60a01b602082015291506146c09050565b156132d157600281146131e25760405162461bcd60e51b815260040180806020018281038252602c81526020018061498a602c913960400191505060405180910390fd5b6000613225600284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147a792505050565b905060008161ffff1611801561323f575060648161ffff16105b613288576040805162461bcd60e51b8152602060048201526015602482015274696e76616c69642072656f70656e2071756f72756d60581b604482015290519081900360640190fd5b604080516e149153d4115397d41493d413d4d053608a1b8152815190819003600f0190206000908152600d60205220805461ffff90921661ffff199092169190911790556134bd565b61333c84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601481527363616e63656c5472616e7366657251756f72756d60601b602082015291506146c09050565b1561348057600281146133805760405162461bcd60e51b81526004018080602001828103825260348152602001806149296034913960400191505060405180910390fd5b60006133c3600284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147a792505050565b905060008161ffff161180156133dd575060648161ffff16105b61342e576040805162461bcd60e51b815260206004820152601e60248201527f696e76616c69642063616e63656c207472616e736665722071756f72756d0000604482015290519081900360640190fd5b604080517710d05390d15317d514905394d1915497d41493d413d4d05360421b815281519081900360180190206000908152600d60205220805461ffff90921661ffff199092169190911790556134bd565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b6008602052600090815260409020546001600160401b031681565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081565b61100281565b60005460ff166135d9576040805162461bcd60e51b81526020600482015260196024820152600080516020614a60833981519152604482015290519081900360640190fd5b6040805163569e4ed360e11b815233600482015290516000916110009163ad3c9da691602480820192602092909190829003018186803b15801561361c57600080fd5b505afa158015613630573d6000803e3d6000fd5b505050506040513d602081101561364657600080fd5b505160408051633d42651560e11b8152905191925060009161100091637a84ca2a916004808301926020929190829003018186803b15801561368757600080fd5b505afa15801561369b573d6000803e3d6000fd5b505050506040513d60208110156136b157600080fd5b50519050806136be575060155b6000821180156136ce5750808211155b61370d576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd0818d8589a5b995d60aa1b604482015290519081900360640190fd5b600b5460ff16613754576040805162461bcd60e51b815260206004820152600d60248201526c1b9bdd081cdd5cdc195b991959609a1b604482015290519081900360640190fd5b604080516e149153d4115397d41493d413d4d053608a1b8152905190819003600f0190206000906137a5907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470614191565b905080156137e357600b805460ff1916905560405133907f899fe8c37dc61708a3aaa99c4bf143346c1d1da69af79be9e8920c0a6785b75290600090a25b505050565b600660209081526000928352604080842090915290825290205460ff1681565b6040518060400160405280600381526020016269626360e81b81525081565b610e1081565b61100381565b61200481565b60005460ff1615613891576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b7f1471eb6eb2c5e789fc3de43f8ce62938c7d1836ec861730447e2ada8fd81017b80546001600160a01b0319908116611008179091557f92e85d02570a8092d09a6e3a57665bc3815a2699a4074001bf1ccabf660f5a36805460ff199081169091557fd8af288fc1c8680b4f4706064cf021e264efb6828fcaf7eb5ca36818eb365bcc8054821660019081179091557f89832631fb3c3307a103ba2c84ab569c64d6182a18893dcd163f0f1c2090733a805484166110049081179091557f6cde3cea4b3a3fb2488b2808bae7556f4a405e50f65e1794383bc026131b13c38054841690557f72e4efa1513b071517c6c74dba31b5934a81aa83cddd400e7081df5529c9943680548416831790557fa9bc9a3a348c357ba16b37005d7e6b3236198c0e939f4af8c5f19b8deeb8ebc08054851690911790557fc575c31fea594a6eb97c8e9d3f9caee4c16218c6ef37e923234c0fe9014a61e78054831690557f4e523af77f034e9810f1c94057f5e931fb3d16a51511a4c3add793617d18610580548316821790557ffb33122aa9f93cc639ebe80a7bc4784c11e6053dde89c6f4f7e268c6a623da1e805484166110001790557fc7694af312c4f286114180fd0ba6a52461fcee8a381636770b19a343af92538a80548316821790557f01112dd68e482ba8d68a7e828cff8b3abcea08eab88941953c180a7e650e9cd480548316821790557fc0a4a8be475dfebc377ebef2d7c4ff47656f572a08dd92b81017efcdba0febe1805484166110071790557f87e8a52529e8ece4ef759037313542a6429ff494a9fab9027fb79db90124eba680548316821790557f4c7666bbcb22d46469f7cc282f70764a7012dca2cce630ff8d83db9a9cdd48f080548316821790557f40f28f99a40bc9f6beea1013afdbc3cdcc689eb76b82c4de06c0acf1e1932ed58054909316611001179092557f0d9cf2cd531699eed8dd34e40ff2884a14a698c4898184fba85194e6f6772d248054821683179055600b60009081527f23f68c9bd22b8a93d06adabe17481c87c016bcbd20adc8bfd707a4d813a572176020527fdf0d5d05428057f5455c2dc8e810dd86d1e9350faa72f16bda8a45443c5b39328054831684179055603283556004805467ffffffffffffffff19166001600160401b031790556002819055600381905580549091169091179055565b6007602052600090815260409020546001600160401b031681565b60005460ff16613c50576040805162461bcd60e51b81526020600482015260196024820152600080516020614a60833981519152604482015290519081900360640190fd5b6040805163569e4ed360e11b815233600482015290516000916110009163ad3c9da691602480820192602092909190829003018186803b158015613c9357600080fd5b505afa158015613ca7573d6000803e3d6000fd5b505050506040513d6020811015613cbd57600080fd5b505160408051633d42651560e11b8152905191925060009161100091637a84ca2a916004808301926020929190829003018186803b158015613cfe57600080fd5b505afa158015613d12573d6000803e3d6000fd5b505050506040513d6020811015613d2857600080fd5b5051905080613d35575060155b600082118015613d455750808211155b613d84576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd0818d8589a5b995d60aa1b604482015290519081900360640190fd5b600b5460ff1615613dc8576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b604080516f14d554d411539117d41493d413d4d05360821b81529051908190036010019020600090613e1a907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470614191565b905080156137e3576137e36140c8565b601181565b60005460ff16613e74576040805162461bcd60e51b81526020600482015260196024820152600080516020614a60833981519152604482015290519081900360640190fd5b33600090815260066020908152604080832060ff8089168552925290912054859116613ed15760405162461bcd60e51b815260040180806020018281038252603181526020018061489e6031913960400191505060405180910390fd5b60ff85166000908152600760209081526040808320548151601f88018490048402810184019092528682526001600160401b031692613f369284928a9261212492909189918c908c90819084018382808284376000920191909152506113a792505050565b60ff959095166000908152600760205260409020805467ffffffffffffffff191660019096016001600160401b03169590951790945550505050565b61100081565b600381565b61100481565b60408051600e808252818301909252606091630100610060ff851617918391602082018180368337505050600e81810187905260068201939093529182525090505b92915050565b600085613fda575060006140bf565b606082518451865160800101016040519080825280601f01601f191660200182016040528015614011576020820181803683370190505b509050600061401f826147b2565b60208089015182520190508660008061403789614146565b8086526020909501949092509050614050828583614150565b9283019261405d88614146565b8086526020909501949092509050614076828583614150565b9283018a81526020019261408987614146565b9092509050614099828583614150565b5083516020016140a76147b8565b60208183886065600019fa5051600114955050505050505b95945050505050565b600b5460ff161561410c576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b600b805460ff1916600117905560405133907f6f123d3d54c84a7960a573b31c221dcd86e13fd849c5adb0c6ca851468cc1ae490600090a2565b8051602090910191565b5b60208110614170578251825260209283019290910190601f1901614151565b915181516020939093036101000a6000190180199091169216919091179052565b6000828152600d602052604081205461ffff1661425a57604080516f14d554d411539117d41493d413d4d05360821b815281519081900360100181206000908152600d6020818152848320805461ffff199081166001179091556e149153d4115397d41493d413d4d053608a1b8552855194859003600f01852084528282528584208054821660029081179091557710d05390d15317d514905394d1915497d41493d413d4d05360421b8652865195869003601801909520845291905292902080549092161790555b6000838152600c6020526040902080546201000090046001600160801b03164210158061428b575082816001015414155b1561435e576000848152600d602090815260409182902054835461ffff90911661ffff199091161771ffffffffffffffffffffffffffffffff0000191662010000610e1042016001600160801b03160217835560018084018690558251918201909252338152614300916002840191906147d6565b5080546040805161ffff83168152620100009092046001600160801b0316602083015281810185905251339186917f9e109f0e55ef32e99e4880be2ec357f1ddb3469c79d0747ef4762da6e89fabe5916060908290030190a3614412565b60005b60028201548110156143e957336001600160a01b031682600201828154811061438657fe5b6000918252602090912001546001600160a01b031614156143e1576040805162461bcd60e51b815260206004820152601060248201526f185b1c9958591e48185c1c1c9bdd995960821b604482015290519081900360640190fd5b600101614361565b50600281018054600181018255600091825260209091200180546001600160a01b031916331790555b8054600282015461ffff9091161161446c576000848152600c60205260408120805471ffffffffffffffffffffffffffffffffffff191681556001810182905590614460600283018261483b565b50506001915050613fc5565b5060009392505050565b600080600060606021855110156144a657505060408051600080825260208201909252909250829150819061451f565b600185015160218601518651604080516020198301808252601f19600119909401939093168101602001909152604189019392916060919080156144f1576020820181803683370190505b50905060006144ff82614146565b509050614511858260218d5103614150565b506001975091955093509150505b9193509193565b600b5460ff161561456a576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b6002544311156145a9576004805467ffffffffffffffff1981166001600160401b036001600793840b810190930b1617909155600355436002556145ea565b600380546001908101918290555410156145ea576004805467ffffffffffffffff1981166001600160401b036001600793840b810190930b16179091556003555b8160ff16836001600160401b0316600460009054906101000a900460070b6001600160401b03167f3a6e0fc61675aa2a100bcba0568368bb92bcec91c97673391074f11138f0cffe606185604051808361ffff1661ffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614680578181015183820152602001614668565b50505050905090810190601f1680156146ad5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a4505050565b6000816040516020018082805190602001908083835b602083106146f55780518252601f1990920191602091820191016146d6565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106147635780518252601f199092019160209182019101614744565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b3b151590565b60200190565b60405180602001604052806001906020820280368337509192915050565b82805482825590600052602060002090810192821561482b579160200282015b8281111561482b57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906147f6565b5061483792915061485c565b5090565b50805460008255906000526020600020908101906148599190614883565b50565b61488091905b808211156148375780546001600160a01b0319168155600101614862565b90565b61488091905b80821115614837576000815560010161488956fe74686520636f6e747261637420616e64206368616e6e656c2068617665206e6f74206265656e20726567697374657265646c656e677468206f662076616c756520666f72206164644f725570646174654368616e6e656c2073686f756c642062652032322c206368616e6e656c49643a697346726f6d53797374656d3a68616e646c6572416464726573736c656e677468206f662076616c756520666f722063616e63656c5472616e7366657251756f72756d2073686f756c6420626520326c656e677468206f662076616c756520666f722073757370656e6451756f72756d2073686f756c6420626520326c656e677468206f662076616c756520666f722072656f70656e51756f72756d2073686f756c642062652032746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662076616c756520666f7220656e61626c654f7244697361626c654368616e6e656c2073686f756c6420626520322c206368616e6e656c49643a6973456e61626c65746865206e6577426174636853697a65466f724f7261636c652073686f756c6420626520696e205b31302c2031303030305d74686520636f6e7472616374206e6f7420696e697420796574000000000000006c6967687420636c69656e74206e6f742073796e632074686520626c6f636b20796574a164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(StakingContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106103d25760003560e01c8063718a8aa8116101fd578063b88a802f11610118578063dc927faf116100ab578063f45fd80b1161007a578063f45fd80b14610cdb578063f9a2bbc714610d20578063fa03f79714610d35578063fc3e5908146106d3578063fd6a687914610d4a576103d9565b8063dc927faf14610c87578063df8079e914610c9c578063edc1a5b014610cb1578063f1fad10414610cc6576103d9565b8063c81b1662116100e7578063c81b166214610bb2578063c8509d8114610bc7578063d61b9b9314610c4c578063d7ecfcb614610890576103d9565b8063b88a802f14610b38578063baaafd3b14610b4d578063bf8546ca14610b62578063c2117d8214610b9d576103d9565b80639dc0926211610190578063aad560631161015f578063aad5606314610a2e578063ab51bb9614610a43578063ac43175114610a58578063b14315df14610b23576103d9565b80639dc09262146109c6578063a1a11bf5146109db578063a78abc16146109f0578063aa82dce114610a19576103d9565b80637e434d54116101cc5780637e434d5414610917578063831d65d11461092c57806392b888a41461066a57806396713da9146109b1576103d9565b8063718a8aa8146108a557806375aca593146108ba57806375d47a0a146108ed5780637942fd0514610902576103d9565b8063413d9c3a116102ed5780635d17c8bd116102805780636bd8f8041161024f5780636bd8f804146108125780636e47b482146108485780636fb7f7eb1461085d57806370fd5bad14610890576103d9565b80635d17c8bd146107be5780635d499b1b146107d357806362b171d2146107e857806369b635b6146107fd576103d9565b80634d99dd16116102bc5780634d99dd161461075357806351b4dce31461077f57806351e8067214610794578063552aaf93146107a9576103d9565b8063413d9c3a146106e857806343756e5c146106fd578063493279b1146107125780634bf6c8821461073e576103d9565b8063151817e311610365578063333ad3e711610334578063333ad3e7146106a957806334c43354146106be5780633dffc3871461066a5780633fdfa7e4146106d3576103d9565b8063151817e31461063f57806317c9efb01461066a578063280870281461067f5780632fdeb11114610694576103d9565b80630c795715116103a15780630c795715146104cc5780630e2374a5146104e15780631182b8751461051257806311fe9ec61461060c576103d9565b8063026e402b146103de578063029859921461040c578063047636d1146104335780630bee7a671461049e576103d9565b366103d957005b600080fd5b61040a600480360360408110156103f457600080fd5b506001600160a01b038135169060200135610d5f565b005b34801561041857600080fd5b50610421610d9c565b60408051918252519081900360200190f35b34801561043f57600080fd5b506104666004803603602081101561045657600080fd5b50356001600160a01b0316610da2565b6040518082606080838360005b8381101561048b578181015183820152602001610473565b5050505090500191505060405180910390f35b3480156104aa57600080fd5b506104b3610df6565b6040805163ffffffff9092168252519081900360200190f35b3480156104d857600080fd5b50610421610dfb565b3480156104ed57600080fd5b506104f6610e01565b604080516001600160a01b039092168252519081900360200190f35b34801561051e57600080fd5b506105976004803603604081101561053557600080fd5b60ff8235169190810190604081016020820135600160201b81111561055957600080fd5b82018360208201111561056b57600080fd5b803590602001918460018302840111600160201b8311171561058c57600080fd5b509092509050610e07565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105d15781810151838201526020016105b9565b50505050905090810190601f1680156105fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561061857600080fd5b506104216004803603602081101561062f57600080fd5b50356001600160a01b0316610fc3565b34801561064b57600080fd5b50610654610fde565b6040805160ff9092168252519081900360200190f35b34801561067657600080fd5b50610654610fe3565b34801561068b57600080fd5b506104f6610fe8565b3480156106a057600080fd5b50610421610fee565b3480156106b557600080fd5b506104b3610ff4565b3480156106ca57600080fd5b50610421610ff9565b3480156106df57600080fd5b50610654611004565b3480156106f457600080fd5b50610421611009565b34801561070957600080fd5b506104f6611010565b34801561071e57600080fd5b50610727611016565b6040805161ffff9092168252519081900360200190f35b34801561074a57600080fd5b5061065461101b565b61040a6004803603604081101561076957600080fd5b506001600160a01b038135169060200135611020565b34801561078b57600080fd5b506104f661164d565b3480156107a057600080fd5b506104f6611653565b3480156107b557600080fd5b50610654611659565b3480156107ca57600080fd5b5061042161165e565b3480156107df57600080fd5b50610421611664565b3480156107f457600080fd5b5061042161166d565b34801561080957600080fd5b5061042161180d565b61040a6004803603606081101561082857600080fd5b506001600160a01b03813581169160208101359091169060400135610d5f565b34801561085457600080fd5b506104f6611813565b34801561086957600080fd5b506104216004803603602081101561088057600080fd5b50356001600160a01b0316611819565b34801561089c57600080fd5b50610654611834565b3480156108b157600080fd5b50610654611839565b3480156108c657600080fd5b50610421600480360360208110156108dd57600080fd5b50356001600160a01b031661183e565b3480156108f957600080fd5b506104f6611859565b34801561090e57600080fd5b5061065461185f565b34801561092357600080fd5b506104f6611864565b34801561093857600080fd5b5061040a6004803603604081101561094f57600080fd5b60ff8235169190810190604081016020820135600160201b81111561097357600080fd5b82018360208201111561098557600080fd5b803590602001918460018302840111600160201b831117156109a657600080fd5b50909250905061186a565b3480156109bd57600080fd5b50610654611b32565b3480156109d257600080fd5b506104f6611b37565b3480156109e757600080fd5b506104f6611b3d565b3480156109fc57600080fd5b50610a05611b43565b604080519115158252519081900360200190f35b348015610a2557600080fd5b506104f6611b4c565b348015610a3a57600080fd5b506104f6611b52565b348015610a4f57600080fd5b506104b3611659565b348015610a6457600080fd5b5061040a60048036036040811015610a7b57600080fd5b810190602081018135600160201b811115610a9557600080fd5b820183602082011115610aa757600080fd5b803590602001918460018302840111600160201b83111715610ac857600080fd5b919390929091602081019035600160201b811115610ae557600080fd5b820183602082011115610af757600080fd5b803590602001918460018302840111600160201b83111715610b1857600080fd5b509092509050611b58565b348015610b2f57600080fd5b506106546122ea565b348015610b4457600080fd5b506104216122ef565b348015610b5957600080fd5b5061042161248c565b348015610b6e57600080fd5b5061042160048036036040811015610b8557600080fd5b506001600160a01b0381358116916020013516612497565b348015610ba957600080fd5b506104216124c4565b348015610bbe57600080fd5b506104f66124ca565b348015610bd357600080fd5b5061040a60048036036040811015610bea57600080fd5b60ff8235169190810190604081016020820135600160201b811115610c0e57600080fd5b820183602082011115610c2057600080fd5b803590602001918460018302840111600160201b83111715610c4157600080fd5b5090925090506124d0565b348015610c5857600080fd5b5061042160048036036040811015610c6f57600080fd5b506001600160a01b03813581169160200135166126f3565b348015610c9357600080fd5b506104f661271e565b348015610ca857600080fd5b506104f6612724565b348015610cbd57600080fd5b5061042161272a565b348015610cd257600080fd5b50610654612737565b348015610ce757600080fd5b5061042160048036036060811015610cfe57600080fd5b506001600160a01b03813581169160208101358216916040909101351661273c565b348015610d2c57600080fd5b506104f6612771565b348015610d4157600080fd5b50610421612777565b348015610d5657600080fd5b506104f661277d565b6040805162461bcd60e51b815260206004820152600d60248201526c1b9bdd081cdd5c1c1bdc9d1959609a1b604482015290519081900360640190fd5b60035481565b610daa614800565b610db2614800565b6001600160a01b0383166000818152600b60209081526040808320548552838352600c82528083205485830152928252600d9052819020549082015290505b919050565b606481565b6108fc81565b61200181565b60603361200014610e495760405162461bcd60e51b815260040180806020018281038252602f8152602001806149e3602f913960400191505060405180910390fd5b60005460ff16610e8c576638d7ea4c6800006001908155662386f26fc1000060025568056bc75e2d631000006003556108fc6011556000805460ff191690911790555b610e9461481e565b610edb610ed685858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061278392505050565b6127a8565b90506000610ef0610eeb836127f2565b612840565b90506000606060ff831660041415610f1557610f0b846128f7565b9092509050610f6c565b60ff831660051415610f2a57610f0b84612ad7565b6040805162461bcd60e51b8152602060048201526012602482015271756e6b6e6f776e206576656e74207479706560701b604482015290519081900360640190fd5b63ffffffff821615610fb8576040805163ffffffff84168152905160ff8516917f391d6e5ea6ab6c49b9a0abb1782cae5def8d711f973b00c729658c0b2a80b31b919081900360200190a25b979650505050505050565b6001600160a01b031660009081526006602052604090205490565b600581565b600181565b61200581565b60015481565b606581565b662386f26fc1000081565b600381565b620a8c0081565b61100181565b606181565b600881565b60105460ff166002141561106c576040805162461bcd60e51b815260206004820152600e60248201526d4e6f2072652d656e7472616e637960901b604482015290519081900360640190fd5b6010805460ff19166002179055806402540be400340615801561109457506402540be4008106155b6110e5576040805162461bcd60e51b815260206004820152601c60248201527f707265636973696f6e206c6f737320696e20636f6e76657273696f6e00000000604482015290519081900360640190fd5b60005460ff16611128576638d7ea4c6800006001908155662386f26fc1000060025568056bc75e2d631000006003556108fc6011556000805460ff191690911790555b600154341015611176576040805162461bcd60e51b81526020600482015260146024820152736e6f7420656e6f7567682072656c61792066656560601b604482015290519081900360640190fd5b600354821015611231573360009081526005602090815260408083206001600160a01b038716845290915290205482146111e8576040805162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b604482015290519081900360640190fd5b6002548211611231576040805162461bcd60e51b815260206004820152601060248201526f6e6f7420656e6f7567682066756e647360801b604482015290519081900360640190fd5b3360009081526007602090815260408083206001600160a01b03871684529091529020544210156112a9576040805162461bcd60e51b815260206004820152601a60248201527f70656e64696e6720756e64656c65676174696f6e206578697374000000000000604482015290519081900360640190fd5b604080518082018252601081526f6e6f7420656e6f7567682066756e647360801b602080830191909152336000908152600582528381206001600160a01b03881682529091529182205461130491859063ffffffff612df716565b9050801561134c57600254811161134c5760405162461bcd60e51b81526004018080602001828103825260258152602001806149be6025913960400191505060405180910390fd5b6000611363846402540be40063ffffffff612e8e16565b600254909150349060009061137f90839063ffffffff612ed716565b6040805160038082526080820190925291925060609190816020015b606081526020019060019003908161139b5790505090506113bb33612f19565b816000815181106113c857fe5b60200260200101819052506113e5886001600160a01b0316612f19565b816001815181106113f257fe5b602002602001018190525061140684612f3c565b8160028151811061141357fe5b60200260200101819052506060611433600261142e84612f4f565b612fd9565b8051602080830191909120600f80546000908152600a845260408082209390935581546001908101909255338152600c909352912080549091019055905061148442620a8c0063ffffffff61305f16565b3360009081526007602090815260408083206001600160a01b038e16845290915290205561200063f7a251d76010836114c8876402540be40063ffffffff612e8e16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561152657818101518382015260200161150e565b50505050905090810190601f1680156115535780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561157457600080fd5b505af1158015611588573d6000803e3d6000fd5b5050604051611004925085156108fc02915085906000818181858888f193505050501580156115bb573d6000803e3d6000fd5b506002546040516110029180156108fc02916000818181858888f193505050501580156115ec573d6000803e3d6000fd5b50604080518981526020810185905281516001600160a01b038c169233927fdf0b6ac27f3f3bb31cee3dab0f4fe40cc19c6a3f8daaec52e06b261e58a12519929081900390910190a350506010805460ff1916600117905550505050505050565b61200681565b61200081565b600081565b60025481565b6402540be40081565b60105460009060ff16600214156116bc576040805162461bcd60e51b815260206004820152600e60248201526d4e6f2072652d656e7472616e637960901b604482015290519081900360640190fd5b506010805460ff191660021790553360009081526008602052604090205480611723576040805162461bcd60e51b81526020600482015260146024820152736e6f20756e64656c6567617465642066756e647360601b604482015290519081900360640190fd5b336000818152600860205260408082208290556011549051919291849084818181858888f193505050503d8060008114611779576040519150601f19603f3d011682016040523d82523d6000602084013e61177e565b606091505b50509050806117c6576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b60408051838152905133917fc712d133b8d448221aaed2198ed1f0db6dfc860fb01bc3a630916fe6cbef946f919081900360200190a2506010805460ff1916600117905590565b60035490565b61100581565b6001600160a01b031660009081526004602052604090205490565b600281565b601081565b6001600160a01b031660009081526008602052604090205490565b61100881565b600b81565b61200381565b33612000146118aa5760405162461bcd60e51b815260040180806020018281038252602f8152602001806149e3602f913960400191505060405180910390fd5b60005460ff166118ed576638d7ea4c6800006001908155662386f26fc1000060025568056bc75e2d631000006003556108fc6011556000805460ff191690911790555b6118f561481e565b611937610ed684848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061278392505050565b905060008060606000805b61194b866130b9565b156119b6578061196857611961610eeb876127f2565b94506119ae565b80600114156119845761197d610eeb876127f2565b93506119ae565b80600214156119a95761199e611999876127f2565b6130da565b9250600191506119ae565b6119b6565b600101611942565b816119fc576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b611a058361314a565b611a48576040805162461bcd60e51b815260206004820152600f60248201526e0eee4dedcce40e0c2c6d640d0c2e6d608b1b604482015290519081900360640190fd5b611a54610ed684612783565b95506000611a64610eeb886127f2565b9050611a6e61481e565b611a77886130b9565b15611a9a57611a93610ed6611a8e6119998b6127f2565b612783565b9050611adb565b6040805162461bcd60e51b8152602060048201526011602482015270656d7074792061636b207061636b61676560781b604482015290519081900360640190fd5b60ff821660011415611af757611af281888861319e565b611b25565b60ff821660021415611b0e57611af2818888613555565b60ff821660031415610f2a57611af2818888613822565b5050505050505050505050565b600981565b61100781565b61100681565b60005460ff1681565b61200281565b61300081565b60005460ff16611baf576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604482015290519081900360640190fd5b3361100714611bef5760405162461bcd60e51b815260040180806020018281038252602e815260200180614934602e913960400191505060405180910390fd5b611c5084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600a81526972656c6179657246656560b01b60208201529150613b879050565b15611db65760208114611caa576040805162461bcd60e51b815260206004820152601d60248201527f6c656e677468206f662072656c61796572466565206d69736d61746368000000604482015290519081900360640190fd5b604080516020601f8401819004810282018101909252828152600091611ce891858580838501838280828437600092019190915250613c6e92505050565b90506003548110611d2a5760405162461bcd60e51b815260040180806020018281038252602e815260200180614962602e913960400191505060405180910390fd5b6002548111611d6a5760405162461bcd60e51b815260040180806020018281038252602e815260200180614990602e913960400191505060405180910390fd5b6402540be400810615611dae5760405162461bcd60e51b815260040180806020018281038252602c815260200180614908602c913960400191505060405180910390fd5b600155612258565b611e1a84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c62534352656c6179657246656560981b60208201529150613b879050565b15611f7c5760208114611e74576040805162461bcd60e51b815260206004820181905260248201527f6c656e677468206f662062534352656c61796572466565206d69736d61746368604482015290519081900360640190fd5b604080516020601f8401819004810282018101909252828152600091611eb291858580838501838280828437600092019190915250613c6e92505050565b905080611ef05760405162461bcd60e51b8152600401808060200182810382526022815260200180614a126022913960400191505060405180910390fd5b6001548110611f305760405162461bcd60e51b815260040180806020018281038252602e815260200180614888602e913960400191505060405180910390fd5b6402540be400810615611f745760405162461bcd60e51b815260040180806020018281038252602f815260200180614859602f913960400191505060405180910390fd5b600255612258565b611fe084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c36b4b72232b632b3b0ba34b7b760991b60208201529150613b879050565b156120c2576020811461203a576040805162461bcd60e51b815260206004820181905260248201527f6c656e677468206f66206d696e44656c65676174696f6e206d69736d61746368604482015290519081900360640190fd5b604080516020601f840181900481028201810190925282815260009161207891858580838501838280828437600092019190915250613c6e92505050565b905060015481116120ba5760405162461bcd60e51b81526004018080602001828103825260318152602001806148b66031913960400191505060405180910390fd5b600355612258565b61212484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600b81526a7472616e7366657247617360a81b60208201529150613b879050565b1561221b576020811461217e576040805162461bcd60e51b815260206004820152601e60248201527f6c656e677468206f66207472616e73666572476173206d69736d617463680000604482015290519081900360640190fd5b604080516020601f84018190048102820181019092528281526000916121bc91858580838501838280828437600092019190915250613c6e92505050565b905060008111612213576040805162461bcd60e51b815260206004820152601e60248201527f746865207472616e736665724761732063616e6e6f74206265207a65726f0000604482015290519081900360640190fd5b601155612258565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b600481565b60105460009060ff166002141561233e576040805162461bcd60e51b815260206004820152600e60248201526d4e6f2072652d656e7472616e637960901b604482015290519081900360640190fd5b506010805460ff1916600217905533600090815260066020526040902054806123a2576040805162461bcd60e51b81526020600482015260116024820152701b9bc81c195b991a5b99c81c995dd85c99607a1b604482015290519081900360640190fd5b336000818152600660205260408082208290556011549051919291849084818181858888f193505050503d80600081146123f8576040519150601f19603f3d011682016040523d82523d6000602084013e6123fd565b606091505b5050905080612445576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b60408051838152905133917f83b78188b13346b2ffb484da70d42ee27de7fbf9f2bd8045269e10ed643ccd76919081900360200190a2506010805460ff1916600117905590565b6638d7ea4c68000081565b6001600160a01b038083166000908152600760209081526040808320938516835292905220545b92915050565b60015490565b61100281565b33612000146125105760405162461bcd60e51b815260040180806020018281038252602f8152602001806149e3602f913960400191505060405180910390fd5b60005460ff16612553576638d7ea4c6800006001908155662386f26fc1000060025568056bc75e2d631000006003556108fc6011556000805460ff191690911790555b61259282828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061314a92505050565b6125d5576040805162461bcd60e51b815260206004820152600f60248201526e0eee4dedcce40e0c2c6d640d0c2e6d608b1b604482015290519081900360640190fd5b6125dd61481e565b61261f610ed684848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061278392505050565b9050600061262f610eeb836127f2565b905061263961481e565b612642836130b9565b1561266057612659610ed6611a8e611999866127f2565b90506126a6565b6040805162461bcd60e51b8152602060048201526016602482015275656d707479206661696c2061636b207061636b61676560501b604482015290519081900360640190fd5b60ff8216600114156126c0576126bb81613c73565b6126ea565b60ff8216600214156126d5576126bb81613e8d565b60ff821660031415610f2a576126bb81613fb7565b5050505b505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205490565b61100381565b61200481565b68056bc75e2d6310000081565b601181565b6001600160a01b0392831660009081526009602090815260408083209486168352938152838220929094168152925290205490565b61100081565b60115481565b61100481565b61278b61483e565b506040805180820190915281518152602082810190820152919050565b6127b061481e565b6127b98261411c565b6127c257600080fd5b60006127d18360200151614156565b60208085015160408051808201909152868152920190820152915050919050565b6127fa61483e565b612803826130b9565b61280c57600080fd5b6020820151600061281c826141b9565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061285557508151602110155b61285e57600080fd5b600061286d8360200151614156565b905080836000015110156128c8576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b8251602080850151830180519284900392918310156128ee57826020036101000a820491505b50949350505050565b600060606000806000805b61290b876130b9565b1561295d578261292d57612926612921886127f2565b6142ec565b9150612952565b826001141561294d57612942610eeb886127f2565b905060019350612952565b61295d565b826001019250612902565b836129a3576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b60006110046001600160a01b031663727be1f8836040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156129ed57600080fd5b505af1158015612a01573d6000803e3d6000fd5b505050506040513d6020811015612a1757600080fd5b5051905080612a3c57612a2e600484846065614306565b965096505050505050612ad2565b6001600160a01b038316600090815260066020526040902054612a65908363ffffffff61305f16565b6001600160a01b038416600081815260066020908152604091829020939093558051858152905191927f7cc266c7b444f808013fa187f7b904d470a051a6564e78f482aa496581ba4bf892918290030190a260408051600080825260208201909252909750955050505050505b915091565b600060606000806000806000805b612aee896130b9565b15612b785784612b0b57612b046129218a6127f2565b9350612b6d565b8460011415612b2757612b206129218a6127f2565b9250612b6d565b8460021415612b4757612b3c610eeb8a6127f2565b915060019550612b6d565b8460031415612b6857612b61612b5c8a6127f2565b614402565b9050612b6d565b612b78565b846001019450612ae5565b85612bbe576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b60006110046001600160a01b031663727be1f8846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015612c0857600080fd5b505af1158015612c1c573d6000803e3d6000fd5b505050506040513d6020811015612c3257600080fd5b5051905080612c5957612c49600586856065614306565b9850985050505050505050612ad2565b6001600160a01b038086166000818152600760209081526040808320948916835293815283822082905591815260089091522054612c9d908463ffffffff61305f16565b6001600160a01b0386166000908152600860205260409020558115612d8b576001600160a01b038516600090815260046020526040902054612ce5908463ffffffff612ed716565b6001600160a01b03808716600090815260046020908152604080832094909455600581528382209288168252919091522054612d27908463ffffffff612ed716565b6001600160a01b038087166000818152600560209081526040808320948a16808452948252918290209490945580518781529051929391927fd6f878a5bcbbe79a64e6418bb0d56aaa20b9a60587d45749819df88dfc7c3c44929181900390910190a35b836001600160a01b0316856001600160a01b03167f35a799836f74fac7eccf5c73902823b970543d2274d3b93d8da3d37a255772a2856040518082815260200191505060405180910390a360408051600080825260208201909252909950975050505050505050915091565b60008184841115612e865760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e4b578181015183820152602001612e33565b50505050905090810190601f168015612e785780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000612ed083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614446565b9392505050565b6000612ed083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612df7565b60408051600560a21b8318601482015260348101909152606090612ed0816144ab565b60606124be612f4a83614501565b6144ab565b6060815160001415612f705750604080516000815260208101909152610df1565b606082600081518110612f7f57fe5b602002602001015190506000600190505b8351811015612fc057612fb682858381518110612fa957fe5b60200260200101516145e7565b9150600101612f90565b50612ed0612fd3825160c060ff16614664565b826145e7565b6040805160028082526060828101909352829190816020015b6060815260200190600190039081612ff25790505090506130158460ff16612f3c565b8160008151811061302257fe5b6020026020010181905250613036836144ab565b8160018151811061304357fe5b602002602001018190525061305781612f4f565b949350505050565b600082820183811015612ed0576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006130c361483e565b505080518051602091820151919092015191011190565b80516060906130e857600080fd5b60006130f78360200151614156565b83516040805191839003808352601f19601f820116830160200190915291925060609082801561312e576020820181803683370190505b50905060008160200190506128ee84876020015101828561475c565b8051602080830191909120600e546000908152600a909252604082205480821461317957600092505050610df1565b5050600e80546000908152600a60205260408120558054600190810190915592915050565b60008060008060005b6131b0886130b9565b1561321957836131cd576131c6612921896127f2565b925061320e565b83600114156131e9576131e2612921896127f2565b915061320e565b8360021415613209576131fe610eeb896127f2565b90506001945061320e565b613219565b8360010193506131a7565b8461325f576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6000613276826402540be40063ffffffff6147a716565b6001600160a01b0385166000908152600b602052604090208054600019019055905060ff8816600114156133bc5760ff8716156132e9576040805162461bcd60e51b815260206004820152600c60248201526b77726f6e672073746174757360a01b604482015290519081900360640190fd5b6001600160a01b038416600090815260046020526040902054613312908263ffffffff61305f16565b6001600160a01b03808616600090815260046020908152604080832094909455600581528382209287168252919091522054613354908263ffffffff61305f16565b6001600160a01b038086166000818152600560209081526040808320948916808452948252918290209490945580518581529051929391927f9a57c81564ab02642f34fd87e41baa9b074c18342cec3b7268b62bf752018fd1929181900390910190a361354a565b60ff881661350e576001600160a01b0384166000908152600860205260409020546133ed908263ffffffff61305f16565b6001600160a01b0385166000908152600860209081526040808320939093558251630e4f7c3f60e31b81526004810185905292516110049363727be1f89360248083019493928390030190829087803b15801561344957600080fd5b505af115801561345d573d6000803e3d6000fd5b505050506040513d602081101561347357600080fd5b50516134bc576040805162461bcd60e51b81526020600482015260136024820152721dda5d1a191c985dc8189b988819985a5b1959606a1b604482015290519081900360640190fd5b6040805182815260ff8916602082015281516001600160a01b0380871693908816927fcbd481ae600289fad8c0484d07ce0ffe4f010d7c844ecfdeaf2a13fead52886e929081900390910190a361354a565b6040805162461bcd60e51b815260206004820152600c60248201526b77726f6e672073746174757360a01b604482015290519081900360640190fd5b505050505050505050565b60008060008060005b613567886130b9565b156135d057836135845761357d612921896127f2565b92506135c5565b83600114156135a057613599612921896127f2565b91506135c5565b83600214156135c0576135b5610eeb896127f2565b9050600194506135c5565b6135d0565b83600101935061355e565b84613616576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b600061362d826402540be40063ffffffff6147a716565b6001600160a01b0385166000908152600c602052604090208054600019019055905060ff8816600114156137ac5760ff8716156136a0576040805162461bcd60e51b815260206004820152600c60248201526b77726f6e672073746174757360a01b604482015290519081900360640190fd5b6001600160a01b0384166000908152600460205260409020546136c9908263ffffffff612ed716565b6001600160a01b0380861660009081526004602090815260408083209490945560058152838220928716825291909152205461370b908263ffffffff612ed716565b6001600160a01b0380861660009081526005602090815260408083209388168352929052205561374442620a8c0063ffffffff61305f16565b6001600160a01b038086166000818152600760209081526040808320948916808452948252918290209490945580518581529051929391927fd6f878a5bcbbe79a64e6418bb0d56aaa20b9a60587d45749819df88dfc7c3c44929181900390910190a361354a565b60ff881661350e576001600160a01b03808516600081815260076020908152604080832094881680845294825280832092909255815185815260ff8c169181019190915281517f4417d10c1e33efa83a770b8d4f47176e78c08c1298d534901ad3b16bb585fa2e929181900390910190a361354a565b6000806000806000805b613835896130b9565b156138ba57846138525761384b6129218a6127f2565b93506138af565b846001141561386e576138676129218a6127f2565b92506138af565b846002141561388a576138836129218a6127f2565b91506138af565b84600314156138aa5761389f610eeb8a6127f2565b9050600195506138af565b6138ba565b84600101945061382c565b85613900576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6000613917826402540be40063ffffffff6147a716565b6001600160a01b0386166000908152600d602052604090208054600019019055905060ff891660011415613aea5760ff88161561398a576040805162461bcd60e51b815260206004820152600c60248201526b77726f6e672073746174757360a01b604482015290519081900360640190fd5b6001600160a01b038086166000908152600560209081526040808320938816835292905220546139c0908263ffffffff612ed716565b6001600160a01b038681166000908152600560209081526040808320898516845290915280822093909355908516815220546139fc908261305f565b6001600160a01b03808716600090815260056020908152604080832093881683529290522055613a3542620a8c0063ffffffff61305f16565b6001600160a01b0380871660009081526009602090815260408083208985168452825280832093881683529290522055613a7842620a8c0063ffffffff61305f16565b6001600160a01b038087166000818152600960209081526040808320898616808552908352818420958b1680855295835292819020959095558451868152945191947f78bffae3f8c6691ac7fc1a3bff800cb2d612f5ad9ae5b0444cfe2eb15c189e18929081900390910190a4613b7b565b60ff891661350e576001600160a01b038581166000818152600960209081526040808320898616808552818452828520968a16808652968452828520859055908352818420818552835281842093909355805186815260ff8e169281019290925280519293927fb93bee5c59f85ede6b074a99f4ffcd3e3fc0d5c3d8156de331de89a49e0ce77c9281900390910190a45b50505050505050505050565b6000816040516020018082805190602001908083835b60208310613bbc5780518252601f199092019160209182019101613b9d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310613c2a5780518252601f199092019160209182019101613c0b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b60008060008060005b613c85866130b9565b15613cee5783613ca257613c9b612921876127f2565b9250613ce3565b8360011415613cbe57613cb7612921876127f2565b9150613ce3565b8360021415613cde57613cd3610eeb876127f2565b905060019450613ce3565b613cee565b836001019350613c7c565b84613d34576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6000613d4b826402540be40063ffffffff6147a716565b6001600160a01b0385166000908152600b6020908152604080832080546000190190556008909152902054909150613d89908263ffffffff61305f16565b6001600160a01b0385166000908152600860209081526040808320939093558251630e4f7c3f60e31b81526004810185905292516110049363727be1f89360248083019493928390030190829087803b158015613de557600080fd5b505af1158015613df9573d6000803e3d6000fd5b505050506040513d6020811015613e0f57600080fd5b5051613e58576040805162461bcd60e51b81526020600482015260136024820152721dda5d1a191c985dc8189b988819985a5b1959606a1b604482015290519081900360640190fd5b6040516001907ff83de021914a4585482db5ca47d520a5657165b443fa2c7ef8ed4635f054da9b90600090a250505050505050565b60008060008060005b613e9f866130b9565b15613f085783613ebc57613eb5612921876127f2565b9250613efd565b8360011415613ed857613ed1612921876127f2565b9150613efd565b8360021415613ef857613eed610eeb876127f2565b905060019450613efd565b613f08565b836001019350613e96565b84613f4e576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600c60209081526040808320805460001901905560078252808320938616835292905281812081905590516002917ff83de021914a4585482db5ca47d520a5657165b443fa2c7ef8ed4635f054da9b91a2505050505050565b6000806000806000805b613fca876130b9565b1561404f5784613fe757613fe0612921886127f2565b9350614044565b846001141561400357613ffc612921886127f2565b9250614044565b846002141561401f57614018612921886127f2565b9150614044565b846003141561403f57614034610eeb886127f2565b905060019550614044565b61404f565b846001019450613fc1565b85614095576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6001600160a01b038481166000908152600d602090815260408083208054600019019055600982528083208785168085528184528285209588168552948352818420849055825280832093835292905281812081905590516003917ff83de021914a4585482db5ca47d520a5657165b443fa2c7ef8ed4635f054da9b91a250505050505050565b805160009061412d57506000610df1565b6020820151805160001a9060c082101561414c57600092505050610df1565b5060019392505050565b8051600090811a6080811015614170576000915050610df1565b60b881108061418b575060c0811080159061418b575060f881105b1561419a576001915050610df1565b60c08110156141ae5760b519019050610df1565b60f519019050610df1565b80516000908190811a60808110156141d457600191506142e5565b60b88110156141e957607e19810191506142e5565b60c081101561426357600060b78203600186019550806020036101000a86510491506001810182019350508083101561425d576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b506142e5565b60f88110156142785760be19810191506142e5565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156142e3576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b80516000906015146142fd57600080fd5b6124be82612840565b6000606061431f846402540be40063ffffffff612e8e16565b60408051600480825260a0820190925291955060609190816020015b606081526020019060019003908161433b57905050905061435e8760ff16612f3c565b8160008151811061436b57fe5b6020026020010181905250614388866001600160a01b0316612f19565b8160018151811061439557fe5b60200260200101819052506143a985612f3c565b816002815181106143b657fe5b60200260200101819052506143d08463ffffffff16612f3c565b816003815181106143dd57fe5b602002602001018190525060606143f382612f4f565b94989497509395505050505050565b805160009060011461441357600080fd5b6020820151805160001a9081158061442b5750608082145b1561443b57600092505050610df1565b600192505050610df1565b600081836144955760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612e4b578181015183820152602001612e33565b5060008385816144a157fe5b0495945050505050565b6060815160011480156144dd5750607f60f81b826000815181106144cb57fe5b01602001516001600160f81b03191611155b156144e9575080610df1565b6124be6144fb8351608060ff16614664565b836145e7565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff19841661454557506018614569565b6fffffffffffffffffffffffffffffffff19841661456557506010614569565b5060005b602081101561459f5781818151811061457e57fe5b01602001516001600160f81b031916156145975761459f565b600101614569565b60008160200390506060816040519080825280601f01601f1916602001820160405280156145d4576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b81831015614618578051835260209283019201614600565b50855184518101855292509050808201602086015b8183101561464557805183526020928301920161462d565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106146b4576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b6040805160018082528183019092526060916020820181803683370190505090506037841161470e5782840160f81b816000815181106146f057fe5b60200101906001600160f81b031916908160001a90535090506124be565b606061471985614501565b90508381510160370160f81b8260008151811061473257fe5b60200101906001600160f81b031916908160001a90535061475382826145e7565b95945050505050565b80614766576126ee565b5b60208110614786578251825260209283019290910190601f1901614767565b915181516020939093036101000a6000190180199091169216919091179052565b6000826147b6575060006124be565b828202828482816147c357fe5b0414612ed05760405162461bcd60e51b81526004018080602001828103825260218152602001806148e76021913960400191505060405180910390fd5b60405180606001604052806003906020820280368337509192915050565b604051806040016040528061483161483e565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe7468652042534352656c61796572466565206d6f642074656e20646563696d616c73206d757374206265207a65726f7468652042534352656c61796572466565206d757374206265206c657373207468616e2072656c61796572466565746865206d696e44656c65676174696f6e206d7573742062652067726561746572207468616e2072656c61796572466565536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f777468652072656c61796572466565206d6f642074656e20646563696d616c73206d757374206265207a65726f746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163747468652072656c61796572466565206d757374206265206c657373207468616e206d696e44656c65676174696f6e7468652072656c61796572466565206d757374206265206d6f7265207468616e2042534352656c61796572466565696e73756666696369656e742062616c616e636520616674657220756e64656c6567617465746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e74726163747468652042534352656c61796572466565206d757374206e6f74206265207a65726fa164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(StakeHubContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405260043610620003db5760003560e01c806386d545061162000203578063d115a2061162000117578063e992aaf511620000ad578063f80a34021162000078578063f80a34021462000bef578063fb50b31f1462000c14578063fc0c5ff11462000c39578063ff69ab611462000c5157600080fd5b8063e992aaf51462000b6c578063efdbf0e11462000b84578063f1f74d841462000bc0578063f1fad1041462000bd857600080fd5b8063d8ca511f11620000ee578063d8ca511f1462000aff578063daacdb661462000b17578063dbda7fb31462000b2f578063e8f67c3b1462000b5457600080fd5b8063d115a2061462000a9d578063d6ca429d1462000ab5578063d7c2dfc81462000ada57600080fd5b8063b187bd261162000199578063c38fbec81162000164578063c38fbec81462000a1f578063c473318f1462000a44578063c8509d81146200083d578063cbb04d9d1462000a5c57600080fd5b8063b187bd26146200098c578063baa7199e14620009ac578063bdceadf314620009d1578063bff02e2014620009e957600080fd5b8063982ef0a711620001da578063982ef0a714620008f7578063a43569b3146200090e578063aad3ec961462000942578063ac431751146200096757600080fd5b806386d54506146200087a5780638a4d3fa814620008b45780638cd22b2214620008d257600080fd5b80634bf6c88211620002fb578063663706d3116200029157806376e7d6d6116200025c57806376e7d6d6146200080d5780638129fc1c1462000825578063831d65d1146200083d5780638456cb59146200086257600080fd5b8063663706d3146200073a5780636ec01b27146200076b5780636f8e2fa414620007c357806375cc7d8914620007e857600080fd5b80635949187111620002d25780635949187114620006a25780635e7cc1c914620006c757806363a036b514620006ec57806364028fbd146200072357600080fd5b80634bf6c882146200063b5780634d99dd1614620006655780634e6fd6c4146200068a57600080fd5b80631fa8882b1162000371578063449ecfe61162000348578063449ecfe6146200058757806345211bfd14620005ac5780634838d16514620005d15780634a49ac4c146200061657600080fd5b80631fa8882b146200053157806338409988146200054a578063417c73a7146200056257600080fd5b8063092193ab11620003b2578063092193ab146200047c5780630e9fbf5114620004935780631182b87514620004b857806317b4f35314620004ec57600080fd5b8063046f7da214620003fb578063059ddd2214620004135780630661806e146200045557600080fd5b36620003f65760345460ff16600114620003f457600080fd5b005b600080fd5b3480156200040857600080fd5b50620003f462000c69565b3480156200042057600080fd5b506200043862000432366004620093e3565b62000cfb565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156200046257600080fd5b506200046d60365481565b6040519081526020016200044c565b620003f46200048d366004620093e3565b62001110565b348015620004a057600080fd5b50620003f4620004b236600462009447565b6200174e565b348015620004c557600080fd5b50620004dd620004d73660046200948c565b62001a7a565b6040516200044c91906200953f565b348015620004f957600080fd5b50620004386200050b36600462009635565b80516020818301810180516045825292820191909301209152546001600160a01b031681565b3480156200053e57600080fd5b506200046d6201518081565b3480156200055757600080fd5b506200046d60375481565b3480156200056f57600080fd5b50620003f462000581366004620093e3565b62001d53565b3480156200059457600080fd5b50620003f4620005a6366004620093e3565b62001dd5565b348015620005b957600080fd5b50620003f4620005cb366004620093e3565b62001fba565b348015620005de57600080fd5b5062000605620005f0366004620093e3565b60016020526000908152604090205460ff1681565b60405190151581526020016200044c565b3480156200062357600080fd5b50620003f462000635366004620093e3565b62002197565b3480156200064857600080fd5b5062000652600881565b60405160ff90911681526020016200044c565b3480156200067257600080fd5b50620003f4620006843660046200968a565b62002213565b3480156200069757600080fd5b506200043861dead81565b348015620006af57600080fd5b50620003f4620006c1366004620096c8565b62002830565b348015620006d457600080fd5b50620003f4620006e636600462009738565b62003602565b348015620006f957600080fd5b50620007116200070b36600462009758565b6200380a565b6040516200044c9493929190620097c1565b620003f4620007343660046200987d565b62003e9c565b3480156200074757600080fd5b506200046d62000759366004620093e3565b60446020526000908152604090205481565b3480156200077857600080fd5b50620007906200078a366004620093e3565b620044e6565b6040805182516001600160401b03908116825260208085015182169083015292820151909216908201526060016200044c565b348015620007d057600080fd5b50620004dd620007e2366004620093e3565b62004590565b348015620007f557600080fd5b50620003f462000807366004620093e3565b620049a9565b3480156200081a57600080fd5b506200046d603d5481565b3480156200083257600080fd5b50620003f462004b7b565b3480156200084a57600080fd5b50620003f46200085c3660046200948c565b62004e92565b3480156200086f57600080fd5b50620003f462004efc565b3480156200088757600080fd5b506200043862000899366004620093e3565b6043602052600090815260409020546001600160a01b031681565b348015620008c157600080fd5b506200046d670de0b6b3a764000081565b348015620008df57600080fd5b506200046d620008f13660046200968a565b62004f94565b620003f46200090836600462009955565b6200504d565b3480156200091b57600080fd5b50620009336200092d366004620093e3565b620056d7565b6040516200044c919062009993565b3480156200094f57600080fd5b50620003f4620009613660046200968a565b620059c4565b3480156200097457600080fd5b50620003f46200098636600462009a10565b62005a31565b3480156200099957600080fd5b5060005462010000900460ff1662000605565b348015620009b957600080fd5b50620003f4620009cb36600462009ac9565b620068d0565b348015620009de57600080fd5b506200046d603c5481565b348015620009f657600080fd5b5062000a0e62000a0836600462009758565b62006a9d565b6040516200044c9392919062009b25565b34801562000a2c57600080fd5b50620003f462000a3e366004620093e3565b62006c79565b34801562000a5157600080fd5b506200046d60385481565b34801562000a6957600080fd5b5062000a8162000a7b366004620093e3565b62006f3b565b604080519384529115156020840152908201526060016200044c565b34801562000aaa57600080fd5b506200046d61271081565b34801562000ac257600080fd5b50620003f462000ad436600462009b82565b6200736b565b34801562000ae757600080fd5b50620003f462000af936600462009c6b565b6200756f565b34801562000b0c57600080fd5b506200046d603b5481565b34801562000b2457600080fd5b506200046d60495481565b34801562000b3c57600080fd5b506200043862000b4e366004620093e3565b62007665565b34801562000b6157600080fd5b506200046d60355481565b34801562000b7957600080fd5b506200046d603a5481565b34801562000b9157600080fd5b506200046d62000ba336600462009635565b805160208183018101805160468252928201919093012091525481565b34801562000bcd57600080fd5b506200046d603e5481565b34801562000be557600080fd5b5062000652601181565b34801562000bfc57600080fd5b506200046d62000c0e3660046200968a565b62007a7c565b34801562000c2157600080fd5b50620003f462000c3336600462009a10565b62007aed565b34801562000c4657600080fd5b506200046d60395481565b34801562000c5e57600080fd5b506200046d604a5481565b600054630100000090046001600160a01b0316331462000c9c576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1662000cc657604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b6001600160a01b038082166000908152604160209081526040808320815161016081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162000d669062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462000d949062009cd1565b801562000de55780601f1062000db95761010080835404028352916020019162000de5565b820191906000526020600020905b81548152906001019060200180831162000dc757829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462000e109062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462000e3e9062009cd1565b801562000e8f5780601f1062000e635761010080835404028352916020019162000e8f565b820191906000526020600020905b81548152906001019060200180831162000e7157829003601f168201915b5050505050815260200160018201805462000eaa9062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462000ed89062009cd1565b801562000f295780601f1062000efd5761010080835404028352916020019162000f29565b820191906000526020600020905b81548152906001019060200180831162000f0b57829003601f168201915b5050505050815260200160028201805462000f449062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462000f729062009cd1565b801562000fc35780601f1062000f975761010080835404028352916020019162000fc3565b820191906000526020600020905b81548152906001019060200180831162000fa557829003601f168201915b5050505050815260200160038201805462000fde9062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200100c9062009cd1565b80156200105d5780601f1062001031576101008083540402835291602001916200105d565b820191906000526020600020905b8154815290600101906020018083116200103f57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620010e9575050509190925250509051949350505050565b33611000146200113c57604051630f22c43960e41b815261100060048201526024015b60405180910390fd5b6001600160a01b03808216600090815260436020908152604080832054841680845260418352818420825161016081018452815487168152600182015487169481019490945260028101549095169183019190915260038401546060830152600484018054919491608084019190620011b59062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620011e39062009cd1565b8015620012345780601f10620012085761010080835404028352916020019162001234565b820191906000526020600020905b8154815290600101906020018083116200121657829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200125f9062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200128d9062009cd1565b8015620012de5780601f10620012b257610100808354040283529160200191620012de565b820191906000526020600020905b815481529060010190602001808311620012c057829003601f168201915b50505050508152602001600182018054620012f99062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620013279062009cd1565b8015620013785780601f106200134c5761010080835404028352916020019162001378565b820191906000526020600020905b8154815290600101906020018083116200135a57829003601f168201915b50505050508152602001600282018054620013939062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620013c19062009cd1565b8015620014125780601f10620013e65761010080835404028352916020019162001412565b820191906000526020600020905b815481529060010190602001808311620013f457829003601f168201915b505050505081526020016003820180546200142d9062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200145b9062009cd1565b8015620014ac5780601f106200148057610100808354040283529160200191620014ac565b820191906000526020600020905b8154815290600101906020018083116200148e57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b81548152602001906001019080831162001538575050509190925250505060408101519091506001600160a01b031615806200157557508060e001515b156200163257604051611002903490600081818185875af1925050503d8060008114620015bf576040519150601f19603f3d011682016040523d82523d6000602084013e620015c4565b606091505b505050816001600160a01b03167ffc8bff675087dd2da069cc3fb517b9ed001e19750c0865241a5542dba1ba170d604051620016259060208082526011908201527024a72b20a624a22fab20a624a220aa27a960791b604082015260600190565b60405180910390a2505050565b60408181015160c0830151519151632f303ebb60e11b81526001600160401b0390921660048301526001600160a01b031690635e607d769034906024016000604051808303818588803b1580156200168957600080fd5b505af11580156200169e573d6000803e3d6000fd5b5050505050816001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea634604051620016df91815260200190565b60405180910390a26040808201519051633041949b60e01b815261200591633041949b91620017149190869060040162009d07565b600060405180830381600087803b1580156200172f57600080fd5b505af115801562001744573d6000803e3d6000fd5b5050505050505b50565b33611001146200177657604051630f22c43960e41b8152611001600482015260240162001133565b60005462010000900460ff1615620017a157604051631785c68160e01b815260040160405180910390fd5b600060458383604051620017b792919062009d21565b908152604051908190036020019020546001600160a01b03169050620017df603f8262007d41565b620017fd5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062001825620151804262009d47565b604a546000828152604b602052604090205491925011620018595760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b602052604081208054600192906200187a90849062009d6a565b909155505060405160469062001894908790879062009d21565b908152602001604051809103902054600014158015620018e55750426201518060468787604051620018c892919062009d21565b908152602001604051809103902054620018e3919062009d6a565b105b156200190457604051631898eb6b60e01b815260040160405180910390fd5b6000806200191485600262007d64565b91509150816200193757604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af11580156200198a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b0919062009d80565b9050620019be858362007dee565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb283836002604051620019fe9392919062009db0565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162001a3c916001600160a01b0316908a9060040162009d07565b600060405180830381600087803b15801562001a5757600080fd5b505af115801562001a6c573d6000803e3d6000fd5b505050505050505050505050565b6060336120001462001aa457604051630f22c43960e41b8152612000600482015260240162001133565b6034805460ff19166001179055604080516020601f8501819004810282018101909252838152600091829162001af591879087908190840183828082843760009201919091525062007fb592505050565b915091508062001b185760405163035ede3560e21b815260040160405180910390fd5b816060015160000362001b3e575050604080516000815260208101909152905062001d42565b606082015160405163e04c83a760e01b81526000916110049163e04c83a79162001b6e9160040190815260200190565b6020604051808303816000875af115801562001b8e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001bb4919062009ddf565b90508062001c5b5782602001516001600160a01b031683600001516001600160a01b03167fa9084c89a291b43bc984e045671d394974730a159b9a826b577bb148ab504c3a8560600151600160405162001c1092919062009dff565b60405180910390a385858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092965062001d4295505050505050565b600062001c688462008118565b9050600081600381111562001c815762001c8162009d9a565b0362001ca3575050604080516000815260208101909152925062001d42915050565b83602001516001600160a01b031684600001516001600160a01b03167fa9084c89a291b43bc984e045671d394974730a159b9a826b577bb148ab504c3a86606001518460405162001cf692919062009dff565b60405180910390a386868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092975062001d429650505050505050565b6034805460ff191690559392505050565b600054630100000090046001600160a01b0316331462001d86576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60005462010000900460ff161562001e0057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562001e325760405163b1d02c3d60e01b815260040160405180910390fd5b8062001e40603f8262007d41565b62001e5e5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166000908152604160205260409020600a81015460ff1662001e9c57604051634b6b857d60e01b815260040160405180910390fd5b6036546002820154604051630913db4760e01b81526001600160a01b03868116600483015290911690630913db4790602401602060405180830381865afa15801562001eec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f12919062009d80565b101562001f32576040516317b204bf60e11b815260040160405180910390fd5b4281600b0154111562001f585760405163170cb76760e21b815260040160405180910390fd5b600a8101805460ff19169055604980546001919060009062001f7c90849062009e26565b90915550506040516001600160a01b038416907f9390b453426557da5ebdc31f19a37753ca04addf656d32f35232211bb2af3f1990600090a2505050565b60005462010000900460ff161562001fe557604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620020175760405163b1d02c3d60e01b815260040160405180910390fd5b3362002025603f8262007d41565b620020435760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166200206b57604051636520611b60e11b815260040160405180910390fd5b6001600160a01b0382811660009081526043602052604090205416151580620020ac57506001600160a01b03821660009081526047602052604090205460ff165b15620020cb57604051631e6f587560e11b815260040160405180910390fd5b336000818152604160205260409020600c8101544290620020f190620151809062009d6a565b11156200211157604051631f92cdbd60e11b815260040160405180910390fd5b80546001600160a01b039081166000908152604460209081526040808320429081905585548986166001600160a01b031991821681178855600c88019290925581855260439093528184208054958816959093168517909255519092917f6e4e747ca35203f16401c69805c7dd52fff67ef60b0ebc5c7fe16890530f223591a350505050565b600054630100000090046001600160a01b03163314620021ca576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60005462010000900460ff16156200223e57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620022705760405163b1d02c3d60e01b815260040160405180910390fd5b816200227e603f8262007d41565b6200229c5760405163056e881160e01b815260040160405180910390fd5b81600003620022be57604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b0380841660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180543394916080840191620023269062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620023549062009cd1565b8015620023a55780601f106200237957610100808354040283529160200191620023a5565b820191906000526020600020905b8154815290600101906020018083116200238757829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620023d09062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620023fe9062009cd1565b80156200244f5780601f1062002423576101008083540402835291602001916200244f565b820191906000526020600020905b8154815290600101906020018083116200243157829003601f168201915b505050505081526020016001820180546200246a9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620024989062009cd1565b8015620024e95780601f10620024bd57610100808354040283529160200191620024e9565b820191906000526020600020905b815481529060010190602001808311620024cb57829003601f168201915b50505050508152602001600282018054620025049062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620025329062009cd1565b8015620025835780601f10620025575761010080835404028352916020019162002583565b820191906000526020600020905b8154815290600101906020018083116200256557829003601f168201915b505050505081526020016003820180546200259e9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620025cc9062009cd1565b80156200261d5780601f10620025f1576101008083540402835291602001916200261d565b820191906000526020600020905b815481529060010190602001808311620025ff57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620026a9575050509190925250505060408082015190516326ccee8b60e11b81526001600160a01b0385811660048301526024820188905292935060009290911690634d99dd16906044016020604051808303816000875af115801562002723573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002749919062009d80565b9050826001600160a01b0316866001600160a01b03167f3aace7340547de7b9156593a7652dc07ee900cea3fd8f82cb6c9d38b4082980287846040516200279a929190918252602082015260400190565b60405180910390a3856001600160a01b0316836001600160a01b031603620027c757620027c786620087ab565b6040808301519051633041949b60e01b815261200591633041949b91620027f49190879060040162009d07565b600060405180830381600087803b1580156200280f57600080fd5b505af115801562002824573d6000803e3d6000fd5b50505050505050505050565b60005462010000900460ff16156200285b57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200288d5760405163b1d02c3d60e01b815260040160405180910390fd5b836200289b603f8262007d41565b620028b95760405163056e881160e01b815260040160405180910390fd5b83620028c7603f8262007d41565b620028e55760405163056e881160e01b815260040160405180910390fd5b6034805460ff1916600117905560008490036200291557604051639811e0c760e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031603620029485760405163f0e3e62960e01b815260040160405180910390fd5b6001600160a01b0380871660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180543394916080840191620029b09062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620029de9062009cd1565b801562002a2f5780601f1062002a035761010080835404028352916020019162002a2f565b820191906000526020600020905b81548152906001019060200180831162002a1157829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002a5a9062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462002a889062009cd1565b801562002ad95780601f1062002aad5761010080835404028352916020019162002ad9565b820191906000526020600020905b81548152906001019060200180831162002abb57829003601f168201915b5050505050815260200160018201805462002af49062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462002b229062009cd1565b801562002b735780601f1062002b475761010080835404028352916020019162002b73565b820191906000526020600020905b81548152906001019060200180831162002b5557829003601f168201915b5050505050815260200160028201805462002b8e9062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462002bbc9062009cd1565b801562002c0d5780601f1062002be15761010080835404028352916020019162002c0d565b820191906000526020600020905b81548152906001019060200180831162002bef57829003601f168201915b5050505050815260200160038201805462002c289062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462002c569062009cd1565b801562002ca75780601f1062002c7b5761010080835404028352916020019162002ca7565b820191906000526020600020905b81548152906001019060200180831162002c8957829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b81548152602001906001019080831162002d3357505050919092525050506001600160a01b0380891660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549495509193909291608084019162002dbe9062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462002dec9062009cd1565b801562002e3d5780601f1062002e115761010080835404028352916020019162002e3d565b820191906000526020600020905b81548152906001019060200180831162002e1f57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002e689062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462002e969062009cd1565b801562002ee75780601f1062002ebb5761010080835404028352916020019162002ee7565b820191906000526020600020905b81548152906001019060200180831162002ec957829003601f168201915b5050505050815260200160018201805462002f029062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462002f309062009cd1565b801562002f815780601f1062002f555761010080835404028352916020019162002f81565b820191906000526020600020905b81548152906001019060200180831162002f6357829003601f168201915b5050505050815260200160028201805462002f9c9062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462002fca9062009cd1565b80156200301b5780601f1062002fef576101008083540402835291602001916200301b565b820191906000526020600020905b81548152906001019060200180831162002ffd57829003601f168201915b50505050508152602001600382018054620030369062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620030649062009cd1565b8015620030b55780601f106200308957610100808354040283529160200191620030b5565b820191906000526020600020905b8154815290600101906020018083116200309757829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620031415750505050508152505090508060e001518015620031845750876001600160a01b0316836001600160a01b031614155b15620031a357604051636468920360e01b815260040160405180910390fd5b60408083015190516352e82ce560e11b81526001600160a01b038581166004830152602482018a9052600092169063a5d059ca906044016020604051808303816000875af1158015620031fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003220919062009d80565b9050603754811015620032465760405163dc6f0bdd60e01b815260040160405180910390fd5b896001600160a01b0316846001600160a01b0316148015620032db57506036546040808501519051630913db4760e01b81526001600160a01b038d8116600483015290911690630913db4790602401602060405180830381865afa158015620032b3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620032d9919062009d80565b105b15620032fa576040516317b204bf60e11b815260040160405180910390fd5b6000612710603a54836200330f919062009e3c565b6200331b919062009d47565b9050600083604001516001600160a01b03168260405160006040518083038185875af1925050503d806000811462003370576040519150601f19603f3d011682016040523d82523d6000602084013e62003375565b606091505b505090508062003398576040516312171d8360e31b815260040160405180910390fd5b620033a4828462009e26565b60408086015190516317066a5760e21b81526001600160a01b03898116600483015292955060009290911690635c19a95c90869060240160206040518083038185885af1158015620033fa573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062003421919062009d80565b9050866001600160a01b03168c6001600160a01b03168e6001600160a01b03167ffdac6e81913996d95abcc289e90f2d8bd235487ce6fe6f821e7d21002a1915b48e858960405162003486939291909283526020830191909152604082015260600190565b60405180910390a4604080516002808252606082018352600092602083019080368337019050509050866040015181600081518110620034ca57620034ca62009e56565b60200260200101906001600160a01b031690816001600160a01b03168152505085604001518160018151811062003505576200350562009e56565b6001600160a01b0390921660209283029190910190910152604051634484077560e01b815261200590634484077590620035469084908c9060040162009e6c565b600060405180830381600087803b1580156200356157600080fd5b505af115801562003576573d6000803e3d6000fd5b505050508a15620035e8576120056001600160a01b031663e5ed5b1e898f6040518363ffffffff1660e01b8152600401620035b392919062009d07565b600060405180830381600087803b158015620035ce57600080fd5b505af1158015620035e3573d6000803e3d6000fd5b505050505b50506034805460ff19169055505050505050505050505050565b60005462010000900460ff16156200362d57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200365f5760405163b1d02c3d60e01b815260040160405180910390fd5b336200366d603f8262007d41565b6200368b5760405163056e881160e01b815260040160405180910390fd5b336000818152604160205260409020600c8101544290620036b190620151809062009d6a565b1115620036d157604051631f92cdbd60e11b815260040160405180910390fd5b60098101546001600160401b03600160401b909104811690851611156200370b5760405163dc81db8560e01b815260040160405180910390fd5b60098101546000906001600160401b03908116908616101562003749576009820154620037439086906001600160401b031662009e98565b62003763565b600982015462003763906001600160401b03168662009e98565b60098301546001600160401b039182169250600160801b9004168111156200379e5760405163dc81db8560e01b815260040160405180910390fd5b60098201805467ffffffffffffffff19166001600160401b03871690811790915542600c8401556040519081526001600160a01b038416907f78cdd96edf59e09cfd4d26ef6ef6c92d166effe6a40970c54821206d541932cb9060200160405180910390a25050505050565b606080606060006200381d603f620088d1565b90508086101562003e9357841562003836578462003838565b805b945060008562003849888462009e26565b1162003861576200385b878362009e26565b62003863565b855b9050806001600160401b0381111562003880576200388062009554565b604051908082528060200260200182016040528015620038aa578160200160208202803683370190505b509450806001600160401b03811115620038c857620038c862009554565b604051908082528060200260200182016040528015620038f2578160200160208202803683370190505b509350806001600160401b0381111562003910576200391062009554565b6040519080825280602002602001820160405280156200394557816020015b60608152602001906001900390816200392f5790505b50925060005b8181101562003e905760006200396f62003966838b62009d6a565b603f90620088dc565b6001600160a01b03808216600090815260416020908152604080832081516101608101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620039dc9062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462003a0a9062009cd1565b801562003a5b5780601f1062003a2f5761010080835404028352916020019162003a5b565b820191906000526020600020905b81548152906001019060200180831162003a3d57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462003a869062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462003ab49062009cd1565b801562003b055780601f1062003ad95761010080835404028352916020019162003b05565b820191906000526020600020905b81548152906001019060200180831162003ae757829003601f168201915b5050505050815260200160018201805462003b209062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462003b4e9062009cd1565b801562003b9f5780601f1062003b735761010080835404028352916020019162003b9f565b820191906000526020600020905b81548152906001019060200180831162003b8157829003601f168201915b5050505050815260200160028201805462003bba9062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462003be89062009cd1565b801562003c395780601f1062003c0d5761010080835404028352916020019162003c39565b820191906000526020600020905b81548152906001019060200180831162003c1b57829003601f168201915b5050505050815260200160038201805462003c549062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462003c829062009cd1565b801562003cd35780601f1062003ca75761010080835404028352916020019162003cd3565b820191906000526020600020905b81548152906001019060200180831162003cb557829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b81548152602001906001019080831162003d5f575050505050815250509050806000015188848151811062003d985762003d9862009e56565b60200260200101906001600160a01b031690816001600160a01b0316815250508060e0015162003e315780604001516001600160a01b03166315d1f8986040518163ffffffff1660e01b8152600401602060405180830381865afa15801562003e05573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e2b919062009d80565b62003e34565b60005b87848151811062003e495762003e4962009e56565b602002602001018181525050806080015186848151811062003e6f5762003e6f62009e56565b602002602001018190525050508062003e889062009ebb565b90506200394b565b50505b92959194509250565b60005462010000900460ff161562003ec757604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562003ef95760405163b1d02c3d60e01b815260040160405180910390fd5b3362003f07603f8262007d41565b1562003f2657604051635f28f62b60e01b815260040160405180910390fd5b6001600160a01b038881166000908152604360205260409020541615158062003f6757506001600160a01b03881660009081526047602052604090205460ff165b1562003f8657604051631e6f587560e11b815260040160405180910390fd5b60006001600160a01b03166045888860405162003fa592919062009d21565b908152604051908190036020019020546001600160a01b031614158062003fef57506048878760405162003fdb92919062009d21565b9081526040519081900360200190205460ff165b156200400e576040516311fdb94760e01b815260040160405180910390fd5b60006200401c838062009ed7565b6040516020016200402f92919062009d21565b60408051601f1981840301815291815281516020928301206000818152604290935291205490915060ff1615620040795760405163c0bf414360e01b815260040160405180910390fd5b60006200408f670de0b6b3a76400003462009e26565b9050603654811015620040b5576040516317b204bf60e11b815260040160405180910390fd5b6001600160a01b038a16620040dd57604051636520611b60e11b815260040160405180910390fd5b611388620040f2604087016020880162009738565b6001600160401b0316118062004138575062004115604086016020870162009738565b6001600160401b03166200412d602087018762009738565b6001600160401b0316115b8062004177575062004151604086016020870162009738565b6001600160401b03166200416c606087016040880162009738565b6001600160401b0316115b15620041965760405163dc81db8560e01b815260040160405180910390fd5b620041e1620041a6858062009ed7565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620088ea92505050565b620041ff57604051635dba5ad760e01b815260040160405180910390fd5b6200420e838a8a8a8a62008a8c565b6200422c57604051631647e3cb60e11b815260040160405180910390fd5b60006200427a846200423f878062009ed7565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062008bbc92505050565b905062004289603f8562008cbd565b506000838152604260209081526040808320805460ff191660019081179091556001600160a01b0380891680865260419094529190932080548f83166001600160a01b031991821617825593810180548516909317909255600282018054918516919093161790915542600382015560048101620043098b8d8362009f7f565b5085600582016200431b82826200a047565b50879050600982016200432f82826200a180565b505042600c8201556001600160a01b038c81166000908152604360205260409081902080546001600160a01b031916928816929092179091555185906045906200437d908e908e9062009d21565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316856001600160a01b03168d6001600160a01b03167faecd9fb95e79c75a3a1de93362c6be5fe6ab65770d8614be583884161cd8228d8e8e604051620044009291906200a250565b60405180910390a460408051848152602081018590526001600160a01b0387169182916000805160206200b757833981519152910160405180910390a360408051670de0b6b3a7640000808252602082015261dead916001600160a01b038816916000805160206200b757833981519152910160405180910390a3604051633041949b60e01b815261200590633041949b90620044a4908590899060040162009d07565b600060405180830381600087803b158015620044bf57600080fd5b505af1158015620044d4573d6000803e3d6000fd5b50505050505050505050505050505050565b60408051606081018252600080825260208201819052918101919091528162004511603f8262007d41565b6200452f5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03831660009081526041602090815260409182902082516060810184526009909101546001600160401b038082168352600160401b8204811693830193909352600160801b90049091169181019190915291505b50919050565b6001600160a01b03808216600090815260416020908152604080832081516101608101835281548616815260018201548616938101939093526002810154909416908201526003830154606082810191909152600484018054919491608084019190620045fd9062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200462b9062009cd1565b80156200467c5780601f1062004650576101008083540402835291602001916200467c565b820191906000526020600020905b8154815290600101906020018083116200465e57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620046a79062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620046d59062009cd1565b8015620047265780601f10620046fa5761010080835404028352916020019162004726565b820191906000526020600020905b8154815290600101906020018083116200470857829003601f168201915b50505050508152602001600182018054620047419062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200476f9062009cd1565b8015620047c05780601f106200479457610100808354040283529160200191620047c0565b820191906000526020600020905b815481529060010190602001808311620047a257829003601f168201915b50505050508152602001600282018054620047db9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620048099062009cd1565b80156200485a5780601f106200482e576101008083540402835291602001916200485a565b820191906000526020600020905b8154815290600101906020018083116200483c57829003601f168201915b50505050508152602001600382018054620048759062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620048a39062009cd1565b8015620048f45780601f10620048c857610100808354040283529160200191620048f4565b820191906000526020600020905b815481529060010190602001808311620048d657829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620049805750505091909252505050608001519392505050565b3361100114620049d157604051630f22c43960e41b8152611001600482015260240162001133565b6001600160a01b0380821660009081526043602052604090205416620049f9603f8262007d41565b62004a175760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038181166000908152604160205260408082206002810154603b54925163045bc4d160e41b81526004810193909352909316906345bc4d10906024016020604051808303816000875af115801562004a7a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062004aa0919062009d80565b90506000603d544262004ab4919062009d6a565b905062004ac2838262007dee565b836001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28284600160405162004b029392919062009db0565b60405180910390a26002830154604051633041949b60e01b815261200591633041949b9162004b40916001600160a01b031690889060040162009d07565b600060405180830381600087803b15801562004b5b57600080fd5b505af115801562004b70573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff161580801562004b9c5750600054600160ff909116105b8062004bb85750303b15801562004bb8575060005460ff166001145b62004c1d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840162001133565b6000805460ff19166001179055801562004c41576000805461ff0019166101001790555b33411462004c625760405163022d8c9560e31b815260040160405180910390fd5b3a1562004c82576040516383f1b1d360e01b815260040160405180910390fd5b611388603555686c6b935b8bbd400000603655670de0b6b3a7640000603755600960385562093a806039556002603a819055678ac7230489e80000603b55680ad78ebc5ac6200000603c556202a300603d5562069780603e55604a5560408051610220810190915261020080825260609182916200b557602083013980602001905181019062004d1391906200a28c565b915060405180610360016040528061034081526020016200b777610340913980602001905181019062004d4791906200a330565b905060005b825181101562004db65760016047600085848151811062004d715762004d7162009e56565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905562004dae8162009ebb565b905062004d4c565b5060005b815181101562004e27576001604883838151811062004ddd5762004ddd62009e56565b602002602001015160405162004df491906200a42d565b908152604051908190036020019020805491151560ff1990921691909117905562004e1f8162009ebb565b905062004dba565b5062004e477330151da466ec8ab345bef3d6983023e050fb067362008cd4565b505080156200174b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b336120001462004eba57604051630f22c43960e41b8152612000600482015260240162001133565b7faa5ba621c8b3d7d05bb9e51a7506108251d4d5dbe542ca66fc7bb52aacb02b6583838360405162004eef939291906200a44b565b60405180910390a1505050565b600054630100000090046001600160a01b0316331462004f2f576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff161562004f5a57604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b600062004fa3603f8462007d41565b62004fc15760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383811660009081526041602052604090819020600201549051636bbf224960e01b815260048101859052911690636bbf2249906024015b602060405180830381865afa1580156200501e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062005044919062009d80565b90505b92915050565b60005462010000900460ff16156200507857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620050aa5760405163b1d02c3d60e01b815260040160405180910390fd5b81620050b8603f8262007d41565b620050d65760405163056e881160e01b815260040160405180910390fd5b6037543490811015620050fc5760405163dc6f0bdd60e01b815260040160405180910390fd5b6001600160a01b0380851660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180543394916080840191620051649062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620051929062009cd1565b8015620051e35780601f10620051b757610100808354040283529160200191620051e3565b820191906000526020600020905b815481529060010190602001808311620051c557829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200520e9062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200523c9062009cd1565b80156200528d5780601f1062005261576101008083540402835291602001916200528d565b820191906000526020600020905b8154815290600101906020018083116200526f57829003601f168201915b50505050508152602001600182018054620052a89062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620052d69062009cd1565b8015620053275780601f10620052fb5761010080835404028352916020019162005327565b820191906000526020600020905b8154815290600101906020018083116200530957829003601f168201915b50505050508152602001600282018054620053429062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620053709062009cd1565b8015620053c15780601f106200539557610100808354040283529160200191620053c1565b820191906000526020600020905b815481529060010190602001808311620053a357829003601f168201915b50505050508152602001600382018054620053dc9062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200540a9062009cd1565b80156200545b5780601f106200542f576101008083540402835291602001916200545b565b820191906000526020600020905b8154815290600101906020018083116200543d57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620054e75750505050508152505090508060e0015180156200552a5750856001600160a01b0316826001600160a01b031614155b156200554957604051636468920360e01b815260040160405180910390fd5b60408082015190516317066a5760e21b81526001600160a01b0384811660048301526000921690635c19a95c90869060240160206040518083038185885af11580156200559a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190620055c1919062009d80565b9050826001600160a01b0316876001600160a01b03166000805160206200b757833981519152838760405162005601929190918252602082015260400190565b60405180910390a36040808301519051633041949b60e01b815261200591633041949b91620056369190879060040162009d07565b600060405180830381600087803b1580156200565157600080fd5b505af115801562005666573d6000803e3d6000fd5b50505050851562001744576040516372f6ad8f60e11b81526120059063e5ed5b1e906200569a9086908b9060040162009d07565b600060405180830381600087803b158015620056b557600080fd5b505af1158015620056ca573d6000803e3d6000fd5b5050505050505050505050565b620057036040518060800160405280606081526020016060815260200160608152602001606081525090565b8162005711603f8262007d41565b6200572f5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03831660009081526041602052604090819020815160808101909252600501805482908290620057669062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620057949062009cd1565b8015620057e55780601f10620057b957610100808354040283529160200191620057e5565b820191906000526020600020905b815481529060010190602001808311620057c757829003601f168201915b50505050508152602001600182018054620058009062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200582e9062009cd1565b80156200587f5780601f1062005853576101008083540402835291602001916200587f565b820191906000526020600020905b8154815290600101906020018083116200586157829003601f168201915b505050505081526020016002820180546200589a9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620058c89062009cd1565b8015620059195780601f10620058ed5761010080835404028352916020019162005919565b820191906000526020600020905b815481529060010190602001808311620058fb57829003601f168201915b50505050508152602001600382018054620059349062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620059629062009cd1565b8015620059b35780601f106200598757610100808354040283529160200191620059b3565b820191906000526020600020905b8154815290600101906020018083116200599557829003601f168201915b505050505081525050915050919050565b60005462010000900460ff1615620059ef57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562005a215760405163b1d02c3d60e01b815260040160405180910390fd5b62005a2d828262008d6d565b5050565b336110071462005a5957604051630f22c43960e41b8152611007600482015260240162001133565b62005ac66040518060400160405280601081526020016f1d1c985b9cd9995c91d85cd31a5b5a5d60821b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b1562005b81576020811462005af85783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f840181900481028201810190925282815260009162005b3b91858580838501838280828437600092019190915250929392505062008ed69050565b90506108fc81108062005b4f575061271081115b1562005b785784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b6035556200688b565b62005bf26040518060400160405280601481526020017336b4b729b2b6332232b632b3b0ba34b7b721272160611b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b1562005cbc576020811462005c245783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f840181900481028201810190925282815260009162005c6791858580838501838280828437600092019190915250929392505062008ed69050565b9050683635c9adc5dea0000081108062005c8a575069152d02c7e14af680000081115b1562005cb35784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b6036556200688b565b62005d2f604051806040016040528060168152602001756d696e44656c65676174696f6e424e424368616e676560501b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b1562005df6576020811462005d615783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f840181900481028201810190925282815260009162005da491858580838501838280828437600092019190915250929392505062008ed69050565b905067016345785d8a000081108062005dc45750678ac7230489e8000081115b1562005ded5784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b6037556200688b565b62005e67604051806040016040528060148152602001736d6178456c656374656456616c696461746f727360601b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b1562005f1f576020811462005e995783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f840181900481028201810190925282815260009162005edc91858580838501838280828437600092019190915250929392505062008ed69050565b905080158062005eed57506101f481115b1562005f165784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b6038556200688b565b62005f886040518060400160405280600c81526020016b1d5b989bdb9914195c9a5bd960a21b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b1562006045576020811462005fba5783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f840181900481028201810190925282815260009162005ffd91858580838501838280828437600092019190915250929392505062008ed69050565b90506203f48081108062006013575062278d0081115b156200603c5784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b6039556200688b565b620060b360405180604001604052806011815260200170726564656c65676174654665655261746560781b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b15620061605760208114620060e55783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f84018190048102820181019092528281526000916200612891858580838501838280828437600092019190915250929392505062008ed69050565b90506064811115620061575784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b603a556200688b565b620061d060405180604001604052806013815260200172191bdddb9d1a5b5954db185cda105b5bdd5b9d606a1b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b15620062915760208114620062025783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f84018190048102820181019092528281526000916200624591858580838501838280828437600092019190915250929392505062008ed69050565b9050674563918244f400008110806200625f5750603c5481115b15620062885784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b603b556200688b565b620062ff6040518060400160405280601181526020017019995b1bdb9e54db185cda105b5bdd5b9d607a1b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b15620063c25760208114620063315783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f84018190048102820181019092528281526000916200637491858580838501838280828437600092019190915250929392505062008ed69050565b905068056bc75e2d63100000811080620063905750603b548111155b15620063b95784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b603c556200688b565b6200642f6040518060400160405280601081526020016f646f776e74696d654a61696c54696d6560801b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b15620064ec5760208114620064615783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f8401819004810282018101909252828152600091620064a491858580838501838280828437600092019190915250929392505062008ed69050565b90506202a300811080620064ba5750603e548110155b15620064e35784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b603d556200688b565b620065576040518060400160405280600e81526020016d66656c6f6e794a61696c54696d6560901b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b15620066145760208114620065895783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f8401819004810282018101909252828152600091620065cc91858580838501838280828437600092019190915250929392505062008ed69050565b9050620d2f00811080620065e25750603d548111155b156200660b5784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b603e556200688b565b6200668e6040518060400160405280601c81526020017f6d617846656c6f6e794265747765656e42726561746865426c6f636b0000000081525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b156200673a5760208114620066c05783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b604080516020601f84018190048102820181019092528281526000916200670391858580838501838280828437600092019190915250929392505062008ed69050565b905080600003620067315784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b604a556200688b565b620067a86040518060400160405280601181526020017039ba30b5b2a43ab1283937ba32b1ba37b960791b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e799050565b15620068685760148114620067da5783838383604051630a5a604160e01b81526004016200113394939291906200a46a565b600062006822601484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008ed69050565b90506001600160a01b038116620068565784848484604051630a5a604160e01b81526004016200113394939291906200a46a565b620068618162008edb565b506200688b565b838383836040516325ee20d560e21b81526004016200113394939291906200a46a565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e63384848484604051620068c294939291906200a46a565b60405180910390a150505050565b60005462010000900460ff1615620068fb57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200692d5760405163b1d02c3d60e01b815260040160405180910390fd5b816000816001600160401b038111156200694b576200694b62009554565b60405190808252806020026020018201604052801562006975578160200160208202803683370190505b5090506000805b8381101562006a7357620069be8787838181106200699e576200699e62009e56565b9050602002016020810190620069b59190620093e3565b603f9062007d41565b620069dc5760405163056e881160e01b815260040160405180910390fd5b60416000888884818110620069f557620069f562009e56565b905060200201602081019062006a0c9190620093e3565b6001600160a01b039081168252602082019290925260400160002060020154845191169250829084908390811062006a485762006a4862009e56565b6001600160a01b039092166020928302919091019091015262006a6b8162009ebb565b90506200697c565b50604051634484077560e01b815261200590634484077590620027f4908590889060040162009e6c565b606080600062006aae603f620088d1565b90508085101562006c7257831562006ac7578362006ac9565b805b935060008462006ada878462009e26565b1162006af25762006aec868362009e26565b62006af4565b845b9050806001600160401b0381111562006b115762006b1162009554565b60405190808252806020026020018201604052801562006b3b578160200160208202803683370190505b509350806001600160401b0381111562006b595762006b5962009554565b60405190808252806020026020018201604052801562006b83578160200160208202803683370190505b50925060005b8181101562006c6f5762006ba262003966828962009d6a565b85828151811062006bb75762006bb762009e56565b60200260200101906001600160a01b031690816001600160a01b0316815250506041600086838151811062006bf05762006bf062009e56565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060020160009054906101000a90046001600160a01b031684828151811062006c445762006c4462009e56565b6001600160a01b039092166020928302919091019091015262006c678162009ebb565b905062006b89565b50505b9250925092565b336110011462006ca157604051630f22c43960e41b8152611001600482015260240162001133565b60005462010000900460ff161562006ccc57604051631785c68160e01b815260040160405180910390fd5b6001600160a01b038082166000908152604360205260409020541662006cf4603f8262007d41565b62006d125760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062006d3a620151804262009d47565b604a546000828152604b60205260409020549192501162006d6e5760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062006d8f90849062009d6a565b90915550506001600160a01b0384166000908152604460205260409020541580159062006de457506001600160a01b038416600090815260446020526040902054429062006de290620151809062009d6a565b105b1562006e03576040516330abb81d60e21b815260040160405180910390fd5b60008062006e1385600062007d64565b915091508162006e3657604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562006e89573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062006eaf919062009d80565b905062006ebd858362007dee565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600060405162006efd9392919062009db0565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b916200569a916001600160a01b0316908a9060040162009d07565b6001600160a01b038082166000908152604160209081526040808320815161016081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384938493849390929160808401919062006fac9062009cd1565b80601f016020809104026020016040519081016040528092919081815260200182805462006fda9062009cd1565b80156200702b5780601f1062006fff576101008083540402835291602001916200702b565b820191906000526020600020905b8154815290600101906020018083116200700d57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620070569062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620070849062009cd1565b8015620070d55780601f10620070a957610100808354040283529160200191620070d5565b820191906000526020600020905b815481529060010190602001808311620070b757829003601f168201915b50505050508152602001600182018054620070f09062009cd1565b80601f01602080910402602001604051908101604052809291908181526020018280546200711e9062009cd1565b80156200716f5780601f1062007143576101008083540402835291602001916200716f565b820191906000526020600020905b8154815290600101906020018083116200715157829003601f168201915b505050505081526020016002820180546200718a9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620071b89062009cd1565b8015620072095780601f10620071dd5761010080835404028352916020019162007209565b820191906000526020600020905b815481529060010190602001808311620071eb57829003601f168201915b50505050508152602001600382018054620072249062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620072529062009cd1565b8015620072a35780601f106200727757610100808354040283529160200191620072a3565b820191906000526020600020905b8154815290600101906020018083116200728557829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b8154815260200190600101908083116200732f5750505091909252505050606081015160e0820151610100909201519097919650945092505050565b60005462010000900460ff16156200739657604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620073c85760405163b1d02c3d60e01b815260040160405180910390fd5b33620073d6603f8262007d41565b620073f45760405163056e881160e01b815260040160405180910390fd5b336000818152604160205260409020600c81015442906200741a90620151809062009d6a565b11156200743a57604051631f92cdbd60e11b815260040160405180910390fd5b6005810180546200744b9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620074799062009cd1565b8015620074ca5780601f106200749e57610100808354040283529160200191620074ca565b820191906000526020600020905b815481529060010190602001808311620074ac57829003601f168201915b5050508287525085916005840191508190620074e790826200a495565b5060208201516001820190620074fe90826200a495565b50604082015160028201906200751590826200a495565b50606082015160038201906200752c90826200a495565b505042600c830155506040516001600160a01b038316907f85d6366b336ade7f106987ec7a8eac1e8799e508aeab045a39d2f63e0dc969d990600090a250505050565b60005462010000900460ff16156200759a57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620075cc5760405163b1d02c3d60e01b815260040160405180910390fd5b828114620075ed576040516341abc80160e01b815260040160405180910390fd5b60005b838110156200765e576200764b85858381811062007612576200761262009e56565b9050602002016020810190620076299190620093e3565b8484848181106200763e576200763e62009e56565b9050602002013562008d6d565b620076568162009ebb565b9050620075f0565b5050505050565b6001600160a01b0380821660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549293849390916080840191620076d09062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620076fe9062009cd1565b80156200774f5780601f1062007723576101008083540402835291602001916200774f565b820191906000526020600020905b8154815290600101906020018083116200773157829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200777a9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620077a89062009cd1565b8015620077f95780601f10620077cd57610100808354040283529160200191620077f9565b820191906000526020600020905b815481529060010190602001808311620077db57829003601f168201915b50505050508152602001600182018054620078149062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620078429062009cd1565b8015620078935780601f10620078675761010080835404028352916020019162007893565b820191906000526020600020905b8154815290600101906020018083116200787557829003601f168201915b50505050508152602001600282018054620078ae9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620078dc9062009cd1565b80156200792d5780601f1062007901576101008083540402835291602001916200792d565b820191906000526020600020905b8154815290600101906020018083116200790f57829003601f168201915b50505050508152602001600382018054620079489062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620079769062009cd1565b8015620079c75780601f106200799b57610100808354040283529160200191620079c7565b820191906000526020600020905b815481529060010190602001808311620079a957829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b81548152602001906001019080831162007a535750505091909252505050604001519392505050565b600062007a8b603f8462007d41565b62007aa95760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038381166000908152604160205260409081902060020154905163aa1966cd60e01b81526004810185905291169063aa1966cd9060240162005000565b60005462010000900460ff161562007b1857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562007b4a5760405163b1d02c3d60e01b815260040160405180910390fd5b3362007b58603f8262007d41565b62007b765760405163056e881160e01b815260040160405180910390fd5b3362007b86818787878762008a8c565b62007ba457604051631647e3cb60e11b815260040160405180910390fd5b60006001600160a01b03166045878760405162007bc392919062009d21565b908152604051908190036020019020546001600160a01b031614158062007c0d57506048868660405162007bf992919062009d21565b9081526040519081900360200190205460ff165b1562007c2c576040516311fdb94760e01b815260040160405180910390fd5b6001600160a01b0381166000908152604160205260409020600c810154429062007c5b90620151809062009d6a565b111562007c7b57604051631f92cdbd60e11b815260040160405180910390fd5b4260468260040160405162007c9191906200a55d565b908152604051908190036020019020556004810162007cb287898362009f7f565b5042600c820155604051829060459062007cd0908a908a9062009d21565b90815260405190819003602001812080546001600160a01b039384166001600160a01b0319909116179055908316907f783156582145bd0ff7924fae6953ba054cf1233eb60739a200ddb10de068ff0d9062007d30908a908a906200a250565b60405180910390a250505050505050565b6001600160a01b0381166000908152600183016020526040812054151562005044565b6000806000848460405160200162007d7e9291906200a5db565b60408051601f1981840301815291815281516020928301206000818152604c9093529120549091504281111562007dbe5760008093509350505062007de7565b603e5462007dcd904262009d6a565b6000928352604c6020526040909220829055506001925090505b9250929050565b8154604051631507fdb760e11b81526001600160a01b03909116600482015261100090632a0ffb6e90602401600060405180830381600087803b15801562007e3557600080fd5b505af115801562007e4a573d6000803e3d6000fd5b505050506000600162007e5e603f620088d1565b62007e6a919062009e26565b604954108015915062007f285760405163d31f968d60e01b81526110006004820152600860248201526120009063d31f968d90604401602060405180830381865afa15801562007ebe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062007ee4919062009ddf565b62007f285760018301546040516001600160a01b03909116907f2afdc18061ac21cff7d9f11527ab9c8dec6fabd4edf6f894ed634bebd6a20d4590600090a2505050565b82600b015482111562007f3d57600b83018290555b600a83015460ff1662007fb057600a8301805460ff191660019081179091556049805460009062007f7090849062009d6a565b909155505060018301546040516001600160a01b03909116907f4905ac32602da3fb8b4b7b00c285e5fc4c6c2308cc908b4a1e4e9625a29c90a390600090a25b505050565b60408051608080820183526000808352602080840182905283850182905260608085018390528551938401865282845283820183905283860183905283018290528451808601865282815281018290528451808601909552855185528581019085015291928290620080279062008f47565b90506000805b620080388362008fba565b156200810b57806000036200806d576200805c620080568462008fe0565b62009044565b6001600160a01b03168452620080f8565b80600103620080995762008085620080568462008fe0565b6001600160a01b03166020850152620080f8565b80600203620080c557620080b1620080568462008fe0565b6001600160a01b03166040850152620080f8565b80600303620080f257620080e3620080dd8462008fe0565b6200905c565b606085015260019150620080f8565b6200810b565b620081038162009ebb565b90506200802d565b5091959194509092505050565b6000805462010000900460ff16156200814457604051631785c68160e01b815260040160405180910390fd5b6020808301516001600160a01b031660009081526001909152604090205460ff16806200817c575060208201516001600160a01b0316155b156200819b5760405163b1d02c3d60e01b815260040160405180910390fd5b8151620081ab90603f9062007d41565b620081b857506002919050565b81516001600160a01b03908116600090815260416020908152604080832081516101608101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805492939192608084019190620082249062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620082529062009cd1565b8015620082a35780601f106200827757610100808354040283529160200191620082a3565b820191906000526020600020905b8154815290600101906020018083116200828557829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620082ce9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620082fc9062009cd1565b80156200834d5780601f1062008321576101008083540402835291602001916200834d565b820191906000526020600020905b8154815290600101906020018083116200832f57829003601f168201915b50505050508152602001600182018054620083689062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620083969062009cd1565b8015620083e75780601f10620083bb57610100808354040283529160200191620083e7565b820191906000526020600020905b815481529060010190602001808311620083c957829003601f168201915b50505050508152602001600282018054620084029062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620084309062009cd1565b8015620084815780601f10620084555761010080835404028352916020019162008481565b820191906000526020600020905b8154815290600101906020018083116200846357829003601f168201915b505050505081526020016003820180546200849c9062009cd1565b80601f0160208091040260200160405190810160405280929190818152602001828054620084ca9062009cd1565b80156200851b5780601f10620084ef576101008083540402835291602001916200851b565b820191906000526020600020905b815481529060010190602001808311620084fd57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620085a75750505050508152505090508060e001518015620085f2575082600001516001600160a01b031683602001516001600160a01b031614155b15620086015750600392915050565b6040808201516060850151602086015192516317066a5760e21b81526001600160a01b03938416600482015260009390921691635c19a95c919060240160206040518083038185885af11580156200865d573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062008684919062009d80565b905083602001516001600160a01b031684600001516001600160a01b03166000805160206200b757833981519152838760600151604051620086d0929190918252602082015260400190565b60405180910390a383602001516001600160a01b031684600001516001600160a01b03167f607b17598da6bdca05650a2fc08bd2bc8e38c3236806a0fa8e0daabc1d6cb1d883876060015160405162008733929190918252602082015260400190565b60405180910390a360408083015160208601519151633041949b60e01b815261200592633041949b926200876d9290919060040162009d07565b600060405180830381600087803b1580156200878857600080fd5b505af11580156200879d573d6000803e3d6000fd5b506000979650505050505050565b6001600160a01b0381166000908152604160205260409020600a81015460ff1615620087d5575050565b6036546002820154604051630913db4760e01b81526001600160a01b03858116600483015290911690630913db4790602401602060405180830381865afa15801562008825573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200884b919062009d80565b101562005a2d576200886d81603d544262008867919062009d6a565b62007dee565b80546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b158015620088b457600080fd5b505af1158015620088c9573d6000803e3d6000fd5b505050505050565b600062005047825490565b600062005044838362009134565b60008082905060038151108062008902575060098151115b15620089115750600092915050565b60418160008151811062008929576200892962009e56565b016020015160f81c10806200895b5750605a8160008151811062008951576200895162009e56565b016020015160f81c115b156200896a5750600092915050565b60015b815181101562008a825760308282815181106200898e576200898e62009e56565b016020015160f81c1080620089bf57506039828281518110620089b557620089b562009e56565b016020015160f81c115b801562008a0f57506041828281518110620089de57620089de62009e56565b016020015160f81c108062008a0f5750605a82828151811062008a055762008a0562009e56565b016020015160f81c115b801562008a5f5750606182828151811062008a2e5762008a2e62009e56565b016020015160f81c108062008a5f5750607a82828151811062008a555762008a5562009e56565b016020015160f81c115b1562008a6f575060009392505050565b62008a7a8162009ebb565b90506200896d565b5060019392505050565b600060308414158062008aa0575060608214155b1562008aaf5750600062008bb3565b60008686864660405160200162008aca94939291906200a619565b60408051808303601f1901815282825280516020918201208184528383019092529092506000919060208201818036833701905050905081602082015260008186868a8a60405160200162008b249594939291906200a646565b60408051808303601f190181526001808452838301909252925060009190602082018180368337019050509050815160016020830182602086016066600019fa62008b6e57600080fd5b5060008160008151811062008b875762008b8762009e56565b016020015160f81c90506001811462008ba95760009550505050505062008bb3565b6001955050505050505b95945050505050565b60008061200361dead60405162008bd390620093bf565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f08015801562008c16573d6000803e3d6000fd5b509050806001600160a01b031663f399e22e3486866040518463ffffffff1660e01b815260040162008c4a9291906200a67e565b6000604051808303818588803b15801562008c6457600080fd5b505af115801562008c79573d6000803e3d6000fd5b50506040516001600160a01b038086169450881692507fd481492e4e93bb36b4c12a5af93f03be3bf04b454dfbc35dd2663fa26f44d5b09150600090a39392505050565b600062005044836001600160a01b03841662009161565b600054610100900460ff1662008d415760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162001133565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b8162008d7b603f8262007d41565b62008d995760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03838116600090815260416020526040808220600201549051635569f64b60e11b8152336004820152602481018690529192169063aad3ec96906044016020604051808303816000875af115801562008dfd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008e23919062009d80565b9050336001600160a01b0316846001600160a01b03167ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd39926838360405162008e6b91815260200190565b60405180910390a350505050565b60008160405160200162008e8e91906200a42d565b604051602081830303815290604052805190602001208360405160200162008eb791906200a42d565b6040516020818303038152906040528051906020012014905092915050565b015190565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b604080516080810182526000918101828152606082018390528152602081019190915262008f7582620091b3565b62008f7f57600080fd5b600062008f908360200151620091e6565b836020015162008fa1919062009d6a565b6040805180820190915293845260208401525090919050565b8051805160208201516000929162008fd29162009d6a565b836020015110915050919050565b604080518082019091526000808252602082015262008fff8262008fba565b6200900957600080fd5b602082015160006200901b8262009275565b905062009029818362009d6a565b60209485015260408051808201909152908152928301525090565b80516000906015146200905657600080fd5b62005047825b8051600090158015906200907257508151602110155b6200907c57600080fd5b60006200908d8360200151620091e6565b90508083600001511015620090e55760405162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015260640162001133565b8251600090620090f790839062009e26565b90506000808386602001516200910e919062009d6a565b90508051915060208310156200912b57826020036101000a820491505b50949350505050565b60008260000182815481106200914e576200914e62009e56565b9060005260206000200154905092915050565b6000818152600183016020526040812054620091aa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562005047565b50600062005047565b80516000908103620091c757506000919050565b6020820151805160001a9060c082101562008a82575060009392505050565b8051600090811a6080811015620092005750600092915050565b60b88110806200921d575060c081108015906200921d575060f881105b156200922c5750600192915050565b60c0811015620092675762009244600160b86200a6a4565b620092539060ff168262009e26565b6200926090600162009d6a565b9392505050565b62009244600160f86200a6a4565b80516000908190811a6080811015620092925760019150620093b8565b60b8811015620092be57620092a960808262009e26565b620092b690600162009d6a565b9150620093b8565b60c08110156200933757600060b78203600186019550806020036101000a865104915060018101820193505080831015620093305760405162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015260640162001133565b50620093b8565b60f88110156200934e57620092a960c08262009e26565b600060f78203600186019550806020036101000a865104915060018101820193505080831015620093b65760405162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015260640162001133565b505b5092915050565b610e96806200a6c183390190565b6001600160a01b03811681146200174b57600080fd5b600060208284031215620093f657600080fd5b81356200926081620093cd565b60008083601f8401126200941657600080fd5b5081356001600160401b038111156200942e57600080fd5b60208301915083602082850101111562007de757600080fd5b600080602083850312156200945b57600080fd5b82356001600160401b038111156200947257600080fd5b620094808582860162009403565b90969095509350505050565b600080600060408486031215620094a257600080fd5b833560ff81168114620094b457600080fd5b925060208401356001600160401b03811115620094d057600080fd5b620094de8682870162009403565b9497909650939450505050565b60005b8381101562009508578181015183820152602001620094ee565b50506000910152565b600081518084526200952b816020860160208601620094eb565b601f01601f19169290920160200192915050565b60208152600062005044602083018462009511565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200958f576200958f62009554565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620095c057620095c062009554565b604052919050565b60006001600160401b03821115620095e457620095e462009554565b50601f01601f191660200190565b6000620096096200960384620095c8565b62009595565b90508281528383830111156200961e57600080fd5b828260208301376000602084830101529392505050565b6000602082840312156200964857600080fd5b81356001600160401b038111156200965f57600080fd5b8201601f810184136200967157600080fd5b6200968284823560208401620095f2565b949350505050565b600080604083850312156200969e57600080fd5b8235620096ab81620093cd565b946020939093013593505050565b80151581146200174b57600080fd5b60008060008060808587031215620096df57600080fd5b8435620096ec81620093cd565b93506020850135620096fe81620093cd565b92506040850135915060608501356200971781620096b9565b939692955090935050565b6001600160401b03811681146200174b57600080fd5b6000602082840312156200974b57600080fd5b8135620092608162009722565b600080604083850312156200976c57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015620097b65781516001600160a01b0316875295820195908201906001016200978f565b509495945050505050565b608081526000620097d660808301876200977b565b82810360208481019190915286518083528782019282019060005b818110156200980f57845183529383019391830191600101620097f1565b5050848103604086015286518082528282019350600581901b8201830183890160005b838110156200986457601f198584030187526200985183835162009511565b9686019692509085019060010162009832565b5050809550505050505082606083015295945050505050565b600080600080600080600087890360e08112156200989a57600080fd5b8835620098a781620093cd565b975060208901356001600160401b0380821115620098c457600080fd5b620098d28c838d0162009403565b909950975060408b0135915080821115620098ec57600080fd5b620098fa8c838d0162009403565b90975095508591506060605f19840112156200991557600080fd5b60608b01945060c08b01359250808311156200993057600080fd5b505088016080818b0312156200994557600080fd5b8091505092959891949750929550565b600080604083850312156200996957600080fd5b82356200997681620093cd565b915060208301356200998881620096b9565b809150509250929050565b602081526000825160806020840152620099b160a084018262009511565b90506020840151601f1980858403016040860152620099d1838362009511565b92506040860151915080858403016060860152620099f0838362009511565b925060608601519150808584030160808601525062008bb3828262009511565b6000806000806040858703121562009a2757600080fd5b84356001600160401b038082111562009a3f57600080fd5b62009a4d8883890162009403565b9096509450602087013591508082111562009a6757600080fd5b5062009a768782880162009403565b95989497509550505050565b60008083601f84011262009a9557600080fd5b5081356001600160401b0381111562009aad57600080fd5b6020830191508360208260051b850101111562007de757600080fd5b60008060006040848603121562009adf57600080fd5b83356001600160401b0381111562009af657600080fd5b62009b048682870162009a82565b909450925050602084013562009b1a81620093cd565b809150509250925092565b60608152600062009b3a60608301866200977b565b828103602084015262009b4e81866200977b565b915050826040830152949350505050565b600082601f83011262009b7157600080fd5b6200504483833560208501620095f2565b60006020828403121562009b9557600080fd5b81356001600160401b038082111562009bad57600080fd5b908301906080828603121562009bc257600080fd5b62009bcc6200956a565b82358281111562009bdc57600080fd5b62009bea8782860162009b5f565b82525060208301358281111562009c0057600080fd5b62009c0e8782860162009b5f565b60208301525060408301358281111562009c2757600080fd5b62009c358782860162009b5f565b60408301525060608301358281111562009c4e57600080fd5b62009c5c8782860162009b5f565b60608301525095945050505050565b6000806000806040858703121562009c8257600080fd5b84356001600160401b038082111562009c9a57600080fd5b62009ca88883890162009a82565b9096509450602087013591508082111562009cc257600080fd5b5062009a768782880162009a82565b600181811c9082168062009ce657607f821691505b6020821081036200458a57634e487b7160e01b600052602260045260246000fd5b6001600160a01b0392831681529116602082015260400190565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b60008262009d6557634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562005047576200504762009d31565b60006020828403121562009d9357600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b83815260208101839052606081016003831062009dd15762009dd162009d9a565b826040830152949350505050565b60006020828403121562009df257600080fd5b81516200926081620096b9565b828152604081016004831062009e195762009e1962009d9a565b8260208301529392505050565b8181038181111562005047576200504762009d31565b808202811582820484141762005047576200504762009d31565b634e487b7160e01b600052603260045260246000fd5b60408152600062009e8160408301856200977b565b905060018060a01b03831660208301529392505050565b6001600160401b03828116828216039080821115620093b857620093b862009d31565b60006001820162009ed05762009ed062009d31565b5060010190565b6000808335601e1984360301811262009eef57600080fd5b8301803591506001600160401b0382111562009f0a57600080fd5b60200191503681900382131562007de757600080fd5b601f82111562007fb057600081815260208120601f850160051c8101602086101562009f495750805b601f850160051c820191505b81811015620088c95782815560010162009f55565b600019600383901b1c191660019190911b1790565b6001600160401b0383111562009f995762009f9962009554565b62009fb18362009faa835462009cd1565b8362009f20565b6000601f84116001811462009fe4576000851562009fcf5750838201355b62009fdb868262009f6a565b8455506200765e565b600083815260209020601f19861690835b828110156200a017578685013582556020948501946001909201910162009ff5565b50868210156200a0355760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6200a053828362009ed7565b6001600160401b038111156200a06d576200a06d62009554565b6200a085816200a07e855462009cd1565b8562009f20565b6000601f8211600181146200a0b857600083156200a0a35750838201355b6200a0af848262009f6a565b8655506200a115565b600085815260209020601f19841690835b828110156200a0eb57868501358255602094850194600190920191016200a0c9565b50848210156200a1095760001960f88660031b161c19848701351681555b505060018360011b0185555b505050506200a128602083018362009ed7565b6200a13881836001860162009f7f565b50506200a149604083018362009ed7565b6200a15981836002860162009f7f565b50506200a16a606083018362009ed7565b6200a17a81836003860162009f7f565b50505050565b81356200a18d8162009722565b6001600160401b03811690508154816001600160401b0319821617835560208401356200a1ba8162009722565b6fffffffffffffffff0000000000000000604091821b166fffffffffffffffffffffffffffffffff198316841781178555908501356200a1fa8162009722565b6001600160c01b0319929092169092179190911760809190911b67ffffffffffffffff60801b1617905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000620096826020830184866200a227565b60006001600160401b038211156200a282576200a28262009554565b5060051b60200190565b600060208083850312156200a2a057600080fd5b82516001600160401b038111156200a2b757600080fd5b8301601f810185136200a2c957600080fd5b80516200a2da62009603826200a266565b81815260059190911b820183019083810190878311156200a2fa57600080fd5b928401925b828410156200a3255783516200a31581620093cd565b825292840192908401906200a2ff565b979650505050505050565b600060208083850312156200a34457600080fd5b82516001600160401b03808211156200a35c57600080fd5b818501915085601f8301126200a37157600080fd5b81516200a38262009603826200a266565b81815260059190911b830184019084810190888311156200a3a257600080fd5b8585015b838110156200a420578051858111156200a3c05760008081fd5b8601603f81018b136200a3d35760008081fd5b8781015160406200a3e86200960383620095c8565b8281528d828486010111156200a3fe5760008081fd5b6200a40f838c8301848701620094eb565b86525050509186019186016200a3a6565b5098975050505050505050565b600082516200a441818460208701620094eb565b9190910192915050565b60ff8416815260406020820152600062008bb36040830184866200a227565b6040815260006200a4806040830186886200a227565b82810360208401526200a3258185876200a227565b81516001600160401b038111156200a4b1576200a4b162009554565b6200a4c9816200a4c2845462009cd1565b8462009f20565b602080601f8311600181146200a4fd57600084156200a4e85750858301515b6200a4f4858262009f6a565b865550620088c9565b600085815260208120601f198616915b828110156200a52e578886015182559484019460019091019084016200a50d565b50858210156200a54d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200a56d8162009cd1565b600182811680156200a58857600181146200a59e576200a5cf565b60ff19841687528215158302870194506200a5cf565b8760005260208060002060005b858110156200a5c65781548a8201529084019082016200a5ab565b50505082870194505b50929695505050505050565b6bffffffffffffffffffffffff198360601b1681526000600383106200a605576200a60562009d9a565b5060f89190911b6014820152601501919050565b6bffffffffffffffffffffffff198560601b16815282846014830137601492019182015260340192915050565b600086516200a65a818460208b01620094eb565b82018587823760009086019081528385823760009301928352509095945050505050565b6001600160a01b0383168152604060208201819052600090620096829083018462009511565b60ff828116828216039081111562005047576200504762009d3156fe608060405260405162000e9638038062000e96833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e6f60279139620002f8565b9392505050565b60006200018060008051602062000e4f83398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e4f83398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61087580620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65640000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000001284214b9b9c85549ab3d2b972df0deef66ac2c9000000000000000000000000a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0000000000000000000000000980a75ecd1309ea12fa2ed87a8744fbfc9b863d5000000000000000000000000b71b214cb885500844365e95cd9942c7276e7fd800000000000000000000000035552c16704d214347f29fa77f77da6d75d7c752000000000000000000000000f474cf03cceff28abc65c9cbae594f725c80e12d00000000000000000000000096c5d20b2a975c050e4220be276ace4892f4b41a00000000000000000000000047788386d0ed6c748e03a53160b4b30ed3748cc5000000000000000000000000bdfbc016c1bd481f5d8ca6f754f4b200a7ed66ce000000000000000000000000372e4887005ec21a5aff9ff62eda9e7713e3643700000000000000000000000055c968cf3430f3ba0534ef49ff4b3fbc9086c7ce000000000000000000000000136bd6343049c9690569db79dcd9208a57d342ad000000000000000000000000977ecef7de795cd248d77fd0d080ce3a35dec013000000000000000000000000b334ced91dff560bc9b5b3c30ae613bf335f181324d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e040000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000308e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b973c2d38487e58fd6e145491b110080fb14ac915a0411fc78f19e09a399ddee0d20c63a75d8f930f1694544ad2dc01b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003089037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003096c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b87800000000000000000000000000000000a164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(StakeCreditContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106101e75760003560e01c8063647df75911610102578063a9664feb11610095578063d241c1ea11610064578063d241c1ea1461068d578063dd62ed3e146106cf578063f1fad104146106ef578063f399e22e1461070457600080fd5b8063a9664feb14610600578063aa1966cd14610620578063aad3ec961461064d578063c2cde2b21461066d57600080fd5b806395d89b41116100d157806395d89b411461058b578063a457c2d7146105a0578063a5d059ca146105c0578063a9059cbb146105e057600080fd5b8063647df759146104e85780636bbf22491461050857806370a082311461053557806391faf0b41461056b57600080fd5b8063313ce5671161017a5780634bf6c882116101495780634bf6c8821461048b5780634d99dd16146104a05780635c19a95c146104c05780635e607d76146104d357600080fd5b8063313ce567146103f157806339509351146104135780633a5381b51461043357806345bc4d101461046b57600080fd5b806315d1f898116101b657806315d1f8981461038657806318160ddd1461039c57806323b872dd146103b15780632f2d448a146103d157600080fd5b8063038c0023146102e157806306fdde03146103145780630913db4714610336578063095ea7b31461035657600080fd5b366102dc57336120021461021757604051630f22c43960e41b815261200260048201526024015b60405180910390fd5b60006120026001600160a01b0316631fa8882b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610259573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027d9190611de4565b6102879042611e13565b6098546000828152609d6020908152604080832093909355609c9052908120805492935034929091906102bb908490611e35565b9250508190555034609860008282546102d49190611e35565b925050819055005b600080fd5b3480156102ed57600080fd5b506103016102fc366004611e60565b610717565b6040519081526020015b60405180910390f35b34801561032057600080fd5b50610329610747565b60405161030b9190611e84565b34801561034257600080fd5b50610301610351366004611e60565b6107d9565b34801561036257600080fd5b50610376610371366004611ed2565b6107fb565b604051901515815260200161030b565b34801561039257600080fd5b5061030160985481565b3480156103a857600080fd5b50606754610301565b3480156103bd57600080fd5b506103766103cc366004611efe565b610813565b3480156103dd57600080fd5b506103016103ec366004611e60565b610837565b3480156103fd57600080fd5b5060125b60405160ff909116815260200161030b565b34801561041f57600080fd5b5061037661042e366004611ed2565b6108fc565b34801561043f57600080fd5b50609754610453906001600160a01b031681565b6040516001600160a01b03909116815260200161030b565b34801561047757600080fd5b50610301610486366004611f3f565b61091e565b34801561049757600080fd5b50610401600881565b3480156104ac57600080fd5b506103016104bb366004611ed2565b610a11565b6103016104ce366004611e60565b610c28565b6104e66104e1366004611f58565b610c9e565b005b3480156104f457600080fd5b50610301610503366004611f3f565b610e11565b34801561051457600080fd5b50610301610523366004611f3f565b609d6020526000908152604090205481565b34801561054157600080fd5b50610301610550366004611e60565b6001600160a01b031660009081526065602052604090205490565b34801561057757600080fd5b50610301610586366004611f3f565b610e50565b34801561059757600080fd5b50610329610e8b565b3480156105ac57600080fd5b506103766105bb366004611ed2565b610e9a565b3480156105cc57600080fd5b506103016105db366004611ed2565b610f15565b3480156105ec57600080fd5b506103766105fb366004611ed2565b611016565b34801561060c57600080fd5b5061030161061b366004611ed2565b611024565b34801561062c57600080fd5b5061030161063b366004611f3f565b609c6020526000908152604090205481565b34801561065957600080fd5b50610301610668366004611ed2565b61114d565b34801561067957600080fd5b50610301610688366004611e60565b6113f0565b34801561069957600080fd5b506106ad6106a8366004611ed2565b61140e565b604080518251815260208084015190820152918101519082015260600161030b565b3480156106db57600080fd5b506103016106ea366004611f82565b611491565b3480156106fb57600080fd5b50610401601181565b6104e6610712366004611fbb565b6114bc565b6001600160a01b0381166000908152609a6020526040812054600f81810b600160801b909204900b035b92915050565b60606068805461075690612040565b80601f016020809104026020016040519081016040528092919081815260200182805461078290612040565b80156107cf5780601f106107a4576101008083540402835291602001916107cf565b820191906000526020600020905b8154815290600101906020018083116107b257829003601f168201915b5050505050905090565b6001600160a01b03811660009081526065602052604081205461074190610e50565b600033610809818585611672565b5060019392505050565b60003361082185828561168b565b61082c8585856116ff565b506001949350505050565b6001600160a01b0381166000908152609a6020526040812054600f81810b600160801b909204900b0381805b828110156108f4576001600160a01b0385166000908152609a6020526040812061088d9083611718565b6000818152609960209081526040918290208251606081018452815481526001820154928101929092526002015491810182905291925042106108da576108d384612074565b93506108e1565b50506108f4565b5050806108ed90612074565b9050610863565b509392505050565b60003361080981858561090f8383611491565b6109199190611e35565b611672565b6000336120021461094657604051630f22c43960e41b8152612002600482015260240161020e565b6097546001600160a01b03166000908152606560205260408120549061096b84610e11565b905081811161097a578061097c565b815b609754909150600090610998906001600160a01b031683611789565b6040519091506000906110029083908381818185875af1925050503d80600081146109df576040519150601f19603f3d011682016040523d82523d6000602084013e6109e4565b606091505b5050905080610a06576040516312171d8360e31b815260040160405180910390fd5b50925050505b919050565b60003361200214610a3957604051630f22c43960e41b8152612002600482015260240161020e565b81600003610a5a57604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038316600090815260656020526040902054821115610a9357604051631e9acf1760e31b815260040160405180910390fd5b610a9d8383611789565b905060006120026001600160a01b031663fc0c5ff16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b059190611de4565b610b0f9042611e35565b6040805160608101825285815260208101859052908101829052909150600085610b38816117be565b60405160609290921b6bffffffffffffffffffffffff19166020830152603482015260540160408051601f1981840301815291815281516020928301206000818152609990935291205490915015610ba35760405163b19e911560e01b815260040160405180910390fd5b600081815260996020908152604080832085518155828601516001820155818601516002909101556001600160a01b0389168352609a9091529020610c1f90828154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b50505092915050565b60003361200214610c5057604051630f22c43960e41b8152612002600482015260240161020e565b34600003610c7157604051631f2a200560e01b815260040160405180910390fd5b610c7b82346117e6565b905080600003610a0c57604051639811e0c760e01b815260040160405180910390fd5b3361200214610cc457604051630f22c43960e41b8152612002600482015260240161020e565b346000612710610cde67ffffffffffffffff85168461208d565b610ce89190611e13565b90506000610cf682846120a4565b905060006120026001600160a01b0316631fa8882b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5e9190611de4565b610d689042611e13565b6098546000828152609d6020908152604080832093909355609c905290812080549293508492909190610d9c908490611e35565b925050819055508160986000828254610db59190611e35565b9091555050609754610dd0906001600160a01b0316846117e6565b5060408051838152602081018590527ffb0e1482d62102ab9594f69d4c6d693749e3e2bf1c21af272f5456b2d5a4f6b5910160405180910390a15050505050565b6000609854600003610e36576040516307b76ce760e51b815260040160405180910390fd5b609854606754610e46908461208d565b6107419190611e13565b6000610e5b60675490565b600003610e7b57604051632fe8dae960e01b815260040160405180910390fd5b606754609854610e46908461208d565b60606069805461075690612040565b60003381610ea88286611491565b905083811015610f085760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161020e565b61082c8286868403611672565b60003361200214610f3d57604051630f22c43960e41b8152612002600482015260240161020e565b81600003610f5e57604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038316600090815260656020526040902054821115610f9757604051631e9acf1760e31b815260040160405180910390fd5b610fa18383611789565b6040519091506000906120029083908381818185875af1925050503d8060008114610fe8576040519150601f19603f3d011682016040523d82523d6000602084013e610fed565b606091505b505090508061100f576040516312171d8360e31b815260040160405180910390fd5b5092915050565b6000336108098185856116ff565b6001600160a01b0382166000908152609a6020526040812054600f81810b600160801b909204900b0360000361105c57506000610741565b81158061109057506001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b0382115b61109a57816110c4565b6001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b035b91506000805b838110156108f4576001600160a01b0385166000908152609a602052604081206110f49083611718565b600081815260996020908152604091829020825160608101845281548152600182015492810183905260029091015492810192909252919250906111389085611e35565b935050508061114690612074565b90506110ca565b6000336120021461117557604051630f22c43960e41b8152612002600482015260240161020e565b61117d61180f565b6001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b036000036111c65760405163ad41893760e01b815260040160405180910390fd5b8115806111fa57506001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b0382115b611204578161122e565b6001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b035b915060005b82156112e4576001600160a01b0384166000908152609a6020526040812061125a90611868565b6000818152609960209081526040918290208251606081018452815481526001820154928101929092526002015491810182905291925042101561129f5750506112e4565b6001600160a01b0386166000908152609a602052604090206112c0906118bc565b5060208101516112d09084611e35565b92506112db856120b7565b94505050611233565b80600003611305576040516303cd8e0960e21b815260040160405180910390fd5b60006120026001600160a01b031663e8f67c3b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136b9190611de4565b90506000856001600160a01b03168284604051600060405180830381858888f193505050503d80600081146113bc576040519150601f19603f3d011682016040523d82523d6000602084013e6113c1565b606091505b50509050806113e3576040516312171d8360e31b815260040160405180910390fd5b5050600180559050610741565b6001600160a01b0381166000908152609b6020526040812054610741565b61143260405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152609a602052604081206114549084611718565b6000908152609960209081526040918290208251606081018452815481526001820154928101929092526002015491810191909152949350505050565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205490565b600054610100900460ff16158080156114dc5750600054600160ff909116105b806114f65750303b1580156114f6575060005460ff166001145b6115595760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161020e565b6000805460ff19166001179055801561157c576000805461ff0019166101001790555b33612002146115a257604051630f22c43960e41b8152612002600482015260240161020e565b600083836040516020016115b79291906120ce565b6040516020818303038152906040529050600084846040516020016115dd9291906120fe565b60405160208183030381529060405290506115f88282611941565b611600611986565b609780546001600160a01b0319166001600160a01b038816179055611624346119ad565b5050801561166c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b604051632028747160e01b815260040160405180910390fd5b60006116978484611491565b9050600019811461166c57818110156116f25760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161020e565b61166c8484848403611672565b604051638cd22d1960e01b815260040160405180910390fd5b60008061173b61172784611b1d565b85546117369190600f0b61211c565b611b8b565b8454909150600160801b9004600f90810b9082900b1261176e57604051632d0483c560e21b815260040160405180910390fd5b600f0b60009081526001939093016020525050604090205490565b600061179482610e50565b90506117a08383611bef565b80609860008282546117b291906120a4565b90915550909392505050565b6001600160a01b0381166000908152609b602052604090208054600181018255905b50919050565b60006117f182610e11565b90506117fd8382611d23565b81609860008282546117b29190611e35565b6002600154036118615760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161020e565b6002600155565b60006118838254600f81810b600160801b909204900b131590565b156118a157604051631ed9509560e11b815260040160405180910390fd5b508054600f0b60009081526001909101602052604090205490565b60006118d78254600f81810b600160801b909204900b131590565b156118f557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b60018055565b600054610100900460ff166119685760405162461bcd60e51b815260040161020e90612144565b606861197483826121f3565b50606961198182826121f3565b505050565b600054610100900460ff1661193b5760405162461bcd60e51b815260040161020e90612144565b600054610100900460ff166119d45760405162461bcd60e51b815260040161020e90612144565b60006120026001600160a01b0316638a4d3fa86040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3a9190611de4565b90508082111580611a5457506097546001600160a01b0316155b80611a60575060675415155b15611a7e57604051632163e6b960e21b815260040160405180910390fd5b60006120026001600160a01b0316634e6fd6c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ac0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae491906122b3565b9050611af08183611d23565b6000611afc83856120a4565b609754909150611b15906001600160a01b031682611d23565b505050609855565b60006001600160ff1b03821115611b875760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b606482015260840161020e565b5090565b80600f81900b8114610a0c5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b606482015260840161020e565b6001600160a01b038216611c4f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161020e565b6001600160a01b03821660009081526065602052604090205481811015611cc35760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161020e565b6001600160a01b03831660008181526065602090815260408083208686039055606780548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6001600160a01b038216611d795760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161020e565b8060676000828254611d8b9190611e35565b90915550506001600160a01b0382166000818152606560209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208284031215611df657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082611e3057634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561074157610741611dfd565b6001600160a01b0381168114611e5d57600080fd5b50565b600060208284031215611e7257600080fd5b8135611e7d81611e48565b9392505050565b600060208083528351808285015260005b81811015611eb157858101830151858201604001528201611e95565b506000604082860101526040601f19601f8301168501019250505092915050565b60008060408385031215611ee557600080fd5b8235611ef081611e48565b946020939093013593505050565b600080600060608486031215611f1357600080fd5b8335611f1e81611e48565b92506020840135611f2e81611e48565b929592945050506040919091013590565b600060208284031215611f5157600080fd5b5035919050565b600060208284031215611f6a57600080fd5b813567ffffffffffffffff81168114611e7d57600080fd5b60008060408385031215611f9557600080fd5b8235611fa081611e48565b91506020830135611fb081611e48565b809150509250929050565b600080600060408486031215611fd057600080fd5b8335611fdb81611e48565b9250602084013567ffffffffffffffff80821115611ff857600080fd5b818601915086601f83011261200c57600080fd5b81358181111561201b57600080fd5b87602082850101111561202d57600080fd5b6020830194508093505050509250925092565b600181811c9082168061205457607f821691505b6020821081036117e057634e487b7160e01b600052602260045260246000fd5b60006001820161208657612086611dfd565b5060010190565b808202811582820484141761074157610741611dfd565b8181038181111561074157610741611dfd565b6000816120c6576120c6611dfd565b506000190190565b65029ba30b5b2960d51b815281836006830137660810dc99591a5d60ca1b91016006810191909152600d01919050565b611cdd60f21b81528183600283013760009101600201908152919050565b808201828112600083128015821682158216171561213c5761213c611dfd565b505092915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561198157600081815260208120601f850160051c810160208610156121cc5750805b601f850160051c820191505b818110156121eb578281556001016121d8565b505050505050565b815167ffffffffffffffff81111561220d5761220d61218f565b6122218161221b8454612040565b846121a5565b602080601f831160018114612256576000841561223e5750858301515b600019600386901b1c1916600185901b1785556121eb565b600085815260208120601f198616915b8281101561228557888601518255948401946001909101908401612266565b50858210156122a35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156122c557600080fd5b8151611e7d81611e4856fea164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(GovernorContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106103f35760003560e01c80637b3c71d311610208578063c28bc2fa11610118578063e23a9a52116100ab578063f1fad1041161007a578063f1fad10414610e46578063f23a6e6114610e5b578063f8ce560a14610e87578063fc0c546a14610ea7578063fe0d94c114610ec857600080fd5b8063e23a9a5214610d1b578063ea0217cf14610de6578063eb9019d414610e06578063ece40cc114610e2657600080fd5b8063da95691a116100e7578063da95691a14610c61578063dd4e2ba514610c81578063ddf0b00914610cc7578063deaaa7cc14610ce757600080fd5b8063c28bc2fa14610bef578063c59057e414610c02578063d07f91e914610c22578063d33219b414610c4257600080fd5b8063a7713a701161019b578063b187bd261161016a578063b187bd2614610b55578063b58131b014610b73578063bc197c8114610b88578063c01f9e3714610bb4578063c170ec0b14610bd457600080fd5b8063a7713a7014610ae0578063a890c91014610af5578063ab58fb8e14610b15578063ac43175114610b3557600080fd5b806384b0196e116101d757806384b0196e14610a5857806391ddadf414610a8057806397c3d33414610aac5780639a802a6d14610ac057600080fd5b80637b3c71d3146109ee5780637d5e81e214610a0e5780638129fc1c14610a2e5780638456cb5914610a4357600080fd5b80633932abb1116103035780634a49ac4c1161029657806354fd4d501161026557806354fd4d5014610944578063567813881461096e5780635f398a141461098e57806360c4247f146109ae57806370b0f660146109ce57600080fd5b80634a49ac4c146108b75780634bf5d7e9146108d75780634bf6c882146108ec578063533ddd141461091357600080fd5b8063417c73a7116102d2578063417c73a7146107fc578063438596321461081c578063452115d6146108675780634838d1651461088757600080fd5b80633932abb1146107795780633bccf4fd1461078f5780633e4f49e6146107af57806340e58ee5146107dc57600080fd5b8063150b7a02116103865780632656227d116103555780632656227d146106a25780632d63f693146106b55780632fe3e261146106ec578063328dd9821461072057806332b8113e1461075057600080fd5b8063150b7a02146105fb578063160cbed71461063f57806317977c611461065f57806324bc1a641461068d57600080fd5b8063046f7da2116103c2578063046f7da21461054e57806306f3f9e61461056357806306fdde0314610583578063143489d0146105a557600080fd5b8063013cf08b1461046357806301ffc9a7146104de57806302a251a31461050e578063034201811461052e57600080fd5b3661045e5730610401610edb565b6001600160a01b03161461045c5760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206d7573742073656e6420746f206578656375746f720060448201526064015b60405180910390fd5b005b600080fd5b34801561046f57600080fd5b5061048361047e366004615c8a565b610ef5565b604080519a8b526001600160a01b0390991660208b0152978901969096526060880194909452608087019290925260a086015260c085015260e084015215156101008301521515610120820152610140015b60405180910390f35b3480156104ea57600080fd5b506104fe6104f9366004615ca3565b610fb0565b60405190151581526020016104d5565b34801561051a57600080fd5b50610195545b6040519081526020016104d5565b34801561053a57600080fd5b50610520610549366004615de9565b610fc1565b34801561055a57600080fd5b5061045c6110b9565b34801561056f57600080fd5b5061045c61057e366004615c8a565b611149565b34801561058f57600080fd5b506105986111d4565b6040516104d59190615edf565b3480156105b157600080fd5b506105e36105c0366004615c8a565b60009081526101636020526040902054600160401b90046001600160a01b031690565b6040516001600160a01b0390911681526020016104d5565b34801561060757600080fd5b50610626610616366004615f07565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016104d5565b34801561064b57600080fd5b5061052061065a3660046160de565b611267565b34801561066b57600080fd5b5061052061067a36600461616d565b6102c36020526000908152604090205481565b34801561069957600080fd5b50610520611352565b6105206106b03660046160de565b611378565b3480156106c157600080fd5b506105206106d0366004615c8a565b600090815261016360205260409020546001600160401b031690565b3480156106f857600080fd5b506105207fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b34801561072c57600080fd5b5061074061073b366004615c8a565b61146b565b6040516104d59493929190616253565b34801561075c57600080fd5b5061028f546040516001600160401b0390911681526020016104d5565b34801561078557600080fd5b5061019454610520565b34801561079b57600080fd5b506105206107aa3660046162a0565b6116fd565b3480156107bb57600080fd5b506107cf6107ca366004615c8a565b611773565b6040516104d59190616304565b3480156107e857600080fd5b5061045c6107f7366004615c8a565b61177e565b34801561080857600080fd5b5061045c61081736600461616d565b6117a9565b34801561082857600080fd5b506104fe61083736600461632c565b60008281526101c6602090815260408083206001600160a01b038516845260080190915290205460ff1692915050565b34801561087357600080fd5b506105206108823660046160de565b61182a565b34801561089357600080fd5b506104fe6108a236600461616d565b60016020526000908152604090205460ff1681565b3480156108c357600080fd5b5061045c6108d236600461616d565b611838565b3480156108e357600080fd5b506105986118b3565b3480156108f857600080fd5b50610901600881565b60405160ff90911681526020016104d5565b34801561091f57600080fd5b506104fe61092e36600461616d565b6102c16020526000908152604090205460ff1681565b34801561095057600080fd5b506040805180820190915260018152603160f81b6020820152610598565b34801561097a57600080fd5b5061052061098936600461635c565b611960565b34801561099a57600080fd5b506105206109a9366004616388565b611989565b3480156109ba57600080fd5b506105206109c9366004615c8a565b6119d3565b3480156109da57600080fd5b5061045c6109e9366004615c8a565b611a88565b3480156109fa57600080fd5b50610520610a0936600461640b565b611b10565b348015610a1a57600080fd5b50610520610a29366004616464565b611b62565b348015610a3a57600080fd5b5061045c611c7d565b348015610a4f57600080fd5b5061045c611eae565b348015610a6457600080fd5b50610a6d611f44565b6040516104d59796959493929190616504565b348015610a8c57600080fd5b50610a95611fe2565b60405165ffffffffffff90911681526020016104d5565b348015610ab857600080fd5b506064610520565b348015610acc57600080fd5b50610520610adb366004616566565b612056565b348015610aec57600080fd5b5061052061206d565b348015610b0157600080fd5b5061045c610b1036600461616d565b61209a565b348015610b2157600080fd5b50610520610b30366004615c8a565b612122565b348015610b4157600080fd5b5061045c610b503660046165be565b6121be565b348015610b6157600080fd5b5060005462010000900460ff166104fe565b348015610b7f57600080fd5b50610520612903565b348015610b9457600080fd5b50610626610ba336600461661d565b63bc197c8160e01b95945050505050565b348015610bc057600080fd5b50610520610bcf366004615c8a565b61290f565b348015610be057600080fd5b506102c2546104fe9060ff1681565b61045c610bfd3660046166b0565b61291a565b348015610c0e57600080fd5b50610520610c1d3660046160de565b612a2a565b348015610c2e57600080fd5b5061045c610c3d3660046166f3565b612a64565b348015610c4e57600080fd5b5061022b546001600160a01b03166105e3565b348015610c6d57600080fd5b50610520610c7c36600461671c565b612aec565b348015610c8d57600080fd5b5060408051808201909152601a81527f737570706f72743d627261766f2671756f72756d3d627261766f0000000000006020820152610598565b348015610cd357600080fd5b5061045c610ce2366004615c8a565b612b73565b348015610cf357600080fd5b506105207f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610d2757600080fd5b50610db6610d3636600461632c565b60408051606081018252600080825260208201819052918101919091525060009182526101c6602090815260408084206001600160a01b0393909316845260089092018152918190208151606081018352905460ff8082161515835261010082041693820193909352620100009092046001600160601b03169082015290565b6040805182511515815260208084015160ff1690820152918101516001600160601b0316908201526060016104d5565b348015610df257600080fd5b5061045c610e01366004615c8a565b612b96565b348015610e1257600080fd5b50610520610e213660046167bd565b612c1e565b348015610e3257600080fd5b5061045c610e41366004615c8a565b612c3f565b348015610e5257600080fd5b50610901601181565b348015610e6757600080fd5b50610626610e763660046167e9565b63f23a6e6160e01b95945050505050565b348015610e9357600080fd5b50610520610ea2366004615c8a565b612cc7565b348015610eb357600080fd5b506101f8546105e3906001600160a01b031681565b61045c610ed6366004615c8a565b612d56565b6000610ef061022b546001600160a01b031690565b905090565b8060008080808080808080610f098a612122565b60008c815261016360205260409020549098506001600160401b03169650610f308b61290f565b60008c81526101c66020526040812080546005820154600683015460078401546001600160a01b039093169e50949a509850929650919450610f718d611773565b90506002816007811115610f8757610f876162ee565b1493506007816007811115610f9e57610f9e6162ee565b14925050509193959799509193959799565b6000610fbb82612d79565b92915050565b60008061106561105d7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c604051610ffd929190616851565b60405180910390208b80519060200120604051602001611042959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b60405160208183030381529060405280519060200120612d9e565b868686612dcb565b90506110ab8a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d9250612de9915050565b9a9950505050505050505050565b600054630100000090046001600160a01b031633146110eb576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1661111457604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b611151610edb565b6001600160a01b0316336001600160a01b0316146111815760405162461bcd60e51b815260040161045390616861565b3061118a610edb565b6001600160a01b0316146111c857600080366040516111aa929190616851565b604051809103902090505b806111c1610164612e52565b036111b557505b6111d181612ed1565b50565b606061016280546111e490616898565b80601f016020809104026020016040519081016040528092919081815260200182805461121090616898565b801561125d5780601f106112325761010080835404028352916020019161125d565b820191906000526020600020905b81548152906001019060200180831161124057829003601f168201915b5050505050905090565b6000805462010000900460ff161561129257604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156112c35760405163b1d02c3d60e01b815260040160405180910390fd5b60005b855181101561133c576102c160008783815181106112e6576112e66168d2565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1661132a57604051630b094f2760e31b815260040160405180910390fd5b80611334816168fe565b9150506112c6565b5061134985858585613042565b95945050505050565b6000610ef06001611361611fe2565b61136b9190616917565b65ffffffffffff16612cc7565b60008061138786868686612a2a565b9050600061139482611773565b905060048160078111156113aa576113aa6162ee565b14806113c7575060058160078111156113c5576113c56162ee565b145b6113e35760405162461bcd60e51b81526004016104539061693d565b6000828152610163602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f906114329084815260200190565b60405180910390a16114478288888888613247565b61145482888888886132e8565b61146182888888886133ca565b5095945050505050565b60608060608060006101c66000878152602001908152602001600020905080600101816002018260030183600401838054806020026020016040519081016040528092919081815260200182805480156114ee57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114d0575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561154057602002820191906000526020600020905b81548152602001906001019080831161152c575b5050505050925081805480602002602001604051908101604052809291908181526020016000905b8282101561161457838290600052602060002001805461158790616898565b80601f01602080910402602001604051908101604052809291908181526020018280546115b390616898565b80156116005780601f106115d557610100808354040283529160200191611600565b820191906000526020600020905b8154815290600101906020018083116115e357829003601f168201915b505050505081526020019060010190611568565b50505050915080805480602002602001604051908101604052809291908181526020016000905b828210156116e757838290600052602060002001805461165a90616898565b80601f016020809104026020016040519081016040528092919081815260200182805461168690616898565b80156116d35780601f106116a8576101008083540402835291602001916116d3565b820191906000526020600020905b8154815290600101906020018083116116b657829003601f168201915b50505050508152602001906001019061163b565b5050505090509450945094509450509193509193565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff85166060820152600090819061174b9061105d90608001611042565b905061176887828860405180602001604052806000815250613405565b979650505050505050565b6000610fbb82613428565b60008060008061178d85613575565b93509350935093506117a18484848461182a565b505050505050565b600054630100000090046001600160a01b031633146117db576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b600061134985858585613806565b600054630100000090046001600160a01b0316331461186a576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b6101f85460408051634bf5d7e960e01b815290516060926001600160a01b031691634bf5d7e99160048083019260009291908290030181865afa92505050801561191f57506040513d6000823e601f3d908101601f1916820160405261191c919081019061697e565b60015b61195b575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b60008033905061198184828560405180602001604052806000815250613405565b949350505050565b60008033905061176887828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250612de9915050565b61025e546000908082036119ec57505061025d54919050565b600061025e6119fc6001846169eb565b81548110611a0c57611a0c6168d2565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b03169282019290925291508410611a6257602001516001600160e01b03169392505050565b611a77611a6e856138d1565b61025e9061393a565b6001600160e01b0316949350505050565b611a90610edb565b6001600160a01b0316336001600160a01b031614611ac05760405162461bcd60e51b815260040161045390616861565b30611ac9610edb565b6001600160a01b031614611b075760008036604051611ae9929190616851565b604051809103902090505b80611b00610164612e52565b03611af457505b6111d1816139ed565b600080339050611b5886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061340592505050565b9695505050505050565b6000805462010000900460ff1615611b8d57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615611bbe5760405163b1d02c3d60e01b815260040160405180910390fd5b611bc6613a30565b3360009081526102c360205260409020548015611c3b576000611be882611773565b90506001816007811115611bfe57611bfe6162ee565b1480611c1b57506000816007811115611c1957611c196162ee565b145b15611c395760405163867f3ee560e01b815260040160405180910390fd5b505b825160208401206000611c5088888885612a2a565b3360009081526102c3602052604090208190559050611c7188888888613adb565b98975050505050505050565b600054610100900460ff1615808015611c9d5750600054600160ff909116105b80611cb75750303b158015611cb7575060005460ff166001145b611d1a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610453565b6000805460ff191660011790558015611d3d576000805461ff0019166101001790555b334114611d5d5760405163022d8c9560e31b815260040160405180910390fd5b3a15611d7c576040516383f1b1d360e01b815260040160405180910390fd5b611da86040518060400160405280600b81526020016a2129a1a3b7bb32b93737b960a91b815250613b43565b611dd4611db760036000616a14565b611dc5600362015180616a14565b68056bc75e2d63100000613b9a565b611ddc613bd1565b611de7612005613bf8565b611df2612006613c28565b611dfc600a613c58565b611e11611e0c6003610e10616a14565b613c88565b6110076000526102c16020527f2f832952f0ef896b8c8edd6d16a2e4f2591a90375e33021e3b9ff197f3793fc0805460ff19166001179055611e667330151da466ec8ab345bef3d6983023e050fb0673613cb8565b80156111d1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b600054630100000090046001600160a01b03163314611ee0576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1615611f0a57604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b6000606080600080600060606098546000801b148015611f645750609954155b611fa85760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606401610453565b611fb0613d0b565b611fb8613d1a565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6101f854604080516324776b7d60e21b815290516000926001600160a01b0316916391ddadf49160048083019260209291908290030181865afa925050508015612049575060408051601f3d908101601f1916820190925261204691810190616a36565b60015b61195b57610ef043613d29565b6000612063848484613d90565b90505b9392505050565b61025e54600090156120925761208461025e613e07565b6001600160e01b0316905090565b5061025d5490565b6120a2610edb565b6001600160a01b0316336001600160a01b0316146120d25760405162461bcd60e51b815260040161045390616861565b306120db610edb565b6001600160a01b03161461211957600080366040516120fb929190616851565b604051809103902090505b80612112610164612e52565b0361210657505b6111d181613e37565b61022b54600082815261022c602052604080822054905163d45c443560e01b81526004810191909152909182916001600160a01b039091169063d45c443590602401602060405180830381865afa158015612181573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a59190616a5e565b9050806001146121b55780612066565b60009392505050565b33611007146121e457604051630f22c43960e41b81526110076004820152602401610453565b61224a6040518060400160405280600b81526020016a766f74696e6744656c617960a81b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ea29050565b156122ff57602081146122785783838383604051630a5a604160e01b81526004016104539493929190616aa0565b604080516020601f84018190048102820181019092528281526000916122b9918585808385018382808284376000920191909152509293925050613efb9050565b90508015806122ca57506201518081115b156122f05784848484604051630a5a604160e01b81526004016104539493929190616aa0565b6122f9816139ed565b506128c0565b6123666040518060400160405280600c81526020016b1d9bdd1a5b99d4195c9a5bd960a21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ea29050565b1561241557602081146123945783838383604051630a5a604160e01b81526004016104539493929190616aa0565b604080516020601f84018190048102820181019092528281526000916123d5918585808385018382808284376000920191909152509293925050613efb9050565b90508015806123e6575062278d0081115b1561240c5784848484604051630a5a604160e01b81526004016104539493929190616aa0565b6122f981613f00565b612481604051806040016040528060118152602001701c1c9bdc1bdcd85b151a1c995cda1bdb19607a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ea29050565b1561253757602081146124af5783838383604051630a5a604160e01b81526004016104539493929190616aa0565b604080516020601f84018190048102820181019092528281526000916124f0918585808385018382808284376000920191909152509293925050613efb9050565b9050801580612508575069021e19e0c9bab240000081115b1561252e5784848484604051630a5a604160e01b81526004016104539493929190616aa0565b6122f981613fa3565b6125a16040518060400160405280600f81526020016e38bab7b93ab6a73ab6b2b930ba37b960891b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ea29050565b1561265057602081146125cf5783838383604051630a5a604160e01b81526004016104539493929190616aa0565b604080516020601f8401819004810282018101909252828152600091612610918585808385018382808284376000920191909152509293925050613efb9050565b905060058110806126215750601481115b156126475784848484604051630a5a604160e01b81526004016104539493929190616aa0565b6122f981612ed1565b6126bf604051806040016040528060148152602001736d696e506572696f64416674657251756f72756d60601b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ea29050565b1561278557600881146126ed5783838383604051630a5a604160e01b81526004016104539493929190616aa0565b6000612733600884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613efb9050565b90506001600160401b038116158061275657506202a300816001600160401b0316115b1561277c5784848484604051630a5a604160e01b81526004016104539493929190616aa0565b6122f981613fe6565b6127f16040518060400160405280601181526020017033b7bb32b93737b9283937ba32b1ba37b960791b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ea29050565b1561289f576014811461281f5783838383604051630a5a604160e01b81526004016104539493929190616aa0565b6000612865601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613efb9050565b90506001600160a01b0381166128965784848484604051630a5a604160e01b81526004016104539493929190616aa0565b6122f981614052565b838383836040516325ee20d560e21b81526004016104539493929190616aa0565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516128f59493929190616aa0565b60405180910390a150505050565b6000610ef06101965490565b6000610fbb826140be565b612922610edb565b6001600160a01b0316336001600160a01b0316146129525760405162461bcd60e51b815260040161045390616861565b3061295b610edb565b6001600160a01b031614612999576000803660405161297b929190616851565b604051809103902090505b80612992610164612e52565b0361298657505b600080856001600160a01b03168585856040516129b7929190616851565b60006040518083038185875af1925050503d80600081146129f4576040519150601f19603f3d011682016040523d82523d6000602084013e6129f9565b606091505b5091509150612a218282604051806060016040528060288152602001616efd602891396140fc565b50505050505050565b600084848484604051602001612a439493929190616ac7565b60408051601f19818403018152919052805160209091012095945050505050565b612a6c610edb565b6001600160a01b0316336001600160a01b031614612a9c5760405162461bcd60e51b815260040161045390616861565b30612aa5610edb565b6001600160a01b031614612ae35760008036604051612ac5929190616851565b604051809103902090505b80612adc610164612e52565b03612ad057505b6111d181613fe6565b60008251845114612b505760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72427261766f3a20696e76616c6964207369676e61747572656044820152670e640d8cadccee8d60c31b6064820152608401610453565b612b5e338787878787614115565b611b588686612b6d87876141d3565b85611b62565b600080600080612b8285613575565b93509350935093506117a184848484611267565b612b9e610edb565b6001600160a01b0316336001600160a01b031614612bce5760405162461bcd60e51b815260040161045390616861565b30612bd7610edb565b6001600160a01b031614612c155760008036604051612bf7929190616851565b604051809103902090505b80612c0e610164612e52565b03612c0257505b6111d181613f00565b60006120668383612c3a60408051602081019091526000815290565b613d90565b612c47610edb565b6001600160a01b0316336001600160a01b031614612c775760405162461bcd60e51b815260040161045390616861565b30612c80610edb565b6001600160a01b031614612cbe5760008036604051612ca0929190616851565b604051809103902090505b80612cb7610164612e52565b03612cab57505b6111d181613fa3565b60006064612cd4836119d3565b6101f854604051632394e7a360e21b8152600481018690526001600160a01b0390911690638e539e8c90602401602060405180830381865afa158015612d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d429190616a5e565b612d4c9190616b12565b610fbb9190616a14565b600080600080612d6585613575565b93509350935093506117a184848484611378565b60006001600160e01b03198216636e665ced60e01b1480610fbb5750610fbb82614305565b6000610fbb612dab6143a1565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000612ddc878787876143ab565b915091506114618161446f565b6000805462010000900460ff1615612e1457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615612e455760405163b1d02c3d60e01b815260040160405180910390fd5b611b5886868686866145b9565b6000612e6d8254600f81810b600160801b909204900b131590565b15612e8b57604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b6064811115612f545760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610453565b6000612f5e61206d565b90508015801590612f70575061025e54155b15612fd557604080518082019091526000815261025e9060208101612f94846146bc565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b613003612ff0612fe3611fe2565b65ffffffffffff166138d1565b612ff9846146bc565b61025e9190614725565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60008061305186868686612a2a565b9050600461305e82611773565b600781111561306f5761306f6162ee565b1461308c5760405162461bcd60e51b81526004016104539061693d565b61022b546040805163793d064960e11b815290516000926001600160a01b03169163f27a0c929160048083019260209291908290030181865afa1580156130d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130fb9190616a5e565b61022b5460405163b1c5f42760e01b81529192506001600160a01b03169063b1c5f42790613136908a908a908a906000908b90600401616b29565b602060405180830381865afa158015613153573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131779190616a5e565b600083815261022c60205260408082209290925561022b5491516308f2a0bb60e41b81526001600160a01b0390921691638f2a0bb0916131c4918b918b918b91908b908990600401616b77565b600060405180830381600087803b1580156131de57600080fd5b505af11580156131f2573d6000803e3d6000fd5b505050507f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda28928282426132249190616bcf565b604080519283526020830191909152015b60405180910390a15095945050505050565b30613250610edb565b6001600160a01b0316146132e15760005b84518110156117a157306001600160a01b0316858281518110613286576132866168d2565b60200260200101516001600160a01b0316036132d1576132d18382815181106132b1576132b16168d2565b60200260200101518051906020012061016461474090919063ffffffff16565b6132da816168fe565b9050613261565b5050505050565b60005462010000900460ff161561331257604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156133435760405163b1d02c3d60e01b815260040160405180910390fd5b60005b84518110156133bc576102c16000868381518110613366576133666168d2565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff166133aa57604051630b094f2760e31b815260040160405180910390fd5b806133b4816168fe565b915050613346565b506132e1858585858561477c565b306133d3610edb565b6001600160a01b0316146132e15761016454600f81810b600160801b909204900b13156132e1576000610164556132e1565b60006113498585858561342360408051602081019091526000815290565b612de9565b600080613434836147f1565b9050600481600781111561344a5761344a6162ee565b146134555792915050565b600083815261022c602052604090205480613471575092915050565b61022b54604051632ab0f52960e01b8152600481018390526001600160a01b0390911690632ab0f52990602401602060405180830381865afa1580156134bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134df9190616be2565b156134ee575060079392505050565b61022b54604051632c258a9f60e11b8152600481018390526001600160a01b039091169063584b153e90602401602060405180830381865afa158015613538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061355c9190616be2565b1561356b575060059392505050565b5060029392505050565b60608060606000806101c660008781526020019081526020016000209050806001018160020161374783600301805480602002602001604051908101604052809291908181526020016000905b8282101561366e5783829060005260206000200180546135e190616898565b80601f016020809104026020016040519081016040528092919081815260200182805461360d90616898565b801561365a5780601f1061362f5761010080835404028352916020019161365a565b820191906000526020600020905b81548152906001019060200180831161363d57829003601f168201915b5050505050815260200190600101906135c2565b50505060048601805460408051602080840282018101909252828152935060009084015b8282101561373e5783829060005260206000200180546136b190616898565b80601f01602080910402602001604051908101604052809291908181526020018280546136dd90616898565b801561372a5780601f106136ff5761010080835404028352916020019161372a565b820191906000526020600020905b81548152906001019060200180831161370d57829003601f168201915b505050505081526020019060010190613692565b505050506141d3565b600984015483546040805160208084028201810190925282815291869183018282801561379d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161377f575b50505050509350828054806020026020016040519081016040528092919081815260200182805480156137ef57602002820191906000526020600020905b8154815260200190600101908083116137db575b505050505092509450945094509450509193509193565b60008061381586868686612a2a565b60008181526101c660205260409020549091506001600160a01b0316338114806138695750613842612903565b613867826001613850611fe2565b61385a9190616917565b65ffffffffffff16612c1e565b105b6138c55760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72427261766f3a2070726f706f7365722061626f76652074686044820152661c995cda1bdb1960ca1b6064820152608401610453565b61176887878787614929565b600063ffffffff8211156139365760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610453565b5090565b81546000908181600581111561399757600061395584614937565b61395f90856169eb565b60008881526020902090915081015463ffffffff908116908716101561398757809150613995565b613992816001616bcf565b92505b505b60006139a587878585614a1f565b905080156139e0576139ca876139bc6001846169eb565b600091825260209091200190565b54600160201b90046001600160e01b0316611768565b6000979650505050505050565b6101945460408051918252602082018390527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a93910160405180910390a161019455565b6102c25460ff16613ad9576a084595161401484a0000006120056001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aab9190616a5e565b1015613aca576040516311b6707f60e01b815260040160405180910390fd5b6102c2805460ff191660011790555b565b6000613b3733868686516001600160401b03811115613afc57613afc615d26565b604051908082528060200260200182016040528015613b2f57816020015b6060815260200190600190039081613b1a5790505b508787614115565b61134985858585614a75565b600054610100900460ff16613b6a5760405162461bcd60e51b815260040161045390616c04565b613b9181613b8c6040805180820190915260018152603160f81b602082015290565b614e54565b6111d181614ea3565b600054610100900460ff16613bc15760405162461bcd60e51b815260040161045390616c04565b613bcc838383614edb565b505050565b600054610100900460ff16613ad95760405162461bcd60e51b815260040161045390616c04565b600054610100900460ff16613c1f5760405162461bcd60e51b815260040161045390616c04565b6111d181614f1d565b600054610100900460ff16613c4f5760405162461bcd60e51b815260040161045390616c04565b6111d181614f67565b600054610100900460ff16613c7f5760405162461bcd60e51b815260040161045390616c04565b6111d181614f8e565b600054610100900460ff16613caf5760405162461bcd60e51b815260040161045390616c04565b6111d181614fb5565b600054610100900460ff16613cdf5760405162461bcd60e51b815260040161045390616c04565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b6060609a80546111e490616898565b6060609b80546111e490616898565b600065ffffffffffff8211156139365760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610453565b6101f854604051630748d63560e31b81526001600160a01b038581166004830152602482018590526000921690633a46b1a890604401602060405180830381865afa158015613de3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120639190616a5e565b805460009080156121b557613e21836139bc6001846169eb565b54600160201b90046001600160e01b0316612066565b61022b54604080516001600160a01b03928316815291831660208301527f08f74ea46ef7894f65eabfb5e6e695de773a000b47c529ab559178069b226401910160405180910390a161022b80546001600160a01b0319166001600160a01b0392909216919091179055565b600081604051602001613eb59190616c4f565b6040516020818303038152906040528051906020012083604051602001613edc9190616c4f565b6040516020818303038152906040528051906020012014905092915050565b015190565b60008111613f605760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253657474696e67733a20766f74696e6720706572696f6420604482015266746f6f206c6f7760c81b6064820152608401610453565b6101955460408051918252602082018390527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828910160405180910390a161019555565b6101965460408051918252602082018390527fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc05461910160405180910390a161019655565b61028f54604080516001600160401b03928316815291831660208301527f7ca4ac117ed3cdce75c1161d8207c440389b1a15d69d096831664657c07dafc2910160405180910390a161028f805467ffffffffffffffff19166001600160401b0392909216919091179055565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008181526101636020526040812060010154610fbb906001600160401b0316600084815261029060205260409020546001600160401b0316614fdc565b6060831561410b575081612066565b6120668383614ff2565b805160208201206000614133878761412d88886141d3565b85612a2a565b60008181526101c6602052604090206009810154919250906141c85780546001600160a01b0319166001600160a01b038a16178155875161417d90600183019060208b0190615ac1565b50865161419390600283019060208a0190615b22565b5085516141a99060038301906020890190615b5d565b5084516141bf9060048301906020880190615baf565b50600981018390555b505050505050505050565b6060600082516001600160401b038111156141f0576141f0615d26565b60405190808252806020026020018201604052801561422357816020015b606081526020019060019003908161420e5790505b50905060005b81518110156142fd57848181518110614244576142446168d2565b6020026020010151516000146142b457848181518110614266576142666168d2565b602002602001015180519060200120848281518110614287576142876168d2565b60200260200101516040516020016142a0929190616c6b565b6040516020818303038152906040526142cf565b8381815181106142c6576142c66168d2565b60200260200101515b8282815181106142e1576142e16168d2565b6020026020010181905250806142f6906168fe565b9050614229565b509392505050565b600063288ace0360e11b6318df743f60e31b63bf26d89760e01b6379dd796f60e01b6001600160e01b0319861682148061434b57506001600160e01b0319868116908216145b8061436257506001600160e01b0319868116908516145b8061437d57506001600160e01b03198616630271189760e51b145b80611b5857506301ffc9a760e01b6001600160e01b03198716149695505050505050565b6000610ef061501c565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143e25750600090506003614466565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614436573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661445f57600060019250925050614466565b9150600090505b94509492505050565b6000816004811115614483576144836162ee565b0361448b5750565b600181600481111561449f5761449f6162ee565b036144ec5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610453565b6002816004811115614500576145006162ee565b0361454d5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610453565b6003816004811115614561576145616162ee565b036111d15760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610453565b6000806145c98787878787615090565b600088815261029060205260409020549091506001600160401b03161580156145f657506145f6876151e6565b15611b5857600061461061028f546001600160401b031690565b614618611fe2565b65ffffffffffff1661462a9190616c9c565b90506146358861290f565b816001600160401b03161115614684576040516001600160401b038216815288907f541f725fb9f7c98a30cc9c0ff32fbb14358cd7159c847a3aa20a2bdc442ba5119060200160405180910390a25b600088815261029060205260409020805467ffffffffffffffff19166001600160401b03929092169190911790559695505050505050565b60006001600160e01b038211156139365760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610453565b600080614733858585615226565b915091505b935093915050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b61022b5460405163e38335e560e01b81526001600160a01b039091169063e38335e59034906147b8908890889088906000908990600401616b29565b6000604051808303818588803b1580156147d157600080fd5b505af11580156147e5573d6000803e3d6000fd5b50505050505050505050565b600081815261016360205260408120600281015460ff16156148165750600792915050565b6002810154610100900460ff16156148315750600292915050565b600083815261016360205260408120546001600160401b03169081900361489a5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610453565b60006148a4611fe2565b65ffffffffffff1690508082106148c057506000949350505050565b60006148cb8661290f565b90508181106148e05750600195945050505050565b6148e9866151e6565b801561490c575060008681526101c6602052604090206006810154600590910154115b1561491d5750600495945050505050565b50600395945050505050565b6000611349858585856153c5565b60008160000361494957506000919050565b600060016149568461547b565b901c6001901b9050600181848161496f5761496f6169fe565b048201901c90506001818481614987576149876169fe565b048201901c9050600181848161499f5761499f6169fe565b048201901c905060018184816149b7576149b76169fe565b048201901c905060018184816149cf576149cf6169fe565b048201901c905060018184816149e7576149e76169fe565b048201901c905060018184816149ff576149ff6169fe565b048201901c905061206681828581614a1957614a196169fe565b0461550f565b60005b818310156142fd576000614a36848461551e565b60008781526020902090915063ffffffff86169082015463ffffffff161115614a6157809250614a6f565b614a6c816001616bcf565b93505b50614a22565b600033614a828184615539565b614ace5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73657220726573747269637465640000006044820152606401610453565b6000614ad8611fe2565b65ffffffffffff169050614aea612903565b614af983610e216001856169eb565b1015614b615760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610453565b6000614b768888888880519060200120612a2a565b90508651885114614b995760405162461bcd60e51b815260040161045390616cbc565b8551885114614bba5760405162461bcd60e51b815260040161045390616cbc565b6000885111614c0b5760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610453565b600081815261016360205260409020546001600160401b031615614c7b5760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610453565b6000614c876101945490565b614c919084616bcf565b90506000614c9f6101955490565b614ca99083616bcf565b90506040518060e00160405280614cbf8461562a565b6001600160401b031681526001600160a01b038716602082015260006040820152606001614cec8361562a565b6001600160401b03908116825260006020808401829052604080850183905260609485018390528883526101638252918290208551815492870151878501519186166001600160e01b031990941693909317600160401b6001600160a01b039094168402176001600160e01b0316600160e01b60e09290921c91909102178155938501516080860151908416921c0217600183015560a08301516002909201805460c09094015161ffff1990941692151561ff00191692909217610100931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e91811115614df157614df1615d26565b604051908082528060200260200182016040528015614e2457816020015b6060815260200190600190039081614e0f5790505b508d88888f604051614e3e99989796959493929190616cfd565b60405180910390a1509098975050505050505050565b600054610100900460ff16614e7b5760405162461bcd60e51b815260040161045390616c04565b609a614e878382616ddb565b50609b614e948282616ddb565b50506000609881905560995550565b600054610100900460ff16614eca5760405162461bcd60e51b815260040161045390616c04565b610162614ed78282616ddb565b5050565b600054610100900460ff16614f025760405162461bcd60e51b815260040161045390616c04565b614f0b836139ed565b614f1482613f00565b613bcc81613fa3565b600054610100900460ff16614f445760405162461bcd60e51b815260040161045390616c04565b6101f880546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166121195760405162461bcd60e51b815260040161045390616c04565b600054610100900460ff166111c85760405162461bcd60e51b815260040161045390616c04565b600054610100900460ff16612ae35760405162461bcd60e51b815260040161045390616c04565b6000818311614feb5781612066565b5090919050565b8151156150025781518083602001fd5b8060405162461bcd60e51b81526004016104539190615edf565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f615047615692565b61504f6156eb565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60008581526101636020526040812060016150aa88611773565b60078111156150bb576150bb6162ee565b146151145760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610453565b805460009061512e9088906001600160401b031686613d90565b905061513d888888848861571c565b835160000361519257866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516151859493929190616e9a565b60405180910390a2611768565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb871289888489896040516151d3959493929190616ec2565b60405180910390a2979650505050505050565b60008181526101c660205260408120600581015461521d610ea285600090815261016360205260409020546001600160401b031690565b11159392505050565b82546000908190801561536c576000615244876139bc6001856169eb565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090871610156152c55760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610453565b805163ffffffff80881691160361530d57846152e6886139bc6001866169eb565b80546001600160e01b0392909216600160201b0263ffffffff90921691909117905561535c565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b6020015192508391506147389050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b029190931617920191909155905081614738565b6000806153d4868686866158ba565b600081815261022c6020526040902054909150156113495761022b54600082815261022c60205260409081902054905163c4d252f560e01b81526001600160a01b039092169163c4d252f5916154309160040190815260200190565b600060405180830381600087803b15801561544a57600080fd5b505af115801561545e573d6000803e3d6000fd5b505050600082815261022c60205260408120555095945050505050565b600080608083901c1561549057608092831c92015b604083901c156154a257604092831c92015b602083901c156154b457602092831c92015b601083901c156154c657601092831c92015b600883901c156154d857600892831c92015b600483901c156154ea57600492831c92015b600283901c156154fc57600292831c92015b600183901c15610fbb5760010192915050565b6000818310614feb5781612066565b600061552d6002848418616a14565b61206690848416616bcf565b80516000906034811015615551576001915050610fbb565b82810160131901516001600160a01b031981166b046e0e4dee0dee6cae47a60f60a31b1461558457600192505050610fbb565b6000806155926028856169eb565b90505b83811015615609576000806155c98884815181106155b5576155b56168d2565b01602001516001600160f81b0319166159c7565b91509150816155e15760019650505050505050610fbb565b8060ff166004856001600160a01b0316901b179350505080615602906168fe565b9050615595565b50856001600160a01b0316816001600160a01b031614935050505092915050565b60006001600160401b038211156139365760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610453565b60008061569d613d0b565b8051909150156156b4578051602090910120919050565b60985480156156c35792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b6000806156f6613d1a565b80519091501561570d578051602090910120919050565b60995480156156c35792915050565b60008581526101c6602090815260408083206001600160a01b038816845260088101909252909120805460ff16156157ac5760405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20766f746560448201526c08185b1c9958591e4818d85cdd609a1b6064820152608401610453565b805460ff86166101000261ffff199091161760011781556157cc84615a59565b81546001600160601b039190911662010000026dffffffffffffffffffffffff00001990911617815560ff851661581c57838260060160008282546158119190616bcf565b90915550612a219050565b60001960ff86160161583c57838260050160008282546158119190616bcf565b60011960ff86160161585c57838260070160008282546158119190616bcf565b60405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20696e766160448201526c6c696420766f7465207479706560981b6064820152608401610453565b6000806158c986868686612a2a565b905060006158d682611773565b905060028160078111156158ec576158ec6162ee565b1415801561590c57506006816007811115615909576159096162ee565b14155b801561592a57506007816007811115615927576159276162ee565b14155b6159765760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610453565b6000828152610163602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c906132359084815260200190565b60008060f883901c602f811180156159e25750603a8160ff16105b156159f757600194602f199091019350915050565b8060ff166040108015615a0d575060478160ff16105b15615a22576001946036199091019350915050565b8060ff166060108015615a38575060678160ff16105b15615a4d576001946056199091019350915050565b50600093849350915050565b60006001600160601b038211156139365760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610453565b828054828255906000526020600020908101928215615b16579160200282015b82811115615b1657825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615ae1565b50613936929150615c01565b828054828255906000526020600020908101928215615b16579160200282015b82811115615b16578251825591602001919060010190615b42565b828054828255906000526020600020908101928215615ba3579160200282015b82811115615ba35782518290615b939082616ddb565b5091602001919060010190615b7d565b50613936929150615c16565b828054828255906000526020600020908101928215615bf5579160200282015b82811115615bf55782518290615be59082616ddb565b5091602001919060010190615bcf565b50613936929150615c33565b5b808211156139365760008155600101615c02565b80821115613936576000615c2a8282615c50565b50600101615c16565b80821115613936576000615c478282615c50565b50600101615c33565b508054615c5c90616898565b6000825580601f10615c6c575050565b601f0160209004906000526020600020908101906111d19190615c01565b600060208284031215615c9c57600080fd5b5035919050565b600060208284031215615cb557600080fd5b81356001600160e01b03198116811461206657600080fd5b803560ff8116811461195b57600080fd5b60008083601f840112615cf057600080fd5b5081356001600160401b03811115615d0757600080fd5b602083019150836020828501011115615d1f57600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715615d6457615d64615d26565b604052919050565b60006001600160401b03821115615d8557615d85615d26565b50601f01601f191660200190565b600082601f830112615da457600080fd5b8135615db7615db282615d6c565b615d3c565b818152846020838601011115615dcc57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060e0898b031215615e0557600080fd5b88359750615e1560208a01615ccd565b965060408901356001600160401b0380821115615e3157600080fd5b615e3d8c838d01615cde565b909850965060608b0135915080821115615e5657600080fd5b50615e638b828c01615d93565b945050615e7260808a01615ccd565b925060a0890135915060c089013590509295985092959890939650565b60005b83811015615eaa578181015183820152602001615e92565b50506000910152565b60008151808452615ecb816020860160208601615e8f565b601f01601f19169290920160200192915050565b6020815260006120666020830184615eb3565b6001600160a01b03811681146111d157600080fd5b60008060008060808587031215615f1d57600080fd5b8435615f2881615ef2565b93506020850135615f3881615ef2565b92506040850135915060608501356001600160401b03811115615f5a57600080fd5b615f6687828801615d93565b91505092959194509250565b60006001600160401b03821115615f8b57615f8b615d26565b5060051b60200190565b600082601f830112615fa657600080fd5b81356020615fb6615db283615f72565b82815260059290921b84018101918181019086841115615fd557600080fd5b8286015b84811015615ff9578035615fec81615ef2565b8352918301918301615fd9565b509695505050505050565b600082601f83011261601557600080fd5b81356020616025615db283615f72565b82815260059290921b8401810191818101908684111561604457600080fd5b8286015b84811015615ff95780358352918301918301616048565b600082601f83011261607057600080fd5b81356020616080615db283615f72565b82815260059290921b8401810191818101908684111561609f57600080fd5b8286015b84811015615ff95780356001600160401b038111156160c25760008081fd5b6160d08986838b0101615d93565b8452509183019183016160a3565b600080600080608085870312156160f457600080fd5b84356001600160401b038082111561610b57600080fd5b61611788838901615f95565b9550602087013591508082111561612d57600080fd5b61613988838901616004565b9450604087013591508082111561614f57600080fd5b5061615c8782880161605f565b949793965093946060013593505050565b60006020828403121561617f57600080fd5b813561206681615ef2565b600081518084526020808501945080840160005b838110156161c35781516001600160a01b03168752958201959082019060010161619e565b509495945050505050565b600081518084526020808501945080840160005b838110156161c3578151875295820195908201906001016161e2565b600081518084526020808501808196508360051b8101915082860160005b85811015616246578284038952616234848351615eb3565b9885019893509084019060010161621c565b5091979650505050505050565b608081526000616266608083018761618a565b828103602084015261627881876161ce565b9050828103604084015261628c81866161fe565b9050828103606084015261176881856161fe565b600080600080600060a086880312156162b857600080fd5b853594506162c860208701615ccd565b93506162d660408701615ccd565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b602081016008831061632657634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561633f57600080fd5b82359150602083013561635181615ef2565b809150509250929050565b6000806040838503121561636f57600080fd5b8235915061637f60208401615ccd565b90509250929050565b6000806000806000608086880312156163a057600080fd5b853594506163b060208701615ccd565b935060408601356001600160401b03808211156163cc57600080fd5b6163d889838a01615cde565b909550935060608801359150808211156163f157600080fd5b506163fe88828901615d93565b9150509295509295909350565b6000806000806060858703121561642157600080fd5b8435935061643160208601615ccd565b925060408501356001600160401b0381111561644c57600080fd5b61645887828801615cde565b95989497509550505050565b6000806000806080858703121561647a57600080fd5b84356001600160401b038082111561649157600080fd5b61649d88838901615f95565b955060208701359150808211156164b357600080fd5b6164bf88838901616004565b945060408701359150808211156164d557600080fd5b6164e18883890161605f565b935060608701359150808211156164f757600080fd5b50615f6687828801615d93565b60ff60f81b8816815260e06020820152600061652360e0830189615eb3565b82810360408401526165358189615eb3565b606084018890526001600160a01b038716608085015260a0840186905283810360c085015290506110ab81856161ce565b60008060006060848603121561657b57600080fd5b833561658681615ef2565b92506020840135915060408401356001600160401b038111156165a857600080fd5b6165b486828701615d93565b9150509250925092565b600080600080604085870312156165d457600080fd5b84356001600160401b03808211156165eb57600080fd5b6165f788838901615cde565b9096509450602087013591508082111561661057600080fd5b5061645887828801615cde565b600080600080600060a0868803121561663557600080fd5b853561664081615ef2565b9450602086013561665081615ef2565b935060408601356001600160401b038082111561666c57600080fd5b61667889838a01616004565b9450606088013591508082111561668e57600080fd5b61669a89838a01616004565b935060808801359150808211156163f157600080fd5b600080600080606085870312156166c657600080fd5b84356166d181615ef2565b93506020850135925060408501356001600160401b0381111561644c57600080fd5b60006020828403121561670557600080fd5b81356001600160401b038116811461206657600080fd5b600080600080600060a0868803121561673457600080fd5b85356001600160401b038082111561674b57600080fd5b61675789838a01615f95565b9650602088013591508082111561676d57600080fd5b61677989838a01616004565b9550604088013591508082111561678f57600080fd5b61679b89838a0161605f565b945060608801359150808211156167b157600080fd5b61669a89838a0161605f565b600080604083850312156167d057600080fd5b82356167db81615ef2565b946020939093013593505050565b600080600080600060a0868803121561680157600080fd5b853561680c81615ef2565b9450602086013561681c81615ef2565b9350604086013592506060860135915060808601356001600160401b0381111561684557600080fd5b6163fe88828901615d93565b8183823760009101908152919050565b60208082526018908201527f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000604082015260600190565b600181811c908216806168ac57607f821691505b6020821081036168cc57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201616910576169106168e8565b5060010190565b65ffffffffffff828116828216039080821115616936576169366168e8565b5092915050565b60208082526021908201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756040820152601b60fa1b606082015260800190565b60006020828403121561699057600080fd5b81516001600160401b038111156169a657600080fd5b8201601f810184136169b757600080fd5b80516169c5615db282615d6c565b8181528560208385010111156169da57600080fd5b611349826020830160208601615e8f565b81810381811115610fbb57610fbb6168e8565b634e487b7160e01b600052601260045260246000fd5b600082616a3157634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215616a4857600080fd5b815165ffffffffffff8116811461206657600080fd5b600060208284031215616a7057600080fd5b5051919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000616ab4604083018688616a77565b8281036020840152611768818587616a77565b608081526000616ada608083018761618a565b8281036020840152616aec81876161ce565b90508281036040840152616b0081866161fe565b91505082606083015295945050505050565b8082028115828204841417610fbb57610fbb6168e8565b60a081526000616b3c60a083018861618a565b8281036020840152616b4e81886161ce565b90508281036040840152616b6281876161fe565b60608401959095525050608001529392505050565b60c081526000616b8a60c083018961618a565b8281036020840152616b9c81896161ce565b90508281036040840152616bb081886161fe565b60608401969096525050608081019290925260a0909101529392505050565b80820180821115610fbb57610fbb6168e8565b600060208284031215616bf457600080fd5b8151801515811461206657600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251616c61818460208701615e8f565b9190910192915050565b6001600160e01b0319831681528151600090616c8e816004850160208701615e8f565b919091016004019392505050565b6001600160401b03818116838216019080821115616936576169366168e8565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b8981526001600160a01b038916602082015261012060408201819052600090616d288382018b61618a565b90508281036060840152616d3c818a6161ce565b90508281036080840152616d5081896161fe565b905082810360a0840152616d6481886161fe565b90508560c08401528460e0840152828103610100840152616d858185615eb3565b9c9b505050505050505050505050565b601f821115613bcc57600081815260208120601f850160051c81016020861015616dbc5750805b601f850160051c820191505b818110156117a157828155600101616dc8565b81516001600160401b03811115616df457616df4615d26565b616e0881616e028454616898565b84616d95565b602080601f831160018114616e3d5760008415616e255750858301515b600019600386901b1c1916600185901b1785556117a1565b600085815260208120601f198616915b82811015616e6c57888601518255948401946001909101908401616e4d565b5085821015616e8a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b84815260ff84166020820152826040820152608060608201526000611b586080830184615eb3565b85815260ff8516602082015283604082015260a060608201526000616eea60a0830185615eb3565b8281036080840152611c718185615eb356fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765a164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(GovTokenContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b50600436106102065760003560e01c806370a082311161011a5780639ab24eb0116100ad578063d505accf1161007c578063d505accf1461049d578063dd62ed3e146104b0578063e5ed5b1e146104c3578063f1127ed8146104d6578063f1fad1041461051357600080fd5b80639ab24eb014610451578063a457c2d714610464578063a9059cbb14610477578063c3cda5201461048a57600080fd5b806384b0196e116100e957806384b0196e146103fc5780638e539e8c1461041757806391ddadf41461042a57806395d89b411461044957600080fd5b806370a08231146103aa57806379cc6790146103d35780637ecebe00146103e15780638129fc1c146103f457600080fd5b8063395093511161019d5780634bf5d7e91161016c5780634bf5d7e91461031b5780634bf6c88214610323578063587cde1e1461032b5780635c19a95c1461036f5780636fcfff451461038257600080fd5b806339509351146102cf5780633a46b1a8146102e257806342966c68146102f5578063448407751461030857600080fd5b806323b872dd116101d957806323b872dd1461028a5780633041949b1461029d578063313ce567146102b25780633644e515146102c757600080fd5b8063039c91fc1461020b57806306fdde031461024a578063095ea7b31461025f57806318160ddd14610282575b600080fd5b6102376102193660046120c7565b61013060209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b61025261051b565b6040516102419190612140565b61027261026d366004612153565b6105ad565b6040519015158152602001610241565b603554610237565b61027261029836600461217d565b6105c7565b6102b06102ab3660046120c7565b6105eb565b005b60125b60405160ff9091168152602001610241565b610237610624565b6102726102dd366004612153565b610633565b6102376102f0366004612153565b610655565b6102b06103033660046121b9565b6106da565b6102b06103163660046121d2565b6106f3565b61025261076c565b6102b5600881565b610357610339366004612256565b6001600160a01b03908116600090815260fe60205260409020541690565b6040516001600160a01b039091168152602001610241565b6102b061037d366004612256565b610804565b610395610390366004612256565b610811565b60405163ffffffff9091168152602001610241565b6102376103b8366004612256565b6001600160a01b031660009081526033602052604090205490565b6102b0610303366004612153565b6102376103ef366004612256565b610833565b6102b0610851565b610404610a31565b6040516102419796959493929190612271565b6102376104253660046121b9565b610acf565b610432610b37565b60405165ffffffffffff9091168152602001610241565b610252610b42565b61023761045f366004612256565b610b51565b610272610472366004612153565b610bd3565b610272610485366004612153565b610c4e565b6102b0610498366004612318565b610c5c565b6102b06104ab366004612370565b610d92565b6102376104be3660046120c7565b610ef6565b6102b06104d13660046120c7565b610f21565b6104e96104e43660046123da565b610f51565b60408051825163ffffffff1681526020928301516001600160e01b03169281019290925201610241565b6102b5601181565b60606036805461052a9061241a565b80601f01602080910402602001604051908101604052809291908181526020018280546105569061241a565b80156105a35780601f10610578576101008083540402835291602001916105a3565b820191906000526020600020905b81548152906001019060200180831161058657829003601f168201915b5050505050905090565b6000336105bb818585610fd5565b60019150505b92915050565b6000336105d5858285610fee565b6105e0858585611068565b506001949350505050565b336120021461061657604051630f22c43960e41b815261200260048201526024015b60405180910390fd5b6106208282611081565b5050565b600061062e6111b1565b905090565b6000336105bb8185856106468383610ef6565b6106509190612464565b610fd5565b600061065f610b37565b65ffffffffffff1682106106b15760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b604482015260640161060d565b6001600160a01b038316600090815260ff602052604090206106d390836111bb565b9392505050565b60405163e5d8776760e01b815260040160405180910390fd5b336120021461071957604051630f22c43960e41b8152612002600482015260240161060d565b8160005b818110156107655761075585858381811061073a5761073a612477565b905060200201602081019061074f9190612256565b84611081565b61075e8161248d565b905061071d565b5050505050565b606043610777610b37565b65ffffffffffff16146107cc5760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a2062726f6b656e20636c6f636b206d6f6465000000604482015260640161060d565b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b61080e33826112a4565b50565b6001600160a01b038116600090815260ff60205260408120546105c19061131e565b6001600160a01b038116600090815260cb60205260408120546105c1565b600054610100900460ff16158080156108715750600054600160ff909116105b8061088b5750303b15801561088b575060005460ff166001145b6108ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161060d565b6000805460ff191660011790558015610911576000805461ff0019166101001790555b3341146109315760405163022d8c9560e31b815260040160405180910390fd5b3a15610950576040516383f1b1d360e01b815260040160405180910390fd5b6109a4604051806040016040528060148152602001732129a19023b7bb32b93730b731b2902a37b5b2b760611b8152506040518060400160405280600681526020016533b7bb21272160d11b815250611387565b6109ac6113b8565b6109e1604051806040016040528060148152602001732129a19023b7bb32b93730b731b2902a37b5b2b760611b8152506113e1565b6109e96113b8565b801561080e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b6000606080600080600060606097546000801b148015610a515750609854155b610a955760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b604482015260640161060d565b610a9d61142b565b610aa561143a565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6000610ad9610b37565b65ffffffffffff168210610b2b5760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b604482015260640161060d565b6105c1610100836111bb565b600061062e43611449565b60606037805461052a9061241a565b6001600160a01b038116600090815260ff60205260408120548015610bc0576001600160a01b038316600090815260ff6020526040902080546000198301908110610b9e57610b9e612477565b60009182526020909120015464010000000090046001600160e01b0316610bc3565b60005b6001600160e01b03169392505050565b60003381610be18286610ef6565b905083811015610c415760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161060d565b6105e08286868403610fd5565b6000336105bb818585611068565b83421115610cac5760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a207369676e61747572652065787069726564000000604482015260640161060d565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090610d2690610d1e9060a001604051602081830303815290604052805190602001206114b0565b8585856114dd565b9050610d3181611505565b8614610d7f5760405162461bcd60e51b815260206004820152601960248201527f4552433230566f7465733a20696e76616c6964206e6f6e636500000000000000604482015260640161060d565b610d8981886112a4565b50505050505050565b83421115610de25760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015260640161060d565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610e118c611505565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610e6c826114b0565b90506000610e7c828787876114dd565b9050896001600160a01b0316816001600160a01b031614610edf5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015260640161060d565b610eea8a8a8a610fd5565b50505050505050505050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b3361200214610f4757604051630f22c43960e41b8152612002600482015260240161060d565b61062082826112a4565b60408051808201909152600080825260208201526001600160a01b038316600090815260ff60205260409020805463ffffffff8416908110610f9557610f95612477565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160e01b0316918101919091529392505050565b604051632028747160e01b815260040160405180910390fd5b6000610ffa8484610ef6565b9050600019811461106257818110156110555760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161060d565b6110628484848403610fd5565b50505050565b604051638cd22d1960e01b815260040160405180910390fd5b604051630913db4760e01b81526001600160a01b03828116600483015260009190841690630913db4790602401602060405180830381865afa1580156110cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ef91906124bc565b6001600160a01b03808516600090815261013060209081526040808320938716835292905220549091508181101561116857600061112d82846124d5565b6001600160a01b038087166000908152610130602090815260408083209389168352929052208490559050611162848261152d565b50611062565b8181111561106257600061117c83836124d5565b6001600160a01b0380871660009081526101306020908152604080832093891683529290522084905590506107658482611537565b600061062e611541565b8154600090818160058111156112155760006111d6846115b5565b6111e090856124d5565b600088815260209020909150869082015463ffffffff16111561120557809150611213565b611210816001612464565b92505b505b80821015611262576000611229838361169d565b600088815260209020909150869082015463ffffffff16111561124e5780915061125c565b611259816001612464565b92505b50611215565b801561128e576000868152602090208101600019015464010000000090046001600160e01b0316611291565b60005b6001600160e01b03169695505050505050565b6001600160a01b03828116600081815260fe6020818152604080842080546033845282862054949093528787166001600160a01b03198416811790915590519190951694919391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46110628284836116b8565b600063ffffffff8211156113835760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840161060d565b5090565b600054610100900460ff166113ae5760405162461bcd60e51b815260040161060d906124e8565b61062082826117f6565b600054610100900460ff166113df5760405162461bcd60e51b815260040161060d906124e8565b565b600054610100900460ff166114085760405162461bcd60e51b815260040161060d906124e8565b61080e81604051806040016040528060018152602001603160f81b815250611836565b60606099805461052a9061241a565b6060609a805461052a9061241a565b600065ffffffffffff8211156113835760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b606482015260840161060d565b60006105c16114bd6111b1565b8360405161190160f01b8152600281019290925260228201526042902090565b60008060006114ee87878787611885565b915091506114fb81611949565b5095945050505050565b6001600160a01b038116600090815260cb602052604090208054600181018255905b50919050565b6106208282611a93565b6106208282611b1e565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61156c611b37565b611574611b90565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6000816000036115c757506000919050565b600060016115d484611bc1565b901c6001901b905060018184816115ed576115ed612533565b048201901c9050600181848161160557611605612533565b048201901c9050600181848161161d5761161d612533565b048201901c9050600181848161163557611635612533565b048201901c9050600181848161164d5761164d612533565b048201901c9050600181848161166557611665612533565b048201901c9050600181848161167d5761167d612533565b048201901c90506106d38182858161169757611697612533565b04611c55565b60006116ac6002848418612549565b6106d390848416612464565b816001600160a01b0316836001600160a01b0316141580156116da5750600081115b156117f1576001600160a01b03831615611768576001600160a01b038316600090815260ff60205260408120819061171590611c6b85611c77565b91509150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405161175d929190918252602082015260400190565b60405180910390a250505b6001600160a01b038216156117f1576001600160a01b038216600090815260ff60205260408120819061179e90611dec85611c77565b91509150836001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516117e6929190918252602082015260400190565b60405180910390a250505b505050565b600054610100900460ff1661181d5760405162461bcd60e51b815260040161060d906124e8565b603661182983826125b9565b5060376117f182826125b9565b600054610100900460ff1661185d5760405162461bcd60e51b815260040161060d906124e8565b609961186983826125b9565b50609a61187682826125b9565b50506000609781905560985550565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156118bc5750600090506003611940565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611910573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661193957600060019250925050611940565b9150600090505b94509492505050565b600081600481111561195d5761195d612679565b036119655750565b600181600481111561197957611979612679565b036119c65760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161060d565b60028160048111156119da576119da612679565b03611a275760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161060d565b6003816004811115611a3b57611a3b612679565b0361080e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161060d565b611a9d8282611df8565b6035546001600160e01b031015611b0f5760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b606482015260840161060d565b611062610100611dec83611c77565b611b288282611ec1565b611062610100611c6b83611c77565b600080611b4261142b565b805190915015611b59578051602090910120919050565b6097548015611b685792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b600080611b9b61143a565b805190915015611bb2578051602090910120919050565b6098548015611b685792915050565b600080608083901c15611bd657608092831c92015b604083901c15611be857604092831c92015b602083901c15611bfa57602092831c92015b601083901c15611c0c57601092831c92015b600883901c15611c1e57600892831c92015b600483901c15611c3057600492831c92015b600283901c15611c4257600292831c92015b600183901c156105c15760010192915050565b6000818310611c6457816106d3565b5090919050565b60006106d382846124d5565b82546000908190818115611cc45760008781526020902082016000190160408051808201909152905463ffffffff8116825264010000000090046001600160e01b03166020820152611cd9565b60408051808201909152600080825260208201525b905080602001516001600160e01b03169350611cf984868863ffffffff16565b9250600082118015611d235750611d0e610b37565b65ffffffffffff16816000015163ffffffff16145b15611d6857611d3183611ffc565b60008881526020902083016000190180546001600160e01b03929092166401000000000263ffffffff909216919091179055611de2565b866040518060400160405280611d8c611d7f610b37565b65ffffffffffff1661131e565b63ffffffff168152602001611da086611ffc565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b5050935093915050565b60006106d38284612464565b6001600160a01b038216611e4e5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161060d565b8060356000828254611e609190612464565b90915550506001600160a01b0382166000818152603360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361062060008383612065565b6001600160a01b038216611f215760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161060d565b6001600160a01b03821660009081526033602052604090205481811015611f955760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161060d565b6001600160a01b03831660008181526033602090815260408083208686039055603580548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36117f183600084612065565b60006001600160e01b038211156113835760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b606482015260840161060d565b6117f18383836001600160a01b03808416600090815260fe60205260409020546117f191166001600160a01b03808516600090815260fe602052604090205416836116b8565b80356001600160a01b03811681146120c257600080fd5b919050565b600080604083850312156120da57600080fd5b6120e3836120ab565b91506120f1602084016120ab565b90509250929050565b6000815180845260005b8181101561212057602081850181015186830182015201612104565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006106d360208301846120fa565b6000806040838503121561216657600080fd5b61216f836120ab565b946020939093013593505050565b60008060006060848603121561219257600080fd5b61219b846120ab565b92506121a9602085016120ab565b9150604084013590509250925092565b6000602082840312156121cb57600080fd5b5035919050565b6000806000604084860312156121e757600080fd5b833567ffffffffffffffff808211156121ff57600080fd5b818601915086601f83011261221357600080fd5b81358181111561222257600080fd5b8760208260051b850101111561223757600080fd5b60209283019550935061224d91860190506120ab565b90509250925092565b60006020828403121561226857600080fd5b6106d3826120ab565b60ff60f81b881681526000602060e08184015261229160e084018a6120fa565b83810360408501526122a3818a6120fa565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156122f5578351835292840192918401916001016122d9565b50909c9b505050505050505050505050565b803560ff811681146120c257600080fd5b60008060008060008060c0878903121561233157600080fd5b61233a876120ab565b9550602087013594506040870135935061235660608801612307565b92506080870135915060a087013590509295509295509295565b600080600080600080600060e0888a03121561238b57600080fd5b612394886120ab565b96506123a2602089016120ab565b955060408801359450606088013593506123be60808901612307565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156123ed57600080fd5b6123f6836120ab565b9150602083013563ffffffff8116811461240f57600080fd5b809150509250929050565b600181811c9082168061242e57607f821691505b60208210810361152757634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156105c1576105c161244e565b634e487b7160e01b600052603260045260246000fd5b60006001820161249f5761249f61244e565b5060010190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156124ce57600080fd5b5051919050565b818103818111156105c1576105c161244e565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b60008261256657634e487b7160e01b600052601260045260246000fd5b500490565b601f8211156117f157600081815260208120601f850160051c810160208610156125925750805b601f850160051c820191505b818110156125b15782815560010161259e565b505050505050565b815167ffffffffffffffff8111156125d3576125d36124a6565b6125e7816125e1845461241a565b8461256b565b602080601f83116001811461261c57600084156126045750858301515b600019600386901b1c1916600185901b1785556125b1565b600085815260208120601f198616915b8281101561264b5788860151825594840194600190910190840161262c565b50858210156126695787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fdfea164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(TimelockContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106101e75760003560e01c80638129fc1c11610102578063bc197c8111610095578063e38335e511610064578063e38335e5146105e1578063f1fad104146105f4578063f23a6e6114610609578063f27a0c921461063557600080fd5b8063bc197c8114610548578063c4d252f514610574578063d45c443514610594578063d547741f146105c157600080fd5b8063a217fddf116100d1578063a217fddf146104d1578063ac431751146104e6578063b08e51c014610506578063b1c5f4271461052857600080fd5b80638129fc1c1461045a5780638f2a0bb01461046f5780638f61f4f51461048f57806391d14854146104b157600080fd5b80632ab0f5291161017a5780634bf6c882116101495780634bf6c882146103d3578063584b153e146103fa57806364d623531461041a5780638065657f1461043a57600080fd5b80632ab0f529146103435780632f2ff15d1461037357806331d507501461039357806336568abe146103b357600080fd5b8063134008d3116101b6578063134008d31461029c57806313bc9f20146102af578063150b7a02146102cf578063248a9ca31461031357600080fd5b806301d5062a146101f357806301ffc9a71461021557806307bd02651461024a5780630d3cf6fc1461027a57600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061021361020e366004611aa5565b61064a565b005b34801561022157600080fd5b50610235610230366004611b19565b61070e565b60405190151581526020015b60405180910390f35b34801561025657600080fd5b5061026c60008051602061258983398151915281565b604051908152602001610241565b34801561028657600080fd5b5061026c60008051602061254983398151915281565b6102136102aa366004611b43565b610739565b3480156102bb57600080fd5b506102356102ca366004611bae565b6107dc565b3480156102db57600080fd5b506102fa6102ea366004611c7c565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610241565b34801561031f57600080fd5b5061026c61032e366004611bae565b60009081526065602052604090206001015490565b34801561034f57600080fd5b5061023561035e366004611bae565b60009081526097602052604090205460011490565b34801561037f57600080fd5b5061021361038e366004611ce3565b610802565b34801561039f57600080fd5b506102356103ae366004611bae565b61082c565b3480156103bf57600080fd5b506102136103ce366004611ce3565b610845565b3480156103df57600080fd5b506103e8600881565b60405160ff9091168152602001610241565b34801561040657600080fd5b50610235610415366004611bae565b6108c8565b34801561042657600080fd5b50610213610435366004611bae565b6108df565b34801561044657600080fd5b5061026c610455366004611b43565b610983565b34801561046657600080fd5b506102136109c2565b34801561047b57600080fd5b5061021361048a366004611d53565b610b73565b34801561049b57600080fd5b5061026c60008051602061256983398151915281565b3480156104bd57600080fd5b506102356104cc366004611ce3565b610cf4565b3480156104dd57600080fd5b5061026c600081565b3480156104f257600080fd5b50610213610501366004611e04565b610d1f565b34801561051257600080fd5b5061026c6000805160206125a983398151915281565b34801561053457600080fd5b5061026c610543366004611e6f565b610f09565b34801561055457600080fd5b506102fa610563366004611f96565b63bc197c8160e01b95945050505050565b34801561058057600080fd5b5061021361058f366004611bae565b610f4e565b3480156105a057600080fd5b5061026c6105af366004611bae565b60009081526097602052604090205490565b3480156105cd57600080fd5b506102136105dc366004611ce3565b611011565b6102136105ef366004611e6f565b611036565b34801561060057600080fd5b506103e8601181565b34801561061557600080fd5b506102fa61062436600461203f565b63f23a6e6160e01b95945050505050565b34801561064157600080fd5b5060985461026c565b600080516020612569833981519152610662816111ae565b6000610672898989898989610983565b905061067e81846111b8565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516106ba969594939291906120cc565b60405180910390a3831561070357807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387856040516106fa91815260200190565b60405180910390a25b505050505050505050565b60006001600160e01b03198216630271189760e51b14806107335750610733826112a7565b92915050565b600080516020612589833981519152610753816000610cf4565b6107615761076181336112dc565b6000610771888888888888610983565b905061077d8185611335565b610789888888886113d0565b6000817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516107c19493929190612109565b60405180910390a36107d2816114a3565b5050505050505050565b6000818152609760205260408120546001811180156107fb5750428111155b9392505050565b60008281526065602052604090206001015461081d816111ae565b61082783836114dc565b505050565b60008181526097602052604081205481905b1192915050565b6001600160a01b03811633146108ba5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6108c48282611562565b5050565b60008181526097602052604081205460019061083e565b3330146109425760405162461bcd60e51b815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201526a62652074696d656c6f636b60a81b60648201526084016108b1565b60985460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1609855565b60008686868686866040516020016109a0969594939291906120cc565b6040516020818303038152906040528051906020012090509695505050505050565b600054610100900460ff16158080156109e25750600054600160ff909116105b806109fc5750303b1580156109fc575060005460ff166001145b610a5f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016108b1565b6000805460ff191660011790558015610a82576000805461ff0019166101001790555b334114610aa25760405163022d8c9560e31b815260040160405180910390fd5b3a15610ac1576040516383f1b1d360e01b815260040160405180910390fd5b6040805160018082528183019092526000916020808301908036833701905050905061200481600081518110610af957610af961213b565b60200260200101906001600160a01b031690816001600160a01b031681525050610b2961546082836120046115c9565b508015610b70576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b600080516020612569833981519152610b8b816111ae565b888714610baa5760405162461bcd60e51b81526004016108b190612151565b888514610bc95760405162461bcd60e51b81526004016108b190612151565b6000610bdb8b8b8b8b8b8b8b8b610f09565b9050610be781846111b8565b60005b8a811015610ca55780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c2757610c2761213b565b9050602002016020810190610c3c9190612194565b8d8d86818110610c4e57610c4e61213b565b905060200201358c8c87818110610c6757610c6761213b565b9050602002810190610c7991906121af565b8c8b604051610c8d969594939291906120cc565b60405180910390a3610c9e8161220b565b9050610bea565b508315610ce757807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d038785604051610cde91815260200190565b60405180910390a25b5050505050505050505050565b60009182526065602090815260408084206001600160a01b0393909316845291905290205460ff1690565b3361100714610d4557604051630f22c43960e41b815261100760048201526024016108b1565b610da8604051806040016040528060088152602001676d696e44656c617960c01b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506116029050565b15610ea55760208114610dd65783838383604051630a5a604160e01b81526004016108b19493929190612224565b604080516020601f8401819004810282018101909252828152600091610e1791858580838501838280828437600092019190915250929392505061165b9050565b9050801580610e2857506212750081115b15610e4e5784848484604051630a5a604160e01b81526004016108b19493929190612224565b6040516364d6235360e01b81526004810182905230906364d6235390602401600060405180830381600087803b158015610e8757600080fd5b505af1158015610e9b573d6000803e3d6000fd5b5050505050610ec6565b838383836040516325ee20d560e21b81526004016108b19493929190612224565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e63384848484604051610efb9493929190612224565b60405180910390a150505050565b60008888888888888888604051602001610f2a9897969594939291906122d9565b60405160208183030381529060405280519060200120905098975050505050505050565b6000805160206125a9833981519152610f66816111ae565b610f6f826108c8565b610fd55760405162461bcd60e51b815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e2063616044820152701b9b9bdd0818994818d85b98d95b1b1959607a1b60648201526084016108b1565b6000828152609760205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b60008281526065602052604090206001015461102c816111ae565b6108278383611562565b600080516020612589833981519152611050816000610cf4565b61105e5761105e81336112dc565b87861461107d5760405162461bcd60e51b81526004016108b190612151565b87841461109c5760405162461bcd60e51b81526004016108b190612151565b60006110ae8a8a8a8a8a8a8a8a610f09565b90506110ba8185611335565b60005b898110156111985760008b8b838181106110d9576110d961213b565b90506020020160208101906110ee9190612194565b905060008a8a848181106111045761110461213b565b9050602002013590503660008a8a868181106111225761112261213b565b905060200281019061113491906121af565b91509150611144848484846113d0565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588686868660405161117b9493929190612109565b60405180910390a350505050806111919061220b565b90506110bd565b506111a2816114a3565b50505050505050505050565b610b7081336112dc565b6111c18261082c565b156112265760405162461bcd60e51b815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201526e1c9958591e481cd8da19591d5b1959608a1b60648201526084016108b1565b6098548110156112875760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e746044820152652064656c617960d01b60648201526084016108b1565b611291814261237a565b6000928352609760205260409092209190915550565b60006001600160e01b03198216637965db0b60e01b148061073357506301ffc9a760e01b6001600160e01b0319831614610733565b6112e68282610cf4565b6108c4576112f381611660565b6112fe836020611672565b60405160200161130f9291906123b1565b60408051601f198184030181529082905262461bcd60e51b82526108b191600401612426565b61133e826107dc565b61135a5760405162461bcd60e51b81526004016108b190612459565b80158061137557506000818152609760205260409020546001145b6108c45760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e6720646570656044820152656e64656e637960d01b60648201526084016108b1565b6000846001600160a01b03168484846040516113ed9291906124a3565b60006040518083038185875af1925050503d806000811461142a576040519150601f19603f3d011682016040523d82523d6000602084013e61142f565b606091505b505090508061149c5760405162461bcd60e51b815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e6720746044820152721c985b9cd858dd1a5bdb881c995d995c9d1959606a1b60648201526084016108b1565b5050505050565b6114ac816107dc565b6114c85760405162461bcd60e51b81526004016108b190612459565b600090815260976020526040902060019055565b6114e68282610cf4565b6108c45760008281526065602090815260408083206001600160a01b03851684529091529020805460ff1916600117905561151e3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61156c8282610cf4565b156108c45760008281526065602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600054610100900460ff166115f05760405162461bcd60e51b81526004016108b1906124b3565b6115fc8484848461180d565b50505050565b60008160405160200161161591906124fe565b604051602081830303815290604052805190602001208360405160200161163c91906124fe565b6040516020818303038152906040528051906020012014905092915050565b015190565b60606107336001600160a01b03831660145b6060600061168183600261251a565b61168c90600261237a565b6001600160401b038111156116a3576116a3611bc7565b6040519080825280601f01601f1916602001820160405280156116cd576020820181803683370190505b509050600360fc1b816000815181106116e8576116e861213b565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106117175761171761213b565b60200101906001600160f81b031916908160001a905350600061173b84600261251a565b61174690600161237a565b90505b60018111156117be576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061177a5761177a61213b565b1a60f81b8282815181106117905761179061213b565b60200101906001600160f81b031916908160001a90535060049490941c936117b781612531565b9050611749565b5083156107fb5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108b1565b600054610100900460ff166118345760405162461bcd60e51b81526004016108b1906124b3565b61184c600080516020612549833981519152806119ec565b6118726000805160206125698339815191526000805160206125498339815191526119ec565b6118986000805160206125898339815191526000805160206125498339815191526119ec565b6118be6000805160206125a98339815191526000805160206125498339815191526119ec565b6118d660008051602061254983398151915230611a37565b6001600160a01b038116156118fd576118fd60008051602061254983398151915282611a37565b60005b835181101561196e5761193a60008051602061256983398151915285838151811061192d5761192d61213b565b6020026020010151611a37565b61195e6000805160206125a983398151915285838151811061192d5761192d61213b565b6119678161220b565b9050611900565b5060005b82518110156119af5761199f60008051602061258983398151915284838151811061192d5761192d61213b565b6119a88161220b565b9050611972565b5060988490556040805160008152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d59101610efb565b600082815260656020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6108c482826114dc565b80356001600160a01b0381168114611a5857600080fd5b919050565b60008083601f840112611a6f57600080fd5b5081356001600160401b03811115611a8657600080fd5b602083019150836020828501011115611a9e57600080fd5b9250929050565b600080600080600080600060c0888a031215611ac057600080fd5b611ac988611a41565b96506020880135955060408801356001600160401b03811115611aeb57600080fd5b611af78a828b01611a5d565b989b979a50986060810135976080820135975060a09091013595509350505050565b600060208284031215611b2b57600080fd5b81356001600160e01b0319811681146107fb57600080fd5b60008060008060008060a08789031215611b5c57600080fd5b611b6587611a41565b95506020870135945060408701356001600160401b03811115611b8757600080fd5b611b9389828a01611a5d565b979a9699509760608101359660809091013595509350505050565b600060208284031215611bc057600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611c0557611c05611bc7565b604052919050565b600082601f830112611c1e57600080fd5b81356001600160401b03811115611c3757611c37611bc7565b611c4a601f8201601f1916602001611bdd565b818152846020838601011115611c5f57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611c9257600080fd5b611c9b85611a41565b9350611ca960208601611a41565b92506040850135915060608501356001600160401b03811115611ccb57600080fd5b611cd787828801611c0d565b91505092959194509250565b60008060408385031215611cf657600080fd5b82359150611d0660208401611a41565b90509250929050565b60008083601f840112611d2157600080fd5b5081356001600160401b03811115611d3857600080fd5b6020830191508360208260051b8501011115611a9e57600080fd5b600080600080600080600080600060c08a8c031215611d7157600080fd5b89356001600160401b0380821115611d8857600080fd5b611d948d838e01611d0f565b909b50995060208c0135915080821115611dad57600080fd5b611db98d838e01611d0f565b909950975060408c0135915080821115611dd257600080fd5b50611ddf8c828d01611d0f565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060408587031215611e1a57600080fd5b84356001600160401b0380821115611e3157600080fd5b611e3d88838901611a5d565b90965094506020870135915080821115611e5657600080fd5b50611e6387828801611a5d565b95989497509550505050565b60008060008060008060008060a0898b031215611e8b57600080fd5b88356001600160401b0380821115611ea257600080fd5b611eae8c838d01611d0f565b909a50985060208b0135915080821115611ec757600080fd5b611ed38c838d01611d0f565b909850965060408b0135915080821115611eec57600080fd5b50611ef98b828c01611d0f565b999c989b509699959896976060870135966080013595509350505050565b600082601f830112611f2857600080fd5b813560206001600160401b03821115611f4357611f43611bc7565b8160051b611f52828201611bdd565b9283528481018201928281019087851115611f6c57600080fd5b83870192505b84831015611f8b57823582529183019190830190611f72565b979650505050505050565b600080600080600060a08688031215611fae57600080fd5b611fb786611a41565b9450611fc560208701611a41565b935060408601356001600160401b0380821115611fe157600080fd5b611fed89838a01611f17565b9450606088013591508082111561200357600080fd5b61200f89838a01611f17565b9350608088013591508082111561202557600080fd5b5061203288828901611c0d565b9150509295509295909350565b600080600080600060a0868803121561205757600080fd5b61206086611a41565b945061206e60208701611a41565b9350604086013592506060860135915060808601356001600160401b0381111561209757600080fd5b61203288828901611c0d565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a0604082015260006120f460a0830186886120a3565b60608301949094525060800152949350505050565b60018060a01b03851681528360208201526060604082015260006121316060830184866120a3565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b60208082526023908201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d616040820152620e8c6d60eb1b606082015260800190565b6000602082840312156121a657600080fd5b6107fb82611a41565b6000808335601e198436030181126121c657600080fd5b8301803591506001600160401b038211156121e057600080fd5b602001915036819003821315611a9e57600080fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161221d5761221d6121f5565b5060010190565b6040815260006122386040830186886120a3565b8281036020840152611f8b8185876120a3565b818352600060208085019450848460051b86018460005b878110156122cc5783830389528135601e1988360301811261228357600080fd5b870185810190356001600160401b0381111561229e57600080fd5b8036038213156122ad57600080fd5b6122b88582846120a3565b9a87019a9450505090840190600101612262565b5090979650505050505050565b60a0808252810188905260008960c08301825b8b81101561231a576001600160a01b0361230584611a41565b168252602092830192909101906001016122ec565b5083810360208501528881526001600160fb1b0389111561233a57600080fd5b8860051b9150818a60208301370182810360209081016040850152612362908201878961224b565b60608401959095525050608001529695505050505050565b80820180821115610733576107336121f5565b60005b838110156123a8578181015183820152602001612390565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516123e981601785016020880161238d565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161241a81602884016020880161238d565b01602801949350505050565b602081526000825180602084015261244581604085016020870161238d565b601f01601f19169190910160400192915050565b6020808252602a908201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e206973604082015269206e6f7420726561647960b01b606082015260800190565b8183823760009101908152919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000825161251081846020870161238d565b9190910192915050565b8082028115828204841417610733576107336121f5565b600081612540576125406121f5565b50600019019056fe5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63fd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783a164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(TokenRecoverPortalContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b506004361061010b5760003560e01c80638129fc1c116100a2578063b187bd2611610071578063b187bd261461022c578063bfb5a6a114610237578063e33f8d321461024a578063e842426a1461026d578063f1fad1041461029857600080fd5b80638129fc1c146101fc5780638456cb59146102045780639fcb50121461020c578063ac4317511461021957600080fd5b80634a49ac4c116100de5780634a49ac4c1461017c5780634bf6c8821461018f578063572c9980146101a957806374be2150146101bc57600080fd5b8063046f7da2146101105780632eb4a7ab1461011a578063417c73a7146101365780634838d16514610149575b600080fd5b6101186102a0565b005b61012360685481565b6040519081526020015b60405180910390f35b6101186101443660046116a8565b610328565b61016c6101573660046116a8565b60346020526000908152604090205460ff1681565b604051901515815260200161012d565b61011861018a3660046116a8565b6103a4565b610197600881565b60405160ff909116815260200161012d565b6101186101b73660046116c3565b61041d565b6101ef6040518060400160405280601481526020017342696e616e63652d436861696e2d47616e67657360601b81525081565b60405161012d919061173f565b6101186104b3565b610118610625565b60695461016c9060ff1681565b61011861022736600461179b565b6106b1565b60335460ff1661016c565b61011861024536600461184c565b610ad0565b61016c610258366004611926565b6000908152606a602052604090205460ff1690565b606754610280906001600160a01b031681565b6040516001600160a01b03909116815260200161012d565b610197601181565b60335461010090046001600160a01b031633146102d0576040516306fbb1e360e01b815260040160405180910390fd5b60335460ff166102f357604051636cd6020160e01b815260040160405180910390fd5b6033805460ff191690556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f990600090a1565b60335461010090046001600160a01b03163314610358576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260346020526040808220805460ff19166001179055517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60335461010090046001600160a01b031633146103d4576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260346020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60335461010090046001600160a01b0316331461044d576040516306fbb1e360e01b815260040160405180910390fd5b604051638525db0360e01b8152600481018390526001600160a01b038216602482015261100490638525db0390604401600060405180830381600087803b15801561049757600080fd5b505af11580156104ab573d6000803e3d6000fd5b505050505050565b600054610100900460ff16158080156104d35750600054600160ff909116105b806104ed5750303b1580156104ed575060005460ff166001145b6105555760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610578576000805461ff0019166101001790555b3341146105985760405163022d8c9560e31b815260040160405180910390fd5b3a156105b7576040516383f1b1d360e01b815260040160405180910390fd5b6105bf610e30565b6105dc7330151da466ec8ab345bef3d6983023e050fb0673610e5d565b8015610622576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60335461010090046001600160a01b03163314610655576040516306fbb1e360e01b815260040160405180910390fd5b60335460ff161561067957604051631785c68160e01b815260040160405180910390fd5b6033805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b33611007146106d757604051630f22c43960e41b8152611007600482015260240161054c565b6107416040518060400160405280600f81526020016e617070726f76616c4164647265737360881b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610eac9050565b1561080b576014811461076f5783838383604051630a5a604160e01b815260040161054c9493929190611968565b60006107b5601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610f069050565b90506001600160a01b0381166107e65784848484604051630a5a604160e01b815260040161054c9493929190611968565b606780546001600160a01b0319166001600160a01b0392909216919091179055610a8d565b6108706040518060400160405280600a8152602001691b595c9adb19549bdbdd60b21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610eac9050565b156109405760695460ff1615610899576040516379b3306f60e11b815260040160405180910390fd5b602081146108c25783838383604051630a5a604160e01b815260040161054c9493929190611968565b604080516020601f8401819004810282018101909252828152600091610903918585808385018382808284376000920191909152509293925050610f069050565b90508061092b5784848484604051630a5a604160e01b815260040161054c9493929190611968565b6068556069805460ff19166001179055610a8d565b6109b86040518060400160405280601b81526020017f746f6b656e5265636f766572506f7274616c50726f746563746f72000000000081525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610eac9050565b15610a6c57601481146109e65783838383604051630a5a604160e01b815260040161054c9493929190611968565b6000610a2c601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610f069050565b90506001600160a01b038116610a5d5784848484604051630a5a604160e01b815260040161054c9493929190611968565b610a6681610f0b565b50610a8d565b838383836040516325ee20d560e21b815260040161054c9493929190611968565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e63384848484604051610ac29493929190611968565b60405180910390a150505050565b60695460ff16610af35760405163678f619760e11b815260040160405180910390fd5b606854610b135760405163678f619760e11b815260040160405180910390fd5b6067546001600160a01b0316610b3c57604051631a1b977b60e31b815260040160405180910390fd5b60335460ff1615610b6057604051631785c68160e01b815260040160405180910390fd5b610b68610f72565b6000610bf689898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600081840152601f19601f82011690508083019250505050505050610bf18e8e33610fcb565b6110ec565b90506000818c8c604051602001610c0f9392919061199a565b604051602081830303815290604052805190602001209050610c40816000908152606a602052604090205460ff1690565b15610c5d57604051623e493160e81b815260040160405180910390fd5b610d053389898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a908190840183828082843760009201919091525050604080516020808c0282810182019093528b82528994509092508b918b918291908501908490808284376000920191909152506111c492505050565b610d468484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060685491508490506112cf565b610d63576040516309bde33960e01b815260040160405180910390fd5b6000818152606a602052604090819020805460ff191660011790555163799758b960e01b8152600481018d9052336024820152604481018c90526110049063799758b990606401600060405180830381600087803b158015610dc457600080fd5b505af1158015610dd8573d6000803e3d6000fd5b505050507f39cc0b7297a0ef9102d75ebc4919ffec0347d50008c2b865eda4125d5812cb64828d338e604051610e1194939291906119c1565b60405180910390a15050610e2460018055565b50505050505050505050565b600054610100900460ff16610e575760405162461bcd60e51b815260040161054c906119f9565b60018055565b600054610100900460ff16610e845760405162461bcd60e51b815260040161054c906119f9565b603380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600081604051602001610ebf9190611a44565b6040516020818303038152906040528051906020012083604051602001610ee69190611a44565b604051602081830303815290604052805190602001201490505b92915050565b015190565b6033546040516001600160a01b0380841692610100900416907f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b90600090a3603380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600260015403610fc45760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161054c565b6002600155565b600060026040518060400160405280601481526020017342696e616e63652d436861696e2d47616e67657360601b8152506110288560405160200161101291815260200190565b60405160208183030381529060405260006112e5565b6040516bffffffffffffffffffffffff19606087901b1660208201526110619060340160405160208183030381529060405260016112e5565b6110778860405160200161101291815260200190565b60405160200161108a9493929190611a60565b60408051601f19818403018152908290526110a491611a44565b602060405180830381855afa1580156110c1573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906110e49190611b8f565b949350505050565b6060835160211461111057604051638152ea1b60e01b815260040160405180910390fd5b825160401461113257604051635e4bd79760e11b815260040160405180910390fd5b604080516020808252818301909252600091602082018180368337019050509050826020820152600085858360405160200161117093929190611bbe565b60408051808303601f190181526014808452838301909252925060009190602082018180368337019050509050815160146020830182602086016069600019fa6111b957600080fd5b509695505050505050565b606060005b825181101561122257818382815181106111e5576111e5611c01565b60200260200101516040516020016111fe929190611c17565b6040516020818303038152906040529150808061121a90611c4f565b9150506111c9565b5060006040518060400160405280601481526020017342696e616e63652d436861696e2d47616e67657360601b8152508787866068548660405160200161126e96959493929190611c68565b60408051601f1981840301815291905280516020909101206067549091506001600160a01b031661129f86836114b7565b6001600160a01b0316146112c6576040516356b00a4f60e11b815260040160405180910390fd5b50505050505050565b6000826112dc8584611551565b14949350505050565b60606000835160026112f79190611cd9565b67ffffffffffffffff81111561130f5761130f611ba8565b6040519080825280601f01601f191660200182016040528015611339576020820181803683370190505b5060408051808201909152601081526f181899199a1a9b1b9c1cb0b131b232b360811b602082015290915060005b855181101561147f5781825187838151811061138557611385611c01565b0160200151611397919060f81c611d06565b815181106113a7576113a7611c01565b01602001516001600160f81b031916836113c2836002611cd9565b815181106113d2576113d2611c01565b60200101906001600160f81b031916908160001a9053508182518783815181106113fe576113fe611c01565b0160200151611410919060f81c611d1a565b8151811061142057611420611c01565b01602001516001600160f81b0319168361143b836002611cd9565b611446906001611d2e565b8151811061145657611456611c01565b60200101906001600160f81b031916908160001a9053508061147781611c4f565b915050611367565b5083156114af57816040516020016114979190611d41565b60405160208183030381529060405292505050610f00565b509392505050565b600082516041146114db576040516356b00a4f60e11b815260040160405180910390fd5b60208301516040840151606085015160001a601b81101561150457611501601b82611d6b565b90505b601b8160ff1610806115195750601c8160ff16115b15611537576040516356b00a4f60e11b815260040160405180910390fd5b600061154586838686611596565b50979650505050505050565b600081815b84518110156114af576115828286838151811061157557611575611c01565b602002602001015161165a565b91508061158e81611c4f565b915050611556565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156115cd5750600090506003611651565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611621573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661164a57600060019250925050611651565b9150600090505b94509492505050565b6000818310611676576000828152602084905260409020611685565b60008381526020839052604090205b9392505050565b80356001600160a01b03811681146116a357600080fd5b919050565b6000602082840312156116ba57600080fd5b6116858261168c565b600080604083850312156116d657600080fd5b823591506116e66020840161168c565b90509250929050565b60005b8381101561170a5781810151838201526020016116f2565b50506000910152565b6000815180845261172b8160208601602086016116ef565b601f01601f19169290920160200192915050565b6020815260006116856020830184611713565b60008083601f84011261176457600080fd5b50813567ffffffffffffffff81111561177c57600080fd5b60208301915083602082850101111561179457600080fd5b9250929050565b600080600080604085870312156117b157600080fd5b843567ffffffffffffffff808211156117c957600080fd5b6117d588838901611752565b909650945060208701359150808211156117ee57600080fd5b506117fb87828801611752565b95989497509550505050565b60008083601f84011261181957600080fd5b50813567ffffffffffffffff81111561183157600080fd5b6020830191508360208260051b850101111561179457600080fd5b60008060008060008060008060008060c08b8d03121561186b57600080fd5b8a35995060208b0135985060408b013567ffffffffffffffff8082111561189157600080fd5b61189d8e838f01611752565b909a50985060608d01359150808211156118b657600080fd5b6118c28e838f01611752565b909850965060808d01359150808211156118db57600080fd5b6118e78e838f01611752565b909650945060a08d013591508082111561190057600080fd5b5061190d8d828e01611807565b915080935050809150509295989b9194979a5092959850565b60006020828403121561193857600080fd5b5035919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60408152600061197c60408301868861193f565b828103602084015261198f81858761193f565b979650505050505050565b600084516119ac8184602089016116ef565b91909101928352506020820152604001919050565b6080815260006119d46080830187611713565b6020830195909552506001600160a01b03929092166040830152606090910152919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251611a568184602087016116ef565b9190910192915050565b7f7b226163636f756e745f6e756d626572223a2230222c22636861696e5f6964228152611d1160f11b602082015260008551611aa3816022850160208a016116ef565b7f222c2264617461223a6e756c6c2c226d656d6f223a22222c226d736773223a5b6022918401918201526a3d9130b6b7bab73a111d1160a91b60428201528551611af481604d840160208a016116ef565b6e1116113932b1b4b834b2b73a111d1160891b604d92909101918201528451611b2481605c8401602089016116ef565b711116113a37b5b2b72fb9bcb6b137b6111d1160711b605c92909101918201528351611b5781606e8401602088016116ef565b7f227d5d2c2273657175656e6365223a2230222c22736f75726365223a2230227d606e9290910191820152608e019695505050505050565b600060208284031215611ba157600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b60008451611bd08184602089016116ef565b845190830190611be48183602089016116ef565b8451910190611bf78183602088016116ef565b0195945050505050565b634e487b7160e01b600052603260045260246000fd5b60008351611c298184602088016116ef565b9190910191825250602001919050565b634e487b7160e01b600052601160045260246000fd5b600060018201611c6157611c61611c39565b5060010190565b60008751611c7a818460208c016116ef565b606088901b6bffffffffffffffffffffffff19169083019081528651611ca7816014840160208b016116ef565b0160148101869052603481018590528351611cc98160548401602088016116ef565b0160540198975050505050505050565b8082028115828204841417610f0057610f00611c39565b634e487b7160e01b600052601260045260246000fd5b600082611d1557611d15611cf0565b500490565b600082611d2957611d29611cf0565b500690565b80820180821115610f0057610f00611c39565b61060f60f31b815260008251611d5e8160028501602087016116ef565b9190910160020192915050565b60ff8181168382160190811115610f0057610f00611c3956fea164736f6c6343000811000a",
+ },
+ },
+ }
+
+ feynmanUpgrade[rialtoNet] = &Upgrade{
+ UpgradeName: "feynman",
+ Configs: []*UpgradeConfig{
+ {
+ ContractAddr: common.HexToAddress(ValidatorContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106104fb5760003560e01c806388b32f111161028c578063c6d339451161015a578063e40716a1116100cc578063f92eb86b11610085578063f92eb86b14610d2d578063f9a2bbc714610d42578063fc3e590814610d57578063fccc281314610d6c578063fd4ad81f14610d81578063fd6a687914610db057610502565b8063e40716a114610c9b578063ea321e4914610cb0578063eb57e20214610cd0578063eda5868c14610cf0578063f1fad10414610d05578063f340fa0114610d1a57610502565b8063d86222d51161011e578063d86222d514610c1d578063daacdb6614610c32578063dc927faf14610c47578063df8079e914610c5c578063e086c7b114610c71578063e1c7392a14610c8657610502565b8063c6d3394514610bbe578063c81b166214610bd3578063c8509d811461098d578063ce910b0c14610be8578063d68fb56a14610c0857610502565b8063a78abc16116101fe578063ad3c9da6116101b7578063ad3c9da614610b3d578063aef198a914610b5d578063b7ab4db514610b72578063b8cf4ef114610b94578063bf9f4995146106fe578063c466689d14610ba957610502565b8063a78abc1614610ab4578063aa82dce114610ac9578063aad5606314610ade578063aaf5eb6814610af3578063ab51bb9614610b08578063ac43175114610b1d57610502565b806396713da91161025057806396713da914610a365780639dc0926214610a4b5780639fe0f81614610a60578063a0dc275814610a75578063a1a11bf514610a8a578063a5422d5c14610a9f57610502565b806388b32f11146109c25780638a7beb01146109d75780638b5ad0c9146109ec5780638d19a41014610a015780639369d7de14610a2157610502565b806351b4dce3116103c957806370fd5bad1161033b5780637e434d54116102f45780637e434d541461094e57806381650b6214610963578063820dcaa814610978578063831d65d11461098d578063853230aa1461090f57806386249882146109ad57610502565b806370fd5bad146108d0578063718a8aa8146108e557806375d47a0a146108fa57806378dfed4a1461090f5780637942fd05146109245780637a84ca2a1461093957610502565b80635d77156c1161038d5780635d77156c1461082a5780635de1e22c1461083f57806360eba4fe1461085457806362b72cf5146108745780636969a25c146108895780636e47b482146108bb57610502565b806351b4dce3146107ab57806351e80672146107c057806355614fcc146107d5578063565c56b3146107f55780635667515a1461081557610502565b8063300c35671161046d57806343756e5c1161042657806343756e5c1461072057806345cf9daf14610735578063493279b11461074a5780634bf6c8821461076c5780634df6e0c3146107815780635192c82c1461079657610502565b8063300c35671461065b578063321d398a1461067b5780633365af3a1461069b57806335409f7f146106bb5780633b071dcc146106db5780633dffc387146106fe57610502565b8063152ad3b8116104bf578063152ad3b8146105ba5780631e4c1524146105dc5780631ff18069146105fc578063219f22d51461061157806328087028146106265780632a0ffb6e1461063b57610502565b806304c4fec61461050757806307a568471461051e5780630bee7a67146105495780630e2374a51461056b5780631182b8751461058d57610502565b3661050257005b600080fd5b34801561051357600080fd5b5061051c610dc5565b005b34801561052a57600080fd5b50610533610e37565b6040516105409190618fa3565b60405180910390f35b34801561055557600080fd5b5061055e610e3d565b6040516105409190618fcd565b34801561057757600080fd5b50610580610e42565b60405161054091906182b6565b34801561059957600080fd5b506105ad6105a836600461819c565b610e48565b6040516105409190618449565b3480156105c657600080fd5b506105cf611144565b604051610540919061843e565b3480156105e857600080fd5b5061051c6105f7366004617faa565b61114d565b34801561060857600080fd5b50610533611823565b34801561061d57600080fd5b5061055e611829565b34801561063257600080fd5b5061058061182e565b34801561064757600080fd5b5061051c610656366004617f0a565b611834565b34801561066757600080fd5b5061051c610676366004617f42565b6118e1565b34801561068757600080fd5b506105cf610696366004618149565b611c2a565b3480156106a757600080fd5b506105cf6106b6366004618149565b611cf9565b3480156106c757600080fd5b5061051c6106d6366004617f0a565b611daa565b3480156106e757600080fd5b506106f0611f0f565b604051610540929190618354565b34801561070a57600080fd5b506107136121eb565b6040516105409190618fde565b34801561072c57600080fd5b506105806121f0565b34801561074157600080fd5b506105336121f6565b34801561075657600080fd5b5061075f6121fc565b6040516105409190618f94565b34801561077857600080fd5b50610713612202565b34801561078d57600080fd5b506106f0612207565b3480156107a257600080fd5b50610533612393565b3480156107b757600080fd5b50610580612399565b3480156107cc57600080fd5b5061058061239f565b3480156107e157600080fd5b506105cf6107f0366004617f0a565b6123a5565b34801561080157600080fd5b50610533610810366004617f0a565b6123da565b34801561082157600080fd5b5061071361242b565b34801561083657600080fd5b5061055e612430565b34801561084b57600080fd5b50610533612435565b34801561086057600080fd5b506105ad61086f366004618149565b61243b565b34801561088057600080fd5b506105336124e1565b34801561089557600080fd5b506108a96108a4366004618149565b6124e7565b604051610540969594939291906182e3565b3480156108c757600080fd5b5061058061254b565b3480156108dc57600080fd5b50610713612551565b3480156108f157600080fd5b50610713612556565b34801561090657600080fd5b5061058061255b565b34801561091b57600080fd5b50610533612561565b34801561093057600080fd5b50610713612567565b34801561094557600080fd5b5061053361256c565b34801561095a57600080fd5b50610580612572565b34801561096f57600080fd5b5061055e612578565b34801561098457600080fd5b5061053361257d565b34801561099957600080fd5b5061051c6109a836600461819c565b612583565b3480156109b957600080fd5b506105336125e4565b3480156109ce57600080fd5b506105336125ea565b3480156109e357600080fd5b506105cf6125f0565b3480156109f857600080fd5b506105336125f9565b348015610a0d57600080fd5b50610533610a1c366004617f0a565b6125ff565b348015610a2d57600080fd5b5061051c61263f565b348015610a4257600080fd5b50610713612753565b348015610a5757600080fd5b50610580612758565b348015610a6c57600080fd5b5061053361275e565b348015610a8157600080fd5b50610533612763565b348015610a9657600080fd5b50610580612768565b348015610aab57600080fd5b506105ad61276e565b348015610ac057600080fd5b506105cf61278a565b348015610ad557600080fd5b50610580612793565b348015610aea57600080fd5b50610580612799565b348015610aff57600080fd5b5061053361279f565b348015610b1457600080fd5b5061055e61242b565b348015610b2957600080fd5b5061051c610b383660046180ed565b6127a8565b348015610b4957600080fd5b50610533610b58366004617f0a565b613061565b348015610b6957600080fd5b50610533613073565b348015610b7e57600080fd5b50610b87613080565b6040516105409190618341565b348015610ba057600080fd5b5061053361316c565b348015610bb557600080fd5b50610533613171565b348015610bca57600080fd5b50610533612551565b348015610bdf57600080fd5b50610580613177565b348015610bf457600080fd5b506105ad610c03366004618149565b61317d565b348015610c1457600080fd5b5061053361318a565b348015610c2957600080fd5b506105336131c9565b348015610c3e57600080fd5b506105336131d5565b348015610c5357600080fd5b506105806131db565b348015610c6857600080fd5b506105806131e1565b348015610c7d57600080fd5b50610533610e3d565b348015610c9257600080fd5b5061051c6131e7565b348015610ca757600080fd5b50610533613478565b348015610cbc57600080fd5b506105cf610ccb3660046180ae565b61347e565b348015610cdc57600080fd5b5061051c610ceb366004617f0a565b613604565b348015610cfc57600080fd5b5061055e613708565b348015610d1157600080fd5b5061071361370d565b61051c610d28366004617f0a565b613712565b348015610d3957600080fd5b50610533613a91565b348015610d4e57600080fd5b50610580613a97565b348015610d6357600080fd5b5061071361275e565b348015610d7857600080fd5b50610580613a9d565b348015610d8d57600080fd5b50610da1610d9c366004618149565b613aa3565b60405161054093929190618fac565b348015610dbc57600080fd5b50610580613b65565b6000610dd0336125ff565b9050600b8181548110610ddf57fe5b600091825260209091206001601690920201015460ff16610e1b5760405162461bcd60e51b8152600401610e1290618baf565b60405180910390fd5b6000610e2561318a565b9050610e32338383613b6b565b505050565b60095481565b606481565b61200181565b60005460609060ff16610e6d5760405162461bcd60e51b8152600401610e1290618670565b600b54610f2b57610e7c617ab6565b60015460005b81811015610f2757600b805460018101825560009190915283516000805160206190b083398151915260169092029182019081556020808601516000805160206190f08339815191528401805460ff1916911515919091179055604086015180518794610f03936000805160206190d0833981519152909101920190617ae5565b506060820151610f199060038301906013617b5f565b505050806001019050610e82565b5050505b610f33617b8c565b6000610f7485858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613e3c92505050565b9150915080610f9057610f876064613ff8565b9250505061113d565b815160009060ff16610fb557610fae83602001518460400151614059565b9050611109565b825160ff166001141561110557826020015151600114610ffa57600080516020619090833981519152604051610fea90618a68565b60405180910390a1506067611100565b6000836020015160008151811061100d57fe5b602090810291909101810151516001600160a01b0381166000908152600490925260409091205490915080158061106e575060018082038154811061104e57fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b156110ac576040516001600160a01b038316907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a26110f9565b60006110bb836001840361521b565b9050806110f7576040516001600160a01b038416907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a25b505b6000925050505b611109565b5060655b63ffffffff811661112e575050604080516000815260208101909152915061113d9050565b61113781613ff8565b93505050505b9392505050565b60075460ff1681565b33411461116c5760405162461bcd60e51b8152600401610e1290618dff565b3a1561118a5760405162461bcd60e51b8152600401610e1290618aee565b82516040805182815260208084028201019091526060908280156111c857816020015b6111b5617bb0565b8152602001906001900390816111ad5790505b50905060005b82811015611272576040518060c001604052808783815181106111ed57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200186838151811061122f57fe5b60200260200101516001600160401b03168152602001600015158152602001600081525082828151811061125f57fe5b60209081029190910101526001016111ce565b5060405163d31f968d60e01b81526120009063d31f968d9061129d9061100090600890600401618325565b60206040518083038186803b1580156112b557600080fd5b505afa1580156112c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ed919061808e565b156116105780516015548181111561138f57815b8181101561138d57601580548061131457fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055601680548061136757fe5b6001900381819060005260206000200160006113839190617be5565b9055600101611301565b505b60005b828110156115cf578181106114b75760158482815181106113af57fe5b602090810291909101810151825460018181018555600094855293839020825160049092020180546001600160a01b039283166001600160a01b0319918216178255938301519481018054958316958516959095179094556040820151600285018054606085015160808601511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590961692909716919091179290921692909217169290921790915560a00151600390910155855160169087908390811061147f57fe5b602090810291909101810151825460018101845560009384529282902081516114b19491909101929190910190617ae5565b506115c7565b8381815181106114c357fe5b6020026020010151601582815481106114d857fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a090910151600390910155855186908290811061159357fe5b6020026020010151601682815481106115a857fe5b9060005260206000200190805190602001906115c5929190617ae5565b505b600101611392565b507fb8e726330a0dad1cf3d04e925663b17e391f1ed547d79b7f4e5f344119b44246826040516115ff9190618fa3565b60405180910390a150505050610e32565b60608061161d83866155de565b9150915060005b6001548110156117135760006001828154811061163d57fe5b90600052602060002090600402016003015490508060001461170a5760006001838154811061166857fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab826001858154811061169c57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b1681526116d7926001600160a01b0390921691016182b6565b6000604051808303818588803b1580156116f057600080fd5b505af1158015611704573d6000803e3d6000fd5b50505050505b50600101611624565b504715611781577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516117499190618fa3565b60405180910390a1604051611002904780156108fc02916000818181858888f1935050505015801561177f573d6000803e3d6000fd5b505b6000600381905560055581511561179c5761179c8282615ac5565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117d957600080fd5b505af11580156117ed573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b606881565b61200581565b33612002146118555760405162461bcd60e51b8152600401610e1290618f5d565b60005b6015548110156118dd57816001600160a01b03166015828154811061187957fe5b60009182526020909120600490910201546001600160a01b031614156118d5576001601582815481106118a857fe5b9060005260206000209060040201600201601c6101000a81548160ff0219169083151502179055506118dd565b600101611858565b5050565b3341146119005760405162461bcd60e51b8152600401610e1290618dff565b60105443116119215760405162461bcd60e51b8152600401610e1290618803565b3a1561193f5760405162461bcd60e51b8152600401610e1290618aee565b60005460ff166119615760405162461bcd60e51b8152600401610e1290618670565b60006110023168056bc75e2d63100000811115611998576119918168056bc75e2d6310000063ffffffff6162b416565b915061199f565b5050611c20565b6040516309a99b4f60e41b815261100290639a99b4f0906119c690309086906004016182ca565b602060405180830381600087803b1580156119e057600080fd5b505af11580156119f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a189190618161565b915081611a26575050611c20565b6000805b84811015611a5457858582818110611a3e57fe5b9050602002013582019150806001019050611a2a565b5080611a6257505050611c20565b6000806000805b89811015611c185784898983818110611a7e57fe5b90506020020135880281611a8e57fe5b0493508a8a82818110611a9d57fe5b9050602002016020810190611ab29190617f0a565b6001600160a01b03811660009081526004602052604090205490935091508115611bce576000600180840381548110611ae757fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611b5457836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8586604051611b479190618fa3565b60405180910390a2611bc8565b600354611b67908663ffffffff6162f616565b6003908155810154611b7f908663ffffffff6162f616565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b290611bbf908890618fa3565b60405180910390a25b50611c10565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8585604051611c079190618fa3565b60405180910390a25b600101611a69565b505050505050505b5050436010555050565b6001546000908210611c3e57506000611cf4565b60006001600160a01b031660018381548110611c5657fe5b60009182526020909120600490910201546001600160a01b03161480611c8657506008541580611c865750600a54155b80611c95575060085460095410155b80611ca65750611ca482611cf9565b155b80611ccf57506000600b8381548110611cbb57fe5b906000526020600020906016020160000154115b80611ce357506001611cdf613080565b5111155b15611cf057506000611cf4565b5060015b919050565b6001546000908210611d0d57506000611cf4565b600b548210611d4a5760018281548110611d2357fe5b9060005260206000209060040201600201601c9054906101000a900460ff16159050611cf4565b60018281548110611d5757fe5b9060005260206000209060040201600201601c9054906101000a900460ff16158015611da45750600b8281548110611d8b57fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611e6857611db9617ab6565b60015460005b81811015611e6457600b805460018101825560009190915283516000805160206190b083398151915260169092029182019081556020808601516000805160206190f08339815191528401805460ff1916911515919091179055604086015180518794611e40936000805160206190d0833981519152909101920190617ae5565b506060820151611e569060038301906013617b5f565b505050806001019050611dbf565b5050505b336110011480611e79575033612002145b611e955760405162461bcd60e51b8152600401610e12906186a7565b6001600160a01b03811660009081526004602052604090205480611eb95750611f0c565b6001810390506000600b8281548110611ece57fe5b600091825260209091206001601690920201015460ff169050611ef1838361521b565b8015611efa5750805b15610e32576009805460001901905550505b50565b60015460609081906000805b82811015611f625760018181548110611f3057fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611f5a576001909101905b600101611f1b565b50606081604051908082528060200260200182016040528015611f8f578160200160208202803683370190505b509050606082604051908082528060200260200182016040528015611fc857816020015b6060815260200190600190039081611fb35790505b50600b54600094509091508414156121435760005b8481101561213d5760018181548110611ff257fe5b9060005260206000209060040201600201601c9054906101000a900460ff16612135576001818154811061202257fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061204d57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061207a57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156121125780601f106120e757610100808354040283529160200191612112565b820191906000526020600020905b8154815290600101906020018083116120f557829003601f168201915b505050505082858151811061212357fe5b60209081029190910101526001909301925b600101611fdd565b506121df565b60005b848110156121dd576001818154811061215b57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166121d5576001818154811061218b57fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106121b657fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101612146565b505b909450925050505b9091565b600181565b61100181565b60085481565b6102ca81565b600881565b6060806000600e549050600080600c5411612223576015612227565b600c545b90506060612233613080565b905060606122408261631b565b9050828251116122575790945092506121e7915050565b83838351031015612269578282510393505b831561229f576014430461228583838388880360008a8a616489565b61229d8383838888038989038a8b8b8b510301616489565b505b6060836040519080825280602002602001820160405280156122cb578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561230457816020015b60608152602001906001900390816122ef5790505b50905060005b858110156123855784818151811061231e57fe5b602002602001015183828151811061233257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083818151811061235e57fe5b602002602001015182828151811061237257fe5b602090810291909101015260010161230a565b509096509450505050509091565b60065481565b61200681565b61200081565b6001600160a01b038116600090815260046020526040812054806123cd576000915050611cf4565b6000190161113d81611cf9565b6001600160a01b03811660009081526004602052604081205480612402576000915050611cf4565b60018082038154811061241157fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b600f5481565b6012818154811061244857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156124d95780601f106124ae576101008083540402835291602001916124d9565b820191906000526020600020905b8154815290600101906020018083116124bc57829003601f168201915b505050505081565b60105481565b600181815481106124f457fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b61200381565b606681565b61271081565b33612000146125a45760405162461bcd60e51b8152600401610e1290618db0565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f389021016058383836040516125d793929190618fec565b60405180910390a1505050565b60025481565b60115481565b60145460ff1681565b600a5481565b6001600160a01b038116600090815260046020526040812054806126355760405162461bcd60e51b8152600401610e1290618d38565b6000190192915050565b600b546126fd5761264e617ab6565b60015460005b818110156126f957600b805460018101825560009190915283516000805160206190b083398151915260169092029182019081556020808601516000805160206190f08339815191528401805460ff19169115159190911790556040860151805187946126d5936000805160206190d0833981519152909101920190617ae5565b5060608201516126eb9060038301906013617b5f565b505050806001019050612654565b5050505b60085461270a5760036008555b600a54612717576002600a555b6000612722336125ff565b905061272d81611c2a565b6127495760405162461bcd60e51b8152600401610e1290618a25565b611f0c33826165e0565b600981565b61100781565b600381565b601481565b61100681565b6040518060a00160405280607881526020016191106078913981565b60005460ff1681565b61200281565b61300081565b6402540be40081565b60005460ff166127ca5760405162461bcd60e51b8152600401610e1290618670565b33611007146127eb5760405162461bcd60e51b8152600401610e1290618b1c565b61285584848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506166789050565b156128f2576020811461287a5760405162461bcd60e51b8152600401610e1290618cf2565b604080516020601f84018190048102820181019092528281526000916128b8918585808385018382808284376000920191909152506166d192505050565b9050606481101580156128ce5750620186a08111155b6128ea5760405162461bcd60e51b8152600401610e1290618915565b60025561301e565b61295284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506166789050565b156129f557602081146129775760405162461bcd60e51b8152600401610e129061848e565b604080516020601f84018190048102820181019092528281526000916129b5918585808385018382808284376000920191909152506166d192505050565b90506127106129cf600f54836162f690919063ffffffff16565b11156129ed5760405162461bcd60e51b8152600401610e12906184c5565b60065561301e565b612a5f84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506166789050565b15612af95760208114612a845760405162461bcd60e51b8152600401610e129061852d565b604080516020601f8401819004810282018101909252828152600091612ac2918585808385018382808284376000920191909152506166d192505050565b600c5490915080612ad1575060155b808210612af05760405162461bcd60e51b8152600401610e129061886d565b5060085561301e565b612b6284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506166789050565b15612bfb5760208114612b875760405162461bcd60e51b8152600401610e12906185f6565b604080516020601f8401819004810282018101909252828152600091612bc5918585808385018382808284376000920191909152506166d192505050565b9050600081118015612bd75750600a81105b612bf35760405162461bcd60e51b8152600401610e1290618e90565b600a5561301e565b612c6f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506166789050565b15612cfe5760208114612c945760405162461bcd60e51b8152600401610e12906185aa565b604080516020601f8401819004810282018101909252828152600091612cd2918585808385018382808284376000920191909152506166d192505050565b9050600d54811115612cf65760405162461bcd60e51b8152600401610e129061898b565b600e5561301e565b612d6784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506166789050565b15612de95760208114612d8c5760405162461bcd60e51b8152600401610e1290618b6a565b604080516020601f8401819004810282018101909252828152600091612dca918585808385018382808284376000920191909152506166d192505050565b600d819055600e54909150811015612de357600d54600e555b5061301e565b612e4d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506166789050565b15612efb5760208114612e725760405162461bcd60e51b8152600401610e129061863b565b604080516020601f8401819004810282018101909252828152600091612eb0918585808385018382808284376000920191909152506166d192505050565b905060008111612ed25760405162461bcd60e51b8152600401610e1290618715565b6064811115612ef35760405162461bcd60e51b8152600401610e129061875d565b600c5561301e565b612f6384848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601181527073797374656d526577617264526174696f60781b602082015291506166789050565b156130065760208114612f885760405162461bcd60e51b8152600401610e1290618e4c565b604080516020601f8401819004810282018101909252828152600091612fc6918585808385018382808284376000920191909152506166d192505050565b9050612710612fe0600654836162f690919063ffffffff16565b1115612ffe5760405162461bcd60e51b8152600401610e1290618c53565b600f5561301e565b60405162461bcd60e51b8152600401610e1290618eed565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a84848484604051613053949392919061845c565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156130af5761309b81611cf9565b156130a7578160010191505b60010161308a565b506060816040519080825280602002602001820160405280156130dc578160200160208202803683370190505b5090506000915060005b83811015613163576130f781611cf9565b1561315b576001818154811061310957fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061313457fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b6001016130e6565b50925050505b90565b601581565b61027181565b61100281565b6013818154811061244857fe5b6000613194613080565b519050600080600c54116131a95760156131ad565b600c545b9050808211156131bb578091505b816131c557600191505b5090565b67016345785d8a000081565b60055481565b61100381565b61200481565b60005460ff161561320a5760405162461bcd60e51b8152600401610e1290618c1c565b613212617b8c565b60006132356040518060a001604052806078815260200161911060789139613e3c565b91509150806132565760405162461bcd60e51b8152600401610e1290618d6f565b61325e617ab6565b60005b83602001515181101561345f57600b805460018101825560009190915282516000805160206190b083398151915260169092029182019081556020808501516000805160206190f08339815191528401805460ff19169115159190911790556040850151805186946132e7936000805160206190d0833981519152909101920190617ae5565b5060608201516132fd9060038301906013617b5f565b5050508360400151818151811061331057fe5b6020026020010151600b828154811061332557fe5b90600052602060002090601602016002019080519060200190613349929190617ae5565b5060018460200151828151811061335c57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591870151805191850193918590811061343257fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101613261565b50506103e860025550506000805460ff19166001179055565b600d5481565b601354600090815b818110156135875761356f85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506013805490925085915081106134d757fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156135655780601f1061353a57610100808354040283529160200191613565565b820191906000526020600020905b81548152906001019060200180831161354857829003601f168201915b50505050506166d6565b1561357f57600192505050611da4565b600101613486565b5060125460005b818110156135f8576135df86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506012805490925085915081106134d757fe5b156135f05760019350505050611da4565b60010161358e565b50600095945050505050565b33611001146136255760405162461bcd60e51b8152600401610e1290618f14565b600b546136e357613634617ab6565b60015460005b818110156136df57600b805460018101825560009190915283516000805160206190b083398151915260169092029182019081556020808601516000805160206190f08339815191528401805460ff19169115159190911790556040860151805187946136bb936000805160206190d0833981519152909101920190617ae5565b5060608201516136d19060038301906013617b5f565b50505080600101905061363a565b5050505b60006136ee8261673a565b90506136f981611c2a565b156118dd576118dd82826165e0565b606581565b601181565b3341146137315760405162461bcd60e51b8152600401610e1290618dff565b60005460ff166137535760405162461bcd60e51b8152600401610e1290618670565b600034116137735760405162461bcd60e51b8152600401610e129061895c565b3a156137915760405162461bcd60e51b8152600401610e1290618aee565b6001600160a01b03811660009081526004602052604090205460145434919060ff166137d157610271600f556103e86006556014805460ff191660011790555b6000821180156137e357506000600f54115b15613895576000613811612710613805600f54346168bd90919063ffffffff16565b9063ffffffff6168f716565b90508015613893576040516110029082156108fc029083906000818181858888f19350505050158015613848573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d816040516138789190618fa3565b60405180910390a1613890838263ffffffff6162b416565b92505b505b6000821180156138a757506000600654115b1561394d5760006138c9612710613805600654346168bd90919063ffffffff16565b9050801561394b5760405161dead9082156108fc029083906000818181858888f19350505050158015613900573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee5816040516139309190618fa3565b60405180910390a1613948838263ffffffff6162b416565b92505b505b8015613a4b57600060018083038154811061396457fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff16156139d157836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4846040516139c49190618fa3565b60405180910390a2613a45565b6003546139e4908463ffffffff6162f616565b60039081558101546139fc908463ffffffff6162f616565b60038201556040516001600160a01b038516907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc05590613a3c908690618fa3565b60405180910390a25b50610e32565b826001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b483604051613a849190618fa3565b60405180910390a2505050565b600e5481565b61100081565b61dead81565b600b8181548110613ab057fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015613b5b5780601f10613b3057610100808354040283529160200191613b5b565b820191906000526020600020905b815481529060010190602001808311613b3e57829003601f168201915b5050505050905083565b61100481565b6000600a5460001480613b7c575081155b80613b875750600954155b15613b945750600061113d565b60096000815460019003919050819055506000613bdf600a5461380585613805600b8981548110613bc157fe5b6000918252602090912060169091020154439063ffffffff6162b416565b90506000600b8581548110613bf057fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015613c5557600080fd5b505afa158015613c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c8d9190618179565b9150915060009350808310613dec57613ca6878761521b565b5060405163436aa28360e11b8152600090612002906386d5450690613ccf908b906004016182b6565b60206040518083038186803b158015613ce757600080fd5b505afa158015613cfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d1f9190617f26565b6001600160a01b031614613d8b576040516313d13bdb60e31b815261100190639e89ded890613d54908a9087906004016182ca565b600060405180830381600087803b158015613d6e57600080fd5b505af1158015613d82573d6000803e3d6000fd5b50505050613de3565b6040516305bfb49960e41b815261100190635bfb499090613db0908a906004016182b6565b600060405180830381600087803b158015613dca57600080fd5b505af1158015613dde573d6000803e3d6000fd5b505050505b60019350613dfe565b818310613dfe57613dfc8761673a565b505b6040516001600160a01b038816907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050509392505050565b613e44617b8c565b6000613e4e617b8c565b613e56617c29565b613e67613e6286616939565b61695e565b90506000805b613e76836169a8565b15613fea5780613e9b57613e91613e8c846169c9565b616a17565b60ff168452613fe2565b8060011415613fdd576060613eb7613eb2856169c9565b616a97565b90508051604051908082528060200260200182016040528015613ef457816020015b613ee1617bb0565b815260200190600190039081613ed95790505b5085602001819052508051604051908082528060200260200182016040528015613f3257816020015b6060815260200190600190039081613f1d5790505b50604086015260005b8151811015613fd257613f4c617bb0565b60606000613f6c858581518110613f5f57fe5b6020026020010151616b68565b92509250925080613f8c578860009a509a50505050505050505050613ff3565b8289602001518581518110613f9d57fe5b60200260200101819052508189604001518581518110613fb957fe5b6020026020010181905250505050806001019050613f3b565b506001925050613fe2565b613fea565b600101613e6d565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b60608152602001906001900390816140125790505090506140388363ffffffff16616c82565b8160008151811061404557fe5b602002602001018190525061113d81616c95565b600060648351111561409057600080516020619090833981519152604051614080906187ba565b60405180910390a1506066611da4565b60005b835181101561412e5760005b81811015614125578481815181106140b357fe5b6020026020010151600001516001600160a01b03168583815181106140d457fe5b6020026020010151600001516001600160a01b0316141561411d5760008051602061909083398151915260405161410a906188ca565b60405180910390a1606692505050611da4565b60010161409f565b50600101614093565b5060608060606015805480602002602001604051908101604052809291908181526020016000905b828210156141e05760008481526020908190206040805160c0810182526004860290920180546001600160a01b039081168452600180830154821685870152600283015491821693850193909352600160a01b81046001600160401b03166060850152600160e01b900460ff16151560808401526003015460a08301529083529092019101614156565b50505050905060606016805480602002602001604051908101604052809291908181526020016000905b828210156142b55760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156142a15780601f10614276576101008083540402835291602001916142a1565b820191906000526020600020905b81548152906001019060200180831161428457829003601f168201915b50505050508152602001906001019061420a565b50505050905060005b8251811015614312578281815181106142d357fe5b6020026020010151606001516003028382815181106142ee57fe5b60209081029190910101516001600160401b039091166060909101526001016142be565b5060608061432289898686616d1f565b9150915061433082826155de565b6001546040805182815260208084028201019091529298509096506000955085945092506060915082801561436f578160200160208202803683370190505b50905060005b828110156145005760006001600160a01b03166120026001600160a01b03166386d54506600184815481106143a657fe5b60009182526020909120600491820201546040516001600160e01b031960e085901b1681526143e1926001600160a01b0390921691016182b6565b60206040518083038186803b1580156143f957600080fd5b505afa15801561440d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144319190617f26565b6001600160a01b03161461449357600182828151811061444d57fe5b602002602001019060ff16908160ff16815250506001818154811061446e57fe5b90600052602060002090600402016003015460001461448e578360010193505b6144f8565b67016345785d8a0000600182815481106144a957fe5b906000526020600020906004020160030154106144cb578460010194506144f8565b600181815481106144d857fe5b9060005260206000209060040201600301546000146144f8578360010193505b600101614375565b5060608460405190808252806020026020018201604052801561452d578160200160208202803683370190505b50905060608560405190808252806020026020018201604052801561455c578160200160208202803683370190505b50905060608660405190808252806020026020018201604052801561458b578160200160208202803683370190505b5090506060876040519080825280602002602001820160405280156145ba578160200160208202803683370190505b50905060006060886040519080825280602002602001820160405280156145eb578160200160208202803683370190505b50905060608960405190808252806020026020018201604052801561461a578160200160208202803683370190505b50905060009a506000995060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561466257600080fd5b505afa158015614676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061469a9190618161565b905067016345785d8a00008111156146e6576000805160206190908339815191526040516146c790618bdb565b60405180910390a160689e505050505050505050505050505050611da4565b60005b8a811015614a7a578981815181106146fd57fe5b602002602001015160ff16600114156147f3576001818154811061471d57fe5b9060005260206000209060040201600301546000146147ee576001818154811061474357fe5b600091825260209091206004909102015484516001600160a01b039091169085908e90811061476e57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001818154811061479b57fe5b906000526020600020906004020160030154838d815181106147b957fe5b60200260200101818152505060018a8d815181106147d357fe5b602002602001019060ff16908160ff16815250508b6001019b505b614a72565b67016345785d8a00006001828154811061480957fe5b9060005260206000209060040201600301541061498e576001818154811061482d57fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898e8151811061485e57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be4006001838154811061489357fe5b906000526020600020906004020160030154816148ac57fe5b06600183815481106148ba57fe5b9060005260206000209060040201600301540390506148e283826162b490919063ffffffff16565b898f815181106148ee57fe5b6020026020010181815250506001828154811061490757fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316878f8151811061493857fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888f8151811061496557fe5b6020908102919091010152614980868263ffffffff6162f616565b95508d6001019d5050614a72565b6001818154811061499b57fe5b906000526020600020906004020160030154600014614a7257600181815481106149c157fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848d815181106149f257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060018181548110614a1f57fe5b906000526020600020906004020160030154838d81518110614a3d57fe5b60200260200101818152505060008a8d81518110614a5757fe5b602002602001019060ff16908160ff16815250508b6001019b505b6001016146e9565b5060008415614cf0576002546040516303702b2960e51b815261100491636e056520918891614ab4918e918e918d914201906004016183c4565b6020604051808303818588803b158015614acd57600080fd5b505af193505050508015614afe575060408051601f3d908101601f19168201909252614afb9181019061808e565b60015b614c75576040516000815260443d1015614b1a57506000614bb5565b60046000803e60005160e01c6308c379a08114614b3b576000915050614bb5565b60043d036004833e81513d60248201116001600160401b0382111715614b6657600092505050614bb5565b80830180516001600160401b03811115614b87576000945050505050614bb5565b8060208301013d8601811115614ba557600095505050505050614bb5565b601f01601f191660405250925050505b80614bc05750614c02565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051614bf49190618449565b60405180910390a250614c70565b3d808015614c2c576040519150601f19603f3d011682016040523d82523d6000602084013e614c31565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a4582604051614c669190618449565b60405180910390a2505b614cf0565b8015614cb7577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b7086604051614caa9190618fa3565b60405180910390a1614cee565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280604051614ce590618573565b60405180910390a25b505b8015614ea65760005b8751811015614ea4576000888281518110614d1057fe5b60200260200101519050600060018281548110614d2957fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc9185908110614d5a57fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015614e165760018281548110614d9b57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110614dea57fe5b906000526020600020906004020160030154604051614e099190618fa3565b60405180910390a2614e9a565b60018281548110614e2357fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110614e7257fe5b906000526020600020906004020160030154604051614e919190618fa3565b60405180910390a25b5050600101614cf9565b505b83511561509c5760005b845181101561509a578a8181518110614ec557fe5b602002602001015160ff1660011415614f64576120026001600160a01b031663092193ab858381518110614ef557fe5b6020026020010151878481518110614f0957fe5b60200260200101516040518363ffffffff1660e01b8152600401614f2d91906182b6565b6000604051808303818588803b158015614f4657600080fd5b505af1158015614f5a573d6000803e3d6000fd5b5050505050615092565b6000858281518110614f7257fe5b60200260200101516001600160a01b03166108fc868481518110614f9257fe5b60200260200101519081150290604051600060405180830381858888f193505050509050801561502857858281518110614fc857fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d86848151811061500657fe5b602002602001015160405161501b9190618fa3565b60405180910390a2615090565b85828151811061503457fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d86848151811061507257fe5b60200260200101516040516150879190618fa3565b60405180910390a25b505b600101614eb0565b505b5050505050505050505050505060005b60015481101561510957600181815481106150c357fe5b906000526020600020906004020160030154600014615101576000600182815481106150eb57fe5b9060005260206000209060040201600301819055505b6001016150ac565b504715615177577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d4760405161513f9190618fa3565b60405180910390a1604051611002904780156108fc02916000818181858888f19350505050158015615175573d6000803e3d6000fd5b505b60006003819055600555815115615192576151928282615ac5565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156151cf57600080fd5b505af11580156151e3573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b6000806001838154811061522b57fe5b90600052602060002090600402016003015490506000600180805490500390506001615255613080565b511161528a5760006001858154811061526a57fe5b906000526020600020906004020160030181905550600092505050611da4565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516152c39190618fa3565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156154b0576001816001018154811061530457fe5b90600052602060002090600402016001828154811061531f57fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b8054909183019081106153e057fe5b9060005260206000209060160201600b82815481106153fb57fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054615452938386019390821615610100026000190190911604617c49565b5061546560038281019084016013617cbe565b5090505080600101600460006001848154811061547e57fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020556001016152e6565b5060018054806154bc57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061550f57fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906155416002830182617be5565b61554f600383016000617ce8565b50509055600081838161555e57fe5b04905080156155d25760015460005b818110156155cf576155a6836001838154811061558657fe5b9060005260206000209060040201600301546162f690919063ffffffff16565b600182815481106155b357fe5b600091825260209091206003600490920201015560010161556d565b50505b50600195945050505050565b6060806000808080806155ef61318a565b6001549091505b801561581e57600181039250600b838154811061560f57fe5b600091825260209091206001601690920201015460ff1661562f57615815565b6001838154811061563c57fe5b60009182526020909120600490910201546001600160a01b03169450615663858484613b6b565b93508361566f57615815565b60405163436aa28360e11b81526000908190612002906386d5450690615699908a906004016182b6565b60206040518083038186803b1580156156b157600080fd5b505afa1580156156c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906156e99190617f26565b90506001600160a01b03811615615772576040516302ceee9160e11b81526120029063059ddd229061571f9084906004016182b6565b60206040518083038186803b15801561573757600080fd5b505afa15801561574b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061576f9190617f26565b91505b60005b8c5181101561581157876001600160a01b03168d828151811061579457fe5b6020026020010151600001516001600160a01b031614806157dd5750826001600160a01b03168d82815181106157c657fe5b6020026020010151600001516001600160a01b0316145b156158095760018d82815181106157f057fe5b6020908102919091010151901515608090910152615811565b600101615775565b5050505b600019016155f6565b5060005b895181101561588b5789818151811061583757fe5b60200260200101516080015180615877575060006001600160a01b03168a828151811061586057fe5b6020026020010151600001516001600160a01b0316145b15615883578560010195505b600101615822565b50885185106159735760408051600180825281830190925290816020015b6158b1617bb0565b8152602001906001900390816158a9575050604080516001808252818301909252919850602082015b60608152602001906001900390816158da579050509550886000815181106158fe57fe5b60200260200101518760008151811061591357fe5b60200260200101819052508760008151811061592b57fe5b60200260200101518660008151811061594057fe5b602002602001018190525060008760008151811061595a57fe5b6020908102919091010151901515608090910152615ab8565b848951036040519080825280602002602001820160405280156159b057816020015b61599d617bb0565b8152602001906001900390816159955790505b509650848951036040519080825280602002602001820160405280156159ea57816020015b60608152602001906001900390816159d55790505b5095506000915060005b8951811015615ab657898181518110615a0957fe5b602002602001015160800151158015615a4c575060006001600160a01b03168a8281518110615a3457fe5b6020026020010151600001516001600160a01b031614155b15615aae57898181518110615a5d57fe5b6020026020010151888481518110615a7157fe5b6020026020010181905250888181518110615a8857fe5b6020026020010151878481518110615a9c57fe5b60200260200101819052508260010192505b6001016159f4565b505b50505050505b9250929050565b600154825160005b82811015615be2576001615adf617bb0565b60018381548110615aec57fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015615bb657878181518110615b7c57fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415615bae5760009250615bb6565b600101615b68565b508115615bd85780516001600160a01b03166000908152600460205260408120555b5050600101615acd565b5080821115615ca157805b82811015615c9f576001805480615c0057fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480615c5357fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590615c856002830182617be5565b615c93600383016000617ce8565b50509055600101615bed565b505b6000818310615cb05781615cb2565b825b905060005b8181101561605657615d64868281518110615cce57fe5b602002602001015160018381548110615ce357fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a08201526170eb565b615f18578060010160046000888481518110615d7c57fe5b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550858181518110615db857fe5b602002602001015160018281548110615dcd57fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101558451859082908110615e8857fe5b6020026020010151600b8281548110615e9d57fe5b90600052602060002090601602016002019080519060200190615ec1929190617ae5565b506000600b8281548110615ed157fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110615f0257fe5b600091825260209091206016909102015561604e565b858181518110615f2457fe5b60200260200101516060015160018281548110615f3d57fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b03160217905550616003858281518110615f8157fe5b6020026020010151600b8381548110615f9657fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156135655780601f1061353a57610100808354040283529160200191613565565b61604e5784818151811061601357fe5b6020026020010151600b828154811061602857fe5b9060005260206000209060160201600201908051906020019061604c929190617ae5565b505b600101615cb7565b508282111561622e57616067617ab6565b835b8381101561622b5785818151811061607d57fe5b60200260200101518260400181905250600187828151811061609b57fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b80549283018155909352845160169091026000805160206190b08339815191528101918255858301516000805160206190f08339815191528201805491151560ff19909216919091179055928501518051869492936161d1936000805160206190d083398151915201920190617ae5565b5060608201516161e79060038301906013617b5f565b50505080600101600460008984815181106161fe57fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101616069565b50505b616236617147565b61623e61732f565b6000600981905560015493505b838110156162ac576000600b828154811061626257fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061629357fe5b600091825260209091206016909102015560010161624b565b505050505050565b600061113d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061751d565b60008282018381101561113d5760405162461bcd60e51b8152600401610e12906186de565b60015481516040805182815260208084028201019091526060929190839082801561635a57816020015b60608152602001906001900390816163455790505b50600b549091508314616371579250611cf4915050565b60005b8281101561648057600b60016004600089858151811061639057fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403815481106163c457fe5b600091825260209182902060026016909202018101805460408051601f60001961010060018616150201909316949094049182018590048502840185019052808352919290919083018282801561645c5780601f106164315761010080835404028352916020019161645c565b820191906000526020600020905b81548152906001019060200180831161643f57829003601f168201915b505050505082828151811061646d57fe5b6020908102919091010152600101616374565b50949350505050565b60005b828110156165d657600082878388016040516020016164ac9291906182a8565b6040516020818303038152906040528051906020012060001c816164cc57fe5b069050808501828701146165cd57600089838801815181106164ea57fe5b602002602001015190506060898489018151811061650457fe5b602002602001015190508a8388018151811061651c57fe5b60200260200101518b858a018151811061653257fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b8489018151811061656157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061658f57fe5b60200260200101518a858a01815181106165a557fe5b6020026020010181905250808a848901815181106165bf57fe5b602002602001018190525050505b5060010161648c565b5050505050505050565b600980546001908101909155600b8054839081106165fa57fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b828154811061663057fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b60008160405160200161668b919061828c565b60405160208183030381529060405280519060200120836040516020016166b2919061828c565b6040516020818303038152906040528051906020012014905092915050565b015190565b8151815160009160019181148083146166f25760009250616730565b600160208701838101602088015b60028483851001141561672b57805183511461671f5760009650600093505b60209283019201616700565b505050505b5090949350505050565b6001600160a01b0381166000908152600460205260408120548061676357506000199050611cf4565b60018103905060006001828154811061677857fe5b906000526020600020906004020160030154905060006001838154811061679b57fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d906167f4908590618fa3565b60405180910390a28061680c57829350505050611cf4565b600081838161681757fe5b04905080156168b35760005b848110156168655761683c826001838154811061558657fe5b6001828154811061684957fe5b6000918252602090912060036004909202010155600101616823565b50600180549085015b818110156168b057616887836001838154811061558657fe5b6001828154811061689457fe5b600091825260209091206003600490920201015560010161686e565b50505b5091949350505050565b6000826168cc57506000611da4565b828202828482816168d957fe5b041461113d5760405162461bcd60e51b8152600401610e1290618aad565b600061113d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250617549565b616941617cf7565b506040805180820190915281518152602082810190820152919050565b616966617c29565b61696f82617580565b61697857600080fd5b600061698783602001516175ba565b60208085015160408051808201909152868152920190820152915050919050565b60006169b2617cf7565b505080518051602091820151919092015191011190565b6169d1617cf7565b6169da826169a8565b6169e357600080fd5b602082015160006169f38261761d565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590616a2c57508151602110155b616a3557600080fd5b6000616a4483602001516175ba565b90508083600001511015616a6a5760405162461bcd60e51b8152600401610e1290618cbb565b82516020808501518301805192849003929183101561648057506020919091036101000a90049392505050565b6060616aa282617580565b616aab57600080fd5b6000616ab6836176fe565b9050606081604051908082528060200260200182016040528015616af457816020015b616ae1617cf7565b815260200190600190039081616ad95790505b5090506000616b0685602001516175ba565b60208601510190506000805b84811015616b5d57616b238361761d565b9150604051806040016040528083815260200184815250848281518110616b4657fe5b602090810291909101015291810191600101616b12565b509195945050505050565b616b70617bb0565b60606000616b7c617bb0565b6060616b86617c29565b616b8f8761695e565b90506000805b616b9e836169a8565b15616c735780616bc957616bb9616bb4846169c9565b61775a565b6001600160a01b03168552616c6b565b8060011415616bf157616bde616bb4846169c9565b6001600160a01b03166020860152616c6b565b8060021415616c1957616c06616bb4846169c9565b6001600160a01b03166040860152616c6b565b8060031415616c4557616c2e613e8c846169c9565b6001600160401b0316606086015260019150616c6b565b8060041415616c6657616c5f616c5a846169c9565b617774565b9350616c6b565b616c73565b600101616b95565b50929791965091945092505050565b6060611da4616c90836177e4565b6178ca565b6060815160001415616cb65750604080516000815260208101909152611cf4565b606082600081518110616cc557fe5b602002602001015190506000600190505b8351811015616d0657616cfc82858381518110616cef57fe5b602002602001015161791c565b9150600101616cd6565b5061113d616d19825160c060ff16617999565b8261791c565b60608060006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b158015616d5f57600080fd5b505afa158015616d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190616d979190618161565b90508085518851011015616dac575083518651015b606081604051908082528060200260200182016040528015616de857816020015b616dd5617bb0565b815260200190600190039081616dcd5790505b509050606082604051908082528060200260200182016040528015616e2157816020015b6060815260200190600190039081616e0c5790505b50905060008060005b8b51831080616e395750895182105b8015616e4457508581105b156170d9578b51831415616eb457898281518110616e5e57fe5b6020026020010151858281518110616e7257fe5b6020026020010181905250888281518110616e8957fe5b6020026020010151848281518110616e9d57fe5b602090810291909101015260019182019101616e2a565b8951821415616f1f578b8381518110616ec957fe5b6020026020010151858281518110616edd57fe5b60200260200101819052508a8381518110616ef457fe5b6020026020010151848281518110616f0857fe5b602090810291909101015260019283019201616e2a565b898281518110616f2b57fe5b6020026020010151606001516001600160401b03168c8481518110616f4c57fe5b6020026020010151606001516001600160401b03161115616fc8578b8381518110616f7357fe5b6020026020010151858281518110616f8757fe5b60200260200101819052508a8381518110616f9e57fe5b6020026020010151848281518110616fb257fe5b60200260200101819052508260010192506170d1565b898281518110616fd457fe5b6020026020010151606001516001600160401b03168c8481518110616ff557fe5b6020026020010151606001516001600160401b031610156170715789828151811061701c57fe5b602002602001015185828151811061703057fe5b602002602001018190525088828151811061704757fe5b602002602001015184828151811061705b57fe5b60200260200101819052508160010191506170d1565b89828151811061707d57fe5b6020026020010151600001516001600160a01b03168c848151811061709e57fe5b6020026020010151600001516001600160a01b031610156170c5578b8381518110616f7357fe5b898281518110616e5e57fe5b600101616e2a565b50929a91995090975050505050505050565b805182516000916001600160a01b039182169116148015617125575081602001516001600160a01b031683602001516001600160a01b0316145b801561113d5750506040908101519101516001600160a01b0390811691161490565b6012546013548082111561719257805b8281101561719057601280548061716a57fe5b6001900381819060005260206000200160006171869190617be5565b9055600101617157565b505b60008183106171a157816171a3565b825b905060005b818110156172bb57617260601282815481106171c057fe5b600091825260209182902001805460408051601f600260001961010060018716150201909416939093049283018590048502810185019091528181529283018282801561724e5780601f106172235761010080835404028352916020019161724e565b820191906000526020600020905b81548152906001019060200180831161723157829003601f168201915b5050505050601383815481106134d757fe5b6172b3576013818154811061727157fe5b906000526020600020016012828154811061728857fe5b9060005260206000200190805460018160011615610100020316600290046172b1929190617c49565b505b6001016171a8565b5082821115610e3257825b82811015617329576012601382815481106172dd57fe5b6000918252602080832084546001818101875595855291909320929091018054617320949390920192909160026101009282161592909202600019011604617c49565b506001016172c6565b50505050565b601354600b548082111561737a57805b8281101561737857601380548061735257fe5b60019003818190600052602060002001600061736e9190617be5565b905560010161733f565b505b6000818310617389578161738b565b825b905060005b818110156174aa57617448601382815481106173a857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156174365780601f1061740b57610100808354040283529160200191617436565b820191906000526020600020905b81548152906001019060200180831161741957829003601f168201915b5050505050600b8381548110615f9657fe5b6174a257600b818154811061745957fe5b90600052602060002090601602016002016013828154811061747757fe5b9060005260206000200190805460018160011615610100020316600290046174a0929190617c49565b505b600101617390565b5082821115610e3257825b82811015617329576013600b82815481106174cc57fe5b60009182526020808320845460018082018755958552919093206016929092029092016002908101805461751495939094019390926000199082161561010002011604617c49565b506001016174b5565b600081848411156175415760405162461bcd60e51b8152600401610e129190618449565b505050900390565b6000818361756a5760405162461bcd60e51b8152600401610e129190618449565b50600083858161757657fe5b0495945050505050565b805160009061759157506000611cf4565b6020820151805160001a9060c08210156175b057600092505050611cf4565b5060019392505050565b8051600090811a60808110156175d4576000915050611cf4565b60b88110806175ef575060c081108015906175ef575060f881105b156175fe576001915050611cf4565b60c08110156176125760b519019050611cf4565b60f519019050611cf4565b80516000908190811a608081101561763857600191506176f7565b60b881101561764d57607e19810191506176f7565b60c081101561769e57600060b78203600186019550806020036101000a8651049150600181018201935050808310156176985760405162461bcd60e51b8152600401610e12906189fa565b506176f7565b60f88110156176b35760be19810191506176f7565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156176f55760405162461bcd60e51b8152600401610e12906189fa565b505b5092915050565b805160009061770f57506000611cf4565b6000809050600061772384602001516175ba565b602085015185519181019250015b80821015617751576177428261761d565b82019150826001019250617731565b50909392505050565b805160009060151461776b57600080fd5b611da482616a17565b805160609061778257600080fd5b600061779183602001516175ba565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156177c8576020820181803683370190505b5090506000816020019050616480848760200151018285617a6b565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166178285750601861784c565b6fffffffffffffffffffffffffffffffff1984166178485750601061784c565b5060005b60208110156178825781818151811061786157fe5b01602001516001600160f81b0319161561787a57617882565b60010161784c565b60008160200390506060816040519080825280601f01601f1916602001820160405280156178b7576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156178fc5750607f60f81b826000815181106178ea57fe5b01602001516001600160f81b03191611155b15617908575080611cf4565b611da461791a8351608060ff16617999565b835b6060806040519050835180825260208201818101602087015b8183101561794d578051835260209283019201617935565b50855184518101855292509050808201602086015b8183101561797a578051835260209283019201617962565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106179c35760405162461bcd60e51b8152600401610e1290618845565b60408051600180825281830190925260609160208201818036833701905050905060378411617a1d5782840160f81b816000815181106179ff57fe5b60200101906001600160f81b031916908160001a9053509050611da4565b6060617a28856177e4565b90508381510160370160f81b82600081518110617a4157fe5b60200101906001600160f81b031916908160001a905350617a62828261791c565b95945050505050565b80617a7557610e32565b5b60208110617a95578251825260209283019290910190601f1901617a76565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001617ae0617d11565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617b2657805160ff1916838001178555617b53565b82800160010185558215617b53579182015b82811115617b53578251825591602001919060010190617b38565b506131c5929150617d30565b8260138101928215617b535791602002820182811115617b53578251825591602001919060010190617b38565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b50805460018160011615610100020316600290046000825580601f10617c0b5750611f0c565b601f016020900490600052602060002090810190611f0c9190617d30565b6040518060400160405280617c3c617cf7565b8152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617c825780548555617b53565b82800160010185558215617b5357600052602060002091601f016020900482015b82811115617b53578254825591600101919060010190617ca3565b8260138101928215617b535791820182811115617b53578254825591600101919060010190617ca3565b50611f0c906013810190617d30565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b61316991905b808211156131c55760008155600101617d36565b8035611da48161907a565b60008083601f840112617d66578182fd5b5081356001600160401b03811115617d7c578182fd5b6020830191508360208083028501011115615abe57600080fd5b6000601f8381840112617da7578182fd5b8235617dba617db58261902f565b619009565b818152925060208084019085810160005b84811015617e4c578135880189603f820112617de657600080fd5b838101356001600160401b03811115617dfe57600080fd5b617e0f818901601f19168601619009565b81815260408c81848601011115617e2557600080fd5b82818501888401375060009181018601919091528552509282019290820190600101617dcb565b50505050505092915050565b600082601f830112617e68578081fd5b8135617e76617db58261902f565b818152915060208083019084810181840286018201871015617e9757600080fd5b6000805b85811015617e4c5782356001600160401b0381168114617eb9578283fd5b85529383019391830191600101617e9b565b60008083601f840112617edc578182fd5b5081356001600160401b03811115617ef2578182fd5b602083019150836020828501011115615abe57600080fd5b600060208284031215617f1b578081fd5b813561113d8161907a565b600060208284031215617f37578081fd5b815161113d8161907a565b60008060008060408587031215617f57578283fd5b84356001600160401b0380821115617f6d578485fd5b617f7988838901617d55565b90965094506020870135915080821115617f91578384fd5b50617f9e87828801617d55565b95989497509550505050565b600080600060608486031215617fbe578283fd5b83356001600160401b0380821115617fd4578485fd5b81860187601f820112617fe5578586fd5b80359250617ff5617db58461902f565b80848252602080830192508084018b82838902870101111561801557898afd5b8994505b8685101561803f5761802b8c82617d4a565b845260019490940193928101928101618019565b509097508801359350505080821115618056578384fd5b61806287838801617e58565b93506040860135915080821115618077578283fd5b5061808486828701617d96565b9150509250925092565b60006020828403121561809f578081fd5b8151801515811461113d578182fd5b600080602083850312156180c0578182fd5b82356001600160401b038111156180d5578283fd5b6180e185828601617ecb565b90969095509350505050565b60008060008060408587031215618102578384fd5b84356001600160401b0380821115618118578586fd5b61812488838901617ecb565b9096509450602087013591508082111561813c578384fd5b50617f9e87828801617ecb565b60006020828403121561815a578081fd5b5035919050565b600060208284031215618172578081fd5b5051919050565b6000806040838503121561818b578182fd5b505080516020909101519092909150565b6000806000604084860312156181b0578081fd5b833560ff811681146181c0578182fd5b925060208401356001600160401b038111156181da578182fd5b6181e686828701617ecb565b9497909650939450505050565b6000815180845260208085019450808401835b8381101561822b5781516001600160a01b031687529582019590820190600101618206565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b6000815180845261827881602086016020860161904e565b601f01601f19169290920160200192915050565b6000825161829e81846020870161904e565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0392909216825260ff16602082015260400190565b60006020825261113d60208301846181f3565b60006040825261836760408301856181f3565b602083820381850152818551808452828401915082838202850101838801865b838110156183b557601f198784030185526183a3838351618260565b94860194925090850190600101618387565b50909998505050505050505050565b6000608082526183d760808301876181f3565b828103602084810191909152865180835287820192820190845b8181101561840d578451835293830193918301916001016183f1565b5050848103604086015261842181886181f3565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b60006020825261113d6020830184618260565b600060408252618470604083018688618236565b8281036020840152618483818587618236565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526042908201527f746865206275726e526174696f20706c75732073797374656d5265776172645260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b60208082526042908201527f7468652073797374656d526577617264526174696f20706c7573206275726e5260408201527f6174696f206d757374206265206e6f2067726561746572207468616e20313030606082015261030360f41b608082015260a00190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526024908201527f6c656e677468206f662073797374656d526577617264526174696f206d69736d6040820152630c2e8c6d60e31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152617a626060830184618260565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260406020830152617a62604083018486618236565b6040518181016001600160401b038111828210171561902757600080fd5b604052919050565b60006001600160401b03821115619044578081fd5b5060209081020190565b60005b83811015619069578181015183820152602001619051565b838111156173295750506000910152565b6001600160a01b0381168114611f0c57600080fdfe70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaf87680f873f871949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d79164b085e6972fc98cd3c81d64d40e325acfed44365b97a7567a27939c14dbc7512ddcf54cb1284eb637cfa308ae4e00cb5588a164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(SlashContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b506004361061035d5760003560e01c80637e434d54116101d3578063c80d4b8f11610104578063df8079e9116100a2578063f9a2bbc71161007c578063f9a2bbc714610601578063fc3e590814610609578063fc4333cd14610611578063fd6a6879146106195761035d565b8063df8079e9146105e9578063e1c7392a146105f1578063f1fad104146105f95761035d565b8063c96be4cb116100de578063c96be4cb146105b3578063cc844b73146105c6578063dc927faf146105d9578063dcc6f156146105e15761035d565b8063c80d4b8f14610590578063c81b166214610598578063c8509d81146105a05761035d565b8063a1a11bf511610171578063aad560631161014b578063aad5606314610565578063ab51bb961461056d578063ac0af62914610575578063ac4317511461057d5761035d565b8063a1a11bf51461054d578063a78abc1614610555578063aa82dce11461055d5761035d565b806396713da9116101ad57806396713da9146105225780639dc092621461052a5780639e89ded8146105325780639f804f5f146105455761035d565b80637e434d54146104ff5780638256ace614610507578063831d65d11461050f5761035d565b8063493279b1116102ad57806362b72cf51161024b578063718a8aa811610225578063718a8aa8146104df57806375d47a0a146104e75780637912a65d146104ef5780637942fd05146104f75761035d565b806362b72cf5146104c75780636e47b482146104cf57806370fd5bad146104d75761035d565b806351b4dce31161028757806351b4dce31461049c57806351e80672146104a4578063567a372d146104ac5780635bfb4990146104b45761035d565b8063493279b1146104775780634bf6c8821461048c57806350055f90146104945761035d565b8063280870281161031a57806337c8dab9116102f457806337c8dab914610431578063389f4f71146104525780633dffc3871461045a57806343756e5c1461046f5761035d565b806328087028146104015780633306ccca1461040957806335aa2e441461041e5761035d565b80630bee7a67146103625780630e2374a5146103805780631182b8751461039557806322d1e80b146103b557806323bac5a2146103ca57806327962118146103ec575b600080fd5b61036a610621565b6040516103779190613d67565b60405180910390f35b610388610626565b6040516103779190613545565b6103a86103a336600461347b565b61062c565b604051610377919061357d565b6103bd610692565b6040516103779190613572565b6103dd6103d8366004613192565b61069b565b60405161037793929190613d4f565b6103ff6103fa3660046132d8565b6106be565b005b610388610a13565b610411610a19565b6040516103779190613d38565b61038861042c36600461344b565b610a1e565b61044461043f366004613192565b610a45565b604051610377929190613d41565b610411610a9c565b610462610aa2565b6040516103779190613d78565b610388610aa7565b61047f610aad565b6040516103779190613d29565b610462610ab3565b610411610ab8565b610388610abe565b610388610ac4565b610411610aca565b6103ff6104c2366004613192565b610ad0565b610411610bdc565b610388610be2565b610462610be8565b610462610bed565b610388610bf2565b610411610bf8565b610462610bfd565b610388610c02565b610444610c08565b6103ff61051d36600461347b565b610c12565b610462610d26565b610388610d2b565b6103ff6105403660046131ca565b610d31565b610411610d60565b610388610d66565b6103bd610d6c565b610388610d75565b610388610d7b565b61036a610d81565b610411610d86565b6103ff61058b36600461332f565b610d8b565b610411611327565b61038861132c565b6103ff6105ae36600461347b565b611332565b6103ff6105c1366004613192565b6113a3565b6103ff6105d4366004613398565b611812565b610388611df0565b610411611df6565b610388611dfb565b6103ff611e01565b610462611e4e565b610388611e53565b610462611e59565b6103ff611e5e565b6103886122a7565b606481565b61200181565b606033612000146106585760405162461bcd60e51b815260040161064f90613bcc565b60405180910390fd5b60005460ff1661067a5760405162461bcd60e51b815260040161064f90613672565b60405162461bcd60e51b815260040161064f90613cbd565b60075460ff1681565b600260208190526000918252604090912080546001820154919092015460ff1683565b60005460ff166106e05760405162461bcd60e51b815260040161064f90613672565b6006546106ed5760146006555b6008546106fa57603c6008555b81511580159061070a5750805115155b6107265760405162461bcd60e51b815260040161064f90613b2a565b60408051600380825260808201909252606091816020015b606081526020019060019003908161073e5790505090506107606102ca6122ad565b8160008151811061076d57fe5b6020026020010181905250610781836122c8565b8160018151811061078e57fe5b60200260200101819052506107a2826122c8565b816002815181106107af57fe5b602002602001018190525060606107c58261231e565b60408051603480825260608281019093529293509091602082018180368337019050509050815160346020830182602086016068600019fa61080657600080fd5b506014810151603482015160405163436aa28360e11b8152600090612002906386d5450690610839908690600401613545565b60206040518083038186803b15801561085157600080fd5b505afa158015610865573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088991906131ae565b6001600160a01b031614156108b05760405162461bcd60e51b815260040161064f90613642565b43600854820110156108d45760405162461bcd60e51b815260040161064f906135e3565b604051631871f7d960e31b81526120029063c38fbec8906108f9908590600401613545565b600060405180830381600087803b15801561091357600080fd5b505af1158015610927573d6000803e3d6000fd5b50506040516335409f7f60e01b815261100092506335409f7f9150610950908590600401613545565b600060405180830381600087803b15801561096a57600080fd5b505af115801561097e573d6000803e3d6000fd5b50506006546040516309a99b4f60e41b815260646110028031909302049350909150639a99b4f0906109b69033908590600401613559565b602060405180830381600087803b1580156109d057600080fd5b505af11580156109e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a089190613463565b505050505050505050565b61200581565b603c81565b60018181548110610a2b57fe5b6000918252602090912001546001600160a01b0316905081565b600080610a50612f79565b5050506001600160a01b0316600090815260026020818152604092839020835160608101855281548082526001830154938201849052919093015460ff16151592909301919091529091565b60055481565b600181565b61100181565b6102ca81565b600881565b60065481565b61200681565b61200081565b60045481565b3361100014610af15760405162461bcd60e51b815260040161064f906138b5565b60005460ff16610b135760405162461bcd60e51b815260040161064f90613672565b61200063f7a251d7600b610b26846123af565b60006040518463ffffffff1660e01b8152600401610b4693929190613d86565b600060405180830381600087803b158015610b6057600080fd5b505af1925050508015610b71575060015b610bd9573d808015610b9f576040519150601f19603f3d011682016040523d82523d6000602084013e610ba4565b606091505b50816001600160a01b0316600080516020613e63833981519152600083604051610bcf929190613590565b60405180910390a2505b50565b60035481565b61100581565b600281565b601081565b61100881565b600581565b600b81565b61200381565b6004546005549091565b3361200014610c335760405162461bcd60e51b815260040161064f90613bcc565b60005460ff16610c555760405162461bcd60e51b815260040161064f90613672565b610c5d612f9c565b6000610c9e84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061247992505050565b915091508015610ce55781516040517f7f0956d47419b9525356e7111652b653b530ec6f5096dccc04589bc38e62996791610cd891613d67565b60405180910390a1610d1e565b81516040517f7d45f62d17443dd4547bca8a8112c60e2385669318dc300ec61a5d2492f262e791610d1591613d67565b60405180910390a15b50505b505050565b600981565b61100781565b3361100014610d525760405162461bcd60e51b815260040161064f906138b5565b610d5c82826124f9565b5050565b60085481565b61100681565b60005460ff1681565b61200281565b61300081565b600081565b600481565b60005460ff16610dad5760405162461bcd60e51b815260040161064f90613672565b3361100714610dce5760405162461bcd60e51b815260040161064f90613a19565b610e3984848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260148152731b5a5cd9195b59585b9bdc951a1c995cda1bdb1960621b602082015291506126ac9050565b15610ed45760208114610e5e5760405162461bcd60e51b815260040161064f90613841565b604080516020601f8401819004810282018101909252828152600091610e9c9185858083850183828082843760009201919091525061270692505050565b905060018110158015610eb0575060055481105b610ecc5760405162461bcd60e51b815260040161064f90613b87565b6004556112e4565b610f3a84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e19995b1bdb9e551a1c995cda1bdb19608a1b602082015291506126ac9050565b15610fd65760208114610f5f5760405162461bcd60e51b815260040161064f90613a67565b604080516020601f8401819004810282018101909252828152600091610f9d9185858083850183828082843760009201919091525061270692505050565b90506103e88111158015610fb2575060045481115b610fce5760405162461bcd60e51b815260040161064f9061372b565b6005556112e4565b61104384848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601681527566656c6f6e79536c617368526577617264526174696f60501b602082015291506126ac9050565b156110dd57602081146110685760405162461bcd60e51b815260040161064f906139a1565b604080516020601f84018190048102820181019092528281526000916110a69185858083850183828082843760009201919091525061270692505050565b9050600a81101580156110b95750606481105b6110d55760405162461bcd60e51b815260040161064f90613aa9565b6006556112e4565b61115184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f656e61626c654d616c6963696f7573566f7465536c6173680000000000000000602082015291506126ac9050565b156111c857602081146111765760405162461bcd60e51b815260040161064f90613760565b604080516020601f84018190048102820181019092528281526111b2919084848083850183828082843760009201919091525061270b92505050565b6007805460ff19169115159190911790556112e4565b61122f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601081526f66656c6f6e79536c61736853636f706560801b602082015291506126ac9050565b156112cc57602081146112545760405162461bcd60e51b815260040161064f90613930565b604080516020601f84018190048102820181019092528281526000916112929185858083850183828082843760009201919091525061270692505050565b905061708081101580156112a85750620d2f0081105b6112c45760405162461bcd60e51b815260040161064f906136a9565b6008556112e4565b60405162461bcd60e51b815260040161064f90613c68565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a8484848460405161131994939291906135b1565b60405180910390a150505050565b600a81565b61100281565b33612000146113535760405162461bcd60e51b815260040161064f90613bcc565b60005460ff166113755760405162461bcd60e51b815260040161064f90613672565b6040517f07db600eebe2ac176be8dcebad61858c245a4961bb32ca2aa3d159b09aa0810e90600090a1505050565b3341146113c25760405162461bcd60e51b815260040161064f90613c1b565b60005460ff166113e45760405162461bcd60e51b815260040161064f90613672565b60035443116114055760405162461bcd60e51b815260040161064f90613cf4565b3a156114235760405162461bcd60e51b815260040161064f90613973565b60405163155853f360e21b8152611000906355614fcc90611448908490600401613545565b60206040518083038186803b15801561146057600080fd5b505afa158015611474573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149891906132b8565b6114a15761180b565b6114a9612f79565b506001600160a01b0381166000908152600260208181526040928390208351606081018552815481526001820154928101929092529091015460ff16158015928201929092529061150457602081018051600101905261155d565b60016040820181905260208201819052805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0384161790555b43815260055460208201518161156f57fe5b0661173957600060208201526040516335409f7f60e01b8152611000906335409f7f906115a0908590600401613545565b600060405180830381600087803b1580156115ba57600080fd5b505af11580156115ce573d6000803e3d6000fd5b505060405163436aa28360e11b81526000925061200291506386d54506906115fa908690600401613545565b60206040518083038186803b15801561161257600080fd5b505afa158015611626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164a91906131ae565b6001600160a01b03161461166b576116668282602001516124f9565b611734565b61200063f7a251d7600b61167e856123af565b60006040518463ffffffff1660e01b815260040161169e93929190613d86565b600060405180830381600087803b1580156116b857600080fd5b505af19250505080156116c9575060015b611734573d8080156116f7576040519150601f19603f3d011682016040523d82523d6000602084013e6116fc565b606091505b50826001600160a01b0316600080516020613e6383398151915283602001518360405161172a929190613590565b60405180910390a2505b6117a5565b60045481602001518161174857fe5b066117a5576040516375abf10160e11b81526110009063eb57e20290611772908590600401613545565b600060405180830381600087803b15801561178c57600080fd5b505af11580156117a0573d6000803e3d6000fd5b505050505b6001600160a01b0382166000818152600260208181526040808420865181559186015160018301558581015191909201805460ff1916911515919091179055517fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9190a2505b5043600355565b60005460ff166118345760405162461bcd60e51b815260040161064f90613672565b60075460ff166118565760405162461bcd60e51b815260040161064f9061360d565b6006546118635760146006555b60085461187057603c6008555b60085481516040015143910111801561189457504360085482602001516040015101115b6118b05760405162461bcd60e51b815260040161064f90613c8f565b8060200151602001518160000151602001511480156118de5750806020015160600151816000015160600151145b156118fb5760405162461bcd60e51b815260040161064f90613888565b80516040810151905110801561191a5750602081015160408101519051105b6119365760405162461bcd60e51b815260040161064f9061380a565b60208101515181515110801561195b5750806000015160400151816020015160400151105b8061198657508051516020820151511080156119865750806020015160400151816000015160400151105b806119a05750806020015160400151816000015160400151145b6119bc5760405162461bcd60e51b815260040161064f906136f4565b604080820151905163ea321e4960e01b81526110009163ea321e49916119e5919060040161357d565b60206040518083038186803b1580156119fd57600080fd5b505afa158015611a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3591906132b8565b611a515760405162461bcd60e51b815260040161064f906139ea565b611a6381600001518260400151612733565b8015611a7c5750611a7c81602001518260400151612733565b611a985760405162461bcd60e51b815260040161064f906137ab565b6060806110006001600160a01b0316633b071dcc6040518163ffffffff1660e01b815260040160006040518083038186803b158015611ad657600080fd5b505afa158015611aea573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b1291908101906131f5565b9150915060005b8151811015611c4f57611b43828281518110611b3157fe5b6020026020010151856040015161290b565b15611c47576006546040516309a99b4f60e41b815260646110028031909302049190639a99b4f090611b7b9033908590600401613559565b602060405180830381600087803b158015611b9557600080fd5b505af1158015611ba9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bcd9190613463565b506110006001600160a01b03166335409f7f858481518110611beb57fe5b60200260200101516040518263ffffffff1660e01b8152600401611c0f9190613545565b600060405180830381600087803b158015611c2957600080fd5b505af1158015611c3d573d6000803e3d6000fd5b5050505050611c4f565b600101611b19565b5060408084015190516317b4f35360e01b8152600091612002916317b4f35391611c7b9160040161357d565b60206040518083038186803b158015611c9357600080fd5b505afa158015611ca7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ccb91906131ae565b6001600160a01b031614611d39576040808401519051630e9fbf5160e01b815261200291630e9fbf5191611d02919060040161357d565b600060405180830381600087803b158015611d1c57600080fd5b505af1158015611d30573d6000803e3d6000fd5b50505050610d21565b6120006001600160a01b031663f7a251d7600b611d59866040015161296f565b60006040518463ffffffff1660e01b8152600401611d7993929190613d86565b600060405180830381600087803b158015611d9357600080fd5b505af1158015611da7573d6000803e3d6000fd5b505050506000611dbc846040015160006129aa565b60405190915081907f7b78aadacff901d8b63d0dba4f86283d4db8aef27f9ed70413dd860f1c9532b690600090a250505050565b61100381565b601481565b61200481565b60005460ff1615611e245760405162461bcd60e51b815260040161064f90613af3565b60056004819055600a905560078054600160ff199182168117909255600080549091169091179055565b601181565b61100081565b600381565b3361100014611e7f5760405162461bcd60e51b815260040161064f906138b5565b60005460ff16611ea15760405162461bcd60e51b815260040161064f90613672565b600154611ead576122a5565b600154600090600019015b808211612279576000805b82841015611fdc57611ed3612f79565b6002600060018781548110611ee457fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff161515908201526005549091506004900481602001511115611fc657600460055481611f5157fe5b04816020015103816020018181525050806002600060018881548110611f7357fe5b6000918252602080832091909101546001600160a01b0316835282810193909352604091820190208351815591830151600183015591909101516002909101805460ff1916911515919091179055611fd0565b6001925050611fdc565b50836001019350611ec3565b82841161217357611feb612f79565b6002600060018681548110611ffc57fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156120e45760046005548161206957fe5b0481602001510381602001818152505080600260006001878154811061208b57fe5b6000918252602080832091909101546001600160a01b03168352828101939093526040918201902083518155918301516001808401919091559201516002909101805460ff191691151591909117905591506121739050565b60026000600186815481106120f557fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff1916905580548061213957fe5b600082815260209020810160001990810180546001600160a01b0319169055019055836121665750612173565b5060001990920191611fdc565b81801561217d5750805b1561225c57600260006001868154811061219357fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff191690558054849081106121da57fe5b600091825260209091200154600180546001600160a01b03909216918690811061220057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600180548061223957fe5b600082815260209020810160001990810180546001600160a01b03191690550190555b82612268575050612279565b505060019091019060001901611eb8565b6040517fcfdb3b6ccaeccbdc68be3c59c840e3b3c90f0a7c491f5fff1cf56cfda200dd9c90600090a150505b565b61100481565b60606122c06122bb836129c6565b6122c8565b90505b919050565b6060815160011480156122fa5750607f60f81b826000815181106122e857fe5b01602001516001600160f81b03191611155b156123065750806122c3565b6122c06123188351608060ff16612aac565b83612b7e565b606081516000141561233f57506040805160008152602081019091526122c3565b60608260008151811061234e57fe5b602002602001015190506000600190505b835181101561238f576123858285838151811061237857fe5b6020026020010151612b7e565b915060010161235f565b506123a86123a2825160c060ff16612aac565b82612b7e565b9392505050565b60408051600480825260a08201909252606091829190816020015b60608152602001906001900390816123ca5790505090506123f3836001600160a01b0316612bfb565b8160008151811061240057fe5b6020026020010181905250612414436122ad565b8160018151811061242157fe5b60209081029190910101526124376102ca6122ad565b8160028151811061244457fe5b6020026020010181905250612458426122ad565b8160038151811061246557fe5b60200260200101819052506123a88161231e565b612481612f9c565b600061248b612f9c565b612493612fae565b6124a461249f86612c1e565b612c43565b90506000805b6124b383612c8d565b156124ec57806124df576124ce6124c984612cae565b612cfc565b63ffffffff168452600191506124e4565b6124ec565b6001016124aa565b5091935090915050915091565b6040516375cc7d8960e01b8152612002906375cc7d899061251e908590600401613545565b600060405180830381600087803b15801561253857600080fd5b505af1925050508015612549575060015b610d5c576040516000815260443d101561256557506000612602565b60046000803e60005160e01c6308c379a08114612586576000915050612602565b60043d036004833e81513d602482011167ffffffffffffffff821117156125b257600092505050612602565b808301805167ffffffffffffffff8111156125d4576000945050505050612602565b8060208301013d86018111156125f257600095505050505050612602565b601f01601f191660405250925050505b8061260d5750612644565b826001600160a01b0316600080516020613e638339815191528383604051612636929190613590565b60405180910390a2506126a7565b3d80801561266e576040519150601f19603f3d011682016040523d82523d6000602084013e612673565b606091505b50826001600160a01b0316600080516020613e63833981519152838360405161269d929190613590565b60405180910390a2505b610d5c565b6000816040516020016126bf9190613529565b60405160208183030381529060405280519060200120836040516020016126e69190613529565b604051602081830303815290604052805190602001201490505b92915050565b015190565b8082015160009060ff81161561272557600191508161272b565b60009150815b505092915050565b60408051600480825260a0820190925260009160609190816020015b606081526020019060019003908161274f57505060408051602080825281830190925291925060609190808201818036833701905050905061279485600001516122ad565b826000815181106127a157fe5b60200260200101819052506127bc6020866020015183612d7e565b6127c5816122c8565b826001815181106127d257fe5b60200260200101819052506127ea85604001516122ad565b826002815181106127f757fe5b60200260200101819052506128126020866060015183612d7e565b61281b816122c8565b8260038151811061282857fe5b602002602001018190525061284e60206128418461231e565b8051906020012083612d7e565b6040805160b080825260e0820190925260609160208201818036833701905050905061287e818360006020612d8e565b61289081876080015160206060612d8e565b61289e818660806030612d8e565b604080516001808252818301909252606091602082018180368337019050509050815160016020830182602086016066600019fa6128db57600080fd5b5060016128e9826000612de1565b60ff16146128fe576000945050505050612700565b5060019695505050505050565b8151815160009160019181148083146129275760009250612965565b600160208701838101602088015b6002848385100114156129605780518351146129545760009650600093505b60209283019201612935565b505050505b5090949350505050565b60408051600480825260a08201909252606091829190816020015b606081526020019060019003908161298a5790505090506123f3836122c8565b600081602001835110156129bd57600080fd5b50016020015190565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416612a0a57506018612a2e565b6fffffffffffffffffffffffffffffffff198416612a2a57506010612a2e565b5060005b6020811015612a6457818181518110612a4357fe5b01602001516001600160f81b03191615612a5c57612a64565b600101612a2e565b60008160200390506060816040519080825280601f01601f191660200182016040528015612a99576020820181803683370190505b5080830196909652508452509192915050565b6060680100000000000000008310612ad65760405162461bcd60e51b815260040161064f906137e2565b60408051600180825281830190925260609160208201818036833701905050905060378411612b305782840160f81b81600081518110612b1257fe5b60200101906001600160f81b031916908160001a9053509050612700565b6060612b3b856129c6565b90508381510160370160f81b82600081518110612b5457fe5b60200101906001600160f81b031916908160001a905350612b758282612b7e565b95945050505050565b6060806040519050835180825260208201818101602087015b81831015612baf578051835260209283019201612b97565b50855184518101855292509050808201602086015b81831015612bdc578051835260209283019201612bc4565b508651929092011591909101601f01601f191660405250905092915050565b60408051600560a21b83186014820152603481019091526060906123a8816122c8565b612c26612fce565b506040805180820190915281518152602082810190820152919050565b612c4b612fae565b612c5482612dfd565b612c5d57600080fd5b6000612c6c8360200151612e37565b60208085015160408051808201909152868152920190820152915050919050565b6000612c97612fce565b505080518051602091820151919092015191011190565b612cb6612fce565b612cbf82612c8d565b612cc857600080fd5b60208201516000612cd882612e9a565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590612d1157508151602110155b612d1a57600080fd5b6000612d298360200151612e37565b90508083600001511015612d4f5760405162461bcd60e51b815260040161064f90613b50565b825160208085015183018051928490039291831015612d7557826020036101000a820491505b50949350505050565b9091018181526020918201910152565b60005b81811015610d1e57838181518110612da557fe5b602001015160f81c60f81b858480600101955081518110612dc257fe5b60200101906001600160f81b031916908160001a905350600101612d91565b60008160010183511015612df457600080fd5b50016001015190565b8051600090612e0e575060006122c3565b6020820151805160001a9060c0821015612e2d576000925050506122c3565b5060019392505050565b8051600090811a6080811015612e515760009150506122c3565b60b8811080612e6c575060c08110801590612e6c575060f881105b15612e7b5760019150506122c3565b60c0811015612e8f5760b5190190506122c3565b60f5190190506122c3565b80516000908190811a6080811015612eb55760019150612f72565b60b8811015612eca57607e1981019150612f72565b60c0811015612f1b57600060b78203600186019550806020036101000a865104915060018101820193505080831015612f155760405162461bcd60e51b815260040161064f90613905565b50612f72565b60f8811015612f305760be1981019150612f72565b600060f78203600186019550806020036101000a86510491506001810182019350508083101561272b5760405162461bcd60e51b815260040161064f90613905565b5092915050565b604051806060016040528060008152602001600081526020016000151581525090565b60408051602081019091526000815290565b6040518060400160405280612fc1612fce565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b600082601f830112612ff8578081fd5b815161300b61300682613dd9565b613db2565b818152915060208083019084810160005b84811015613081578151870188603f82011261303757600080fd5b8381015161304761300682613df9565b81815260408b8184860101111561305d57600080fd5b61306c83888401838701613e1d565b5086525050928201929082019060010161301c565b505050505092915050565b60008083601f84011261309d578182fd5b50813567ffffffffffffffff8111156130b4578182fd5b6020830191508360208285010111156130cc57600080fd5b9250929050565b600082601f8301126130e3578081fd5b81356130f161300682613df9565b915080825283602082850101111561310857600080fd5b8060208401602084013760009082016020015292915050565b600060a08284031215613132578081fd5b61313c60a0613db2565b905081358152602082013560208201526040820135604082015260608201356060820152608082013567ffffffffffffffff81111561317a57600080fd5b613186848285016130d3565b60808301525092915050565b6000602082840312156131a3578081fd5b81356123a881613e4d565b6000602082840312156131bf578081fd5b81516123a881613e4d565b600080604083850312156131dc578081fd5b82356131e781613e4d565b946020939093013593505050565b60008060408385031215613207578182fd5b825167ffffffffffffffff8082111561321e578384fd5b81850186601f82011261322f578485fd5b8051925061323f61300684613dd9565b80848252602080830192508084018a82838902870101111561325f578889fd5b8894505b8685101561328a57805161327681613e4d565b845260019490940193928101928101613263565b5088015190965093505050808211156132a1578283fd5b506132ae85828601612fe8565b9150509250929050565b6000602082840312156132c9578081fd5b815180151581146123a8578182fd5b600080604083850312156132ea578182fd5b823567ffffffffffffffff80821115613301578384fd5b61330d868387016130d3565b93506020850135915080821115613322578283fd5b506132ae858286016130d3565b60008060008060408587031215613344578182fd5b843567ffffffffffffffff8082111561335b578384fd5b6133678883890161308c565b9096509450602087013591508082111561337f578384fd5b5061338c8782880161308c565b95989497509550505050565b6000602082840312156133a9578081fd5b813567ffffffffffffffff808211156133c0578283fd5b818401606081870312156133d2578384fd5b6133dc6060613db2565b92508035828111156133ec578485fd5b6133f887828401613121565b84525060208101358281111561340c578485fd5b61341887828401613121565b60208501525060408101358281111561342f578485fd5b61343b878284016130d3565b6040850152509195945050505050565b60006020828403121561345c578081fd5b5035919050565b600060208284031215613474578081fd5b5051919050565b60008060006040848603121561348f578081fd5b833560ff8116811461349f578182fd5b9250602084013567ffffffffffffffff8111156134ba578182fd5b6134c68682870161308c565b9497909650939450505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452613515816020860160208601613e1d565b601f01601f19169290920160200192915050565b6000825161353b818460208701613e1d565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082526123a860208301846134fd565b6000838252604060208301526135a960408301846134fd565b949350505050565b6000604082526135c56040830186886134d3565b82810360208401526135d88185876134d3565b979650505050505050565b60208082526010908201526f195d9a59195b98d9481d1bdbc81bdb1960821b604082015260600190565b6020808252818101527f6d616c6963696f757320766f746520736c617368206e6f7420656e61626c6564604082015260600190565b6020808252601690820152751d985b1a59185d1bdc881b9bdd081b5a59dc985d195960521b604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252602b908201527f746865206d616c6963696f757320766f746520736c6173682073636f7065206f60408201526a7574206f662072616e676560a81b606082015260800190565b6020808252601a908201527f6e6f2076696f6c6174696f6e206f6620766f74652072756c6573000000000000604082015260600190565b6020808252818101527f7468652066656c6f6e795468726573686f6c64206f7574206f662072616e6765604082015260600190565b6020808252602b908201527f6c656e677468206f6620656e61626c654d616c6963696f7573566f7465536c6160408201526a0e6d040dad2e6dac2e8c6d60ab1b606082015260800190565b60208082526017908201527f766572696679207369676e6174757265206661696c6564000000000000000000604082015260600190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526019908201527f7372634e756d20626967676572207468616e207461724e756d00000000000000604082015260600190565b60208082526027908201527f6c656e677468206f66206d697364656d65616e6f725468726573686f6c64206d6040820152660d2e6dac2e8c6d60cb1b606082015260800190565b60208082526013908201527274776f206964656e746963616c20766f74657360681b604082015260600190565b60208082526030908201527f746865206d6573736167652073656e646572206d7573742062652076616c696460408201526f185d1bdc94d95d0818dbdb9d1c9858dd60821b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f6c656e677468206f662066656c6f6e79536c61736853636f7065206d69736d616040820152620e8c6d60eb1b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b60208082526029908201527f6c656e677468206f662066656c6f6e79536c617368526577617264526174696f604082015268040dad2e6dac2e8c6d60bb1b606082015260800190565b6020808252601590820152741d9bdd195059191c881a5cc81b9bdd08199bdd5b99605a1b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526022908201527f6c656e677468206f662066656c6f6e795468726573686f6c64206d69736d61746040820152610c6d60f31b606082015260800190565b6020808252602a908201527f7468652066656c6f6e7920736c6173682072657761726420726174696f206f7560408201526974206f662072616e676560b01b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252600c908201526b32b6b83a3c903432b0b232b960a11b604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526025908201527f746865206d697364656d65616e6f725468726573686f6c64206f7574206f662060408201526472616e676560d81b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b6020808252601490820152731d185c99d95d08189b1bd8dac81d1bdbc81bdb1960621b604082015260600190565b6020808252601e908201527f7265636569766520756e65787065637465642073796e207061636b6167650000604082015260600190565b6020808252818101527f63616e206e6f7420736c61736820747769636520696e206f6e6520626c6f636b604082015260600190565b61ffff91909116815260200190565b90815260200190565b918252602082015260400190565b92835260208301919091521515604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260606020830152613da260608301856134fd565b9050826040830152949350505050565b60405181810167ffffffffffffffff81118282101715613dd157600080fd5b604052919050565b600067ffffffffffffffff821115613def578081fd5b5060209081020190565b600067ffffffffffffffff821115613e0f578081fd5b50601f01601f191660200190565b60005b83811015613e38578181015183820152602001613e20565b83811115613e47576000848401525b50505050565b6001600160a01b0381168114610bd957600080fdfed7bc86ff5d08c8ab043edec743302aba2520e6635172a428bc956721db9e2d1ca164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(TokenHubContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106104405760003560e01c80639509b98011610234578063c81b16621161012e578063ebf71d53116100b6578063fb063e8f1161007a578063fb063e8f146110d3578063fc1a598f146110e8578063fc3e590814610cca578063fd6a68791461111b578063ff9c0027146108a057610488565b8063ebf71d531461106a578063f01484721461107f578063f1fad10414611094578063f9a2bbc7146110a9578063fa9e9159146110be57610488565b8063dc927faf116100fd578063dc927faf14610fce578063df8079e914610fe3578063e04c83a714610ff8578063e1c7392a14611022578063e8f35cea1461103757610488565b8063c81b166214610ef9578063c8509d8114610f0e578063cf41984414610f93578063d9e6dae91461080d57610488565b8063aa7415f5116101bc578063b99328c511610180578063b99328c514610e30578063b9fd21e314610e69578063ba35ead614610e7e578063bbface1f14610e93578063bd46646114610ec657610488565b8063aa7415f514610cdf578063aa82dce114610d26578063aad5606314610d3b578063ab51bb9614610d50578063ac43175114610d6557610488565b80639dc09262116102035780639dc0926214610c76578063a1a11bf514610c8b578063a496fba214610ca0578063a78abc1614610cb5578063a7c9f02d14610cca57610488565b80639509b98014610bda57806396713da914610c135780639a854bbd14610c285780639a99b4f014610c3d57610488565b806359b9278911610345578063727be1f8116102cd578063831d65d111610291578063831d65d114610ac85780638525db0314610b4d5780638b87b21f146107625780638eff336c14610b8657806393ab703f14610bc557610488565b8063727be1f814610a2057806375d47a0a14610a4a5780637942fd0514610a5f578063799758b914610a745780637e434d5414610ab357610488565b80636e056520116103145780636e056520146108b55780636e47b482146109e157806370fd5bad146108a0578063718a8aa8146109f657806371d3086314610a0b57610488565b806359b92789146108615780635d499b1b1461088b578063613684751461080d57806366dea52a146108a057610488565b80633fd8b02f116103c85780634a3acdf4116103975780634a3acdf4146107f85780634bf6c8821461080d57806350432d321461082257806351b4dce31461083757806351e806721461084c57610488565b80633fd8b02f1461078d57806343756e5c146107a257806343a368b9146107b7578063493279b1146107cc57610488565b8063149d14d91161040f578063149d14d91461062157806328087028146106485780632ae454831461065d5780633d713223146106b15780633dffc3871461076257610488565b80630bee7a671461048d5780630e2374a5146104bb5780631182b875146104ec57806312234582146105e657610488565b36610488573415610486576040805133815234602082015281517f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db929181900390910190a15b005b600080fd5b34801561049957600080fd5b506104a2611130565b6040805163ffffffff9092168252519081900360200190f35b3480156104c757600080fd5b506104d0611135565b604080516001600160a01b039092168252519081900360200190f35b3480156104f857600080fd5b506105716004803603604081101561050f57600080fd5b60ff8235169190810190604081016020820135600160201b81111561053357600080fd5b82018360208201111561054557600080fd5b803590602001918460018302840111600160201b8311171561056657600080fd5b50909250905061113b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105ab578181015183820152602001610593565b50505050905090810190601f1680156105d85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156105f257600080fd5b506104866004803603604081101561060957600080fd5b506001600160a01b0381358116916020013516611269565b34801561062d57600080fd5b50610636611363565b60408051918252519081900360200190f35b34801561065457600080fd5b506104d0611369565b34801561066957600080fd5b506106986004803603604081101561068057600080fd5b506001600160a01b038135811691602001351661136f565b6040805192835260208301919091528051918290030190f35b3480156106bd57600080fd5b506104d0600480360360208110156106d457600080fd5b810190602081018135600160201b8111156106ee57600080fd5b82018360208201111561070057600080fd5b803590602001918460018302840111600160201b8311171561072157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611393945050505050565b34801561076e57600080fd5b506107776113b7565b6040805160ff9092168252519081900360200190f35b34801561079957600080fd5b506106366113bc565b3480156107ae57600080fd5b506104d06113c2565b3480156107c357600080fd5b506106366113c8565b3480156107d857600080fd5b506107e16113d4565b6040805161ffff9092168252519081900360200190f35b34801561080457600080fd5b506106366113da565b34801561081957600080fd5b506107776113e0565b34801561082e57600080fd5b506106366113e5565b34801561084357600080fd5b506104d06113f0565b34801561085857600080fd5b506104d06113f6565b34801561086d57600080fd5b506104d06004803603602081101561088457600080fd5b50356113fc565b34801561089757600080fd5b50610636611417565b3480156108ac57600080fd5b50610777611420565b6109cd600480360360808110156108cb57600080fd5b810190602081018135600160201b8111156108e557600080fd5b8201836020820111156108f757600080fd5b803590602001918460208302840111600160201b8311171561091857600080fd5b919390929091602081019035600160201b81111561093557600080fd5b82018360208201111561094757600080fd5b803590602001918460208302840111600160201b8311171561096857600080fd5b919390929091602081019035600160201b81111561098557600080fd5b82018360208201111561099757600080fd5b803590602001918460208302840111600160201b831117156109b857600080fd5b91935091503567ffffffffffffffff16611425565b604080519115158252519081900360200190f35b3480156109ed57600080fd5b506104d06118fa565b348015610a0257600080fd5b50610777611900565b348015610a1757600080fd5b50610636611905565b348015610a2c57600080fd5b506109cd60048036036020811015610a4357600080fd5b503561190b565b348015610a5657600080fd5b506104d061198c565b348015610a6b57600080fd5b50610777611992565b348015610a8057600080fd5b5061048660048036036060811015610a9757600080fd5b508035906001600160a01b036020820135169060400135611997565b348015610abf57600080fd5b506104d0611c47565b348015610ad457600080fd5b5061048660048036036040811015610aeb57600080fd5b60ff8235169190810190604081016020820135600160201b811115610b0f57600080fd5b820183602082011115610b2157600080fd5b803590602001918460018302840111600160201b83111715610b4257600080fd5b509092509050611c4d565b348015610b5957600080fd5b5061048660048036036040811015610b7057600080fd5b50803590602001356001600160a01b0316611d95565b348015610b9257600080fd5b5061048660048036036060811015610ba957600080fd5b508035906001600160a01b036020820135169060400135611efe565b348015610bd157600080fd5b50610636611f84565b348015610be657600080fd5b5061048660048036036040811015610bfd57600080fd5b506001600160a01b038135169060200135611f89565b348015610c1f57600080fd5b50610777612146565b348015610c3457600080fd5b5061063661214b565b348015610c4957600080fd5b5061063660048036036040811015610c6057600080fd5b506001600160a01b038135169060200135612157565b348015610c8257600080fd5b506104d0612295565b348015610c9757600080fd5b506104d061229b565b348015610cac57600080fd5b506107776122a1565b348015610cc157600080fd5b506109cd6122a6565b348015610cd657600080fd5b506107776122af565b6109cd60048036036080811015610cf557600080fd5b5080356001600160a01b03908116916020810135909116906040810135906060013567ffffffffffffffff166122b4565b348015610d3257600080fd5b506104d0612334565b348015610d4757600080fd5b506104d061233a565b348015610d5c57600080fd5b506104a26122a1565b348015610d7157600080fd5b5061048660048036036040811015610d8857600080fd5b810190602081018135600160201b811115610da257600080fd5b820183602082011115610db457600080fd5b803590602001918460018302840111600160201b83111715610dd557600080fd5b919390929091602081019035600160201b811115610df257600080fd5b820183602082011115610e0457600080fd5b803590602001918460018302840111600160201b83111715610e2557600080fd5b509092509050612340565b348015610e3c57600080fd5b5061048660048036036040811015610e5357600080fd5b50803590602001356001600160a01b03166127e8565b348015610e7557600080fd5b50610636612868565b348015610e8a57600080fd5b50610636612872565b348015610e9f57600080fd5b5061063660048036036020811015610eb657600080fd5b50356001600160a01b0316612878565b348015610ed257600080fd5b5061063660048036036020811015610ee957600080fd5b50356001600160a01b031661288a565b348015610f0557600080fd5b506104d06128a5565b348015610f1a57600080fd5b5061048660048036036040811015610f3157600080fd5b60ff8235169190810190604081016020820135600160201b811115610f5557600080fd5b820183602082011115610f6757600080fd5b803590602001918460018302840111600160201b83111715610f8857600080fd5b5090925090506128ab565b348015610f9f57600080fd5b5061048660048036036040811015610fb657600080fd5b506001600160a01b038135811691602001351661297b565b348015610fda57600080fd5b506104d0612c4f565b348015610fef57600080fd5b506104d0612c55565b34801561100457600080fd5b506109cd6004803603602081101561101b57600080fd5b5035612c5b565b34801561102e57600080fd5b50610486612cfb565b34801561104357600080fd5b506106366004803603602081101561105a57600080fd5b50356001600160a01b0316612d9b565b34801561107657600080fd5b50610777612dad565b34801561108b57600080fd5b50610777612db2565b3480156110a057600080fd5b50610777612db7565b3480156110b557600080fd5b506104d0612dbc565b3480156110ca57600080fd5b50610636612dc2565b3480156110df57600080fd5b50610636612dc8565b3480156110f457600080fd5b506105716004803603602081101561110b57600080fd5b50356001600160a01b0316612dd6565b34801561112757600080fd5b506104d0612efd565b606481565b61200181565b60005460609060ff16611183576040805162461bcd60e51b815260206004820152601960248201526000805160206153e1833981519152604482015290519081900360640190fd5b33612000146111c35760405162461bcd60e51b815260040180806020018281038252602f81526020018061538f602f913960400191505060405180910390fd5b60ff8416600214156112155761120e83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f0392505050565b9050611262565b6040805162461bcd60e51b815260206004820152601860248201527f756e7265636f676e697a65642073796e207061636b6167650000000000000000604482015290519081900360640190fd5b9392505050565b33612000146112a95760405162461bcd60e51b815260040180806020018281038252602f81526020018061538f602f913960400191505060405180910390fd5b6001600160a01b0380831660009081526007602090815260408083209385168352929052208054611314576040805162461bcd60e51b815260206004820152601060248201526f1b9bc81b1bd8dad95908185b5bdd5b9d60821b604482015290519081900360640190fd5b8054600082556040805182815290516001600160a01b0380861692908716917f152fb15aa5d80f843e1e4bd5f2fc9161714f169945024decec7e84fb910fdd519181900360200190a350505050565b60015490565b61200581565b60076020908152600092835260408084209091529082529020805460019091015482565b6020818101516000908152600490915260409020546001600160a01b03165b919050565b600181565b60055481565b61100181565b670de0b6b3a764000081565b6102ca81565b61a8c081565b600881565b66071afd498d000081565b61200681565b61200081565b6000908152600460205260409020546001600160a01b031690565b6402540be40081565b600281565b6000805460ff1661146b576040805162461bcd60e51b815260206004820152601960248201526000805160206153e1833981519152604482015290519081900360640190fd5b8685146114a95760405162461bcd60e51b815260040180806020018281038252603b815260200180615354603b913960400191505060405180910390fd5b8683146114e75760405162461bcd60e51b815260040180806020018281038252603f815260200180615266603f913960400191505060405180910390fd5b426078018267ffffffffffffffff1610156115335760405162461bcd60e51b81526004018080602001828103825260248152602001806151e26024913960400191505060405180910390fd5b6402540be4003406156115775760405162461bcd60e51b81526004018080602001828103825260408152602001806154576040913960400191505060405180910390fd5b604080518681526020808802820101909152859060009081906060908480156115aa578160200160208202803683370190505b50905060005b84811015611685576402540be4008b8b838181106115ca57fe5b90506020020135816115d857fe5b06156116155760405162461bcd60e51b815260040180806020018281038252603c8152602001806152a5603c913960400191505060405180910390fd5b61163a8b8b8381811061162457fe5b905060200201358561302790919063ffffffff16565b93506116666402540be4008c8c8481811061165157fe5b9050602002013561308190919063ffffffff16565b82828151811061167257fe5b60209081029190910101526001016115b0565b506001546116aa9061169d908663ffffffff6130c316565b849063ffffffff61302716565b3410156116e85760405162461bcd60e51b81526004018080602001828103825260568152602001806154016056913960600191505060405180910390fd5b6116f8348463ffffffff61311c16565b9150611702615020565b6040518060c001604052806221272160e91b60001b815260200160006001600160a01b031681526020018381526020018e8e808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208c810282810182019093528c82529283019290918d918d91829185019084908082843760009201919091525050509082525067ffffffffffffffff8916602090910152905061200063f7a251d760036117c68461315e565b6117db876402540be40063ffffffff61308116565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611839578181015183820152602001611821565b50505050905090810190601f1680156118665780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561188757600080fd5b505af115801561189b573d6000803e3d6000fd5b505060408051600081523360208201528082018890526060810187905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a15060019c9b505050505050505050505050565b61100581565b601081565b60015481565b6000336120011461194d5760405162461bcd60e51b815260040180806020018281038252603381526020018061513a6033913960400191505060405180910390fd5b8115611984576040516120019083156108fc029084906000818181858888f19350505050158015611982573d6000803e3d6000fd5b505b506001919050565b61100881565b600b81565b60005460ff166119dc576040805162461bcd60e51b815260206004820152601960248201526000805160206153e1833981519152604482015290519081900360640190fd5b3361300014611a1c5760405162461bcd60e51b815260040180806020018281038252602b81526020018061523b602b913960400191505060405180910390fd5b677ce66c50e2840000811115611a635760405162461bcd60e51b81526004018080602001828103825260358152602001806152066035913960400191505060405180910390fd5b60006221272160e91b8414611bcd576000848152600460205260409020546001600160a01b031680611ad6576040805184815290516001600160a01b0386169187917fc16ee9013bf67c846d37735983debb0acc5b2d1419cb5931c9843ad4689505499181900360200190a35050611c42565b6001600160a01b038116600090815260026020526040902054611af98482613419565b604080516370a0823160e01b8152306004820152905191945084916001600160a01b038516916370a08231916024808301926020929190829003018186803b158015611b4457600080fd5b505afa158015611b58573d6000803e3d6000fd5b505050506040513d6020811015611b6e57600080fd5b50511015611bba576040805162461bcd60e51b8152602060048201526014602482015273696e73756666696369656e742062616c616e636560601b604482015290519081900360640190fd5b611bc686838588613459565b5050611c40565b611be2826402540be40063ffffffff6130c316565b905080471015611c30576040805162461bcd60e51b8152602060048201526014602482015273696e73756666696369656e742062616c616e636560601b604482015290519081900360640190fd5b6000611c3e85828487613459565b505b505b505050565b61200381565b60005460ff16611c92576040805162461bcd60e51b815260206004820152601960248201526000805160206153e1833981519152604482015290519081900360640190fd5b3361200014611cd25760405162461bcd60e51b815260040180806020018281038252602f81526020018061538f602f913960400191505060405180910390fd5b60ff831660031415611d2257611d1d82828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506134f192505050565b611c42565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1505050565b3361300014611dd55760405162461bcd60e51b815260040180806020018281038252602b81526020018061523b602b913960400191505060405180910390fd5b60006221272160e91b8314611e4057506000828152600460205260409020546001600160a01b031680611e40576040805162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081cde5b589bdb60921b604482015290519081900360640190fd5b6001600160a01b0380821660009081526007602090815260408083209386168352929052208054611eab576040805162461bcd60e51b815260206004820152601060248201526f1b9bc81b1bd8dad95908185b5bdd5b9d60821b604482015290519081900360640190fd5b8054600082556040805182815290516001600160a01b03808716929086169188917f8041a9a8704332594e2884f5e0f942281cdd7611854c365b4d0aa70b2295d6b6919081900360200190a45050505050565b3361100814611f3e5760405162461bcd60e51b81526004018080602001828103825260238152602001806153be6023913960400191505060405180910390fd5b600083815260046020908152604080832080546001600160a01b039096166001600160a01b03199096168617905593825260038152838220949094556002909352912055565b603c81565b81806001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b158015611fc357600080fd5b505afa158015611fd7573d6000803e3d6000fd5b505050506040513d6020811015611fed57600080fd5b50516001600160a01b0316331461204b576040805162461bcd60e51b815260206004820152601860248201527f6e6f74206f776e6572206f6620424550323020746f6b656e0000000000000000604482015290519081900360640190fd5b60008211612099576040805162461bcd60e51b81526020600482015260166024820152751e995c9bc81b1a5b5a5d081b9bdd08185b1b1bddd95960521b604482015290519081900360640190fd5b6001600160a01b0383166000908152600360205260409020546120ef576040805162461bcd60e51b81526020600482015260096024820152681b9bdd08189bdd5b9960ba1b604482015290519081900360640190fd5b6001600160a01b038316600081815260066020908152604091829020859055815185815291513393927f9df3a90730dbf23b5cc18dbbd5f4af3fa94a0dffb6ff6841f98a9a9a6ac626a892908290030190a3505050565b600981565b677ce66c50e284000081565b6000805460ff1661219d576040805162461bcd60e51b815260206004820152601960248201526000805160206153e1833981519152604482015290519081900360640190fd5b33611005146121dd5760405162461bcd60e51b815260040180806020018281038252602f81526020018061516d602f913960400191505060405180910390fd5b60004783106121ec57476121ee565b825b9050670de0b6b3a764000081111561220a57600091505061228f565b801561228c576040516001600160a01b0385169082156108fc029083906000818181858888f19350505050158015612246573d6000803e3d6000fd5b50604080516001600160a01b03861681526020810183905281517ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0929181900390910190a15b90505b92915050565b61100781565b61100681565b600081565b60005460ff1681565b600381565b6000805460ff166122fa576040805162461bcd60e51b815260206004820152601960248201526000805160206153e1833981519152604482015290519081900360640190fd5b6040805162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b604482015290519081900360640190fd5b61200281565b61300081565b33611007146123805760405162461bcd60e51b815260040180806020018281038252602e815260200180615302602e913960400191505060405180910390fd5b602081146123d5576040805162461bcd60e51b815260206004820152601b60248201527f65787065637465642076616c7565206c656e6774682069732033320000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152939450606093925086915085908190840183828082843760009201919091525050505060208301519091506772656c617946656560c01b8114156124dd576020820151670de0b6b3a7640000811180159061248457506402540be4008106155b6124d5576040805162461bcd60e51b815260206004820152601960248201527f7468652072656c6179466565206f7574206f662072616e676500000000000000604482015290519081900360640190fd5b600155612753565b61255187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601781527f6c617267655472616e736665724c6f636b506572696f640000000000000000006020820152915061354d9050565b156125ed57604080516020601f87018190048102820181019092528581526000916125949188888083850183828082843760009201919091525061363492505050565b905062093a808111156125e5576040805162461bcd60e51b81526020600482015260146024820152736c6f636b20706572696f6420746f6f206c6f6e6760601b604482015290519081900360640190fd5b600555612753565b61265987878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526015815274189b9893185c99d9551c985b9cd9995c931a5b5a5d605a1b6020820152915061354d9050565b1561271657604080516020601f870181900481028201810190925285815260009161269c9188888083850183828082843760009201919091525061363492505050565b905068056bc75e2d631000008110156126e65760405162461bcd60e51b815260040180806020018281038252602281526020018061519c6022913960400191505060405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f855612753565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b33611008146128285760405162461bcd60e51b81526004018080602001828103825260238152602001806153be6023913960400191505060405180910390fd5b600091825260046020908152604080842080546001600160a01b03191690556001600160a01b039290921683526003815281832083905560029052812055565b6221272160e91b81565b61c35081565b60026020526000908152604090205481565b6001600160a01b031660009081526003602052604090205490565b61100281565b60005460ff166128f0576040805162461bcd60e51b815260206004820152601960248201526000805160206153e1833981519152604482015290519081900360640190fd5b33612000146129305760405162461bcd60e51b815260040180806020018281038252602f81526020018061538f602f913960400191505060405180910390fd5b60ff831660031415611d2257611d1d82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061363992505050565b60085460ff16600214156129c7576040805162461bcd60e51b815260206004820152600e60248201526d4e6f2072652d656e7472616e637960901b604482015290519081900360640190fd5b6008805460ff191660021790556001600160a01b0380831660009081526007602090815260408083209385168352929052208054612a3f576040805162461bcd60e51b815260206004820152601060248201526f1b9bc81b1bd8dad95908185b5bdd5b9d60821b604482015290519081900360640190fd5b8060010154421015612a98576040805162461bcd60e51b815260206004820152601760248201527f7374696c6c206f6e206c6f636b696e6720706572696f64000000000000000000604482015290519081900360640190fd5b805460008083556001600160a01b038516612b0b576040516001600160a01b038516906127109084906000818181858888f193505050503d8060008114612afb576040519150601f19603f3d011682016040523d82523d6000602084013e612b00565b606091505b505080915050612b9e565b846001600160a01b031663a9059cbb61c35086856040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015612b6e57600080fd5b5087f1158015612b82573d6000803e3d6000fd5b50505050506040513d6020811015612b9957600080fd5b505190505b80612bf0576040805162461bcd60e51b815260206004820152601e60248201527f776974686472617720756e6c6f636b656420746f6b656e206661696c65640000604482015290519081900360640190fd5b836001600160a01b0316856001600160a01b03167f832fc3e25f2b3e6fb0eb59419a73cba405f2a249fce75f7e31ea5a457a0323f1846040518082815260200191505060405180910390a350506008805460ff19166001179055505050565b61100381565b61200481565b60003361200214612cb3576040805162461bcd60e51b815260206004820152601f60248201527f746865206d73672073656e646572206d757374206265207374616b6548756200604482015290519081900360640190fd5b814710612cf3576040516120029083156108fc029084906000818181858888f19350505050158015612ce9573d6000803e3d6000fd5b50600190506113b2565b506000919050565b60005460ff1615612d53576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b66071afd498d000060019081556000808052600260205260127fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b55805460ff19169091179055565b60066020526000908152604090205481565b600481565b600581565b601181565b61100081565b61271081565b69021e19e0c9bab240000081565b6001600160a01b03811660009081526003602090815260409182902054825182815280840190935260609290918391906020820181803683375050506020810183905290506000805b60208160ff161015612e6657828160ff1681518110612e3a57fe5b01602001516001600160f81b03191615612e5957816001019150612e5e565b612e66565b600101612e1f565b5060608160ff166040519080825280601f01601f191660200182016040528015612e97576020820181803683370190505b50905060005b8260ff168160ff161015612ef357838160ff1681518110612eba57fe5b602001015160f81c60f81b828260ff1681518110612ed457fe5b60200101906001600160f81b031916908160001a905350600101612e9d565b5095945050505050565b61100481565b6060612f0d61506c565b6000612f1884613730565b9150915080612f6e576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b6000612f798361386f565b905063ffffffff81161561300d576040808401516020808601516001600160a01b03166000908152600290915291822054612fb49190613bd5565b9050612fbe6150a1565b60405180608001604052808660000151815260200183815260200186608001516001600160a01b031681526020018463ffffffff16815250905061300181613c0e565b955050505050506113b2565b505060408051600081526020810190915291506113b29050565b60008282018381101561228c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061228c83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613cea565b6000826130d25750600061228f565b828202828482816130df57fe5b041461228c5760405162461bcd60e51b81526004018080602001828103825260218152602001806152e16021913960400191505060405180910390fd5b600061228c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613d8c565b60408051600680825260e08201909252606091829190816020015b6060815260200190600190039081613179575050835190915061319b90613de6565b816000815181106131a857fe5b60200260200101819052506131c983602001516001600160a01b0316613df9565b816001815181106131d657fe5b60200260200101819052506000836040015151905060608160405190808252806020026020018201604052801561322157816020015b606081526020019060019003908161320c5790505b50905060005b8281101561326e5761324f8660400151828151811061324257fe5b6020026020010151613de6565b82828151811061325b57fe5b6020908102919091010152600101613227565b5061327881613e1c565b8360028151811061328557fe5b60200260200101819052506060826040519080825280602002602001820160405280156132c657816020015b60608152602001906001900390816132b15790505b50905060005b8381101561331c576132fd876060015182815181106132e757fe5b60200260200101516001600160a01b0316613df9565b82828151811061330957fe5b60209081029190910101526001016132cc565b5061332681613e1c565b8460038151811061333357fe5b602002602001018190525060608360405190808252806020026020018201604052801561337457816020015b606081526020019060019003908161335f5790505b50905060005b848110156133b457613395886080015182815181106132e757fe5b8282815181106133a157fe5b602090810291909101015260010161337a565b506133be81613e1c565b856004815181106133cb57fe5b60200260200101819052506133ed8760a0015167ffffffffffffffff16613de6565b856005815181106133fa57fe5b602002602001018190525061340e85613e1c565b979650505050505050565b600060088211156134425761343b836007198401600a0a63ffffffff6130c316565b905061228f565b61228c836008849003600a0a63ffffffff61308116565b6001600160a01b0380841660009081526007602090815260408083209385168352929052208054613490908463ffffffff61302716565b815542603c016001820181905560408051858152602081019290925280516001600160a01b03808616939088169289927f446d1aa056e7b903901f49880e9f252762c1b81dc4301cf28db6dae526497eaa9281900390910190a45050505050565b6134f96150c8565b600061350483613ea6565b91509150806135445760405162461bcd60e51b81526004018080602001828103825260248152602001806153306024913960400191505060405180910390fd5b611c4282614071565b6000816040516020018082805190602001908083835b602083106135825780518252601f199092019160209182019101613563565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106135f05780518252601f1990920191602091820191016135d1565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b613641615020565b600061364c836144f5565b915091508061368c5760405162461bcd60e51b81526004018080602001828103825260248152602001806151be6024913960400191505060405180910390fd5b6136946150c8565b602080840180516001600160a01b0390811684526040808701518585015291511660009081526002909252812054905b846040015151811015613715576136f2856040015182815181106136e457fe5b602002602001015183613419565b8560400151828151811061370257fe5b60209081029190910101526001016136c4565b506080840151604083015260056060830152611c3e82614071565b61373861506c565b600061374261506c565b61374a6150ff565b61375b61375686614759565b61477e565b90506000805b61376a836147c8565b15613862578061378c57613785613780846147e9565b614837565b845261385a565b80600114156137b9576137a66137a1846147e9565b6148ee565b6001600160a01b0316602085015261385a565b80600214156137d8576137ce613780846147e9565b604085015261385a565b8060031415613800576137ed6137a1846147e9565b6001600160a01b0316606085015261385a565b8060041415613828576138156137a1846147e9565b6001600160a01b0316608085015261385a565b80600514156138555761383d613780846147e9565b67ffffffffffffffff1660a08501526001915061385a565b613862565b600101613761565b5091935090915050915091565b60208101516000906001600160a01b03166139b3578160a0015167ffffffffffffffff164211156138a2575060016113b2565b81604001514710156138b6575060036113b2565b6138bf82614908565b61393457606082015160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d806000811461391a576040519150601f19603f3d011682016040523d82523d6000602084013e61391f565b606091505b50509050806139325750600490506113b2565b505b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5982602001518360600151846040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060006113b2565b8160a0015167ffffffffffffffff164211156139d1575060016113b2565b81516020808401516001600160a01b0316600090815260039091526040902054146139fe575060026113b2565b602080830151604080516370a0823160e01b815230600482015290516000936001600160a01b03909316926370a082319261c3509260248083019392829003018187803b158015613a4e57600080fd5b5086fa158015613a62573d6000803e3d6000fd5b50505050506040513d6020811015613a7957600080fd5b50516040840151909150811015613a945750600390506113b2565b613a9d83614908565b613b5457600083602001516001600160a01b031663a9059cbb61c350866060015187604001516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015613b1257600080fd5b5087f1158015613b26573d6000803e3d6000fd5b50505050506040513d6020811015613b3d57600080fd5b5051905080613b525750600591506113b29050565b505b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5983602001518460600151856040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a150600090506113b2565b60006008821115613bf75761343b836007198401600a0a63ffffffff61308116565b61228c836008849003600a0a63ffffffff6130c316565b60408051600480825260a08201909252606091829190816020015b6060815260200190600190039081613c295750508351909150613c4b90613de6565b81600081518110613c5857fe5b6020026020010181905250613c708360200151613de6565b81600181518110613c7d57fe5b6020026020010181905250613c9e83604001516001600160a01b0316613df9565b81600281518110613cab57fe5b6020026020010181905250613cc9836060015163ffffffff16613de6565b81600381518110613cd657fe5b602002602001018190525061126281613e1c565b60008183613d765760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613d3b578181015183820152602001613d23565b50505050905090810190601f168015613d685780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613d8257fe5b0495945050505050565b60008184841115613dde5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613d3b578181015183820152602001613d23565b505050900390565b606061228f613df483614a76565b614b5c565b60408051600560a21b831860148201526034810190915260609061126281614b5c565b6060815160001415613e3d57506040805160008152602081019091526113b2565b606082600081518110613e4c57fe5b602002602001015190506000600190505b8351811015613e8d57613e8382858381518110613e7657fe5b6020026020010151614bae565b9150600101613e5d565b50611262613ea0825160c060ff16614c2b565b82614bae565b613eae6150c8565b6000613eb86150c8565b613ec06150ff565b613ecc61375686614759565b90506000805b613edb836147c8565b156138625780613f0157613ef16137a1846147e9565b6001600160a01b03168452614069565b8060011415613fa2576060613f1d613f18856147e9565b614d23565b90508051604051908082528060200260200182016040528015613f4a578160200160208202803683370190505b50602086015260005b8151811015613f9b57613f78828281518110613f6b57fe5b6020026020010151614837565b86602001518281518110613f8857fe5b6020908102919091010152600101613f53565b5050614069565b8060021415614044576060613fb9613f18856147e9565b90508051604051908082528060200260200182016040528015613fe6578160200160208202803683370190505b50604086015260005b8151811015613f9b5761401482828151811061400757fe5b60200260200101516148ee565b8660400151828151811061402457fe5b6001600160a01b0390921660209283029190910190910152600101613fef565b806003141561385557614059613780846147e9565b63ffffffff166060850152600191505b600101613ed2565b80516001600160a01b031661429b5760005b816020015151811015614295576000826040015182815181106140a257fe5b60200260200101516001600160a01b0316612710846020015184815181106140c657fe5b60209081029190910101516040516000818181858888f193505050503d806000811461410e576040519150601f19603f3d011682016040523d82523d6000602084013e614113565b606091505b50509050806141d6577f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061415257fe5b60200260200101518560200151858151811061416a57fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a161428c565b7fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a83600001518460400151848151811061420c57fe5b60200260200101518560200151858151811061422457fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101614083565b506144f2565b60005b8160200151518110156144f057600082600001516001600160a01b031663a9059cbb61c350856040015185815181106142d357fe5b6020026020010151866020015186815181106142eb57fe5b60200260200101516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b15801561434257600080fd5b5087f1158015614356573d6000803e3d6000fd5b50505050506040513d602081101561436d57600080fd5b505190508015614431577fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a8360000151846040015184815181106143ad57fe5b6020026020010151856020015185815181106143c557fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a16144e7565b7f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061446757fe5b60200260200101518560200151858151811061447f57fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b5060010161429e565b505b50565b6144fd615020565b6000614507615020565b61450f6150ff565b61451b61375686614759565b90506000805b61452a836147c8565b15613862578061454757614540613780846147e9565b8452614751565b806001141561456f5761455c6137a1846147e9565b6001600160a01b03166020850152614751565b80600214156145fe576060614586613f18856147e9565b905080516040519080825280602002602001820160405280156145b3578160200160208202803683370190505b50604086015260005b81518110156145f7576145d4828281518110613f6b57fe5b866040015182815181106145e457fe5b60209081029190910101526001016145bc565b5050614751565b8060031415614693576060614615613f18856147e9565b90508051604051908082528060200260200182016040528015614642578160200160208202803683370190505b50606086015260005b81518110156145f75761466382828151811061400757fe5b8660600151828151811061467357fe5b6001600160a01b039092166020928302919091019091015260010161464b565b80600414156147285760606146aa613f18856147e9565b905080516040519080825280602002602001820160405280156146d7578160200160208202803683370190505b50608086015260005b81518110156145f7576146f882828151811061400757fe5b8660800151828151811061470857fe5b6001600160a01b03909216602092830291909101909101526001016146e0565b80600514156138555761473d613780846147e9565b67ffffffffffffffff1660a0850152600191505b600101614521565b61476161511f565b506040805180820190915281518152602082810190820152919050565b6147866150ff565b61478f82614df4565b61479857600080fd5b60006147a78360200151614e2e565b60208085015160408051808201909152868152920190820152915050919050565b60006147d261511f565b505080518051602091820151919092015191011190565b6147f161511f565b6147fa826147c8565b61480357600080fd5b6020820151600061481382614e91565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061484c57508151602110155b61485557600080fd5b60006148648360200151614e2e565b905080836000015110156148bf576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b8251602080850151830180519284900392918310156148e557826020036101000a820491505b50949350505050565b80516000906015146148ff57600080fd5b61228f82614837565b600080805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8541580156149415750600554155b156149835760008052600660205269021e19e0c9bab24000007f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85561a8c06005555b6020808301516001600160a01b03166000908152600690915260409020548015806149b15750808360400151105b156149c05760009150506113b2565b6020808401516001600160a01b039081166000908152600783526040808220606088015190931682529190925290819020908401518154614a069163ffffffff61302716565b8155600554420160018201819055606085015160208087015160408089015181519081529283019490945283516001600160a01b039384169493909116927f3fb83143cd331170da18fb1e8564d97e8ec39264b6ecb1ba248ea7596ab07258928290030190a35060019392505050565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416614aba57506018614ade565b6fffffffffffffffffffffffffffffffff198416614ada57506010614ade565b5060005b6020811015614b1457818181518110614af357fe5b01602001516001600160f81b03191615614b0c57614b14565b600101614ade565b60008160200390506060816040519080825280601f01601f191660200182016040528015614b49576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015614b8e5750607f60f81b82600081518110614b7c57fe5b01602001516001600160f81b03191611155b15614b9a5750806113b2565b61228f614bac8351608060ff16614c2b565b835b6060806040519050835180825260208201818101602087015b81831015614bdf578051835260209283019201614bc7565b50855184518101855292509050808201602086015b81831015614c0c578051835260209283019201614bf4565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310614c7b576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b60408051600180825281830190925260609160208201818036833701905050905060378411614cd55782840160f81b81600081518110614cb757fe5b60200101906001600160f81b031916908160001a905350905061228f565b6060614ce085614a76565b90508381510160370160f81b82600081518110614cf957fe5b60200101906001600160f81b031916908160001a905350614d1a8282614bae565b95945050505050565b6060614d2e82614df4565b614d3757600080fd5b6000614d4283614fc4565b9050606081604051908082528060200260200182016040528015614d8057816020015b614d6d61511f565b815260200190600190039081614d655790505b5090506000614d928560200151614e2e565b60208601510190506000805b84811015614de957614daf83614e91565b9150604051806040016040528083815260200184815250848281518110614dd257fe5b602090810291909101015291810191600101614d9e565b509195945050505050565b8051600090614e05575060006113b2565b6020820151805160001a9060c0821015614e24576000925050506113b2565b5060019392505050565b8051600090811a6080811015614e485760009150506113b2565b60b8811080614e63575060c08110801590614e63575060f881105b15614e725760019150506113b2565b60c0811015614e865760b5190190506113b2565b60f5190190506113b2565b80516000908190811a6080811015614eac5760019150614fbd565b60b8811015614ec157607e1981019150614fbd565b60c0811015614f3b57600060b78203600186019550806020036101000a865104915060018101820193505080831015614f35576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50614fbd565b60f8811015614f505760be1981019150614fbd565b600060f78203600186019550806020036101000a865104915060018101820193505080831015614fbb576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b8051600090614fd5575060006113b2565b60008090506000614fe98460200151614e2e565b602085015185519181019250015b808210156150175761500882614e91565b82019150826001019250614ff7565b50909392505050565b6040518060c001604052806000801916815260200160006001600160a01b03168152602001606081526020016060815260200160608152602001600067ffffffffffffffff1681525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806080016040528060006001600160a01b031681526020016060815260200160608152602001600063ffffffff1681525090565b604051806040016040528061511261511f565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe6f6e6c79207374616b696e672073797374656d20636f6e74726163742063616e2063616c6c20746869732066756e6374696f6e746865206d6573736167652073656e646572206d75737420626520696e63656e746976697a6520636f6e7472616374626e62206c61726765207472616e73666572206c696d697420746f6f20736d616c6c756e7265636f676e697a6564207472616e736665724f75742073796e207061636b61676565787069726554696d65206d7573742062652074776f206d696e75746573206c61746572616d6f756e7420697320746f6f206c617267652c20657863656564206d6178696d756d206265703220746f6b656e20616d6f756e74746865206d73672073656e646572206d75737420626520746f6b656e207265636f76657220706f7274616c4c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620726566756e644164647273696e76616c6964207472616e7366657220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374756e7265636f676e697a6564207472616e736665724f75742061636b207061636b6167654c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620616d6f756e7473746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d73672073656e646572206d75737420626520746f6b656e4d616e6167657274686520636f6e7472616374206e6f7420696e69742079657400000000000000726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e7366657220424e4220616d6f756e7420616e642072656c6179466565696e76616c696420726563656976656420424e4220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6ea164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(GovHubContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b506004361061021c5760003560e01c8063831d65d111610125578063ab51bb96116100ad578063df8079e91161007c578063df8079e914610615578063f1fad1041461061d578063f9a2bbc714610625578063fc3e59081461062d578063fd6a6879146106355761021c565b8063ab51bb9614610585578063c81b16621461058d578063c8509d8114610595578063dc927faf1461060d5761021c565b80639dc09262116100f45780639dc0926214610549578063a1a11bf514610551578063a78abc1614610559578063aa82dce114610575578063aad560631461057d5761021c565b8063831d65d1146103f857806388e4194e1461047257806396713da9146105395780639ab1a373146105415761021c565b80634bf6c882116101a857806370fd5bad1161017757806370fd5bad146103d0578063718a8aa8146103d857806375d47a0a146103e05780637942fd05146103e85780637e434d54146103f05761021c565b80634bf6c882146103b057806351b4dce3146103b857806351e80672146103c05780636e47b482146103c85761021c565b80633a21baae116101ef5780633a21baae1461035b5780633dffc3871461036357806343756e5c146103815780634900c4ea14610389578063493279b1146103915761021c565b80630bee7a67146102215780630e2374a5146102425780631182b875146102665780632808702814610353575b600080fd5b61022961063d565b6040805163ffffffff9092168252519081900360200190f35b61024a610642565b604080516001600160a01b039092168252519081900360200190f35b6102de6004803603604081101561027c57600080fd5b60ff8235169190810190604081016020820135600160201b8111156102a057600080fd5b8201836020820111156102b257600080fd5b803590602001918460018302840111600160201b831117156102d357600080fd5b509092509050610648565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610318578181015183820152602001610300565b50505050905090810190601f1680156103455780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61024a6106f7565b6102296106fd565b61036b610702565b6040805160ff9092168252519081900360200190f35b61024a610707565b61036b61070d565b610399610712565b6040805161ffff9092168252519081900360200190f35b61036b610718565b61024a61071d565b61024a610723565b61024a610729565b61036b61072f565b61036b610734565b61024a610739565b61036b61073f565b61024a610744565b6104706004803603604081101561040e57600080fd5b60ff8235169190810190604081016020820135600160201b81111561043257600080fd5b82018360208201111561044457600080fd5b803590602001918460018302840111600160201b8311171561046557600080fd5b50909250905061074a565b005b6104706004803603606081101561048857600080fd5b810190602081018135600160201b8111156104a257600080fd5b8201836020820111156104b457600080fd5b803590602001918460018302840111600160201b831117156104d557600080fd5b919390929091602081019035600160201b8111156104f257600080fd5b82018360208201111561050457600080fd5b803590602001918460018302840111600160201b8311171561052557600080fd5b9193509150356001600160a01b03166107dc565b61036b6108c7565b6102296108cc565b61024a6108d1565b61024a6108d7565b6105616108dd565b604080519115158252519081900360200190f35b61024a6108e6565b61024a6108ec565b61022961070d565b61024a6108f2565b610470600480360360408110156105ab57600080fd5b60ff8235169190810190604081016020820135600160201b8111156105cf57600080fd5b8201836020820111156105e157600080fd5b803590602001918460018302840111600160201b8311171561060257600080fd5b5090925090506108f8565b61024a61096f565b61024a610975565b61036b61097b565b61024a610980565b61036b610986565b61024a61098b565b606481565b61200181565b60606106526115f9565b600061069385858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061099192505050565b91509150806106af576106a66064610a57565b925050506106f0565b60006106ba83610ac1565b905063ffffffff81166106e157505060408051600081526020810190915291506106f09050565b6106ea81610a57565b93505050505b9392505050565b61200581565b606681565b600181565b61100181565b600081565b6102ca81565b600881565b61200681565b61200081565b61100581565b600281565b601081565b61100881565b600b81565b61200381565b336120001461078a5760405162461bcd60e51b815260040180806020018281038252602f81526020018061165e602f913960400191505060405180910390fd5b6040805162461bcd60e51b815260206004820152601e60248201527f7265636569766520756e65787065637465642061636b207061636b6167650000604482015290519081900360640190fd5b505050565b336120061461081c5760405162461bcd60e51b815260040180806020018281038252603181526020018061168d6031913960400191505060405180910390fd5b6108246115f9565b604051806060016040528087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f8801819004810282018101909252868152918101919087908790819084018382808284376000920191909152505050908252506001600160a01b03841660209091015290506108be81610ac1565b50505050505050565b600981565b606581565b61100781565b61100681565b60005460ff1681565b61200281565b61300081565b61100281565b33612000146109385760405162461bcd60e51b815260040180806020018281038252602f81526020018061165e602f913960400191505060405180910390fd5b60405162461bcd60e51b81526004018080602001828103825260238152602001806116be6023913960400191505060405180910390fd5b61100381565b61200481565b601181565b61100081565b600381565b61100481565b6109996115f9565b60006109a36115f9565b6109ab611623565b6109bc6109b786610e62565b610e87565b90506000805b6109cb83610ed1565b15610a4a57806109ed576109e66109e184610ef2565b610f40565b8452610a42565b8060011415610a0c57610a026109e184610ef2565b6020850152610a42565b8060021415610a3d57610a26610a2184610ef2565b610fb9565b6001600160a01b0316604085015260019150610a42565b610a4a565b6001016109c2565b5091935090915050915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081610a71579050509050610a978363ffffffff16610fd9565b81600081518110610aa457fe5b6020026020010181905250610ab881610fec565b9150505b919050565b6000610ad08260400151611076565b610b3c57604080516020808252601c908201527f74686520746172676574206973206e6f74206120636f6e7472616374000000008183015290517f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb29181900360600190a1506065610abc565b81604001516001600160a01b031663ac431751836000015184602001516040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015610ba9578181015183820152602001610b91565b50505050905090810190601f168015610bd65780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610c09578181015183820152602001610bf1565b50505050905090810190601f168015610c365780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015610c5757600080fd5b505af1925050508015610c68575060015b610e5a576040516000815260443d1015610c8457506000610d21565b60046000803e60005160e01c6308c379a08114610ca5576000915050610d21565b60043d036004833e81513d602482011167ffffffffffffffff82111715610cd157600092505050610d21565b808301805167ffffffffffffffff811115610cf3576000945050505050610d21565b8060208301013d8601811115610d1157600095505050505050610d21565b601f01601f191660405250925050505b80610d2c5750610dcf565b7f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2816040518080602001828103825283818151815260200191508051906020019080838360005b83811015610d8b578181015183820152602001610d73565b50505050905090810190601f168015610db85780820380516001836020036101000a031916815260200191505b509250505060405180910390a16066915050610abc565b3d808015610df9576040519150601f19603f3d011682016040523d82523d6000602084013e610dfe565b606091505b5060408051602080825283518183015283517f1279f84165b4fd69c35e1f338ff107231b036c655cd1688851e011ce617c4e8d938593928392918301919085019080838360008315610d8b578181015183820152602001610d73565b506000919050565b610e6a611643565b506040805180820190915281518152602082810190820152919050565b610e8f611623565b610e988261107c565b610ea157600080fd5b6000610eb083602001516110b6565b60208085015160408051808201909152868152920190820152915050919050565b6000610edb611643565b505080518051602091820151919092015191011190565b610efa611643565b610f0382610ed1565b610f0c57600080fd5b60208201516000610f1c82611119565b80830160209586015260408051808201909152908152938401919091525090919050565b8051606090610f4e57600080fd5b6000610f5d83602001516110b6565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015610f94576020820181803683370190505b5090506000816020019050610fb084876020015101828561124c565b50949350505050565b8051600090601514610fca57600080fd5b610fd382611297565b92915050565b6060610fd3610fe78361134c565b611432565b606081516000141561100d5750604080516000815260208101909152610abc565b60608260008151811061101c57fe5b602002602001015190506000600190505b835181101561105d576110538285838151811061104657fe5b6020026020010151611484565b915060010161102d565b50610ab8611070825160c060ff16611501565b82611484565b3b151590565b805160009061108d57506000610abc565b6020820151805160001a9060c08210156110ac57600092505050610abc565b5060019392505050565b8051600090811a60808110156110d0576000915050610abc565b60b88110806110eb575060c081108015906110eb575060f881105b156110fa576001915050610abc565b60c081101561110e5760b519019050610abc565b60f519019050610abc565b80516000908190811a60808110156111345760019150611245565b60b881101561114957607e1981019150611245565b60c08110156111c357600060b78203600186019550806020036101000a8651049150600181018201935050808310156111bd576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50611245565b60f88110156111d85760be1981019150611245565b600060f78203600186019550806020036101000a865104915060018101820193505080831015611243576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b80611256576107d7565b5b60208110611276578251825260209283019290910190601f1901611257565b915181516020939093036101000a6000190180199091169216919091179052565b8051600090158015906112ac57508151602110155b6112b557600080fd5b60006112c483602001516110b6565b9050808360000151101561131f576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015610fb057506020919091036101000a90049392505050565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416611390575060186113b4565b6fffffffffffffffffffffffffffffffff1984166113b0575060106113b4565b5060005b60208110156113ea578181815181106113c957fe5b01602001516001600160f81b031916156113e2576113ea565b6001016113b4565b60008160200390506060816040519080825280601f01601f19166020018201604052801561141f576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156114645750607f60f81b8260008151811061145257fe5b01602001516001600160f81b03191611155b15611470575080610abc565b610fd36114828351608060ff16611501565b835b6060806040519050835180825260208201818101602087015b818310156114b557805183526020928301920161149d565b50855184518101855292509050808201602086015b818310156114e25780518352602092830192016114ca565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310611551576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116115ab5782840160f81b8160008151811061158d57fe5b60200101906001600160f81b031916908160001a9053509050610fd3565b60606115b68561134c565b90508381510160370160f81b826000815181106115cf57fe5b60200101906001600160f81b031916908160001a9053506115f08282611484565b95945050505050565b6040518060600160405280606081526020016060815260200160006001600160a01b031681525090565b6040518060400160405280611636611643565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d73672073656e646572206d75737420626520676f7665726e6f722074696d656c6f636b20636f6e74726163747265636569766520756e6578706563746564206661696c2061636b207061636b616765a164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(CrossChainContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b50600436106103e65760003560e01c806374f079b81161020a578063c27cdcfb11610125578063df8079e9116100b8578063f1fad10411610087578063f1fad10414610bac578063f7a251d714610bb4578063f9a2bbc714610c2c578063fc3e590814610c34578063fd6a687914610c3c576103e6565b8063df8079e914610b74578063e1c7392a14610b7c578063e3b0480514610b84578063e6400bbe14610ba4576103e6565b8063d31f968d116100f4578063d31f968d14610b2d578063d76a867514610b5c578063dc40433114610b64578063dc927faf14610b6c576103e6565b8063c27cdcfb14610af5578063c780e9de14610b15578063c81b166214610b1d578063ccc108d714610b25576103e6565b80639dc092621161019d578063aad560631161016c578063aad5606314610a27578063ab51bb9614610a2f578063ac43175114610a37578063b0355f5b146107d6576103e6565b80639dc0926214610a07578063a1a11bf514610a0f578063a78abc1614610a17578063aa82dce114610a1f576103e6565b806384013b6a116101d957806384013b6a1461091c578063863fe4ab146109f75780638cc8f561146108e457806396713da9146109ff576103e6565b806374f079b8146108fc57806375d47a0a146109045780637942fd051461090c5780637e434d5414610914576103e6565b806343756e5c116103055780636a3cb34d116102985780636e47a51a116102675780636e47a51a146108bc5780636e47b482146108dc57806370fd5bad146108e4578063718a8aa8146108ec578063719482d5146108f4576103e6565b80636a3cb34d146108645780636bacff2c1461086c5780636c46aa68146108645780636de380bd146108b4576103e6565b806351e80672116102d457806351e806721461081e5780635692ddd3146108265780635f8321771461082e57806363e1394e1461085c576103e6565b806343756e5c146107fe578063493279b1146108065780634bf6c8821461080e57806351b4dce314610816576103e6565b8063299b533d1161037d5780633a648b151161034c5780633a648b15146106725780633bdc47a6146106ae5780633dffc387146107d6578063422f9050146107de576103e6565b8063299b533d146105f85780632af6f3991461062c5780632ff32aea14610649578063308325f41461066a576103e6565b80631d130935116103b95780631d130935146104685780631e275ae11461048457806322556cdc146105e857806328087028146105f0576103e6565b806305e68258146103eb5780630bee7a67146104095780630e2374a51461042a57806314b3023b1461044e575b600080fd5b6103f3610c44565b6040805160ff9092168252519081900360200190f35b610411610c49565b6040805163ffffffff9092168252519081900360200190f35b610432610c4e565b604080516001600160a01b039092168252519081900360200190f35b610456610c54565b60408051918252519081900360200190f35b610470610c5a565b604080519115158252519081900360200190f35b6105e6600480360361010081101561049b57600080fd5b81018160a081016080820135600160201b8111156104b857600080fd5b8201836020820111156104ca57600080fd5b803590602001918460018302840111600160201b831117156104eb57600080fd5b919390929091602081019035600160201b81111561050857600080fd5b82018360208201111561051a57600080fd5b803590602001918460018302840111600160201b8311171561053b57600080fd5b919390929091602081019035600160201b81111561055857600080fd5b82018360208201111561056a57600080fd5b803590602001918460018302840111600160201b8311171561058b57600080fd5b919390929091602081019035600160201b8111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111600160201b831117156105db57600080fd5b509092509050610c63565b005b610456611347565b61043261134c565b6106156004803603602081101561060e57600080fd5b5035611352565b6040805161ffff9092168252519081900360200190f35b6104706004803603602081101561064257600080fd5b5035611368565b61065161137d565b60408051600792830b90920b8252519081900360200190f35b610456611386565b6106926004803603602081101561068857600080fd5b503560ff1661138c565b604080516001600160401b039092168252519081900360200190f35b610761600480360360608110156106c457600080fd5b60ff82351691602081013591810190606081016040820135600160201b8111156106ed57600080fd5b8201836020820111156106ff57600080fd5b803590602001918460018302840111600160201b8311171561072057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506113a7945050505050565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561079b578181015183820152602001610783565b50505050905090810190601f1680156107c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103f361141d565b610470600480360360208110156107f457600080fd5b503560ff16611422565b610432611437565b61061561143d565b6103f3611443565b610432611448565b61043261144e565b610456611454565b6105e66004803603604081101561084457600080fd5b506001600160a01b0381358116916020013516611484565b6104566116e4565b61061561170c565b6108896004803603602081101561088257600080fd5b5035611711565b6040805161ffff90941684526001600160801b03909216602084015282820152519081900360600190f35b610456611740565b610432600480360360208110156108d257600080fd5b503560ff16611767565b610432611782565b6103f361170c565b6103f3611788565b61061561141d565b61045661178d565b610432611793565b6103f3611799565b61043261179e565b6105e6600480360360a081101561093257600080fd5b810190602081018135600160201b81111561094c57600080fd5b82018360208201111561095e57600080fd5b803590602001918460018302840111600160201b8311171561097f57600080fd5b919390929091602081019035600160201b81111561099c57600080fd5b8201836020820111156109ae57600080fd5b803590602001918460018302840111600160201b831117156109cf57600080fd5b919350915080356001600160401b03908116916020810135909116906040013560ff166117a4565b610456612a5e565b6103f3612a66565b610432612a6b565b610432612a71565b610470612a77565b610432612a80565b610432612a86565b610411610c44565b6105e660048036036040811015610a4d57600080fd5b810190602081018135600160201b811115610a6757600080fd5b820183602082011115610a7957600080fd5b803590602001918460018302840111600160201b83111715610a9a57600080fd5b919390929091602081019035600160201b811115610ab757600080fd5b820183602082011115610ac957600080fd5b803590602001918460018302840111600160201b83111715610aea57600080fd5b509092509050612a8c565b61069260048036036020811015610b0b57600080fd5b503560ff16613550565b61045661356b565b61043261358f565b6105e6613595565b61047060048036036040811015610b4357600080fd5b5080356001600160a01b0316906020013560ff166137e9565b610761613809565b610456613828565b61043261382e565b610432613834565b6105e661383a565b61069260048036036020811015610b9a57600080fd5b503560ff16613bf1565b6105e6613c0c565b6103f3613e2b565b6105e660048036036060811015610bca57600080fd5b60ff8235169190810190604081016020820135600160201b811115610bee57600080fd5b820183602082011115610c0057600080fd5b803590602001918460018302840111600160201b83111715610c2157600080fd5b919350915035613e30565b610432613f73565b6103f3613f79565b610432613f7e565b600081565b606481565b61200181565b60015481565b600b5460ff1681565b60005460ff16610ca8576040805162461bcd60e51b81526020600482015260196024820152600080516020614a62833981519152604482015290519081900360640190fd5b604080516337d7f9c160e21b81526001600160401b038b35166004820181905291516110039163df5fe704916024808301926020929190829003018186803b158015610cf357600080fd5b505afa158015610d07573d6000803e3d6000fd5b505050506040513d6020811015610d1d57600080fd5b5051610d5a5760405162461bcd60e51b8152600401808060200182810382526023815260200180614a826023913960400191505060405180910390fd5b604080516337d7f9c160e21b815260208c8101356001600160401b03166004830181905292516110039263df5fe704926024808301939192829003018186803b158015610da657600080fd5b505afa158015610dba573d6000803e3d6000fd5b505050506040513d6020811015610dd057600080fd5b5051610e0d5760405162461bcd60e51b8152600401808060200182810382526023815260200180614a826023913960400191505060405180910390fd5b60608b013560ff81166000908152600560205260409020546001600160401b03909116906001600160a01b0316610e86576040805162461bcd60e51b815260206004820152601860248201527718da185b9b995b081a5cc81b9bdd081cdd5c1c1bdc9d195960421b604482015290519081900360640190fd5b600b5460ff1615610eca576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b8888604051808383808284376040519201829003822094508f93508e9250819050838380828437808301925050509250505060405180910390201415610f46576040805162461bcd60e51b815260206004820152600c60248201526b1cd85b59481c185e5b1bd85960a21b604482015290519081900360640190fd5b60606001600160401b0360408e01358116908e83013516610f678282613f84565b80516020808301919091206000818152600e9092526040909120549194509060ff1615610fd0576040805162461bcd60e51b8152602060048201526012602482015271185b1c9958591e4818da185b1b195b99d95960721b604482015290519081900360640190fd5b6000908152600e60205260408120805460ff191660011790558f8160200201356001600160401b0316905060608f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060608c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805163cba510a960e01b81526001600160401b038a16600482015290519596509094611003945063cba510a9935060248083019350602092829003018186803b1580156110c657600080fd5b505afa1580156110da573d6000803e3d6000fd5b505050506040513d60208110156110f057600080fd5b505160408051808201909152600381526269626360e81b602082015290915061111d908290898686613fcc565b611166576040805162461bcd60e51b81526020600482015260156024820152740696e76616c6964206d65726b6c652070726f6f663605c1b604482015290519081900360640190fd5b5050505060008f60016004811061117957fe5b60200201356001600160401b0316905060608d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815293945060609392508d91508c908190840183828082843760009201829052506040805163cba510a960e01b81526001600160401b038a16600482015290519596509094611003945063cba510a9935060248083019350602092829003018186803b15801561124557600080fd5b505afa158015611259573d6000803e3d6000fd5b505050506040513d602081101561126f57600080fd5b505160408051808201909152600381526269626360e81b602082015290915061129c908290898686613fcc565b6112e5576040805162461bcd60e51b8152602060048201526015602482015274696e76616c6964206d65726b6c652070726f6f663160581b604482015290519081900360640190fd5b505050506112f16140c9565b604080516001600160401b038416815260ff83166020820152815133927f039eb91179ffd7d3b6e97f8ea106e748e827f910b872375dbc9c14a362319c3c928290030190a2505050505050505050505050505050565b603281565b61200581565b600d6020526000908152604090205461ffff1681565b600e6020526000908152604090205460ff1681565b60045460070b81565b60025481565b600a602052600090815260409020546001600160401b031681565b60606000825160210190506060816040519080825280601f01601f1916602001820160405280156113df576020820181803683370190505b506021810186905260018101879052828152905060418101600061140286614147565b50905061141181838851614151565b50909695505050505050565b600181565b60096020526000908152604090205460ff1681565b61100181565b6102ca81565b600881565b61200681565b61200081565b604080517710d05390d15317d514905394d1915497d41493d413d4d05360421b8152905190819003601801902081565b60005460ff166114c9576040805162461bcd60e51b81526020600482015260196024820152600080516020614a62833981519152604482015290519081900360640190fd5b6040805163569e4ed360e11b815233600482015290516000916110009163ad3c9da691602480820192602092909190829003018186803b15801561150c57600080fd5b505afa158015611520573d6000803e3d6000fd5b505050506040513d602081101561153657600080fd5b505160408051633d42651560e11b8152905191925060009161100091637a84ca2a916004808301926020929190829003018186803b15801561157757600080fd5b505afa15801561158b573d6000803e3d6000fd5b505050506040513d60208110156115a157600080fd5b50519050806115ae575060155b6000821180156115be5750808211155b6115fd576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd0818d8589a5b995d60aa1b604482015290519081900360640190fd5b604080516001600160a01b038087166020808401919091529086168284015282518083038401815260608301808552815191909201207710d05390d15317d514905394d1915497d41493d413d4d05360421b909152915190819003607801902060009061166a9083614192565b905080156116dc5760408051630911a2c160e11b81526001600160a01b03888116600483015287166024820152905161100491631223458291604480830192600092919082900301818387803b1580156116c357600080fd5b505af11580156116d7573d6000803e3d6000fd5b505050505b505050505050565b604080516f14d554d411539117d41493d413d4d05360821b8152905190819003601001902081565b600281565b600c602052600090815260409020805460019091015461ffff8216916201000090046001600160801b03169083565b604080516e149153d4115397d41493d413d4d053608a1b8152905190819003600f01902081565b6005602052600090815260409020546001600160a01b031681565b61100581565b601081565b60035481565b61100881565b600b81565b61200381565b60005460ff166117e9576040805162461bcd60e51b81526020600482015260196024820152600080516020614a62833981519152604482015290519081900360640190fd5b60408051630a83aaa960e31b815233600482015290516110069163541d5548916024808301926020929190829003018186803b15801561182857600080fd5b505afa15801561183c573d6000803e3d6000fd5b505050506040513d602081101561185257600080fd5b50516118a5576040805162461bcd60e51b815260206004820152601f60248201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604482015290519081900360640190fd5b60ff8116600090815260086020526040902054829082906001600160401b039081169083168114611915576040805162461bcd60e51b815260206004820152601560248201527439b2b8bab2b731b2903737ba1034b71037b93232b960591b604482015290519081900360640190fd5b60ff8216600090815260086020908152604091829020805467ffffffffffffffff1916600185016001600160401b039081169190911790915582516337d7f9c160e21b81529089166004820152915188926110039263df5fe70492602480840193829003018186803b15801561198a57600080fd5b505afa15801561199e573d6000803e3d6000fd5b505050506040513d60208110156119b457600080fd5b50516119f15760405162461bcd60e51b8152600401808060200182810382526023815260200180614a826023913960400191505060405180910390fd5b60ff851660009081526005602052604090205485906001600160a01b0316611a5b576040805162461bcd60e51b815260206004820152601860248201527718da185b9b995b081a5cc81b9bdd081cdd5c1c1bdc9d195960421b604482015290519081900360640190fd5b60ff86166000908152600a6020526040902054889087906001600160401b039081169083161015611ac4576040805162461bcd60e51b815260206004820152600e60248201526d3a37b79037b632103432b0b232b960911b604482015290519081900360640190fd5b60ff81166000908152600a60205260409020546001600160401b03838116911614611b165760ff81166000908152600a60205260409020805467ffffffffffffffff19166001600160401b0384161790555b600b5460ff1615611b5a576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b60608e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060608d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509050611c9e6110036001600160a01b031663cba510a98e6040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060206040518083038186803b158015611c4757600080fd5b505afa158015611c5b573d6000803e3d6000fd5b505050506040513d6020811015611c7157600080fd5b505160408051808201909152600381526269626360e81b6020820152611c978e8e613f84565b8585613fcc565b611ce6576040805162461bcd60e51b815260206004820152601460248201527334b73b30b634b21036b2b935b63290383937b7b360611b604482015290519081900360640190fd5b60408051631bb5062960e31b81526001600160401b038e16600482015290516000916110039163dda8314891602480820192602092909190829003018186803b158015611d3257600080fd5b505afa158015611d46573d6000803e3d6000fd5b505050506040513d6020811015611d5c57600080fd5b505190508b8b600080806060611d7189614477565b935093509350935083611e33578460ff16866001600160401b03167ff7b2e42d694eb1100184aae86d4245d9e46966100b1dc7e723275b98326854ac8b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611deb578181015183820152602001611dd3565b50505050905090810190601f168015611e185780820380516001836020036101000a031916815260200191505b509250505060405180910390a3505050505050505050612a4e565b6040805160ff85811682529151918716916001600160401b038916917f36afdaf439a8f43fe72135135d804ae620b37a474f0943b5b85f6788312cad40919081900360200190a360ff83166123b85760ff85166000818152600560209081526040808320548151631182b87560e01b815260048101958652602481019283528651604482015286516001600160a01b03909216958695631182b875958d958a9593949093606490910192918601918190849084905b83811015611f00578181015183820152602001611ee8565b50505050905090810190601f168015611f2d5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611f4d57600080fd5b505af192505050801561203157506040513d6000823e601f3d908101601f191682016040526020811015611f8057600080fd5b8101908080516040519392919084600160201b821115611f9f57600080fd5b908301906020820185811115611fb457600080fd5b8251600160201b811182820188101715611fcd57600080fd5b82525081516020918201929091019080838360005b83811015611ffa578181015183820152602001611fe2565b50505050905090810190601f1680156120275780820380516001836020036101000a031916815260200191505b5060405250505060015b612343576040516000815260443d101561204d575060006120e8565b60046000803e60005160e01c6308c379a0811461206e5760009150506120e8565b60043d036004833e81513d60248201116001600160401b0382111715612099576000925050506120e8565b80830180516001600160401b038111156120ba5760009450505050506120e8565b8060208301013d86018111156120d8576000955050505050506120e8565b601f01601f191660405250925050505b806120f35750612205565b60ff871660009081526007602052604081205461212a916001600160401b0390911690899061212590600290886113a7565b614527565b60ff8716600090815260076020908152604080832080546001600160401b038082166001011667ffffffffffffffff19909116179055805182815284518184015284516001600160a01b038716947ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf948794849390840192918601918190849084905b838110156121c55781810151838201526020016121ad565b50505050905090810190601f1680156121f25780820380516001836020036101000a031916815260200191505b509250505060405180910390a25061233e565b3d80801561222f576040519150601f19603f3d011682016040523d82523d6000602084013e612234565b606091505b5060ff8716600090815260076020526040812054612267916001600160401b0390911690899061212590600290886113a7565b60ff8716600090815260076020908152604080832080546001600160401b038082166001011667ffffffffffffffff19909116179055805182815284518184015284516001600160a01b038716947f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351948794849390840192918601918190849084905b838110156123025781810151838201526020016122ea565b50505050905090810190601f16801561232f5780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b6123b2565b8051156123b05760ff871660009081526007602052604081205461237c916001600160401b0390911690899061212590600190866113a7565b60ff8716600090815260076020526040902080546001600160401b038082166001011667ffffffffffffffff199091161790555b505b50612986565b60ff83166001141561265c5760ff8516600081815260056020908152604080832054815163831d65d160e01b815260048101958652602481019283528651604482015286516001600160a01b0390921695869563831d65d1958d958a9593949093606490910192918601918190849084905b8381101561244257818101518382015260200161242a565b50505050905090810190601f16801561246f5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561248f57600080fd5b505af19250505080156124a0575060015b6123b2576040516000815260443d10156124bc57506000612557565b60046000803e60005160e01c6308c379a081146124dd576000915050612557565b60043d036004833e81513d60248201116001600160401b038211171561250857600092505050612557565b80830180516001600160401b03811115612529576000945050505050612557565b8060208301013d860181111561254757600095505050505050612557565b601f01601f191660405250925050505b8061256257506125c7565b60408051602080825283518183015283516001600160a01b038616937ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf93869390928392830191850190808383600083156121c55781810151838201526020016121ad565b3d8080156125f1576040519150601f19603f3d011682016040523d82523d6000602084013e6125f6565b606091505b5060408051602080825283518183015283516001600160a01b038616937f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd297735193869390928392830191850190808383600083156123025781810151838201526020016122ea565b60ff8316600214156129865760ff8516600081815260056020908152604080832054815163c8509d8160e01b815260048101958652602481019283528651604482015286516001600160a01b0390921695869563c8509d81958d958a9593949093606490910192918601918190849084905b838110156126e65781810151838201526020016126ce565b50505050905090810190601f1680156127135780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561273357600080fd5b505af1925050508015612744575060015b612984576040516000815260443d1015612760575060006127fb565b60046000803e60005160e01c6308c379a081146127815760009150506127fb565b60043d036004833e81513d60248201116001600160401b03821117156127ac576000925050506127fb565b80830180516001600160401b038111156127cd5760009450505050506127fb565b8060208301013d86018111156127eb576000955050505050506127fb565b601f01601f191660405250925050505b8061280657506128af565b816001600160a01b03167ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf826040518080602001828103825283818151815260200191508051906020019080838360005b8381101561286f578181015183820152602001612857565b50505050905090810190601f16801561289c5780820380516001836020036101000a031916815260200191505b509250505060405180910390a250612984565b3d8080156128d9576040519150601f19603f3d011682016040523d82523d6000602084013e6128de565b606091505b50816001600160a01b03167f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351826040518080602001828103825283818151815260200191508051906020019080838360005b83811015612948578181015183820152602001612930565b50505050905090810190601f1680156129755780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b505b60ff80861660009081526009602052604090205461100591636f93d2e6918a913391879116806129b8575060ff881615155b604080516001600160e01b031960e088901b1681526001600160a01b039586166004820152939094166024840152604483019190915215156064820152905160848083019260209291908290030181600087803b158015612a1857600080fd5b505af1158015612a2c573d6000803e3d6000fd5b505050506040513d6020811015612a4257600080fd5b50505050505050505050505b5050505050505050505050505050565b630102ca0081565b600981565b61100781565b61100681565b60005460ff1681565b61200281565b61300081565b3361100714612acc5760405162461bcd60e51b815260040180806020018281038252602e8152602001806149b8602e913960400191505060405180910390fd5b600b5460ff1615612b10576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b612b7984848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526012815271626174636853697a65466f724f7261636c6560701b602082015291506146c29050565b15612c1457604080516020601f8401819004810282018101909252828152600091612bbc918585808385018382808284376000920191909152506147a992505050565b90506127108111158015612bd15750600a8110155b612c0c5760405162461bcd60e51b8152600401808060200182810382526032815260200180614a306032913960400191505060405180910390fd5b6001556134be565b612c7d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601281527118591913dc955c19185d1950da185b9b995b60721b602082015291506146c29050565b15612e0557606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060169091149050612d005760405162461bcd60e51b815260040180806020018281038252605a8152602001806148d1605a913960600191505060405180910390fd5b60018101516002820151601683015160ff82161590612d1e816147ae565b612d6f576040805162461bcd60e51b815260206004820152601960248201527f61646472657373206973206e6f74206120636f6e747261637400000000000000604482015290519081900360640190fd5b60ff8416600081815260056020908152604080832080546001600160a01b0319166001600160a01b038716908117909155808452600683528184208585528352818420805460ff199081166001179091556009909352818420805490931687151517909255519092917f7e3b6af43092577ee20e60eaa1d9b114a7031305c895ee7dd3ffe17196d2e1e091a350505050506134be565b612e7284848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526016815275195b98589b1953dc911a5cd8589b1950da185b9b995b60521b602082015291506146c29050565b15612fa357606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060029091149050612ef55760405162461bcd60e51b815260040180806020018281038252604a8152602001806149e6604a913960600191505060405180910390fd5b600181810151600283015160ff80831660009081526005602052604090205492939192908316909114906001600160a01b03168015612f99576001600160a01b038116600090815260066020908152604080832060ff881680855290835292819020805460ff1916861515908117909155815190815290517fa3132e3f9819fbddc7f0ed6d38d7feef59aa95112090b7c592f5cb5bc4aa4adc929181900390910190a25b50505050506134be565b61300784848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c73757370656e6451756f72756d60981b602082015291506146c29050565b1561313c576002811461304b5760405162461bcd60e51b815260040180806020018281038252602d81526020018061495f602d913960400191505060405180910390fd5b600061308e600284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147a992505050565b905060008161ffff161180156130a8575060648161ffff16105b6130f2576040805162461bcd60e51b8152602060048201526016602482015275696e76616c69642073757370656e642071756f72756d60501b604482015290519081900360640190fd5b604080516f14d554d411539117d41493d413d4d05360821b815281519081900360100190206000908152600d60205220805461ffff90921661ffff199092169190911790556134be565b61319f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600c81526b72656f70656e51756f72756d60a01b602082015291506146c29050565b156132d257600281146131e35760405162461bcd60e51b815260040180806020018281038252602c81526020018061498c602c913960400191505060405180910390fd5b6000613226600284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147a992505050565b905060008161ffff16118015613240575060648161ffff16105b613289576040805162461bcd60e51b8152602060048201526015602482015274696e76616c69642072656f70656e2071756f72756d60581b604482015290519081900360640190fd5b604080516e149153d4115397d41493d413d4d053608a1b8152815190819003600f0190206000908152600d60205220805461ffff90921661ffff199092169190911790556134be565b61333d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601481527363616e63656c5472616e7366657251756f72756d60601b602082015291506146c29050565b1561348157600281146133815760405162461bcd60e51b815260040180806020018281038252603481526020018061492b6034913960400191505060405180910390fd5b60006133c4600284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147a992505050565b905060008161ffff161180156133de575060648161ffff16105b61342f576040805162461bcd60e51b815260206004820152601e60248201527f696e76616c69642063616e63656c207472616e736665722071756f72756d0000604482015290519081900360640190fd5b604080517710d05390d15317d514905394d1915497d41493d413d4d05360421b815281519081900360180190206000908152600d60205220805461ffff90921661ffff199092169190911790556134be565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b6008602052600090815260409020546001600160401b031681565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081565b61100281565b60005460ff166135da576040805162461bcd60e51b81526020600482015260196024820152600080516020614a62833981519152604482015290519081900360640190fd5b6040805163569e4ed360e11b815233600482015290516000916110009163ad3c9da691602480820192602092909190829003018186803b15801561361d57600080fd5b505afa158015613631573d6000803e3d6000fd5b505050506040513d602081101561364757600080fd5b505160408051633d42651560e11b8152905191925060009161100091637a84ca2a916004808301926020929190829003018186803b15801561368857600080fd5b505afa15801561369c573d6000803e3d6000fd5b505050506040513d60208110156136b257600080fd5b50519050806136bf575060155b6000821180156136cf5750808211155b61370e576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd0818d8589a5b995d60aa1b604482015290519081900360640190fd5b600b5460ff16613755576040805162461bcd60e51b815260206004820152600d60248201526c1b9bdd081cdd5cdc195b991959609a1b604482015290519081900360640190fd5b604080516e149153d4115397d41493d413d4d053608a1b8152905190819003600f0190206000906137a6907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470614192565b905080156137e457600b805460ff1916905560405133907f899fe8c37dc61708a3aaa99c4bf143346c1d1da69af79be9e8920c0a6785b75290600090a25b505050565b600660209081526000928352604080842090915290825290205460ff1681565b6040518060400160405280600381526020016269626360e81b81525081565b610e1081565b61100381565b61200481565b60005460ff1615613892576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b7f1471eb6eb2c5e789fc3de43f8ce62938c7d1836ec861730447e2ada8fd81017b80546001600160a01b0319908116611008179091557f92e85d02570a8092d09a6e3a57665bc3815a2699a4074001bf1ccabf660f5a36805460ff199081169091557fd8af288fc1c8680b4f4706064cf021e264efb6828fcaf7eb5ca36818eb365bcc8054821660019081179091557f89832631fb3c3307a103ba2c84ab569c64d6182a18893dcd163f0f1c2090733a805484166110049081179091557f6cde3cea4b3a3fb2488b2808bae7556f4a405e50f65e1794383bc026131b13c38054841690557f72e4efa1513b071517c6c74dba31b5934a81aa83cddd400e7081df5529c9943680548416831790557fa9bc9a3a348c357ba16b37005d7e6b3236198c0e939f4af8c5f19b8deeb8ebc08054851690911790557fc575c31fea594a6eb97c8e9d3f9caee4c16218c6ef37e923234c0fe9014a61e78054831690557f4e523af77f034e9810f1c94057f5e931fb3d16a51511a4c3add793617d18610580548316821790557ffb33122aa9f93cc639ebe80a7bc4784c11e6053dde89c6f4f7e268c6a623da1e805484166110001790557fc7694af312c4f286114180fd0ba6a52461fcee8a381636770b19a343af92538a80548316821790557f01112dd68e482ba8d68a7e828cff8b3abcea08eab88941953c180a7e650e9cd480548316821790557fc0a4a8be475dfebc377ebef2d7c4ff47656f572a08dd92b81017efcdba0febe1805484166110071790557f87e8a52529e8ece4ef759037313542a6429ff494a9fab9027fb79db90124eba680548316821790557f4c7666bbcb22d46469f7cc282f70764a7012dca2cce630ff8d83db9a9cdd48f080548316821790557f40f28f99a40bc9f6beea1013afdbc3cdcc689eb76b82c4de06c0acf1e1932ed58054909316611001179092557f0d9cf2cd531699eed8dd34e40ff2884a14a698c4898184fba85194e6f6772d248054821683179055600b60009081527f23f68c9bd22b8a93d06adabe17481c87c016bcbd20adc8bfd707a4d813a572176020527fdf0d5d05428057f5455c2dc8e810dd86d1e9350faa72f16bda8a45443c5b39328054831684179055603283556004805467ffffffffffffffff19166001600160401b031790556002819055600381905580549091169091179055565b6007602052600090815260409020546001600160401b031681565b60005460ff16613c51576040805162461bcd60e51b81526020600482015260196024820152600080516020614a62833981519152604482015290519081900360640190fd5b6040805163569e4ed360e11b815233600482015290516000916110009163ad3c9da691602480820192602092909190829003018186803b158015613c9457600080fd5b505afa158015613ca8573d6000803e3d6000fd5b505050506040513d6020811015613cbe57600080fd5b505160408051633d42651560e11b8152905191925060009161100091637a84ca2a916004808301926020929190829003018186803b158015613cff57600080fd5b505afa158015613d13573d6000803e3d6000fd5b505050506040513d6020811015613d2957600080fd5b5051905080613d36575060155b600082118015613d465750808211155b613d85576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd0818d8589a5b995d60aa1b604482015290519081900360640190fd5b600b5460ff1615613dc9576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b604080516f14d554d411539117d41493d413d4d05360821b81529051908190036010019020600090613e1b907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470614192565b905080156137e4576137e46140c9565b601181565b60005460ff16613e75576040805162461bcd60e51b81526020600482015260196024820152600080516020614a62833981519152604482015290519081900360640190fd5b33600090815260066020908152604080832060ff8089168552925290912054859116613ed25760405162461bcd60e51b81526004018080602001828103825260318152602001806148a06031913960400191505060405180910390fd5b60ff85166000908152600760209081526040808320548151601f88018490048402810184019092528682526001600160401b031692613f379284928a9261212592909189918c908c90819084018382808284376000920191909152506113a792505050565b60ff959095166000908152600760205260409020805467ffffffffffffffff191660019096016001600160401b03169590951790945550505050565b61100081565b600381565b61100481565b60408051600e808252818301909252606091630102ca0060ff851617918391602082018180368337505050600e81810187905260068201939093529182525090505b92915050565b600085613fdb575060006140c0565b606082518451865160800101016040519080825280601f01601f191660200182016040528015614012576020820181803683370190505b5090506000614020826147b4565b60208089015182520190508660008061403889614147565b8086526020909501949092509050614051828583614151565b9283019261405e88614147565b8086526020909501949092509050614077828583614151565b9283018a81526020019261408a87614147565b909250905061409a828583614151565b5083516020016140a86147ba565b60208183886065600019fa5051600114955050505050505b95945050505050565b600b5460ff161561410d576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b600b805460ff1916600117905560405133907f6f123d3d54c84a7960a573b31c221dcd86e13fd849c5adb0c6ca851468cc1ae490600090a2565b8051602090910191565b5b60208110614171578251825260209283019290910190601f1901614152565b915181516020939093036101000a6000190180199091169216919091179052565b6000828152600d602052604081205461ffff1661425b57604080516f14d554d411539117d41493d413d4d05360821b815281519081900360100181206000908152600d6020818152848320805461ffff199081166001179091556e149153d4115397d41493d413d4d053608a1b8552855194859003600f01852084528282528584208054821660029081179091557710d05390d15317d514905394d1915497d41493d413d4d05360421b8652865195869003601801909520845291905292902080549092161790555b6000838152600c6020526040902080546201000090046001600160801b03164210158061428c575082816001015414155b1561435f576000848152600d602090815260409182902054835461ffff90911661ffff199091161771ffffffffffffffffffffffffffffffff0000191662010000610e1042016001600160801b03160217835560018084018690558251918201909252338152614301916002840191906147d8565b5080546040805161ffff83168152620100009092046001600160801b0316602083015281810185905251339186917f9e109f0e55ef32e99e4880be2ec357f1ddb3469c79d0747ef4762da6e89fabe5916060908290030190a3614413565b60005b60028201548110156143ea57336001600160a01b031682600201828154811061438757fe5b6000918252602090912001546001600160a01b031614156143e2576040805162461bcd60e51b815260206004820152601060248201526f185b1c9958591e48185c1c1c9bdd995960821b604482015290519081900360640190fd5b600101614362565b50600281018054600181018255600091825260209091200180546001600160a01b031916331790555b8054600282015461ffff9091161161446d576000848152600c60205260408120805471ffffffffffffffffffffffffffffffffffff191681556001810182905590614461600283018261483d565b50506001915050613fc6565b5060009392505050565b600080600060606021855110156144a7575050604080516000808252602082019092529092508291508190614520565b600185015160218601518651604080516020198301808252601f19600119909401939093168101602001909152604189019392916060919080156144f2576020820181803683370190505b509050600061450082614147565b509050614512858260218d5103614151565b506001975091955093509150505b9193509193565b600b5460ff161561456b576040805162461bcd60e51b81526020600482015260096024820152681cdd5cdc195b99195960ba1b604482015290519081900360640190fd5b6002544311156145aa576004805467ffffffffffffffff1981166001600160401b036001600793840b810190930b1617909155600355436002556145eb565b600380546001908101918290555410156145eb576004805467ffffffffffffffff1981166001600160401b036001600793840b810190930b16179091556003555b8160ff16836001600160401b0316600460009054906101000a900460070b6001600160401b03167f3a6e0fc61675aa2a100bcba0568368bb92bcec91c97673391074f11138f0cffe6102ca85604051808361ffff1661ffff16815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561468257818101518382015260200161466a565b50505050905090810190601f1680156146af5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a4505050565b6000816040516020018082805190602001908083835b602083106146f75780518252601f1990920191602091820191016146d8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106147655780518252601f199092019160209182019101614746565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b3b151590565b60200190565b60405180602001604052806001906020820280368337509192915050565b82805482825590600052602060002090810192821561482d579160200282015b8281111561482d57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906147f8565b5061483992915061485e565b5090565b508054600082559060005260206000209081019061485b9190614885565b50565b61488291905b808211156148395780546001600160a01b0319168155600101614864565b90565b61488291905b80821115614839576000815560010161488b56fe74686520636f6e747261637420616e64206368616e6e656c2068617665206e6f74206265656e20726567697374657265646c656e677468206f662076616c756520666f72206164644f725570646174654368616e6e656c2073686f756c642062652032322c206368616e6e656c49643a697346726f6d53797374656d3a68616e646c6572416464726573736c656e677468206f662076616c756520666f722063616e63656c5472616e7366657251756f72756d2073686f756c6420626520326c656e677468206f662076616c756520666f722073757370656e6451756f72756d2073686f756c6420626520326c656e677468206f662076616c756520666f722072656f70656e51756f72756d2073686f756c642062652032746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662076616c756520666f7220656e61626c654f7244697361626c654368616e6e656c2073686f756c6420626520322c206368616e6e656c49643a6973456e61626c65746865206e6577426174636853697a65466f724f7261636c652073686f756c6420626520696e205b31302c2031303030305d74686520636f6e7472616374206e6f7420696e697420796574000000000000006c6967687420636c69656e74206e6f742073796e632074686520626c6f636b20796574a164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(StakingContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106103d25760003560e01c8063718a8aa8116101fd578063b88a802f11610118578063dc927faf116100ab578063f45fd80b1161007a578063f45fd80b14610cdb578063f9a2bbc714610d20578063fa03f79714610d35578063fc3e5908146106d3578063fd6a687914610d4a576103d9565b8063dc927faf14610c87578063df8079e914610c9c578063edc1a5b014610cb1578063f1fad10414610cc6576103d9565b8063c81b1662116100e7578063c81b166214610bb2578063c8509d8114610bc7578063d61b9b9314610c4c578063d7ecfcb614610890576103d9565b8063b88a802f14610b38578063baaafd3b14610b4d578063bf8546ca14610b62578063c2117d8214610b9d576103d9565b80639dc0926211610190578063aad560631161015f578063aad5606314610a2e578063ab51bb9614610a43578063ac43175114610a58578063b14315df14610b23576103d9565b80639dc09262146109c6578063a1a11bf5146109db578063a78abc16146109f0578063aa82dce114610a19576103d9565b80637e434d54116101cc5780637e434d5414610917578063831d65d11461092c57806392b888a41461066a57806396713da9146109b1576103d9565b8063718a8aa8146108a557806375aca593146108ba57806375d47a0a146108ed5780637942fd0514610902576103d9565b8063413d9c3a116102ed5780635d17c8bd116102805780636bd8f8041161024f5780636bd8f804146108125780636e47b482146108485780636fb7f7eb1461085d57806370fd5bad14610890576103d9565b80635d17c8bd146107be5780635d499b1b146107d357806362b171d2146107e857806369b635b6146107fd576103d9565b80634d99dd16116102bc5780634d99dd161461075357806351b4dce31461077f57806351e8067214610794578063552aaf93146107a9576103d9565b8063413d9c3a146106e857806343756e5c146106fd578063493279b1146107125780634bf6c8821461073e576103d9565b8063151817e311610365578063333ad3e711610334578063333ad3e7146106a957806334c43354146106be5780633dffc3871461066a5780633fdfa7e4146106d3576103d9565b8063151817e31461063f57806317c9efb01461066a578063280870281461067f5780632fdeb11114610694576103d9565b80630c795715116103a15780630c795715146104cc5780630e2374a5146104e15780631182b8751461051257806311fe9ec61461060c576103d9565b8063026e402b146103de578063029859921461040c578063047636d1146104335780630bee7a671461049e576103d9565b366103d957005b600080fd5b61040a600480360360408110156103f457600080fd5b506001600160a01b038135169060200135610d5f565b005b34801561041857600080fd5b50610421610d9c565b60408051918252519081900360200190f35b34801561043f57600080fd5b506104666004803603602081101561045657600080fd5b50356001600160a01b0316610da2565b6040518082606080838360005b8381101561048b578181015183820152602001610473565b5050505090500191505060405180910390f35b3480156104aa57600080fd5b506104b3610df6565b6040805163ffffffff9092168252519081900360200190f35b3480156104d857600080fd5b50610421610dfb565b3480156104ed57600080fd5b506104f6610e01565b604080516001600160a01b039092168252519081900360200190f35b34801561051e57600080fd5b506105976004803603604081101561053557600080fd5b60ff8235169190810190604081016020820135600160201b81111561055957600080fd5b82018360208201111561056b57600080fd5b803590602001918460018302840111600160201b8311171561058c57600080fd5b509092509050610e07565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105d15781810151838201526020016105b9565b50505050905090810190601f1680156105fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561061857600080fd5b506104216004803603602081101561062f57600080fd5b50356001600160a01b0316610fc3565b34801561064b57600080fd5b50610654610fde565b6040805160ff9092168252519081900360200190f35b34801561067657600080fd5b50610654610fe3565b34801561068b57600080fd5b506104f6610fe8565b3480156106a057600080fd5b50610421610fee565b3480156106b557600080fd5b506104b3610ff4565b3480156106ca57600080fd5b50610421610ff9565b3480156106df57600080fd5b50610654611004565b3480156106f457600080fd5b50610421611009565b34801561070957600080fd5b506104f6611010565b34801561071e57600080fd5b50610727611016565b6040805161ffff9092168252519081900360200190f35b34801561074a57600080fd5b5061065461101c565b61040a6004803603604081101561076957600080fd5b506001600160a01b038135169060200135611021565b34801561078b57600080fd5b506104f661164e565b3480156107a057600080fd5b506104f6611654565b3480156107b557600080fd5b5061065461165a565b3480156107ca57600080fd5b5061042161165f565b3480156107df57600080fd5b50610421611665565b3480156107f457600080fd5b5061042161166e565b34801561080957600080fd5b5061042161180e565b61040a6004803603606081101561082857600080fd5b506001600160a01b03813581169160208101359091169060400135610d5f565b34801561085457600080fd5b506104f6611814565b34801561086957600080fd5b506104216004803603602081101561088057600080fd5b50356001600160a01b031661181a565b34801561089c57600080fd5b50610654611835565b3480156108b157600080fd5b5061065461183a565b3480156108c657600080fd5b50610421600480360360208110156108dd57600080fd5b50356001600160a01b031661183f565b3480156108f957600080fd5b506104f661185a565b34801561090e57600080fd5b50610654611860565b34801561092357600080fd5b506104f6611865565b34801561093857600080fd5b5061040a6004803603604081101561094f57600080fd5b60ff8235169190810190604081016020820135600160201b81111561097357600080fd5b82018360208201111561098557600080fd5b803590602001918460018302840111600160201b831117156109a657600080fd5b50909250905061186b565b3480156109bd57600080fd5b50610654611b33565b3480156109d257600080fd5b506104f6611b38565b3480156109e757600080fd5b506104f6611b3e565b3480156109fc57600080fd5b50610a05611b44565b604080519115158252519081900360200190f35b348015610a2557600080fd5b506104f6611b4d565b348015610a3a57600080fd5b506104f6611b53565b348015610a4f57600080fd5b506104b361165a565b348015610a6457600080fd5b5061040a60048036036040811015610a7b57600080fd5b810190602081018135600160201b811115610a9557600080fd5b820183602082011115610aa757600080fd5b803590602001918460018302840111600160201b83111715610ac857600080fd5b919390929091602081019035600160201b811115610ae557600080fd5b820183602082011115610af757600080fd5b803590602001918460018302840111600160201b83111715610b1857600080fd5b509092509050611b59565b348015610b2f57600080fd5b506106546122eb565b348015610b4457600080fd5b506104216122f0565b348015610b5957600080fd5b5061042161248d565b348015610b6e57600080fd5b5061042160048036036040811015610b8557600080fd5b506001600160a01b0381358116916020013516612498565b348015610ba957600080fd5b506104216124c5565b348015610bbe57600080fd5b506104f66124cb565b348015610bd357600080fd5b5061040a60048036036040811015610bea57600080fd5b60ff8235169190810190604081016020820135600160201b811115610c0e57600080fd5b820183602082011115610c2057600080fd5b803590602001918460018302840111600160201b83111715610c4157600080fd5b5090925090506124d1565b348015610c5857600080fd5b5061042160048036036040811015610c6f57600080fd5b506001600160a01b03813581169160200135166126f4565b348015610c9357600080fd5b506104f661271f565b348015610ca857600080fd5b506104f6612725565b348015610cbd57600080fd5b5061042161272b565b348015610cd257600080fd5b50610654612738565b348015610ce757600080fd5b5061042160048036036060811015610cfe57600080fd5b506001600160a01b03813581169160208101358216916040909101351661273d565b348015610d2c57600080fd5b506104f6612772565b348015610d4157600080fd5b50610421612778565b348015610d5657600080fd5b506104f661277e565b6040805162461bcd60e51b815260206004820152600d60248201526c1b9bdd081cdd5c1c1bdc9d1959609a1b604482015290519081900360640190fd5b60035481565b610daa614801565b610db2614801565b6001600160a01b0383166000818152600b60209081526040808320548552838352600c82528083205485830152928252600d9052819020549082015290505b919050565b606481565b6108fc81565b61200181565b60603361200014610e495760405162461bcd60e51b815260040180806020018281038252602f8152602001806149e4602f913960400191505060405180910390fd5b60005460ff16610e8c576638d7ea4c6800006001908155662386f26fc1000060025568056bc75e2d631000006003556108fc6011556000805460ff191690911790555b610e9461481f565b610edb610ed685858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061278492505050565b6127a9565b90506000610ef0610eeb836127f3565b612841565b90506000606060ff831660041415610f1557610f0b846128f8565b9092509050610f6c565b60ff831660051415610f2a57610f0b84612ad8565b6040805162461bcd60e51b8152602060048201526012602482015271756e6b6e6f776e206576656e74207479706560701b604482015290519081900360640190fd5b63ffffffff821615610fb8576040805163ffffffff84168152905160ff8516917f391d6e5ea6ab6c49b9a0abb1782cae5def8d711f973b00c729658c0b2a80b31b919081900360200190a25b979650505050505050565b6001600160a01b031660009081526006602052604090205490565b600581565b600181565b61200581565b60015481565b606581565b662386f26fc1000081565b600381565b620a8c0081565b61100181565b6102ca81565b600881565b60105460ff166002141561106d576040805162461bcd60e51b815260206004820152600e60248201526d4e6f2072652d656e7472616e637960901b604482015290519081900360640190fd5b6010805460ff19166002179055806402540be400340615801561109557506402540be4008106155b6110e6576040805162461bcd60e51b815260206004820152601c60248201527f707265636973696f6e206c6f737320696e20636f6e76657273696f6e00000000604482015290519081900360640190fd5b60005460ff16611129576638d7ea4c6800006001908155662386f26fc1000060025568056bc75e2d631000006003556108fc6011556000805460ff191690911790555b600154341015611177576040805162461bcd60e51b81526020600482015260146024820152736e6f7420656e6f7567682072656c61792066656560601b604482015290519081900360640190fd5b600354821015611232573360009081526005602090815260408083206001600160a01b038716845290915290205482146111e9576040805162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b604482015290519081900360640190fd5b6002548211611232576040805162461bcd60e51b815260206004820152601060248201526f6e6f7420656e6f7567682066756e647360801b604482015290519081900360640190fd5b3360009081526007602090815260408083206001600160a01b03871684529091529020544210156112aa576040805162461bcd60e51b815260206004820152601a60248201527f70656e64696e6720756e64656c65676174696f6e206578697374000000000000604482015290519081900360640190fd5b604080518082018252601081526f6e6f7420656e6f7567682066756e647360801b602080830191909152336000908152600582528381206001600160a01b03881682529091529182205461130591859063ffffffff612df816565b9050801561134d57600254811161134d5760405162461bcd60e51b81526004018080602001828103825260258152602001806149bf6025913960400191505060405180910390fd5b6000611364846402540be40063ffffffff612e8f16565b600254909150349060009061138090839063ffffffff612ed816565b6040805160038082526080820190925291925060609190816020015b606081526020019060019003908161139c5790505090506113bc33612f1a565b816000815181106113c957fe5b60200260200101819052506113e6886001600160a01b0316612f1a565b816001815181106113f357fe5b602002602001018190525061140784612f3d565b8160028151811061141457fe5b60200260200101819052506060611434600261142f84612f50565b612fda565b8051602080830191909120600f80546000908152600a845260408082209390935581546001908101909255338152600c909352912080549091019055905061148542620a8c0063ffffffff61306016565b3360009081526007602090815260408083206001600160a01b038e16845290915290205561200063f7a251d76010836114c9876402540be40063ffffffff612e8f16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561152757818101518382015260200161150f565b50505050905090810190601f1680156115545780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561157557600080fd5b505af1158015611589573d6000803e3d6000fd5b5050604051611004925085156108fc02915085906000818181858888f193505050501580156115bc573d6000803e3d6000fd5b506002546040516110029180156108fc02916000818181858888f193505050501580156115ed573d6000803e3d6000fd5b50604080518981526020810185905281516001600160a01b038c169233927fdf0b6ac27f3f3bb31cee3dab0f4fe40cc19c6a3f8daaec52e06b261e58a12519929081900390910190a350506010805460ff1916600117905550505050505050565b61200681565b61200081565b600081565b60025481565b6402540be40081565b60105460009060ff16600214156116bd576040805162461bcd60e51b815260206004820152600e60248201526d4e6f2072652d656e7472616e637960901b604482015290519081900360640190fd5b506010805460ff191660021790553360009081526008602052604090205480611724576040805162461bcd60e51b81526020600482015260146024820152736e6f20756e64656c6567617465642066756e647360601b604482015290519081900360640190fd5b336000818152600860205260408082208290556011549051919291849084818181858888f193505050503d806000811461177a576040519150601f19603f3d011682016040523d82523d6000602084013e61177f565b606091505b50509050806117c7576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b60408051838152905133917fc712d133b8d448221aaed2198ed1f0db6dfc860fb01bc3a630916fe6cbef946f919081900360200190a2506010805460ff1916600117905590565b60035490565b61100581565b6001600160a01b031660009081526004602052604090205490565b600281565b601081565b6001600160a01b031660009081526008602052604090205490565b61100881565b600b81565b61200381565b33612000146118ab5760405162461bcd60e51b815260040180806020018281038252602f8152602001806149e4602f913960400191505060405180910390fd5b60005460ff166118ee576638d7ea4c6800006001908155662386f26fc1000060025568056bc75e2d631000006003556108fc6011556000805460ff191690911790555b6118f661481f565b611938610ed684848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061278492505050565b905060008060606000805b61194c866130ba565b156119b7578061196957611962610eeb876127f3565b94506119af565b80600114156119855761197e610eeb876127f3565b93506119af565b80600214156119aa5761199f61199a876127f3565b6130db565b9250600191506119af565b6119b7565b600101611943565b816119fd576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b611a068361314b565b611a49576040805162461bcd60e51b815260206004820152600f60248201526e0eee4dedcce40e0c2c6d640d0c2e6d608b1b604482015290519081900360640190fd5b611a55610ed684612784565b95506000611a65610eeb886127f3565b9050611a6f61481f565b611a78886130ba565b15611a9b57611a94610ed6611a8f61199a8b6127f3565b612784565b9050611adc565b6040805162461bcd60e51b8152602060048201526011602482015270656d7074792061636b207061636b61676560781b604482015290519081900360640190fd5b60ff821660011415611af857611af381888861319f565b611b26565b60ff821660021415611b0f57611af3818888613556565b60ff821660031415610f2a57611af3818888613823565b5050505050505050505050565b600981565b61100781565b61100681565b60005460ff1681565b61200281565b61300081565b60005460ff16611bb0576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604482015290519081900360640190fd5b3361100714611bf05760405162461bcd60e51b815260040180806020018281038252602e815260200180614935602e913960400191505060405180910390fd5b611c5184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600a81526972656c6179657246656560b01b60208201529150613b889050565b15611db75760208114611cab576040805162461bcd60e51b815260206004820152601d60248201527f6c656e677468206f662072656c61796572466565206d69736d61746368000000604482015290519081900360640190fd5b604080516020601f8401819004810282018101909252828152600091611ce991858580838501838280828437600092019190915250613c6f92505050565b90506003548110611d2b5760405162461bcd60e51b815260040180806020018281038252602e815260200180614963602e913960400191505060405180910390fd5b6002548111611d6b5760405162461bcd60e51b815260040180806020018281038252602e815260200180614991602e913960400191505060405180910390fd5b6402540be400810615611daf5760405162461bcd60e51b815260040180806020018281038252602c815260200180614909602c913960400191505060405180910390fd5b600155612259565b611e1b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c62534352656c6179657246656560981b60208201529150613b889050565b15611f7d5760208114611e75576040805162461bcd60e51b815260206004820181905260248201527f6c656e677468206f662062534352656c61796572466565206d69736d61746368604482015290519081900360640190fd5b604080516020601f8401819004810282018101909252828152600091611eb391858580838501838280828437600092019190915250613c6f92505050565b905080611ef15760405162461bcd60e51b8152600401808060200182810382526022815260200180614a136022913960400191505060405180910390fd5b6001548110611f315760405162461bcd60e51b815260040180806020018281038252602e815260200180614889602e913960400191505060405180910390fd5b6402540be400810615611f755760405162461bcd60e51b815260040180806020018281038252602f81526020018061485a602f913960400191505060405180910390fd5b600255612259565b611fe184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c36b4b72232b632b3b0ba34b7b760991b60208201529150613b889050565b156120c3576020811461203b576040805162461bcd60e51b815260206004820181905260248201527f6c656e677468206f66206d696e44656c65676174696f6e206d69736d61746368604482015290519081900360640190fd5b604080516020601f840181900481028201810190925282815260009161207991858580838501838280828437600092019190915250613c6f92505050565b905060015481116120bb5760405162461bcd60e51b81526004018080602001828103825260318152602001806148b76031913960400191505060405180910390fd5b600355612259565b61212584848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600b81526a7472616e7366657247617360a81b60208201529150613b889050565b1561221c576020811461217f576040805162461bcd60e51b815260206004820152601e60248201527f6c656e677468206f66207472616e73666572476173206d69736d617463680000604482015290519081900360640190fd5b604080516020601f84018190048102820181019092528281526000916121bd91858580838501838280828437600092019190915250613c6f92505050565b905060008111612214576040805162461bcd60e51b815260206004820152601e60248201527f746865207472616e736665724761732063616e6e6f74206265207a65726f0000604482015290519081900360640190fd5b601155612259565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b600481565b60105460009060ff166002141561233f576040805162461bcd60e51b815260206004820152600e60248201526d4e6f2072652d656e7472616e637960901b604482015290519081900360640190fd5b506010805460ff1916600217905533600090815260066020526040902054806123a3576040805162461bcd60e51b81526020600482015260116024820152701b9bc81c195b991a5b99c81c995dd85c99607a1b604482015290519081900360640190fd5b336000818152600660205260408082208290556011549051919291849084818181858888f193505050503d80600081146123f9576040519150601f19603f3d011682016040523d82523d6000602084013e6123fe565b606091505b5050905080612446576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b60408051838152905133917f83b78188b13346b2ffb484da70d42ee27de7fbf9f2bd8045269e10ed643ccd76919081900360200190a2506010805460ff1916600117905590565b6638d7ea4c68000081565b6001600160a01b038083166000908152600760209081526040808320938516835292905220545b92915050565b60015490565b61100281565b33612000146125115760405162461bcd60e51b815260040180806020018281038252602f8152602001806149e4602f913960400191505060405180910390fd5b60005460ff16612554576638d7ea4c6800006001908155662386f26fc1000060025568056bc75e2d631000006003556108fc6011556000805460ff191690911790555b61259382828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061314b92505050565b6125d6576040805162461bcd60e51b815260206004820152600f60248201526e0eee4dedcce40e0c2c6d640d0c2e6d608b1b604482015290519081900360640190fd5b6125de61481f565b612620610ed684848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061278492505050565b90506000612630610eeb836127f3565b905061263a61481f565b612643836130ba565b156126615761265a610ed6611a8f61199a866127f3565b90506126a7565b6040805162461bcd60e51b8152602060048201526016602482015275656d707479206661696c2061636b207061636b61676560501b604482015290519081900360640190fd5b60ff8216600114156126c1576126bc81613c74565b6126eb565b60ff8216600214156126d6576126bc81613e8e565b60ff821660031415610f2a576126bc81613fb8565b5050505b505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205490565b61100381565b61200481565b68056bc75e2d6310000081565b601181565b6001600160a01b0392831660009081526009602090815260408083209486168352938152838220929094168152925290205490565b61100081565b60115481565b61100481565b61278c61483f565b506040805180820190915281518152602082810190820152919050565b6127b161481f565b6127ba8261411d565b6127c357600080fd5b60006127d28360200151614157565b60208085015160408051808201909152868152920190820152915050919050565b6127fb61483f565b612804826130ba565b61280d57600080fd5b6020820151600061281d826141ba565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061285657508151602110155b61285f57600080fd5b600061286e8360200151614157565b905080836000015110156128c9576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b8251602080850151830180519284900392918310156128ef57826020036101000a820491505b50949350505050565b600060606000806000805b61290c876130ba565b1561295e578261292e57612927612922886127f3565b6142ed565b9150612953565b826001141561294e57612943610eeb886127f3565b905060019350612953565b61295e565b826001019250612903565b836129a4576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b60006110046001600160a01b031663727be1f8836040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156129ee57600080fd5b505af1158015612a02573d6000803e3d6000fd5b505050506040513d6020811015612a1857600080fd5b5051905080612a3d57612a2f600484846065614307565b965096505050505050612ad3565b6001600160a01b038316600090815260066020526040902054612a66908363ffffffff61306016565b6001600160a01b038416600081815260066020908152604091829020939093558051858152905191927f7cc266c7b444f808013fa187f7b904d470a051a6564e78f482aa496581ba4bf892918290030190a260408051600080825260208201909252909750955050505050505b915091565b600060606000806000806000805b612aef896130ba565b15612b795784612b0c57612b056129228a6127f3565b9350612b6e565b8460011415612b2857612b216129228a6127f3565b9250612b6e565b8460021415612b4857612b3d610eeb8a6127f3565b915060019550612b6e565b8460031415612b6957612b62612b5d8a6127f3565b614403565b9050612b6e565b612b79565b846001019450612ae6565b85612bbf576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b60006110046001600160a01b031663727be1f8846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015612c0957600080fd5b505af1158015612c1d573d6000803e3d6000fd5b505050506040513d6020811015612c3357600080fd5b5051905080612c5a57612c4a600586856065614307565b9850985050505050505050612ad3565b6001600160a01b038086166000818152600760209081526040808320948916835293815283822082905591815260089091522054612c9e908463ffffffff61306016565b6001600160a01b0386166000908152600860205260409020558115612d8c576001600160a01b038516600090815260046020526040902054612ce6908463ffffffff612ed816565b6001600160a01b03808716600090815260046020908152604080832094909455600581528382209288168252919091522054612d28908463ffffffff612ed816565b6001600160a01b038087166000818152600560209081526040808320948a16808452948252918290209490945580518781529051929391927fd6f878a5bcbbe79a64e6418bb0d56aaa20b9a60587d45749819df88dfc7c3c44929181900390910190a35b836001600160a01b0316856001600160a01b03167f35a799836f74fac7eccf5c73902823b970543d2274d3b93d8da3d37a255772a2856040518082815260200191505060405180910390a360408051600080825260208201909252909950975050505050505050915091565b60008184841115612e875760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e4c578181015183820152602001612e34565b50505050905090810190601f168015612e795780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000612ed183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614447565b9392505050565b6000612ed183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612df8565b60408051600560a21b8318601482015260348101909152606090612ed1816144ac565b60606124bf612f4b83614502565b6144ac565b6060815160001415612f715750604080516000815260208101909152610df1565b606082600081518110612f8057fe5b602002602001015190506000600190505b8351811015612fc157612fb782858381518110612faa57fe5b60200260200101516145e8565b9150600101612f91565b50612ed1612fd4825160c060ff16614665565b826145e8565b6040805160028082526060828101909352829190816020015b6060815260200190600190039081612ff35790505090506130168460ff16612f3d565b8160008151811061302357fe5b6020026020010181905250613037836144ac565b8160018151811061304457fe5b602002602001018190525061305881612f50565b949350505050565b600082820183811015612ed1576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006130c461483f565b505080518051602091820151919092015191011190565b80516060906130e957600080fd5b60006130f88360200151614157565b83516040805191839003808352601f19601f820116830160200190915291925060609082801561312f576020820181803683370190505b50905060008160200190506128ef84876020015101828561475d565b8051602080830191909120600e546000908152600a909252604082205480821461317a57600092505050610df1565b5050600e80546000908152600a60205260408120558054600190810190915592915050565b60008060008060005b6131b1886130ba565b1561321a57836131ce576131c7612922896127f3565b925061320f565b83600114156131ea576131e3612922896127f3565b915061320f565b836002141561320a576131ff610eeb896127f3565b90506001945061320f565b61321a565b8360010193506131a8565b84613260576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6000613277826402540be40063ffffffff6147a816565b6001600160a01b0385166000908152600b602052604090208054600019019055905060ff8816600114156133bd5760ff8716156132ea576040805162461bcd60e51b815260206004820152600c60248201526b77726f6e672073746174757360a01b604482015290519081900360640190fd5b6001600160a01b038416600090815260046020526040902054613313908263ffffffff61306016565b6001600160a01b03808616600090815260046020908152604080832094909455600581528382209287168252919091522054613355908263ffffffff61306016565b6001600160a01b038086166000818152600560209081526040808320948916808452948252918290209490945580518581529051929391927f9a57c81564ab02642f34fd87e41baa9b074c18342cec3b7268b62bf752018fd1929181900390910190a361354b565b60ff881661350f576001600160a01b0384166000908152600860205260409020546133ee908263ffffffff61306016565b6001600160a01b0385166000908152600860209081526040808320939093558251630e4f7c3f60e31b81526004810185905292516110049363727be1f89360248083019493928390030190829087803b15801561344a57600080fd5b505af115801561345e573d6000803e3d6000fd5b505050506040513d602081101561347457600080fd5b50516134bd576040805162461bcd60e51b81526020600482015260136024820152721dda5d1a191c985dc8189b988819985a5b1959606a1b604482015290519081900360640190fd5b6040805182815260ff8916602082015281516001600160a01b0380871693908816927fcbd481ae600289fad8c0484d07ce0ffe4f010d7c844ecfdeaf2a13fead52886e929081900390910190a361354b565b6040805162461bcd60e51b815260206004820152600c60248201526b77726f6e672073746174757360a01b604482015290519081900360640190fd5b505050505050505050565b60008060008060005b613568886130ba565b156135d157836135855761357e612922896127f3565b92506135c6565b83600114156135a15761359a612922896127f3565b91506135c6565b83600214156135c1576135b6610eeb896127f3565b9050600194506135c6565b6135d1565b83600101935061355f565b84613617576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b600061362e826402540be40063ffffffff6147a816565b6001600160a01b0385166000908152600c602052604090208054600019019055905060ff8816600114156137ad5760ff8716156136a1576040805162461bcd60e51b815260206004820152600c60248201526b77726f6e672073746174757360a01b604482015290519081900360640190fd5b6001600160a01b0384166000908152600460205260409020546136ca908263ffffffff612ed816565b6001600160a01b0380861660009081526004602090815260408083209490945560058152838220928716825291909152205461370c908263ffffffff612ed816565b6001600160a01b0380861660009081526005602090815260408083209388168352929052205561374542620a8c0063ffffffff61306016565b6001600160a01b038086166000818152600760209081526040808320948916808452948252918290209490945580518581529051929391927fd6f878a5bcbbe79a64e6418bb0d56aaa20b9a60587d45749819df88dfc7c3c44929181900390910190a361354b565b60ff881661350f576001600160a01b03808516600081815260076020908152604080832094881680845294825280832092909255815185815260ff8c169181019190915281517f4417d10c1e33efa83a770b8d4f47176e78c08c1298d534901ad3b16bb585fa2e929181900390910190a361354b565b6000806000806000805b613836896130ba565b156138bb57846138535761384c6129228a6127f3565b93506138b0565b846001141561386f576138686129228a6127f3565b92506138b0565b846002141561388b576138846129228a6127f3565b91506138b0565b84600314156138ab576138a0610eeb8a6127f3565b9050600195506138b0565b6138bb565b84600101945061382d565b85613901576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6000613918826402540be40063ffffffff6147a816565b6001600160a01b0386166000908152600d602052604090208054600019019055905060ff891660011415613aeb5760ff88161561398b576040805162461bcd60e51b815260206004820152600c60248201526b77726f6e672073746174757360a01b604482015290519081900360640190fd5b6001600160a01b038086166000908152600560209081526040808320938816835292905220546139c1908263ffffffff612ed816565b6001600160a01b038681166000908152600560209081526040808320898516845290915280822093909355908516815220546139fd9082613060565b6001600160a01b03808716600090815260056020908152604080832093881683529290522055613a3642620a8c0063ffffffff61306016565b6001600160a01b0380871660009081526009602090815260408083208985168452825280832093881683529290522055613a7942620a8c0063ffffffff61306016565b6001600160a01b038087166000818152600960209081526040808320898616808552908352818420958b1680855295835292819020959095558451868152945191947f78bffae3f8c6691ac7fc1a3bff800cb2d612f5ad9ae5b0444cfe2eb15c189e18929081900390910190a4613b7c565b60ff891661350f576001600160a01b038581166000818152600960209081526040808320898616808552818452828520968a16808652968452828520859055908352818420818552835281842093909355805186815260ff8e169281019290925280519293927fb93bee5c59f85ede6b074a99f4ffcd3e3fc0d5c3d8156de331de89a49e0ce77c9281900390910190a45b50505050505050505050565b6000816040516020018082805190602001908083835b60208310613bbd5780518252601f199092019160209182019101613b9e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310613c2b5780518252601f199092019160209182019101613c0c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b60008060008060005b613c86866130ba565b15613cef5783613ca357613c9c612922876127f3565b9250613ce4565b8360011415613cbf57613cb8612922876127f3565b9150613ce4565b8360021415613cdf57613cd4610eeb876127f3565b905060019450613ce4565b613cef565b836001019350613c7d565b84613d35576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6000613d4c826402540be40063ffffffff6147a816565b6001600160a01b0385166000908152600b6020908152604080832080546000190190556008909152902054909150613d8a908263ffffffff61306016565b6001600160a01b0385166000908152600860209081526040808320939093558251630e4f7c3f60e31b81526004810185905292516110049363727be1f89360248083019493928390030190829087803b158015613de657600080fd5b505af1158015613dfa573d6000803e3d6000fd5b505050506040513d6020811015613e1057600080fd5b5051613e59576040805162461bcd60e51b81526020600482015260136024820152721dda5d1a191c985dc8189b988819985a5b1959606a1b604482015290519081900360640190fd5b6040516001907ff83de021914a4585482db5ca47d520a5657165b443fa2c7ef8ed4635f054da9b90600090a250505050505050565b60008060008060005b613ea0866130ba565b15613f095783613ebd57613eb6612922876127f3565b9250613efe565b8360011415613ed957613ed2612922876127f3565b9150613efe565b8360021415613ef957613eee610eeb876127f3565b905060019450613efe565b613f09565b836001019350613e97565b84613f4f576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600c60209081526040808320805460001901905560078252808320938616835292905281812081905590516002917ff83de021914a4585482db5ca47d520a5657165b443fa2c7ef8ed4635f054da9b91a2505050505050565b6000806000806000805b613fcb876130ba565b156140505784613fe857613fe1612922886127f3565b9350614045565b846001141561400457613ffd612922886127f3565b9250614045565b846002141561402057614019612922886127f3565b9150614045565b846003141561404057614035610eeb886127f3565b905060019550614045565b614050565b846001019450613fc2565b85614096576040805162461bcd60e51b81526020600482015260116024820152701c9b1c08191958dbd9194819985a5b1959607a1b604482015290519081900360640190fd5b6001600160a01b038481166000908152600d602090815260408083208054600019019055600982528083208785168085528184528285209588168552948352818420849055825280832093835292905281812081905590516003917ff83de021914a4585482db5ca47d520a5657165b443fa2c7ef8ed4635f054da9b91a250505050505050565b805160009061412e57506000610df1565b6020820151805160001a9060c082101561414d57600092505050610df1565b5060019392505050565b8051600090811a6080811015614171576000915050610df1565b60b881108061418c575060c0811080159061418c575060f881105b1561419b576001915050610df1565b60c08110156141af5760b519019050610df1565b60f519019050610df1565b80516000908190811a60808110156141d557600191506142e6565b60b88110156141ea57607e19810191506142e6565b60c081101561426457600060b78203600186019550806020036101000a86510491506001810182019350508083101561425e576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b506142e6565b60f88110156142795760be19810191506142e6565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156142e4576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b80516000906015146142fe57600080fd5b6124bf82612841565b60006060614320846402540be40063ffffffff612e8f16565b60408051600480825260a0820190925291955060609190816020015b606081526020019060019003908161433c57905050905061435f8760ff16612f3d565b8160008151811061436c57fe5b6020026020010181905250614389866001600160a01b0316612f1a565b8160018151811061439657fe5b60200260200101819052506143aa85612f3d565b816002815181106143b757fe5b60200260200101819052506143d18463ffffffff16612f3d565b816003815181106143de57fe5b602002602001018190525060606143f482612f50565b94989497509395505050505050565b805160009060011461441457600080fd5b6020820151805160001a9081158061442c5750608082145b1561443c57600092505050610df1565b600192505050610df1565b600081836144965760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612e4c578181015183820152602001612e34565b5060008385816144a257fe5b0495945050505050565b6060815160011480156144de5750607f60f81b826000815181106144cc57fe5b01602001516001600160f81b03191611155b156144ea575080610df1565b6124bf6144fc8351608060ff16614665565b836145e8565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166145465750601861456a565b6fffffffffffffffffffffffffffffffff1984166145665750601061456a565b5060005b60208110156145a05781818151811061457f57fe5b01602001516001600160f81b03191615614598576145a0565b60010161456a565b60008160200390506060816040519080825280601f01601f1916602001820160405280156145d5576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b81831015614619578051835260209283019201614601565b50855184518101855292509050808201602086015b8183101561464657805183526020928301920161462e565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106146b5576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b6040805160018082528183019092526060916020820181803683370190505090506037841161470f5782840160f81b816000815181106146f157fe5b60200101906001600160f81b031916908160001a90535090506124bf565b606061471a85614502565b90508381510160370160f81b8260008151811061473357fe5b60200101906001600160f81b031916908160001a90535061475482826145e8565b95945050505050565b80614767576126ef565b5b60208110614787578251825260209283019290910190601f1901614768565b915181516020939093036101000a6000190180199091169216919091179052565b6000826147b7575060006124bf565b828202828482816147c457fe5b0414612ed15760405162461bcd60e51b81526004018080602001828103825260218152602001806148e86021913960400191505060405180910390fd5b60405180606001604052806003906020820280368337509192915050565b604051806040016040528061483261483f565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe7468652042534352656c61796572466565206d6f642074656e20646563696d616c73206d757374206265207a65726f7468652042534352656c61796572466565206d757374206265206c657373207468616e2072656c61796572466565746865206d696e44656c65676174696f6e206d7573742062652067726561746572207468616e2072656c61796572466565536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f777468652072656c61796572466565206d6f642074656e20646563696d616c73206d757374206265207a65726f746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163747468652072656c61796572466565206d757374206265206c657373207468616e206d696e44656c65676174696f6e7468652072656c61796572466565206d757374206265206d6f7265207468616e2042534352656c61796572466565696e73756666696369656e742062616c616e636520616674657220756e64656c6567617465746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e74726163747468652042534352656c61796572466565206d757374206e6f74206265207a65726fa164736f6c6343000604000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(StakeHubContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405260043610620003db5760003560e01c806386d545061162000203578063d115a2061162000117578063e992aaf511620000ad578063f80a34021162000078578063f80a34021462000bed578063fb50b31f1462000c12578063fc0c5ff11462000c37578063ff69ab611462000c4f57600080fd5b8063e992aaf51462000b6a578063efdbf0e11462000b82578063f1f74d841462000bbe578063f1fad1041462000bd657600080fd5b8063d8ca511f11620000ee578063d8ca511f1462000afd578063daacdb661462000b15578063dbda7fb31462000b2d578063e8f67c3b1462000b5257600080fd5b8063d115a2061462000a9b578063d6ca429d1462000ab3578063d7c2dfc81462000ad857600080fd5b8063b187bd261162000199578063c38fbec81162000164578063c38fbec81462000a1d578063c473318f1462000a42578063c8509d81146200083b578063cbb04d9d1462000a5a57600080fd5b8063b187bd26146200098a578063baa7199e14620009aa578063bdceadf314620009cf578063bff02e2014620009e757600080fd5b8063982ef0a711620001da578063982ef0a714620008f5578063a43569b3146200090c578063aad3ec961462000940578063ac431751146200096557600080fd5b806386d5450614620008785780638a4d3fa814620008b25780638cd22b2214620008d057600080fd5b80634bf6c88211620002fb578063663706d3116200029157806376e7d6d6116200025c57806376e7d6d6146200080b5780638129fc1c1462000823578063831d65d1146200083b5780638456cb59146200086057600080fd5b8063663706d314620007385780636ec01b2714620007695780636f8e2fa414620007c157806375cc7d8914620007e657600080fd5b80635949187111620002d25780635949187114620006a05780635e7cc1c914620006c557806363a036b514620006ea57806364028fbd146200072157600080fd5b80634bf6c88214620006395780634d99dd1614620006635780634e6fd6c4146200068857600080fd5b80631fa8882b1162000371578063449ecfe61162000348578063449ecfe6146200058557806345211bfd14620005aa5780634838d16514620005cf5780634a49ac4c146200061457600080fd5b80631fa8882b1462000531578063384099881462000548578063417c73a7146200056057600080fd5b8063092193ab11620003b2578063092193ab146200047c5780630e9fbf5114620004935780631182b87514620004b857806317b4f35314620004ec57600080fd5b8063046f7da214620003fb578063059ddd2214620004135780630661806e146200045557600080fd5b36620003f65760345460ff16600114620003f457600080fd5b005b600080fd5b3480156200040857600080fd5b50620003f462000c67565b3480156200042057600080fd5b506200043862000432366004620093cc565b62000cf9565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156200046257600080fd5b506200046d60365481565b6040519081526020016200044c565b620003f46200048d366004620093cc565b6200110e565b348015620004a057600080fd5b50620003f4620004b236600462009430565b6200174c565b348015620004c557600080fd5b50620004dd620004d736600462009475565b62001a74565b6040516200044c919062009528565b348015620004f957600080fd5b50620004386200050b3660046200961e565b80516020818301810180516045825292820191909301209152546001600160a01b031681565b3480156200053e57600080fd5b506200046d603c81565b3480156200055557600080fd5b506200046d60375481565b3480156200056d57600080fd5b50620003f46200057f366004620093cc565b62001d4d565b3480156200059257600080fd5b50620003f4620005a4366004620093cc565b62001dcf565b348015620005b757600080fd5b50620003f4620005c9366004620093cc565b62001fb4565b348015620005dc57600080fd5b5062000603620005ee366004620093cc565b60016020526000908152604090205460ff1681565b60405190151581526020016200044c565b3480156200062157600080fd5b50620003f462000633366004620093cc565b6200218f565b3480156200064657600080fd5b5062000650600881565b60405160ff90911681526020016200044c565b3480156200067057600080fd5b50620003f46200068236600462009673565b6200220b565b3480156200069557600080fd5b506200043861dead81565b348015620006ad57600080fd5b50620003f4620006bf366004620096b1565b62002828565b348015620006d257600080fd5b50620003f4620006e436600462009721565b620035fa565b348015620006f757600080fd5b506200070f6200070936600462009741565b62003800565b6040516200044c9493929190620097aa565b620003f46200073236600462009866565b62003e92565b3480156200074557600080fd5b506200046d62000757366004620093cc565b60446020526000908152604090205481565b3480156200077657600080fd5b506200078e62000788366004620093cc565b620044dc565b6040805182516001600160401b03908116825260208085015182169083015292820151909216908201526060016200044c565b348015620007ce57600080fd5b50620004dd620007e0366004620093cc565b62004586565b348015620007f357600080fd5b50620003f462000805366004620093cc565b6200499f565b3480156200081857600080fd5b506200046d603d5481565b3480156200083057600080fd5b50620003f462004b71565b3480156200084857600080fd5b50620003f46200085a36600462009475565b62004e83565b3480156200086d57600080fd5b50620003f462004eed565b3480156200088557600080fd5b506200043862000897366004620093cc565b6043602052600090815260409020546001600160a01b031681565b348015620008bf57600080fd5b506200046d670de0b6b3a764000081565b348015620008dd57600080fd5b506200046d620008ef36600462009673565b62004f85565b620003f4620009063660046200993e565b6200503e565b3480156200091957600080fd5b50620009316200092b366004620093cc565b620056c8565b6040516200044c91906200997c565b3480156200094d57600080fd5b50620003f46200095f36600462009673565b620059b5565b3480156200097257600080fd5b50620003f462000984366004620099f9565b62005a22565b3480156200099757600080fd5b5060005462010000900460ff1662000603565b348015620009b757600080fd5b50620003f4620009c936600462009ab2565b620068c1565b348015620009dc57600080fd5b506200046d603c5481565b348015620009f457600080fd5b5062000a0c62000a0636600462009741565b62006a8e565b6040516200044c9392919062009b0e565b34801562000a2a57600080fd5b50620003f462000a3c366004620093cc565b62006c6a565b34801562000a4f57600080fd5b506200046d60385481565b34801562000a6757600080fd5b5062000a7f62000a79366004620093cc565b62006f28565b604080519384529115156020840152908201526060016200044c565b34801562000aa857600080fd5b506200046d61271081565b34801562000ac057600080fd5b50620003f462000ad236600462009b6b565b62007358565b34801562000ae557600080fd5b50620003f462000af736600462009c54565b6200755a565b34801562000b0a57600080fd5b506200046d603b5481565b34801562000b2257600080fd5b506200046d60495481565b34801562000b3a57600080fd5b506200043862000b4c366004620093cc565b62007650565b34801562000b5f57600080fd5b506200046d60355481565b34801562000b7757600080fd5b506200046d603a5481565b34801562000b8f57600080fd5b506200046d62000ba13660046200961e565b805160208183018101805160468252928201919093012091525481565b34801562000bcb57600080fd5b506200046d603e5481565b34801562000be357600080fd5b5062000650601181565b34801562000bfa57600080fd5b506200046d62000c0c36600462009673565b62007a67565b34801562000c1f57600080fd5b50620003f462000c31366004620099f9565b62007ad8565b34801562000c4457600080fd5b506200046d60395481565b34801562000c5c57600080fd5b506200046d604a5481565b600054630100000090046001600160a01b0316331462000c9a576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1662000cc457604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b6001600160a01b038082166000908152604160209081526040808320815161016081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162000d649062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462000d929062009cba565b801562000de35780601f1062000db75761010080835404028352916020019162000de3565b820191906000526020600020905b81548152906001019060200180831162000dc557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462000e0e9062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462000e3c9062009cba565b801562000e8d5780601f1062000e615761010080835404028352916020019162000e8d565b820191906000526020600020905b81548152906001019060200180831162000e6f57829003601f168201915b5050505050815260200160018201805462000ea89062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462000ed69062009cba565b801562000f275780601f1062000efb5761010080835404028352916020019162000f27565b820191906000526020600020905b81548152906001019060200180831162000f0957829003601f168201915b5050505050815260200160028201805462000f429062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462000f709062009cba565b801562000fc15780601f1062000f955761010080835404028352916020019162000fc1565b820191906000526020600020905b81548152906001019060200180831162000fa357829003601f168201915b5050505050815260200160038201805462000fdc9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200100a9062009cba565b80156200105b5780601f106200102f576101008083540402835291602001916200105b565b820191906000526020600020905b8154815290600101906020018083116200103d57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620010e7575050509190925250509051949350505050565b33611000146200113a57604051630f22c43960e41b815261100060048201526024015b60405180910390fd5b6001600160a01b03808216600090815260436020908152604080832054841680845260418352818420825161016081018452815487168152600182015487169481019490945260028101549095169183019190915260038401546060830152600484018054919491608084019190620011b39062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620011e19062009cba565b8015620012325780601f10620012065761010080835404028352916020019162001232565b820191906000526020600020905b8154815290600101906020018083116200121457829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200125d9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200128b9062009cba565b8015620012dc5780601f10620012b057610100808354040283529160200191620012dc565b820191906000526020600020905b815481529060010190602001808311620012be57829003601f168201915b50505050508152602001600182018054620012f79062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620013259062009cba565b8015620013765780601f106200134a5761010080835404028352916020019162001376565b820191906000526020600020905b8154815290600101906020018083116200135857829003601f168201915b50505050508152602001600282018054620013919062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620013bf9062009cba565b8015620014105780601f10620013e45761010080835404028352916020019162001410565b820191906000526020600020905b815481529060010190602001808311620013f257829003601f168201915b505050505081526020016003820180546200142b9062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620014599062009cba565b8015620014aa5780601f106200147e57610100808354040283529160200191620014aa565b820191906000526020600020905b8154815290600101906020018083116200148c57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b81548152602001906001019080831162001536575050509190925250505060408101519091506001600160a01b031615806200157357508060e001515b156200163057604051611002903490600081818185875af1925050503d8060008114620015bd576040519150601f19603f3d011682016040523d82523d6000602084013e620015c2565b606091505b505050816001600160a01b03167ffc8bff675087dd2da069cc3fb517b9ed001e19750c0865241a5542dba1ba170d604051620016239060208082526011908201527024a72b20a624a22fab20a624a220aa27a960791b604082015260600190565b60405180910390a2505050565b60408181015160c0830151519151632f303ebb60e11b81526001600160401b0390921660048301526001600160a01b031690635e607d769034906024016000604051808303818588803b1580156200168757600080fd5b505af11580156200169c573d6000803e3d6000fd5b5050505050816001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea634604051620016dd91815260200190565b60405180910390a26040808201519051633041949b60e01b815261200591633041949b91620017129190869060040162009cf0565b600060405180830381600087803b1580156200172d57600080fd5b505af115801562001742573d6000803e3d6000fd5b5050505050505b50565b33611001146200177457604051630f22c43960e41b8152611001600482015260240162001131565b60005462010000900460ff16156200179f57604051631785c68160e01b815260040160405180910390fd5b600060458383604051620017b592919062009d0a565b908152604051908190036020019020546001600160a01b03169050620017dd603f8262007d2a565b620017fb5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062001821603c4262009d30565b604a546000828152604b602052604090205491925011620018555760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b602052604081208054600192906200187690849062009d53565b909155505060405160469062001890908790879062009d0a565b908152602001604051809103902054600014158015620018df575042603c60468787604051620018c292919062009d0a565b908152602001604051809103902054620018dd919062009d53565b105b15620018fe57604051631898eb6b60e01b815260040160405180910390fd5b6000806200190e85600262007d4d565b91509150816200193157604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562001984573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019aa919062009d69565b9050620019b8858362007dd7565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb283836002604051620019f89392919062009d99565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162001a36916001600160a01b0316908a9060040162009cf0565b600060405180830381600087803b15801562001a5157600080fd5b505af115801562001a66573d6000803e3d6000fd5b505050505050505050505050565b6060336120001462001a9e57604051630f22c43960e41b8152612000600482015260240162001131565b6034805460ff19166001179055604080516020601f8501819004810282018101909252838152600091829162001aef91879087908190840183828082843760009201919091525062007f9e92505050565b915091508062001b125760405163035ede3560e21b815260040160405180910390fd5b816060015160000362001b38575050604080516000815260208101909152905062001d3c565b606082015160405163e04c83a760e01b81526000916110049163e04c83a79162001b689160040190815260200190565b6020604051808303816000875af115801562001b88573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001bae919062009dc8565b90508062001c555782602001516001600160a01b031683600001516001600160a01b03167fa9084c89a291b43bc984e045671d394974730a159b9a826b577bb148ab504c3a8560600151600160405162001c0a92919062009de8565b60405180910390a385858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092965062001d3c95505050505050565b600062001c628462008101565b9050600081600381111562001c7b5762001c7b62009d83565b0362001c9d575050604080516000815260208101909152925062001d3c915050565b83602001516001600160a01b031684600001516001600160a01b03167fa9084c89a291b43bc984e045671d394974730a159b9a826b577bb148ab504c3a86606001518460405162001cf092919062009de8565b60405180910390a386868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092975062001d3c9650505050505050565b6034805460ff191690559392505050565b600054630100000090046001600160a01b0316331462001d80576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60005462010000900460ff161562001dfa57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562001e2c5760405163b1d02c3d60e01b815260040160405180910390fd5b8062001e3a603f8262007d2a565b62001e585760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166000908152604160205260409020600a81015460ff1662001e9657604051634b6b857d60e01b815260040160405180910390fd5b6036546002820154604051630913db4760e01b81526001600160a01b03868116600483015290911690630913db4790602401602060405180830381865afa15801562001ee6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f0c919062009d69565b101562001f2c576040516317b204bf60e11b815260040160405180910390fd5b4281600b0154111562001f525760405163170cb76760e21b815260040160405180910390fd5b600a8101805460ff19169055604980546001919060009062001f7690849062009e0f565b90915550506040516001600160a01b038416907f9390b453426557da5ebdc31f19a37753ca04addf656d32f35232211bb2af3f1990600090a2505050565b60005462010000900460ff161562001fdf57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620020115760405163b1d02c3d60e01b815260040160405180910390fd5b336200201f603f8262007d2a565b6200203d5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166200206557604051636520611b60e11b815260040160405180910390fd5b6001600160a01b0382811660009081526043602052604090205416151580620020a657506001600160a01b03821660009081526047602052604090205460ff165b15620020c557604051631e6f587560e11b815260040160405180910390fd5b336000818152604160205260409020600c8101544290620020e990603c9062009d53565b11156200210957604051631f92cdbd60e11b815260040160405180910390fd5b80546001600160a01b039081166000908152604460209081526040808320429081905585548986166001600160a01b031991821681178855600c88019290925581855260439093528184208054958816959093168517909255519092917f6e4e747ca35203f16401c69805c7dd52fff67ef60b0ebc5c7fe16890530f223591a350505050565b600054630100000090046001600160a01b03163314620021c2576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60005462010000900460ff16156200223657604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620022685760405163b1d02c3d60e01b815260040160405180910390fd5b8162002276603f8262007d2a565b620022945760405163056e881160e01b815260040160405180910390fd5b81600003620022b657604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b03808416600090815260416020908152604080832081516101608101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805433949160808401916200231e9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200234c9062009cba565b80156200239d5780601f1062002371576101008083540402835291602001916200239d565b820191906000526020600020905b8154815290600101906020018083116200237f57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620023c89062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620023f69062009cba565b8015620024475780601f106200241b5761010080835404028352916020019162002447565b820191906000526020600020905b8154815290600101906020018083116200242957829003601f168201915b50505050508152602001600182018054620024629062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620024909062009cba565b8015620024e15780601f10620024b557610100808354040283529160200191620024e1565b820191906000526020600020905b815481529060010190602001808311620024c357829003601f168201915b50505050508152602001600282018054620024fc9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200252a9062009cba565b80156200257b5780601f106200254f576101008083540402835291602001916200257b565b820191906000526020600020905b8154815290600101906020018083116200255d57829003601f168201915b50505050508152602001600382018054620025969062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620025c49062009cba565b8015620026155780601f10620025e95761010080835404028352916020019162002615565b820191906000526020600020905b815481529060010190602001808311620025f757829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620026a1575050509190925250505060408082015190516326ccee8b60e11b81526001600160a01b0385811660048301526024820188905292935060009290911690634d99dd16906044016020604051808303816000875af11580156200271b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002741919062009d69565b9050826001600160a01b0316866001600160a01b03167f3aace7340547de7b9156593a7652dc07ee900cea3fd8f82cb6c9d38b40829802878460405162002792929190918252602082015260400190565b60405180910390a3856001600160a01b0316836001600160a01b031603620027bf57620027bf8662008794565b6040808301519051633041949b60e01b815261200591633041949b91620027ec9190879060040162009cf0565b600060405180830381600087803b1580156200280757600080fd5b505af11580156200281c573d6000803e3d6000fd5b50505050505050505050565b60005462010000900460ff16156200285357604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620028855760405163b1d02c3d60e01b815260040160405180910390fd5b8362002893603f8262007d2a565b620028b15760405163056e881160e01b815260040160405180910390fd5b83620028bf603f8262007d2a565b620028dd5760405163056e881160e01b815260040160405180910390fd5b6034805460ff1916600117905560008490036200290d57604051639811e0c760e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031603620029405760405163f0e3e62960e01b815260040160405180910390fd5b6001600160a01b0380871660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180543394916080840191620029a89062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620029d69062009cba565b801562002a275780601f10620029fb5761010080835404028352916020019162002a27565b820191906000526020600020905b81548152906001019060200180831162002a0957829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002a529062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462002a809062009cba565b801562002ad15780601f1062002aa55761010080835404028352916020019162002ad1565b820191906000526020600020905b81548152906001019060200180831162002ab357829003601f168201915b5050505050815260200160018201805462002aec9062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462002b1a9062009cba565b801562002b6b5780601f1062002b3f5761010080835404028352916020019162002b6b565b820191906000526020600020905b81548152906001019060200180831162002b4d57829003601f168201915b5050505050815260200160028201805462002b869062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462002bb49062009cba565b801562002c055780601f1062002bd95761010080835404028352916020019162002c05565b820191906000526020600020905b81548152906001019060200180831162002be757829003601f168201915b5050505050815260200160038201805462002c209062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462002c4e9062009cba565b801562002c9f5780601f1062002c735761010080835404028352916020019162002c9f565b820191906000526020600020905b81548152906001019060200180831162002c8157829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b81548152602001906001019080831162002d2b57505050919092525050506001600160a01b0380891660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549495509193909291608084019162002db69062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462002de49062009cba565b801562002e355780601f1062002e095761010080835404028352916020019162002e35565b820191906000526020600020905b81548152906001019060200180831162002e1757829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002e609062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462002e8e9062009cba565b801562002edf5780601f1062002eb35761010080835404028352916020019162002edf565b820191906000526020600020905b81548152906001019060200180831162002ec157829003601f168201915b5050505050815260200160018201805462002efa9062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462002f289062009cba565b801562002f795780601f1062002f4d5761010080835404028352916020019162002f79565b820191906000526020600020905b81548152906001019060200180831162002f5b57829003601f168201915b5050505050815260200160028201805462002f949062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462002fc29062009cba565b8015620030135780601f1062002fe75761010080835404028352916020019162003013565b820191906000526020600020905b81548152906001019060200180831162002ff557829003601f168201915b505050505081526020016003820180546200302e9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200305c9062009cba565b8015620030ad5780601f106200308157610100808354040283529160200191620030ad565b820191906000526020600020905b8154815290600101906020018083116200308f57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620031395750505050508152505090508060e0015180156200317c5750876001600160a01b0316836001600160a01b031614155b156200319b57604051636468920360e01b815260040160405180910390fd5b60408083015190516352e82ce560e11b81526001600160a01b038581166004830152602482018a9052600092169063a5d059ca906044016020604051808303816000875af1158015620031f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003218919062009d69565b90506037548110156200323e5760405163dc6f0bdd60e01b815260040160405180910390fd5b896001600160a01b0316846001600160a01b0316148015620032d357506036546040808501519051630913db4760e01b81526001600160a01b038d8116600483015290911690630913db4790602401602060405180830381865afa158015620032ab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620032d1919062009d69565b105b15620032f2576040516317b204bf60e11b815260040160405180910390fd5b6000612710603a548362003307919062009e25565b62003313919062009d30565b9050600083604001516001600160a01b03168260405160006040518083038185875af1925050503d806000811462003368576040519150601f19603f3d011682016040523d82523d6000602084013e6200336d565b606091505b505090508062003390576040516312171d8360e31b815260040160405180910390fd5b6200339c828462009e0f565b60408086015190516317066a5760e21b81526001600160a01b03898116600483015292955060009290911690635c19a95c90869060240160206040518083038185885af1158015620033f2573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062003419919062009d69565b9050866001600160a01b03168c6001600160a01b03168e6001600160a01b03167ffdac6e81913996d95abcc289e90f2d8bd235487ce6fe6f821e7d21002a1915b48e85896040516200347e939291909283526020830191909152604082015260600190565b60405180910390a4604080516002808252606082018352600092602083019080368337019050509050866040015181600081518110620034c257620034c262009e3f565b60200260200101906001600160a01b031690816001600160a01b031681525050856040015181600181518110620034fd57620034fd62009e3f565b6001600160a01b0390921660209283029190910190910152604051634484077560e01b8152612005906344840775906200353e9084908c9060040162009e55565b600060405180830381600087803b1580156200355957600080fd5b505af11580156200356e573d6000803e3d6000fd5b505050508a15620035e0576120056001600160a01b031663e5ed5b1e898f6040518363ffffffff1660e01b8152600401620035ab92919062009cf0565b600060405180830381600087803b158015620035c657600080fd5b505af1158015620035db573d6000803e3d6000fd5b505050505b50506034805460ff19169055505050505050505050505050565b60005462010000900460ff16156200362557604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620036575760405163b1d02c3d60e01b815260040160405180910390fd5b3362003665603f8262007d2a565b620036835760405163056e881160e01b815260040160405180910390fd5b336000818152604160205260409020600c8101544290620036a790603c9062009d53565b1115620036c757604051631f92cdbd60e11b815260040160405180910390fd5b60098101546001600160401b03600160401b90910481169085161115620037015760405163dc81db8560e01b815260040160405180910390fd5b60098101546000906001600160401b0390811690861610156200373f576009820154620037399086906001600160401b031662009e81565b62003759565b600982015462003759906001600160401b03168662009e81565b60098301546001600160401b039182169250600160801b900416811115620037945760405163dc81db8560e01b815260040160405180910390fd5b60098201805467ffffffffffffffff19166001600160401b03871690811790915542600c8401556040519081526001600160a01b038416907f78cdd96edf59e09cfd4d26ef6ef6c92d166effe6a40970c54821206d541932cb9060200160405180910390a25050505050565b6060806060600062003813603f620088ba565b90508086101562003e895784156200382c57846200382e565b805b94506000856200383f888462009e0f565b11620038575762003851878362009e0f565b62003859565b855b9050806001600160401b038111156200387657620038766200953d565b604051908082528060200260200182016040528015620038a0578160200160208202803683370190505b509450806001600160401b03811115620038be57620038be6200953d565b604051908082528060200260200182016040528015620038e8578160200160208202803683370190505b509350806001600160401b038111156200390657620039066200953d565b6040519080825280602002602001820160405280156200393b57816020015b6060815260200190600190039081620039255790505b50925060005b8181101562003e86576000620039656200395c838b62009d53565b603f90620088c5565b6001600160a01b03808216600090815260416020908152604080832081516101608101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620039d29062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462003a009062009cba565b801562003a515780601f1062003a255761010080835404028352916020019162003a51565b820191906000526020600020905b81548152906001019060200180831162003a3357829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462003a7c9062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462003aaa9062009cba565b801562003afb5780601f1062003acf5761010080835404028352916020019162003afb565b820191906000526020600020905b81548152906001019060200180831162003add57829003601f168201915b5050505050815260200160018201805462003b169062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462003b449062009cba565b801562003b955780601f1062003b695761010080835404028352916020019162003b95565b820191906000526020600020905b81548152906001019060200180831162003b7757829003601f168201915b5050505050815260200160028201805462003bb09062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462003bde9062009cba565b801562003c2f5780601f1062003c035761010080835404028352916020019162003c2f565b820191906000526020600020905b81548152906001019060200180831162003c1157829003601f168201915b5050505050815260200160038201805462003c4a9062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462003c789062009cba565b801562003cc95780601f1062003c9d5761010080835404028352916020019162003cc9565b820191906000526020600020905b81548152906001019060200180831162003cab57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b81548152602001906001019080831162003d55575050505050815250509050806000015188848151811062003d8e5762003d8e62009e3f565b60200260200101906001600160a01b031690816001600160a01b0316815250508060e0015162003e275780604001516001600160a01b03166315d1f8986040518163ffffffff1660e01b8152600401602060405180830381865afa15801562003dfb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e21919062009d69565b62003e2a565b60005b87848151811062003e3f5762003e3f62009e3f565b602002602001018181525050806080015186848151811062003e655762003e6562009e3f565b602002602001018190525050508062003e7e9062009ea4565b905062003941565b50505b92959194509250565b60005462010000900460ff161562003ebd57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562003eef5760405163b1d02c3d60e01b815260040160405180910390fd5b3362003efd603f8262007d2a565b1562003f1c57604051635f28f62b60e01b815260040160405180910390fd5b6001600160a01b038881166000908152604360205260409020541615158062003f5d57506001600160a01b03881660009081526047602052604090205460ff165b1562003f7c57604051631e6f587560e11b815260040160405180910390fd5b60006001600160a01b03166045888860405162003f9b92919062009d0a565b908152604051908190036020019020546001600160a01b031614158062003fe557506048878760405162003fd192919062009d0a565b9081526040519081900360200190205460ff165b1562004004576040516311fdb94760e01b815260040160405180910390fd5b600062004012838062009ec0565b6040516020016200402592919062009d0a565b60408051601f1981840301815291815281516020928301206000818152604290935291205490915060ff16156200406f5760405163c0bf414360e01b815260040160405180910390fd5b600062004085670de0b6b3a76400003462009e0f565b9050603654811015620040ab576040516317b204bf60e11b815260040160405180910390fd5b6001600160a01b038a16620040d357604051636520611b60e11b815260040160405180910390fd5b611388620040e8604087016020880162009721565b6001600160401b031611806200412e57506200410b604086016020870162009721565b6001600160401b031662004123602087018762009721565b6001600160401b0316115b806200416d575062004147604086016020870162009721565b6001600160401b031662004162606087016040880162009721565b6001600160401b0316115b156200418c5760405163dc81db8560e01b815260040160405180910390fd5b620041d76200419c858062009ec0565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620088d392505050565b620041f557604051635dba5ad760e01b815260040160405180910390fd5b62004204838a8a8a8a62008a75565b6200422257604051631647e3cb60e11b815260040160405180910390fd5b6000620042708462004235878062009ec0565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062008ba592505050565b90506200427f603f8562008ca6565b506000838152604260209081526040808320805460ff191660019081179091556001600160a01b0380891680865260419094529190932080548f83166001600160a01b031991821617825593810180548516909317909255600282018054918516919093161790915542600382015560048101620042ff8b8d8362009f68565b5085600582016200431182826200a030565b50879050600982016200432582826200a169565b505042600c8201556001600160a01b038c81166000908152604360205260409081902080546001600160a01b0319169288169290921790915551859060459062004373908e908e9062009d0a565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316856001600160a01b03168d6001600160a01b03167faecd9fb95e79c75a3a1de93362c6be5fe6ab65770d8614be583884161cd8228d8e8e604051620043f69291906200a239565b60405180910390a460408051848152602081018590526001600160a01b0387169182916000805160206200b540833981519152910160405180910390a360408051670de0b6b3a7640000808252602082015261dead916001600160a01b038816916000805160206200b540833981519152910160405180910390a3604051633041949b60e01b815261200590633041949b906200449a908590899060040162009cf0565b600060405180830381600087803b158015620044b557600080fd5b505af1158015620044ca573d6000803e3d6000fd5b50505050505050505050505050505050565b60408051606081018252600080825260208201819052918101919091528162004507603f8262007d2a565b620045255760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03831660009081526041602090815260409182902082516060810184526009909101546001600160401b038082168352600160401b8204811693830193909352600160801b90049091169181019190915291505b50919050565b6001600160a01b03808216600090815260416020908152604080832081516101608101835281548616815260018201548616938101939093526002810154909416908201526003830154606082810191909152600484018054919491608084019190620045f39062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620046219062009cba565b8015620046725780601f10620046465761010080835404028352916020019162004672565b820191906000526020600020905b8154815290600101906020018083116200465457829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200469d9062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620046cb9062009cba565b80156200471c5780601f10620046f0576101008083540402835291602001916200471c565b820191906000526020600020905b815481529060010190602001808311620046fe57829003601f168201915b50505050508152602001600182018054620047379062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620047659062009cba565b8015620047b65780601f106200478a57610100808354040283529160200191620047b6565b820191906000526020600020905b8154815290600101906020018083116200479857829003601f168201915b50505050508152602001600282018054620047d19062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620047ff9062009cba565b8015620048505780601f10620048245761010080835404028352916020019162004850565b820191906000526020600020905b8154815290600101906020018083116200483257829003601f168201915b505050505081526020016003820180546200486b9062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620048999062009cba565b8015620048ea5780601f10620048be57610100808354040283529160200191620048ea565b820191906000526020600020905b815481529060010190602001808311620048cc57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620049765750505091909252505050608001519392505050565b3361100114620049c757604051630f22c43960e41b8152611001600482015260240162001131565b6001600160a01b0380821660009081526043602052604090205416620049ef603f8262007d2a565b62004a0d5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038181166000908152604160205260408082206002810154603b54925163045bc4d160e41b81526004810193909352909316906345bc4d10906024016020604051808303816000875af115801562004a70573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062004a96919062009d69565b90506000603d544262004aaa919062009d53565b905062004ab8838262007dd7565b836001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28284600160405162004af89392919062009d99565b60405180910390a26002830154604051633041949b60e01b815261200591633041949b9162004b36916001600160a01b031690889060040162009cf0565b600060405180830381600087803b15801562004b5157600080fd5b505af115801562004b66573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff161580801562004b925750600054600160ff909116105b8062004bae5750303b15801562004bae575060005460ff166001145b62004c135760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840162001131565b6000805460ff19166001179055801562004c37576000805461ff0019166101001790555b33411462004c585760405163022d8c9560e31b815260040160405180910390fd5b3a1562004c78576040516383f1b1d360e01b815260040160405180910390fd5b611388603555686c6b935b8bbd400000603655670de0b6b3a7640000603755602d603855607860398190556002603a819055678ac7230489e80000603b55680ad78ebc5ac6200000603c55603d9190915560b4603e55604a556040805160c0810190915260a080825260609182916200b560602083013980602001905181019062004d0491906200a275565b9150604051806101e001604052806101c081526020016200b6006101c0913980602001905181019062004d3891906200a319565b905060005b825181101562004da75760016047600085848151811062004d625762004d6262009e3f565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905562004d9f8162009ea4565b905062004d3d565b5060005b815181101562004e18576001604883838151811062004dce5762004dce62009e3f565b602002602001015160405162004de591906200a416565b908152604051908190036020019020805491151560ff1990921691909117905562004e108162009ea4565b905062004dab565b5062004e3873df87f0e2b8519ea2dd4abd8b639cdd628497ed2562008cbd565b5050801562001749576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b336120001462004eab57604051630f22c43960e41b8152612000600482015260240162001131565b7faa5ba621c8b3d7d05bb9e51a7506108251d4d5dbe542ca66fc7bb52aacb02b6583838360405162004ee0939291906200a434565b60405180910390a1505050565b600054630100000090046001600160a01b0316331462004f20576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff161562004f4b57604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b600062004f94603f8462007d2a565b62004fb25760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383811660009081526041602052604090819020600201549051636bbf224960e01b815260048101859052911690636bbf2249906024015b602060405180830381865afa1580156200500f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062005035919062009d69565b90505b92915050565b60005462010000900460ff16156200506957604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200509b5760405163b1d02c3d60e01b815260040160405180910390fd5b81620050a9603f8262007d2a565b620050c75760405163056e881160e01b815260040160405180910390fd5b6037543490811015620050ed5760405163dc6f0bdd60e01b815260040160405180910390fd5b6001600160a01b0380851660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180543394916080840191620051559062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620051839062009cba565b8015620051d45780601f10620051a857610100808354040283529160200191620051d4565b820191906000526020600020905b815481529060010190602001808311620051b657829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620051ff9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200522d9062009cba565b80156200527e5780601f1062005252576101008083540402835291602001916200527e565b820191906000526020600020905b8154815290600101906020018083116200526057829003601f168201915b50505050508152602001600182018054620052999062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620052c79062009cba565b8015620053185780601f10620052ec5761010080835404028352916020019162005318565b820191906000526020600020905b815481529060010190602001808311620052fa57829003601f168201915b50505050508152602001600282018054620053339062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620053619062009cba565b8015620053b25780601f106200538657610100808354040283529160200191620053b2565b820191906000526020600020905b8154815290600101906020018083116200539457829003601f168201915b50505050508152602001600382018054620053cd9062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620053fb9062009cba565b80156200544c5780601f1062005420576101008083540402835291602001916200544c565b820191906000526020600020905b8154815290600101906020018083116200542e57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620054d85750505050508152505090508060e0015180156200551b5750856001600160a01b0316826001600160a01b031614155b156200553a57604051636468920360e01b815260040160405180910390fd5b60408082015190516317066a5760e21b81526001600160a01b0384811660048301526000921690635c19a95c90869060240160206040518083038185885af11580156200558b573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190620055b2919062009d69565b9050826001600160a01b0316876001600160a01b03166000805160206200b5408339815191528387604051620055f2929190918252602082015260400190565b60405180910390a36040808301519051633041949b60e01b815261200591633041949b91620056279190879060040162009cf0565b600060405180830381600087803b1580156200564257600080fd5b505af115801562005657573d6000803e3d6000fd5b50505050851562001742576040516372f6ad8f60e11b81526120059063e5ed5b1e906200568b9086908b9060040162009cf0565b600060405180830381600087803b158015620056a657600080fd5b505af1158015620056bb573d6000803e3d6000fd5b5050505050505050505050565b620056f46040518060800160405280606081526020016060815260200160608152602001606081525090565b8162005702603f8262007d2a565b620057205760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03831660009081526041602052604090819020815160808101909252600501805482908290620057579062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620057859062009cba565b8015620057d65780601f10620057aa57610100808354040283529160200191620057d6565b820191906000526020600020905b815481529060010190602001808311620057b857829003601f168201915b50505050508152602001600182018054620057f19062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200581f9062009cba565b8015620058705780601f10620058445761010080835404028352916020019162005870565b820191906000526020600020905b8154815290600101906020018083116200585257829003601f168201915b505050505081526020016002820180546200588b9062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620058b99062009cba565b80156200590a5780601f10620058de576101008083540402835291602001916200590a565b820191906000526020600020905b815481529060010190602001808311620058ec57829003601f168201915b50505050508152602001600382018054620059259062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620059539062009cba565b8015620059a45780601f106200597857610100808354040283529160200191620059a4565b820191906000526020600020905b8154815290600101906020018083116200598657829003601f168201915b505050505081525050915050919050565b60005462010000900460ff1615620059e057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562005a125760405163b1d02c3d60e01b815260040160405180910390fd5b62005a1e828262008d56565b5050565b336110071462005a4a57604051630f22c43960e41b8152611007600482015260240162001131565b62005ab76040518060400160405280601081526020016f1d1c985b9cd9995c91d85cd31a5b5a5d60821b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b1562005b72576020811462005ae95783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f840181900481028201810190925282815260009162005b2c91858580838501838280828437600092019190915250929392505062008ebf9050565b90506108fc81108062005b40575061271081115b1562005b695784848484604051630a5a604160e01b81526004016200113194939291906200a453565b6035556200687c565b62005be36040518060400160405280601481526020017336b4b729b2b6332232b632b3b0ba34b7b721272160611b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b1562005cad576020811462005c155783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f840181900481028201810190925282815260009162005c5891858580838501838280828437600092019190915250929392505062008ebf9050565b9050683635c9adc5dea0000081108062005c7b575069152d02c7e14af680000081115b1562005ca45784848484604051630a5a604160e01b81526004016200113194939291906200a453565b6036556200687c565b62005d20604051806040016040528060168152602001756d696e44656c65676174696f6e424e424368616e676560501b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b1562005de7576020811462005d525783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f840181900481028201810190925282815260009162005d9591858580838501838280828437600092019190915250929392505062008ebf9050565b905067016345785d8a000081108062005db55750678ac7230489e8000081115b1562005dde5784848484604051630a5a604160e01b81526004016200113194939291906200a453565b6037556200687c565b62005e58604051806040016040528060148152602001736d6178456c656374656456616c696461746f727360601b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b1562005f10576020811462005e8a5783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f840181900481028201810190925282815260009162005ecd91858580838501838280828437600092019190915250929392505062008ebf9050565b905080158062005ede57506101f481115b1562005f075784848484604051630a5a604160e01b81526004016200113194939291906200a453565b6038556200687c565b62005f796040518060400160405280600c81526020016b1d5b989bdb9914195c9a5bd960a21b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b1562006036576020811462005fab5783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f840181900481028201810190925282815260009162005fee91858580838501838280828437600092019190915250929392505062008ebf9050565b90506203f48081108062006004575062278d0081115b156200602d5784848484604051630a5a604160e01b81526004016200113194939291906200a453565b6039556200687c565b620060a460405180604001604052806011815260200170726564656c65676174654665655261746560781b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b15620061515760208114620060d65783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f84018190048102820181019092528281526000916200611991858580838501838280828437600092019190915250929392505062008ebf9050565b90506064811115620061485784848484604051630a5a604160e01b81526004016200113194939291906200a453565b603a556200687c565b620061c160405180604001604052806013815260200172191bdddb9d1a5b5954db185cda105b5bdd5b9d606a1b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b15620062825760208114620061f35783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f84018190048102820181019092528281526000916200623691858580838501838280828437600092019190915250929392505062008ebf9050565b9050674563918244f40000811080620062505750603c5481115b15620062795784848484604051630a5a604160e01b81526004016200113194939291906200a453565b603b556200687c565b620062f06040518060400160405280601181526020017019995b1bdb9e54db185cda105b5bdd5b9d607a1b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b15620063b35760208114620063225783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f84018190048102820181019092528281526000916200636591858580838501838280828437600092019190915250929392505062008ebf9050565b905068056bc75e2d63100000811080620063815750603b548111155b15620063aa5784848484604051630a5a604160e01b81526004016200113194939291906200a453565b603c556200687c565b620064206040518060400160405280601081526020016f646f776e74696d654a61696c54696d6560801b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b15620064dd5760208114620064525783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f84018190048102820181019092528281526000916200649591858580838501838280828437600092019190915250929392505062008ebf9050565b90506202a300811080620064ab5750603e548110155b15620064d45784848484604051630a5a604160e01b81526004016200113194939291906200a453565b603d556200687c565b620065486040518060400160405280600e81526020016d66656c6f6e794a61696c54696d6560901b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b156200660557602081146200657a5783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f8401819004810282018101909252828152600091620065bd91858580838501838280828437600092019190915250929392505062008ebf9050565b9050620d2f00811080620065d35750603d548111155b15620065fc5784848484604051630a5a604160e01b81526004016200113194939291906200a453565b603e556200687c565b6200667f6040518060400160405280601c81526020017f6d617846656c6f6e794265747765656e42726561746865426c6f636b0000000081525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b156200672b5760208114620066b15783838383604051630a5a604160e01b81526004016200113194939291906200a453565b604080516020601f8401819004810282018101909252828152600091620066f491858580838501838280828437600092019190915250929392505062008ebf9050565b905080600003620067225784848484604051630a5a604160e01b81526004016200113194939291906200a453565b604a556200687c565b620067996040518060400160405280601181526020017039ba30b5b2a43ab1283937ba32b1ba37b960791b81525085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008e629050565b15620068595760148114620067cb5783838383604051630a5a604160e01b81526004016200113194939291906200a453565b600062006813601484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505062008ebf9050565b90506001600160a01b038116620068475784848484604051630a5a604160e01b81526004016200113194939291906200a453565b620068528162008ec4565b506200687c565b838383836040516325ee20d560e21b81526004016200113194939291906200a453565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e63384848484604051620068b394939291906200a453565b60405180910390a150505050565b60005462010000900460ff1615620068ec57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200691e5760405163b1d02c3d60e01b815260040160405180910390fd5b816000816001600160401b038111156200693c576200693c6200953d565b60405190808252806020026020018201604052801562006966578160200160208202803683370190505b5090506000805b8381101562006a6457620069af8787838181106200698f576200698f62009e3f565b9050602002016020810190620069a69190620093cc565b603f9062007d2a565b620069cd5760405163056e881160e01b815260040160405180910390fd5b60416000888884818110620069e657620069e662009e3f565b9050602002016020810190620069fd9190620093cc565b6001600160a01b039081168252602082019290925260400160002060020154845191169250829084908390811062006a395762006a3962009e3f565b6001600160a01b039092166020928302919091019091015262006a5c8162009ea4565b90506200696d565b50604051634484077560e01b815261200590634484077590620027ec908590889060040162009e55565b606080600062006a9f603f620088ba565b90508085101562006c6357831562006ab8578362006aba565b805b935060008462006acb878462009e0f565b1162006ae35762006add868362009e0f565b62006ae5565b845b9050806001600160401b0381111562006b025762006b026200953d565b60405190808252806020026020018201604052801562006b2c578160200160208202803683370190505b509350806001600160401b0381111562006b4a5762006b4a6200953d565b60405190808252806020026020018201604052801562006b74578160200160208202803683370190505b50925060005b8181101562006c605762006b936200395c828962009d53565b85828151811062006ba85762006ba862009e3f565b60200260200101906001600160a01b031690816001600160a01b0316815250506041600086838151811062006be15762006be162009e3f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060020160009054906101000a90046001600160a01b031684828151811062006c355762006c3562009e3f565b6001600160a01b039092166020928302919091019091015262006c588162009ea4565b905062006b7a565b50505b9250925092565b336110011462006c9257604051630f22c43960e41b8152611001600482015260240162001131565b60005462010000900460ff161562006cbd57604051631785c68160e01b815260040160405180910390fd5b6001600160a01b038082166000908152604360205260409020541662006ce5603f8262007d2a565b62006d035760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062006d29603c4262009d30565b604a546000828152604b60205260409020549192501162006d5d5760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062006d7e90849062009d53565b90915550506001600160a01b0384166000908152604460205260409020541580159062006dd157506001600160a01b038416600090815260446020526040902054429062006dcf90603c9062009d53565b105b1562006df0576040516330abb81d60e21b815260040160405180910390fd5b60008062006e0085600062007d4d565b915091508162006e2357604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562006e76573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062006e9c919062009d69565b905062006eaa858362007dd7565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600060405162006eea9392919062009d99565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b916200568b916001600160a01b0316908a9060040162009cf0565b6001600160a01b038082166000908152604160209081526040808320815161016081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384938493849390929160808401919062006f999062009cba565b80601f016020809104026020016040519081016040528092919081815260200182805462006fc79062009cba565b8015620070185780601f1062006fec5761010080835404028352916020019162007018565b820191906000526020600020905b81548152906001019060200180831162006ffa57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620070439062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620070719062009cba565b8015620070c25780601f106200709657610100808354040283529160200191620070c2565b820191906000526020600020905b815481529060010190602001808311620070a457829003601f168201915b50505050508152602001600182018054620070dd9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200710b9062009cba565b80156200715c5780601f1062007130576101008083540402835291602001916200715c565b820191906000526020600020905b8154815290600101906020018083116200713e57829003601f168201915b50505050508152602001600282018054620071779062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620071a59062009cba565b8015620071f65780601f10620071ca57610100808354040283529160200191620071f6565b820191906000526020600020905b815481529060010190602001808311620071d857829003601f168201915b50505050508152602001600382018054620072119062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200723f9062009cba565b8015620072905780601f10620072645761010080835404028352916020019162007290565b820191906000526020600020905b8154815290600101906020018083116200727257829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b8154815260200190600101908083116200731c5750505091909252505050606081015160e0820151610100909201519097919650945092505050565b60005462010000900460ff16156200738357604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620073b55760405163b1d02c3d60e01b815260040160405180910390fd5b33620073c3603f8262007d2a565b620073e15760405163056e881160e01b815260040160405180910390fd5b336000818152604160205260409020600c81015442906200740590603c9062009d53565b11156200742557604051631f92cdbd60e11b815260040160405180910390fd5b600581018054620074369062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620074649062009cba565b8015620074b55780601f106200748957610100808354040283529160200191620074b5565b820191906000526020600020905b8154815290600101906020018083116200749757829003601f168201915b5050508287525085916005840191508190620074d290826200a47e565b5060208201516001820190620074e990826200a47e565b50604082015160028201906200750090826200a47e565b50606082015160038201906200751790826200a47e565b505042600c830155506040516001600160a01b038316907f85d6366b336ade7f106987ec7a8eac1e8799e508aeab045a39d2f63e0dc969d990600090a250505050565b60005462010000900460ff16156200758557604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620075b75760405163b1d02c3d60e01b815260040160405180910390fd5b828114620075d8576040516341abc80160e01b815260040160405180910390fd5b60005b83811015620076495762007636858583818110620075fd57620075fd62009e3f565b9050602002016020810190620076149190620093cc565b84848481811062007629576200762962009e3f565b9050602002013562008d56565b620076418162009ea4565b9050620075db565b5050505050565b6001600160a01b0380821660009081526041602090815260408083208151610160810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549293849390916080840191620076bb9062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620076e99062009cba565b80156200773a5780601f106200770e576101008083540402835291602001916200773a565b820191906000526020600020905b8154815290600101906020018083116200771c57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620077659062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620077939062009cba565b8015620077e45780601f10620077b857610100808354040283529160200191620077e4565b820191906000526020600020905b815481529060010190602001808311620077c657829003601f168201915b50505050508152602001600182018054620077ff9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200782d9062009cba565b80156200787e5780601f1062007852576101008083540402835291602001916200787e565b820191906000526020600020905b8154815290600101906020018083116200786057829003601f168201915b50505050508152602001600282018054620078999062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620078c79062009cba565b8015620079185780601f10620078ec5761010080835404028352916020019162007918565b820191906000526020600020905b815481529060010190602001808311620078fa57829003601f168201915b50505050508152602001600382018054620079339062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620079619062009cba565b8015620079b25780601f106200798657610100808354040283529160200191620079b2565b820191906000526020600020905b8154815290600101906020018083116200799457829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b81548152602001906001019080831162007a3e5750505091909252505050604001519392505050565b600062007a76603f8462007d2a565b62007a945760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038381166000908152604160205260409081902060020154905163aa1966cd60e01b81526004810185905291169063aa1966cd9060240162004ff1565b60005462010000900460ff161562007b0357604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562007b355760405163b1d02c3d60e01b815260040160405180910390fd5b3362007b43603f8262007d2a565b62007b615760405163056e881160e01b815260040160405180910390fd5b3362007b71818787878762008a75565b62007b8f57604051631647e3cb60e11b815260040160405180910390fd5b60006001600160a01b03166045878760405162007bae92919062009d0a565b908152604051908190036020019020546001600160a01b031614158062007bf857506048868660405162007be492919062009d0a565b9081526040519081900360200190205460ff165b1562007c17576040516311fdb94760e01b815260040160405180910390fd5b6001600160a01b0381166000908152604160205260409020600c810154429062007c4490603c9062009d53565b111562007c6457604051631f92cdbd60e11b815260040160405180910390fd5b4260468260040160405162007c7a91906200a546565b908152604051908190036020019020556004810162007c9b87898362009f68565b5042600c820155604051829060459062007cb9908a908a9062009d0a565b90815260405190819003602001812080546001600160a01b039384166001600160a01b0319909116179055908316907f783156582145bd0ff7924fae6953ba054cf1233eb60739a200ddb10de068ff0d9062007d19908a908a906200a239565b60405180910390a250505050505050565b6001600160a01b0381166000908152600183016020526040812054151562005035565b6000806000848460405160200162007d679291906200a5c4565b60408051601f1981840301815291815281516020928301206000818152604c9093529120549091504281111562007da75760008093509350505062007dd0565b603e5462007db6904262009d53565b6000928352604c6020526040909220829055506001925090505b9250929050565b8154604051631507fdb760e11b81526001600160a01b03909116600482015261100090632a0ffb6e90602401600060405180830381600087803b15801562007e1e57600080fd5b505af115801562007e33573d6000803e3d6000fd5b505050506000600162007e47603f620088ba565b62007e53919062009e0f565b604954108015915062007f115760405163d31f968d60e01b81526110006004820152600860248201526120009063d31f968d90604401602060405180830381865afa15801562007ea7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062007ecd919062009dc8565b62007f115760018301546040516001600160a01b03909116907f2afdc18061ac21cff7d9f11527ab9c8dec6fabd4edf6f894ed634bebd6a20d4590600090a2505050565b82600b015482111562007f2657600b83018290555b600a83015460ff1662007f9957600a8301805460ff191660019081179091556049805460009062007f5990849062009d53565b909155505060018301546040516001600160a01b03909116907f4905ac32602da3fb8b4b7b00c285e5fc4c6c2308cc908b4a1e4e9625a29c90a390600090a25b505050565b60408051608080820183526000808352602080840182905283850182905260608085018390528551938401865282845283820183905283860183905283018290528451808601865282815281018290528451808601909552855185528581019085015291928290620080109062008f30565b90506000805b620080218362008fa3565b15620080f457806000036200805657620080456200803f8462008fc9565b6200902d565b6001600160a01b03168452620080e1565b8060010362008082576200806e6200803f8462008fc9565b6001600160a01b03166020850152620080e1565b80600203620080ae576200809a6200803f8462008fc9565b6001600160a01b03166040850152620080e1565b80600303620080db57620080cc620080c68462008fc9565b62009045565b606085015260019150620080e1565b620080f4565b620080ec8162009ea4565b905062008016565b5091959194509092505050565b6000805462010000900460ff16156200812d57604051631785c68160e01b815260040160405180910390fd5b6020808301516001600160a01b031660009081526001909152604090205460ff168062008165575060208201516001600160a01b0316155b15620081845760405163b1d02c3d60e01b815260040160405180910390fd5b81516200819490603f9062007d2a565b620081a157506002919050565b81516001600160a01b039081166000908152604160209081526040808320815161016081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929391926080840191906200820d9062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200823b9062009cba565b80156200828c5780601f1062008260576101008083540402835291602001916200828c565b820191906000526020600020905b8154815290600101906020018083116200826e57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620082b79062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620082e59062009cba565b8015620083365780601f106200830a5761010080835404028352916020019162008336565b820191906000526020600020905b8154815290600101906020018083116200831857829003601f168201915b50505050508152602001600182018054620083519062009cba565b80601f01602080910402602001604051908101604052809291908181526020018280546200837f9062009cba565b8015620083d05780601f10620083a457610100808354040283529160200191620083d0565b820191906000526020600020905b815481529060010190602001808311620083b257829003601f168201915b50505050508152602001600282018054620083eb9062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620084199062009cba565b80156200846a5780601f106200843e576101008083540402835291602001916200846a565b820191906000526020600020905b8154815290600101906020018083116200844c57829003601f168201915b50505050508152602001600382018054620084859062009cba565b80601f0160208091040260200160405190810160405280929190818152602001828054620084b39062009cba565b8015620085045780601f10620084d85761010080835404028352916020019162008504565b820191906000526020600020905b815481529060010190602001808311620084e657829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152805161028081019182905260a09092019190600d84019060149082845b815481526020019060010190808311620085905750505050508152505090508060e001518015620085db575082600001516001600160a01b031683602001516001600160a01b031614155b15620085ea5750600392915050565b6040808201516060850151602086015192516317066a5760e21b81526001600160a01b03938416600482015260009390921691635c19a95c919060240160206040518083038185885af115801562008646573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200866d919062009d69565b905083602001516001600160a01b031684600001516001600160a01b03166000805160206200b540833981519152838760600151604051620086b9929190918252602082015260400190565b60405180910390a383602001516001600160a01b031684600001516001600160a01b03167f607b17598da6bdca05650a2fc08bd2bc8e38c3236806a0fa8e0daabc1d6cb1d88387606001516040516200871c929190918252602082015260400190565b60405180910390a360408083015160208601519151633041949b60e01b815261200592633041949b92620087569290919060040162009cf0565b600060405180830381600087803b1580156200877157600080fd5b505af115801562008786573d6000803e3d6000fd5b506000979650505050505050565b6001600160a01b0381166000908152604160205260409020600a81015460ff1615620087be575050565b6036546002820154604051630913db4760e01b81526001600160a01b03858116600483015290911690630913db4790602401602060405180830381865afa1580156200880e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008834919062009d69565b101562005a1e576200885681603d544262008850919062009d53565b62007dd7565b80546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b1580156200889d57600080fd5b505af1158015620088b2573d6000803e3d6000fd5b505050505050565b600062005038825490565b60006200503583836200911d565b600080829050600381511080620088eb575060098151115b15620088fa5750600092915050565b60418160008151811062008912576200891262009e3f565b016020015160f81c1080620089445750605a816000815181106200893a576200893a62009e3f565b016020015160f81c115b15620089535750600092915050565b60015b815181101562008a6b57603082828151811062008977576200897762009e3f565b016020015160f81c1080620089a8575060398282815181106200899e576200899e62009e3f565b016020015160f81c115b8015620089f857506041828281518110620089c757620089c762009e3f565b016020015160f81c1080620089f85750605a828281518110620089ee57620089ee62009e3f565b016020015160f81c115b801562008a485750606182828151811062008a175762008a1762009e3f565b016020015160f81c108062008a485750607a82828151811062008a3e5762008a3e62009e3f565b016020015160f81c115b1562008a58575060009392505050565b62008a638162009ea4565b905062008956565b5060019392505050565b600060308414158062008a89575060608214155b1562008a985750600062008b9c565b60008686864660405160200162008ab394939291906200a602565b60408051808303601f1901815282825280516020918201208184528383019092529092506000919060208201818036833701905050905081602082015260008186868a8a60405160200162008b0d9594939291906200a62f565b60408051808303601f190181526001808452838301909252925060009190602082018180368337019050509050815160016020830182602086016066600019fa62008b5757600080fd5b5060008160008151811062008b705762008b7062009e3f565b016020015160f81c90506001811462008b925760009550505050505062008b9c565b6001955050505050505b95945050505050565b60008061200361dead60405162008bbc90620093a8565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f08015801562008bff573d6000803e3d6000fd5b509050806001600160a01b031663f399e22e3486866040518463ffffffff1660e01b815260040162008c339291906200a667565b6000604051808303818588803b15801562008c4d57600080fd5b505af115801562008c62573d6000803e3d6000fd5b50506040516001600160a01b038086169450881692507fd481492e4e93bb36b4c12a5af93f03be3bf04b454dfbc35dd2663fa26f44d5b09150600090a39392505050565b600062005035836001600160a01b0384166200914a565b600054610100900460ff1662008d2a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162001131565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b8162008d64603f8262007d2a565b62008d825760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03838116600090815260416020526040808220600201549051635569f64b60e11b8152336004820152602481018690529192169063aad3ec96906044016020604051808303816000875af115801562008de6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008e0c919062009d69565b9050336001600160a01b0316846001600160a01b03167ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd39926838360405162008e5491815260200190565b60405180910390a350505050565b60008160405160200162008e7791906200a416565b604051602081830303815290604052805190602001208360405160200162008ea091906200a416565b6040516020818303038152906040528051906020012014905092915050565b015190565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b604080516080810182526000918101828152606082018390528152602081019190915262008f5e826200919c565b62008f6857600080fd5b600062008f798360200151620091cf565b836020015162008f8a919062009d53565b6040805180820190915293845260208401525090919050565b8051805160208201516000929162008fbb9162009d53565b836020015110915050919050565b604080518082019091526000808252602082015262008fe88262008fa3565b62008ff257600080fd5b6020820151600062009004826200925e565b905062009012818362009d53565b60209485015260408051808201909152908152928301525090565b80516000906015146200903f57600080fd5b62005038825b8051600090158015906200905b57508151602110155b6200906557600080fd5b6000620090768360200151620091cf565b90508083600001511015620090ce5760405162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015260640162001131565b8251600090620090e090839062009e0f565b9050600080838660200151620090f7919062009d53565b90508051915060208310156200911457826020036101000a820491505b50949350505050565b600082600001828154811062009137576200913762009e3f565b9060005260206000200154905092915050565b6000818152600183016020526040812054620091935750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562005038565b50600062005038565b80516000908103620091b057506000919050565b6020820151805160001a9060c082101562008a6b575060009392505050565b8051600090811a6080811015620091e95750600092915050565b60b881108062009206575060c0811080159062009206575060f881105b15620092155750600192915050565b60c081101562009250576200922d600160b86200a68d565b6200923c9060ff168262009e0f565b6200924990600162009d53565b9392505050565b6200922d600160f86200a68d565b80516000908190811a60808110156200927b5760019150620093a1565b60b8811015620092a7576200929260808262009e0f565b6200929f90600162009d53565b9150620093a1565b60c08110156200932057600060b78203600186019550806020036101000a865104915060018101820193505080831015620093195760405162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015260640162001131565b50620093a1565b60f881101562009337576200929260c08262009e0f565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156200939f5760405162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015260640162001131565b505b5092915050565b610e96806200a6aa83390190565b6001600160a01b03811681146200174957600080fd5b600060208284031215620093df57600080fd5b81356200924981620093b6565b60008083601f840112620093ff57600080fd5b5081356001600160401b038111156200941757600080fd5b60208301915083602082850101111562007dd057600080fd5b600080602083850312156200944457600080fd5b82356001600160401b038111156200945b57600080fd5b6200946985828601620093ec565b90969095509350505050565b6000806000604084860312156200948b57600080fd5b833560ff811681146200949d57600080fd5b925060208401356001600160401b03811115620094b957600080fd5b620094c786828701620093ec565b9497909650939450505050565b60005b83811015620094f1578181015183820152602001620094d7565b50506000910152565b6000815180845262009514816020860160208601620094d4565b601f01601f19169290920160200192915050565b602081526000620050356020830184620094fa565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200957857620095786200953d565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620095a957620095a96200953d565b604052919050565b60006001600160401b03821115620095cd57620095cd6200953d565b50601f01601f191660200190565b6000620095f2620095ec84620095b1565b6200957e565b90508281528383830111156200960757600080fd5b828260208301376000602084830101529392505050565b6000602082840312156200963157600080fd5b81356001600160401b038111156200964857600080fd5b8201601f810184136200965a57600080fd5b6200966b84823560208401620095db565b949350505050565b600080604083850312156200968757600080fd5b82356200969481620093b6565b946020939093013593505050565b80151581146200174957600080fd5b60008060008060808587031215620096c857600080fd5b8435620096d581620093b6565b93506020850135620096e781620093b6565b92506040850135915060608501356200970081620096a2565b939692955090935050565b6001600160401b03811681146200174957600080fd5b6000602082840312156200973457600080fd5b813562009249816200970b565b600080604083850312156200975557600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b838110156200979f5781516001600160a01b03168752958201959082019060010162009778565b509495945050505050565b608081526000620097bf608083018762009764565b82810360208481019190915286518083528782019282019060005b81811015620097f857845183529383019391830191600101620097da565b5050848103604086015286518082528282019350600581901b8201830183890160005b838110156200984d57601f198584030187526200983a838351620094fa565b968601969250908501906001016200981b565b5050809550505050505082606083015295945050505050565b600080600080600080600087890360e08112156200988357600080fd5b88356200989081620093b6565b975060208901356001600160401b0380821115620098ad57600080fd5b620098bb8c838d01620093ec565b909950975060408b0135915080821115620098d557600080fd5b620098e38c838d01620093ec565b90975095508591506060605f1984011215620098fe57600080fd5b60608b01945060c08b01359250808311156200991957600080fd5b505088016080818b0312156200992e57600080fd5b8091505092959891949750929550565b600080604083850312156200995257600080fd5b82356200995f81620093b6565b915060208301356200997181620096a2565b809150509250929050565b6020815260008251608060208401526200999a60a0840182620094fa565b90506020840151601f1980858403016040860152620099ba8383620094fa565b92506040860151915080858403016060860152620099d98383620094fa565b925060608601519150808584030160808601525062008b9c8282620094fa565b6000806000806040858703121562009a1057600080fd5b84356001600160401b038082111562009a2857600080fd5b62009a3688838901620093ec565b9096509450602087013591508082111562009a5057600080fd5b5062009a5f87828801620093ec565b95989497509550505050565b60008083601f84011262009a7e57600080fd5b5081356001600160401b0381111562009a9657600080fd5b6020830191508360208260051b850101111562007dd057600080fd5b60008060006040848603121562009ac857600080fd5b83356001600160401b0381111562009adf57600080fd5b62009aed8682870162009a6b565b909450925050602084013562009b0381620093b6565b809150509250925092565b60608152600062009b23606083018662009764565b828103602084015262009b37818662009764565b915050826040830152949350505050565b600082601f83011262009b5a57600080fd5b6200503583833560208501620095db565b60006020828403121562009b7e57600080fd5b81356001600160401b038082111562009b9657600080fd5b908301906080828603121562009bab57600080fd5b62009bb562009553565b82358281111562009bc557600080fd5b62009bd38782860162009b48565b82525060208301358281111562009be957600080fd5b62009bf78782860162009b48565b60208301525060408301358281111562009c1057600080fd5b62009c1e8782860162009b48565b60408301525060608301358281111562009c3757600080fd5b62009c458782860162009b48565b60608301525095945050505050565b6000806000806040858703121562009c6b57600080fd5b84356001600160401b038082111562009c8357600080fd5b62009c918883890162009a6b565b9096509450602087013591508082111562009cab57600080fd5b5062009a5f8782880162009a6b565b600181811c9082168062009ccf57607f821691505b6020821081036200458057634e487b7160e01b600052602260045260246000fd5b6001600160a01b0392831681529116602082015260400190565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b60008262009d4e57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562005038576200503862009d1a565b60006020828403121562009d7c57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b83815260208101839052606081016003831062009dba5762009dba62009d83565b826040830152949350505050565b60006020828403121562009ddb57600080fd5b81516200924981620096a2565b828152604081016004831062009e025762009e0262009d83565b8260208301529392505050565b8181038181111562005038576200503862009d1a565b808202811582820484141762005038576200503862009d1a565b634e487b7160e01b600052603260045260246000fd5b60408152600062009e6a604083018562009764565b905060018060a01b03831660208301529392505050565b6001600160401b03828116828216039080821115620093a157620093a162009d1a565b60006001820162009eb95762009eb962009d1a565b5060010190565b6000808335601e1984360301811262009ed857600080fd5b8301803591506001600160401b0382111562009ef357600080fd5b60200191503681900382131562007dd057600080fd5b601f82111562007f9957600081815260208120601f850160051c8101602086101562009f325750805b601f850160051c820191505b81811015620088b25782815560010162009f3e565b600019600383901b1c191660019190911b1790565b6001600160401b0383111562009f825762009f826200953d565b62009f9a8362009f93835462009cba565b8362009f09565b6000601f84116001811462009fcd576000851562009fb85750838201355b62009fc4868262009f53565b84555062007649565b600083815260209020601f19861690835b828110156200a000578685013582556020948501946001909201910162009fde565b50868210156200a01e5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6200a03c828362009ec0565b6001600160401b038111156200a056576200a0566200953d565b6200a06e816200a067855462009cba565b8562009f09565b6000601f8211600181146200a0a157600083156200a08c5750838201355b6200a098848262009f53565b8655506200a0fe565b600085815260209020601f19841690835b828110156200a0d457868501358255602094850194600190920191016200a0b2565b50848210156200a0f25760001960f88660031b161c19848701351681555b505060018360011b0185555b505050506200a111602083018362009ec0565b6200a12181836001860162009f68565b50506200a132604083018362009ec0565b6200a14281836002860162009f68565b50506200a153606083018362009ec0565b6200a16381836003860162009f68565b50505050565b81356200a176816200970b565b6001600160401b03811690508154816001600160401b0319821617835560208401356200a1a3816200970b565b6fffffffffffffffff0000000000000000604091821b166fffffffffffffffffffffffffffffffff198316841781178555908501356200a1e3816200970b565b6001600160c01b0319929092169092179190911760809190911b67ffffffffffffffff60801b1617905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815260006200966b6020830184866200a210565b60006001600160401b038211156200a26b576200a26b6200953d565b5060051b60200190565b600060208083850312156200a28957600080fd5b82516001600160401b038111156200a2a057600080fd5b8301601f810185136200a2b257600080fd5b80516200a2c3620095ec826200a24f565b81815260059190911b820183019083810190878311156200a2e357600080fd5b928401925b828410156200a30e5783516200a2fe81620093b6565b825292840192908401906200a2e8565b979650505050505050565b600060208083850312156200a32d57600080fd5b82516001600160401b03808211156200a34557600080fd5b818501915085601f8301126200a35a57600080fd5b81516200a36b620095ec826200a24f565b81815260059190911b830184019084810190888311156200a38b57600080fd5b8585015b838110156200a409578051858111156200a3a95760008081fd5b8601603f81018b136200a3bc5760008081fd5b8781015160406200a3d1620095ec83620095b1565b8281528d828486010111156200a3e75760008081fd5b6200a3f8838c8301848701620094d4565b86525050509186019186016200a38f565b5098975050505050505050565b600082516200a42a818460208701620094d4565b9190910192915050565b60ff8416815260406020820152600062008b9c6040830184866200a210565b6040815260006200a4696040830186886200a210565b82810360208401526200a30e8185876200a210565b81516001600160401b038111156200a49a576200a49a6200953d565b6200a4b2816200a4ab845462009cba565b8462009f09565b602080601f8311600181146200a4e657600084156200a4d15750858301515b6200a4dd858262009f53565b865550620088b2565b600085815260208120601f198616915b828110156200a517578886015182559484019460019091019084016200a4f6565b50858210156200a5365787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200a5568162009cba565b600182811680156200a57157600181146200a587576200a5b8565b60ff19841687528215158302870194506200a5b8565b8760005260208060002060005b858110156200a5af5781548a8201529084019082016200a594565b50505082870194505b50929695505050505050565b6bffffffffffffffffffffffff198360601b1681526000600383106200a5ee576200a5ee62009d83565b5060f89190911b6014820152601501919050565b6bffffffffffffffffffffffff198560601b16815282846014830137601492019182015260340192915050565b600086516200a643818460208b01620094d4565b82018587823760009086019081528385823760009301928352509095945050505050565b6001600160a01b03831681526040602082018190526000906200966b90830184620094fa565b60ff828116828216039081111562005038576200503862009d1a56fe608060405260405162000e9638038062000e96833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e6f60279139620002f8565b9392505050565b60006200018060008051602062000e4f83398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e4f83398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61087580620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c656424d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e0400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000030b86b3146bdd2200b1dbdb1cea5e40d3451c028cbb4fb03b1826f7f2d82bee76bbd5cd68a74a16a7eceea093fd5826b9200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003087ce273bb9b51fd69e50de7a8d9a99cfb3b1a5c6a7b85f6673d137a5a2ce7df3d6ee4e6d579a142d58b0606c4a7a1c27000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a33ac14980d85c0d154c5909ebf7a11d455f54beb4d5d0dc1d8b3670b9c4a6b6c450ee3d623ecc48026f09ed1f0b5c1200000000000000000000000000000000a164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(StakeCreditContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106101e75760003560e01c8063647df75911610102578063a9664feb11610095578063d241c1ea11610064578063d241c1ea1461068d578063dd62ed3e146106cf578063f1fad104146106ef578063f399e22e1461070457600080fd5b8063a9664feb14610600578063aa1966cd14610620578063aad3ec961461064d578063c2cde2b21461066d57600080fd5b806395d89b41116100d157806395d89b411461058b578063a457c2d7146105a0578063a5d059ca146105c0578063a9059cbb146105e057600080fd5b8063647df759146104e85780636bbf22491461050857806370a082311461053557806391faf0b41461056b57600080fd5b8063313ce5671161017a5780634bf6c882116101495780634bf6c8821461048b5780634d99dd16146104a05780635c19a95c146104c05780635e607d76146104d357600080fd5b8063313ce567146103f157806339509351146104135780633a5381b51461043357806345bc4d101461046b57600080fd5b806315d1f898116101b657806315d1f8981461038657806318160ddd1461039c57806323b872dd146103b15780632f2d448a146103d157600080fd5b8063038c0023146102e157806306fdde03146103145780630913db4714610336578063095ea7b31461035657600080fd5b366102dc57336120021461021757604051630f22c43960e41b815261200260048201526024015b60405180910390fd5b60006120026001600160a01b0316631fa8882b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610259573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027d9190611de4565b6102879042611e13565b6098546000828152609d6020908152604080832093909355609c9052908120805492935034929091906102bb908490611e35565b9250508190555034609860008282546102d49190611e35565b925050819055005b600080fd5b3480156102ed57600080fd5b506103016102fc366004611e60565b610717565b6040519081526020015b60405180910390f35b34801561032057600080fd5b50610329610747565b60405161030b9190611e84565b34801561034257600080fd5b50610301610351366004611e60565b6107d9565b34801561036257600080fd5b50610376610371366004611ed2565b6107fb565b604051901515815260200161030b565b34801561039257600080fd5b5061030160985481565b3480156103a857600080fd5b50606754610301565b3480156103bd57600080fd5b506103766103cc366004611efe565b610813565b3480156103dd57600080fd5b506103016103ec366004611e60565b610837565b3480156103fd57600080fd5b5060125b60405160ff909116815260200161030b565b34801561041f57600080fd5b5061037661042e366004611ed2565b6108fc565b34801561043f57600080fd5b50609754610453906001600160a01b031681565b6040516001600160a01b03909116815260200161030b565b34801561047757600080fd5b50610301610486366004611f3f565b61091e565b34801561049757600080fd5b50610401600881565b3480156104ac57600080fd5b506103016104bb366004611ed2565b610a11565b6103016104ce366004611e60565b610c28565b6104e66104e1366004611f58565b610c9e565b005b3480156104f457600080fd5b50610301610503366004611f3f565b610e11565b34801561051457600080fd5b50610301610523366004611f3f565b609d6020526000908152604090205481565b34801561054157600080fd5b50610301610550366004611e60565b6001600160a01b031660009081526065602052604090205490565b34801561057757600080fd5b50610301610586366004611f3f565b610e50565b34801561059757600080fd5b50610329610e8b565b3480156105ac57600080fd5b506103766105bb366004611ed2565b610e9a565b3480156105cc57600080fd5b506103016105db366004611ed2565b610f15565b3480156105ec57600080fd5b506103766105fb366004611ed2565b611016565b34801561060c57600080fd5b5061030161061b366004611ed2565b611024565b34801561062c57600080fd5b5061030161063b366004611f3f565b609c6020526000908152604090205481565b34801561065957600080fd5b50610301610668366004611ed2565b61114d565b34801561067957600080fd5b50610301610688366004611e60565b6113f0565b34801561069957600080fd5b506106ad6106a8366004611ed2565b61140e565b604080518251815260208084015190820152918101519082015260600161030b565b3480156106db57600080fd5b506103016106ea366004611f82565b611491565b3480156106fb57600080fd5b50610401601181565b6104e6610712366004611fbb565b6114bc565b6001600160a01b0381166000908152609a6020526040812054600f81810b600160801b909204900b035b92915050565b60606068805461075690612040565b80601f016020809104026020016040519081016040528092919081815260200182805461078290612040565b80156107cf5780601f106107a4576101008083540402835291602001916107cf565b820191906000526020600020905b8154815290600101906020018083116107b257829003601f168201915b5050505050905090565b6001600160a01b03811660009081526065602052604081205461074190610e50565b600033610809818585611672565b5060019392505050565b60003361082185828561168b565b61082c8585856116ff565b506001949350505050565b6001600160a01b0381166000908152609a6020526040812054600f81810b600160801b909204900b0381805b828110156108f4576001600160a01b0385166000908152609a6020526040812061088d9083611718565b6000818152609960209081526040918290208251606081018452815481526001820154928101929092526002015491810182905291925042106108da576108d384612074565b93506108e1565b50506108f4565b5050806108ed90612074565b9050610863565b509392505050565b60003361080981858561090f8383611491565b6109199190611e35565b611672565b6000336120021461094657604051630f22c43960e41b8152612002600482015260240161020e565b6097546001600160a01b03166000908152606560205260408120549061096b84610e11565b905081811161097a578061097c565b815b609754909150600090610998906001600160a01b031683611789565b6040519091506000906110029083908381818185875af1925050503d80600081146109df576040519150601f19603f3d011682016040523d82523d6000602084013e6109e4565b606091505b5050905080610a06576040516312171d8360e31b815260040160405180910390fd5b50925050505b919050565b60003361200214610a3957604051630f22c43960e41b8152612002600482015260240161020e565b81600003610a5a57604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038316600090815260656020526040902054821115610a9357604051631e9acf1760e31b815260040160405180910390fd5b610a9d8383611789565b905060006120026001600160a01b031663fc0c5ff16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b059190611de4565b610b0f9042611e35565b6040805160608101825285815260208101859052908101829052909150600085610b38816117be565b60405160609290921b6bffffffffffffffffffffffff19166020830152603482015260540160408051601f1981840301815291815281516020928301206000818152609990935291205490915015610ba35760405163b19e911560e01b815260040160405180910390fd5b600081815260996020908152604080832085518155828601516001820155818601516002909101556001600160a01b0389168352609a9091529020610c1f90828154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b50505092915050565b60003361200214610c5057604051630f22c43960e41b8152612002600482015260240161020e565b34600003610c7157604051631f2a200560e01b815260040160405180910390fd5b610c7b82346117e6565b905080600003610a0c57604051639811e0c760e01b815260040160405180910390fd5b3361200214610cc457604051630f22c43960e41b8152612002600482015260240161020e565b346000612710610cde67ffffffffffffffff85168461208d565b610ce89190611e13565b90506000610cf682846120a4565b905060006120026001600160a01b0316631fa8882b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5e9190611de4565b610d689042611e13565b6098546000828152609d6020908152604080832093909355609c905290812080549293508492909190610d9c908490611e35565b925050819055508160986000828254610db59190611e35565b9091555050609754610dd0906001600160a01b0316846117e6565b5060408051838152602081018590527ffb0e1482d62102ab9594f69d4c6d693749e3e2bf1c21af272f5456b2d5a4f6b5910160405180910390a15050505050565b6000609854600003610e36576040516307b76ce760e51b815260040160405180910390fd5b609854606754610e46908461208d565b6107419190611e13565b6000610e5b60675490565b600003610e7b57604051632fe8dae960e01b815260040160405180910390fd5b606754609854610e46908461208d565b60606069805461075690612040565b60003381610ea88286611491565b905083811015610f085760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161020e565b61082c8286868403611672565b60003361200214610f3d57604051630f22c43960e41b8152612002600482015260240161020e565b81600003610f5e57604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038316600090815260656020526040902054821115610f9757604051631e9acf1760e31b815260040160405180910390fd5b610fa18383611789565b6040519091506000906120029083908381818185875af1925050503d8060008114610fe8576040519150601f19603f3d011682016040523d82523d6000602084013e610fed565b606091505b505090508061100f576040516312171d8360e31b815260040160405180910390fd5b5092915050565b6000336108098185856116ff565b6001600160a01b0382166000908152609a6020526040812054600f81810b600160801b909204900b0360000361105c57506000610741565b81158061109057506001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b0382115b61109a57816110c4565b6001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b035b91506000805b838110156108f4576001600160a01b0385166000908152609a602052604081206110f49083611718565b600081815260996020908152604091829020825160608101845281548152600182015492810183905260029091015492810192909252919250906111389085611e35565b935050508061114690612074565b90506110ca565b6000336120021461117557604051630f22c43960e41b8152612002600482015260240161020e565b61117d61180f565b6001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b036000036111c65760405163ad41893760e01b815260040160405180910390fd5b8115806111fa57506001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b0382115b611204578161122e565b6001600160a01b0383166000908152609a6020526040902054600f81810b600160801b909204900b035b915060005b82156112e4576001600160a01b0384166000908152609a6020526040812061125a90611868565b6000818152609960209081526040918290208251606081018452815481526001820154928101929092526002015491810182905291925042101561129f5750506112e4565b6001600160a01b0386166000908152609a602052604090206112c0906118bc565b5060208101516112d09084611e35565b92506112db856120b7565b94505050611233565b80600003611305576040516303cd8e0960e21b815260040160405180910390fd5b60006120026001600160a01b031663e8f67c3b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136b9190611de4565b90506000856001600160a01b03168284604051600060405180830381858888f193505050503d80600081146113bc576040519150601f19603f3d011682016040523d82523d6000602084013e6113c1565b606091505b50509050806113e3576040516312171d8360e31b815260040160405180910390fd5b5050600180559050610741565b6001600160a01b0381166000908152609b6020526040812054610741565b61143260405180606001604052806000815260200160008152602001600081525090565b6001600160a01b0383166000908152609a602052604081206114549084611718565b6000908152609960209081526040918290208251606081018452815481526001820154928101929092526002015491810191909152949350505050565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205490565b600054610100900460ff16158080156114dc5750600054600160ff909116105b806114f65750303b1580156114f6575060005460ff166001145b6115595760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161020e565b6000805460ff19166001179055801561157c576000805461ff0019166101001790555b33612002146115a257604051630f22c43960e41b8152612002600482015260240161020e565b600083836040516020016115b79291906120ce565b6040516020818303038152906040529050600084846040516020016115dd9291906120fe565b60405160208183030381529060405290506115f88282611941565b611600611986565b609780546001600160a01b0319166001600160a01b038816179055611624346119ad565b5050801561166c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b604051632028747160e01b815260040160405180910390fd5b60006116978484611491565b9050600019811461166c57818110156116f25760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161020e565b61166c8484848403611672565b604051638cd22d1960e01b815260040160405180910390fd5b60008061173b61172784611b1d565b85546117369190600f0b61211c565b611b8b565b8454909150600160801b9004600f90810b9082900b1261176e57604051632d0483c560e21b815260040160405180910390fd5b600f0b60009081526001939093016020525050604090205490565b600061179482610e50565b90506117a08383611bef565b80609860008282546117b291906120a4565b90915550909392505050565b6001600160a01b0381166000908152609b602052604090208054600181018255905b50919050565b60006117f182610e11565b90506117fd8382611d23565b81609860008282546117b29190611e35565b6002600154036118615760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161020e565b6002600155565b60006118838254600f81810b600160801b909204900b131590565b156118a157604051631ed9509560e11b815260040160405180910390fd5b508054600f0b60009081526001909101602052604090205490565b60006118d78254600f81810b600160801b909204900b131590565b156118f557604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b60018055565b600054610100900460ff166119685760405162461bcd60e51b815260040161020e90612144565b606861197483826121f3565b50606961198182826121f3565b505050565b600054610100900460ff1661193b5760405162461bcd60e51b815260040161020e90612144565b600054610100900460ff166119d45760405162461bcd60e51b815260040161020e90612144565b60006120026001600160a01b0316638a4d3fa86040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3a9190611de4565b90508082111580611a5457506097546001600160a01b0316155b80611a60575060675415155b15611a7e57604051632163e6b960e21b815260040160405180910390fd5b60006120026001600160a01b0316634e6fd6c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ac0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae491906122b3565b9050611af08183611d23565b6000611afc83856120a4565b609754909150611b15906001600160a01b031682611d23565b505050609855565b60006001600160ff1b03821115611b875760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b606482015260840161020e565b5090565b80600f81900b8114610a0c5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b606482015260840161020e565b6001600160a01b038216611c4f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161020e565b6001600160a01b03821660009081526065602052604090205481811015611cc35760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161020e565b6001600160a01b03831660008181526065602090815260408083208686039055606780548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b6001600160a01b038216611d795760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161020e565b8060676000828254611d8b9190611e35565b90915550506001600160a01b0382166000818152606560209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208284031215611df657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082611e3057634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561074157610741611dfd565b6001600160a01b0381168114611e5d57600080fd5b50565b600060208284031215611e7257600080fd5b8135611e7d81611e48565b9392505050565b600060208083528351808285015260005b81811015611eb157858101830151858201604001528201611e95565b506000604082860101526040601f19601f8301168501019250505092915050565b60008060408385031215611ee557600080fd5b8235611ef081611e48565b946020939093013593505050565b600080600060608486031215611f1357600080fd5b8335611f1e81611e48565b92506020840135611f2e81611e48565b929592945050506040919091013590565b600060208284031215611f5157600080fd5b5035919050565b600060208284031215611f6a57600080fd5b813567ffffffffffffffff81168114611e7d57600080fd5b60008060408385031215611f9557600080fd5b8235611fa081611e48565b91506020830135611fb081611e48565b809150509250929050565b600080600060408486031215611fd057600080fd5b8335611fdb81611e48565b9250602084013567ffffffffffffffff80821115611ff857600080fd5b818601915086601f83011261200c57600080fd5b81358181111561201b57600080fd5b87602082850101111561202d57600080fd5b6020830194508093505050509250925092565b600181811c9082168061205457607f821691505b6020821081036117e057634e487b7160e01b600052602260045260246000fd5b60006001820161208657612086611dfd565b5060010190565b808202811582820484141761074157610741611dfd565b8181038181111561074157610741611dfd565b6000816120c6576120c6611dfd565b506000190190565b65029ba30b5b2960d51b815281836006830137660810dc99591a5d60ca1b91016006810191909152600d01919050565b611cdd60f21b81528183600283013760009101600201908152919050565b808201828112600083128015821682158216171561213c5761213c611dfd565b505092915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561198157600081815260208120601f850160051c810160208610156121cc5750805b601f850160051c820191505b818110156121eb578281556001016121d8565b505050505050565b815167ffffffffffffffff81111561220d5761220d61218f565b6122218161221b8454612040565b846121a5565b602080601f831160018114612256576000841561223e5750858301515b600019600386901b1c1916600185901b1785556121eb565b600085815260208120601f198616915b8281101561228557888601518255948401946001909101908401612266565b50858210156122a35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156122c557600080fd5b8151611e7d81611e4856fea164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(GovernorContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106103f35760003560e01c80637b3c71d311610208578063c28bc2fa11610118578063e23a9a52116100ab578063f1fad1041161007a578063f1fad10414610e46578063f23a6e6114610e5b578063f8ce560a14610e87578063fc0c546a14610ea7578063fe0d94c114610ec857600080fd5b8063e23a9a5214610d1b578063ea0217cf14610de6578063eb9019d414610e06578063ece40cc114610e2657600080fd5b8063da95691a116100e7578063da95691a14610c61578063dd4e2ba514610c81578063ddf0b00914610cc7578063deaaa7cc14610ce757600080fd5b8063c28bc2fa14610bef578063c59057e414610c02578063d07f91e914610c22578063d33219b414610c4257600080fd5b8063a7713a701161019b578063b187bd261161016a578063b187bd2614610b55578063b58131b014610b73578063bc197c8114610b88578063c01f9e3714610bb4578063c170ec0b14610bd457600080fd5b8063a7713a7014610ae0578063a890c91014610af5578063ab58fb8e14610b15578063ac43175114610b3557600080fd5b806384b0196e116101d757806384b0196e14610a5857806391ddadf414610a8057806397c3d33414610aac5780639a802a6d14610ac057600080fd5b80637b3c71d3146109ee5780637d5e81e214610a0e5780638129fc1c14610a2e5780638456cb5914610a4357600080fd5b80633932abb1116103035780634a49ac4c1161029657806354fd4d501161026557806354fd4d5014610944578063567813881461096e5780635f398a141461098e57806360c4247f146109ae57806370b0f660146109ce57600080fd5b80634a49ac4c146108b75780634bf5d7e9146108d75780634bf6c882146108ec578063533ddd141461091357600080fd5b8063417c73a7116102d2578063417c73a7146107fc578063438596321461081c578063452115d6146108675780634838d1651461088757600080fd5b80633932abb1146107795780633bccf4fd1461078f5780633e4f49e6146107af57806340e58ee5146107dc57600080fd5b8063150b7a02116103865780632656227d116103555780632656227d146106a25780632d63f693146106b55780632fe3e261146106ec578063328dd9821461072057806332b8113e1461075057600080fd5b8063150b7a02146105fb578063160cbed71461063f57806317977c611461065f57806324bc1a641461068d57600080fd5b8063046f7da2116103c2578063046f7da21461054e57806306f3f9e61461056357806306fdde0314610583578063143489d0146105a557600080fd5b8063013cf08b1461046357806301ffc9a7146104de57806302a251a31461050e578063034201811461052e57600080fd5b3661045e5730610401610edb565b6001600160a01b03161461045c5760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206d7573742073656e6420746f206578656375746f720060448201526064015b60405180910390fd5b005b600080fd5b34801561046f57600080fd5b5061048361047e366004615c87565b610ef5565b604080519a8b526001600160a01b0390991660208b0152978901969096526060880194909452608087019290925260a086015260c085015260e084015215156101008301521515610120820152610140015b60405180910390f35b3480156104ea57600080fd5b506104fe6104f9366004615ca0565b610fb0565b60405190151581526020016104d5565b34801561051a57600080fd5b50610195545b6040519081526020016104d5565b34801561053a57600080fd5b50610520610549366004615de6565b610fc1565b34801561055a57600080fd5b5061045c6110b9565b34801561056f57600080fd5b5061045c61057e366004615c87565b611149565b34801561058f57600080fd5b506105986111d4565b6040516104d59190615edc565b3480156105b157600080fd5b506105e36105c0366004615c87565b60009081526101636020526040902054600160401b90046001600160a01b031690565b6040516001600160a01b0390911681526020016104d5565b34801561060757600080fd5b50610626610616366004615f04565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016104d5565b34801561064b57600080fd5b5061052061065a3660046160db565b611267565b34801561066b57600080fd5b5061052061067a36600461616a565b6102c36020526000908152604090205481565b34801561069957600080fd5b50610520611352565b6105206106b03660046160db565b611378565b3480156106c157600080fd5b506105206106d0366004615c87565b600090815261016360205260409020546001600160401b031690565b3480156106f857600080fd5b506105207fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b34801561072c57600080fd5b5061074061073b366004615c87565b61146b565b6040516104d59493929190616250565b34801561075c57600080fd5b5061028f546040516001600160401b0390911681526020016104d5565b34801561078557600080fd5b5061019454610520565b34801561079b57600080fd5b506105206107aa36600461629d565b6116fd565b3480156107bb57600080fd5b506107cf6107ca366004615c87565b611773565b6040516104d59190616301565b3480156107e857600080fd5b5061045c6107f7366004615c87565b61177e565b34801561080857600080fd5b5061045c61081736600461616a565b6117a9565b34801561082857600080fd5b506104fe610837366004616329565b60008281526101c6602090815260408083206001600160a01b038516845260080190915290205460ff1692915050565b34801561087357600080fd5b506105206108823660046160db565b61182a565b34801561089357600080fd5b506104fe6108a236600461616a565b60016020526000908152604090205460ff1681565b3480156108c357600080fd5b5061045c6108d236600461616a565b611838565b3480156108e357600080fd5b506105986118b3565b3480156108f857600080fd5b50610901600881565b60405160ff90911681526020016104d5565b34801561091f57600080fd5b506104fe61092e36600461616a565b6102c16020526000908152604090205460ff1681565b34801561095057600080fd5b506040805180820190915260018152603160f81b6020820152610598565b34801561097a57600080fd5b50610520610989366004616359565b611960565b34801561099a57600080fd5b506105206109a9366004616385565b611989565b3480156109ba57600080fd5b506105206109c9366004615c87565b6119d3565b3480156109da57600080fd5b5061045c6109e9366004615c87565b611a88565b3480156109fa57600080fd5b50610520610a09366004616408565b611b10565b348015610a1a57600080fd5b50610520610a29366004616461565b611b62565b348015610a3a57600080fd5b5061045c611c7d565b348015610a4f57600080fd5b5061045c611eab565b348015610a6457600080fd5b50610a6d611f41565b6040516104d59796959493929190616501565b348015610a8c57600080fd5b50610a95611fdf565b60405165ffffffffffff90911681526020016104d5565b348015610ab857600080fd5b506064610520565b348015610acc57600080fd5b50610520610adb366004616563565b612053565b348015610aec57600080fd5b5061052061206a565b348015610b0157600080fd5b5061045c610b1036600461616a565b612097565b348015610b2157600080fd5b50610520610b30366004615c87565b61211f565b348015610b4157600080fd5b5061045c610b503660046165bb565b6121bb565b348015610b6157600080fd5b5060005462010000900460ff166104fe565b348015610b7f57600080fd5b50610520612900565b348015610b9457600080fd5b50610626610ba336600461661a565b63bc197c8160e01b95945050505050565b348015610bc057600080fd5b50610520610bcf366004615c87565b61290c565b348015610be057600080fd5b506102c2546104fe9060ff1681565b61045c610bfd3660046166ad565b612917565b348015610c0e57600080fd5b50610520610c1d3660046160db565b612a27565b348015610c2e57600080fd5b5061045c610c3d3660046166f0565b612a61565b348015610c4e57600080fd5b5061022b546001600160a01b03166105e3565b348015610c6d57600080fd5b50610520610c7c366004616719565b612ae9565b348015610c8d57600080fd5b5060408051808201909152601a81527f737570706f72743d627261766f2671756f72756d3d627261766f0000000000006020820152610598565b348015610cd357600080fd5b5061045c610ce2366004615c87565b612b70565b348015610cf357600080fd5b506105207f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610d2757600080fd5b50610db6610d36366004616329565b60408051606081018252600080825260208201819052918101919091525060009182526101c6602090815260408084206001600160a01b0393909316845260089092018152918190208151606081018352905460ff8082161515835261010082041693820193909352620100009092046001600160601b03169082015290565b6040805182511515815260208084015160ff1690820152918101516001600160601b0316908201526060016104d5565b348015610df257600080fd5b5061045c610e01366004615c87565b612b93565b348015610e1257600080fd5b50610520610e213660046167ba565b612c1b565b348015610e3257600080fd5b5061045c610e41366004615c87565b612c3c565b348015610e5257600080fd5b50610901601181565b348015610e6757600080fd5b50610626610e763660046167e6565b63f23a6e6160e01b95945050505050565b348015610e9357600080fd5b50610520610ea2366004615c87565b612cc4565b348015610eb357600080fd5b506101f8546105e3906001600160a01b031681565b61045c610ed6366004615c87565b612d53565b6000610ef061022b546001600160a01b031690565b905090565b8060008080808080808080610f098a61211f565b60008c815261016360205260409020549098506001600160401b03169650610f308b61290c565b60008c81526101c66020526040812080546005820154600683015460078401546001600160a01b039093169e50949a509850929650919450610f718d611773565b90506002816007811115610f8757610f876162eb565b1493506007816007811115610f9e57610f9e6162eb565b14925050509193959799509193959799565b6000610fbb82612d76565b92915050565b60008061106561105d7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c604051610ffd92919061684e565b60405180910390208b80519060200120604051602001611042959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b60405160208183030381529060405280519060200120612d9b565b868686612dc8565b90506110ab8a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d9250612de6915050565b9a9950505050505050505050565b600054630100000090046001600160a01b031633146110eb576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1661111457604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b611151610edb565b6001600160a01b0316336001600160a01b0316146111815760405162461bcd60e51b81526004016104539061685e565b3061118a610edb565b6001600160a01b0316146111c857600080366040516111aa92919061684e565b604051809103902090505b806111c1610164612e4f565b036111b557505b6111d181612ece565b50565b606061016280546111e490616895565b80601f016020809104026020016040519081016040528092919081815260200182805461121090616895565b801561125d5780601f106112325761010080835404028352916020019161125d565b820191906000526020600020905b81548152906001019060200180831161124057829003601f168201915b5050505050905090565b6000805462010000900460ff161561129257604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156112c35760405163b1d02c3d60e01b815260040160405180910390fd5b60005b855181101561133c576102c160008783815181106112e6576112e66168cf565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1661132a57604051630b094f2760e31b815260040160405180910390fd5b80611334816168fb565b9150506112c6565b506113498585858561303f565b95945050505050565b6000610ef06001611361611fdf565b61136b9190616914565b65ffffffffffff16612cc4565b60008061138786868686612a27565b9050600061139482611773565b905060048160078111156113aa576113aa6162eb565b14806113c7575060058160078111156113c5576113c56162eb565b145b6113e35760405162461bcd60e51b81526004016104539061693a565b6000828152610163602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f906114329084815260200190565b60405180910390a16114478288888888613244565b61145482888888886132e5565b61146182888888886133c7565b5095945050505050565b60608060608060006101c66000878152602001908152602001600020905080600101816002018260030183600401838054806020026020016040519081016040528092919081815260200182805480156114ee57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114d0575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561154057602002820191906000526020600020905b81548152602001906001019080831161152c575b5050505050925081805480602002602001604051908101604052809291908181526020016000905b8282101561161457838290600052602060002001805461158790616895565b80601f01602080910402602001604051908101604052809291908181526020018280546115b390616895565b80156116005780601f106115d557610100808354040283529160200191611600565b820191906000526020600020905b8154815290600101906020018083116115e357829003601f168201915b505050505081526020019060010190611568565b50505050915080805480602002602001604051908101604052809291908181526020016000905b828210156116e757838290600052602060002001805461165a90616895565b80601f016020809104026020016040519081016040528092919081815260200182805461168690616895565b80156116d35780601f106116a8576101008083540402835291602001916116d3565b820191906000526020600020905b8154815290600101906020018083116116b657829003601f168201915b50505050508152602001906001019061163b565b5050505090509450945094509450509193509193565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff85166060820152600090819061174b9061105d90608001611042565b905061176887828860405180602001604052806000815250613402565b979650505050505050565b6000610fbb82613425565b60008060008061178d85613572565b93509350935093506117a18484848461182a565b505050505050565b600054630100000090046001600160a01b031633146117db576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b600061134985858585613803565b600054630100000090046001600160a01b0316331461186a576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b6101f85460408051634bf5d7e960e01b815290516060926001600160a01b031691634bf5d7e99160048083019260009291908290030181865afa92505050801561191f57506040513d6000823e601f3d908101601f1916820160405261191c919081019061697b565b60015b61195b575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b60008033905061198184828560405180602001604052806000815250613402565b949350505050565b60008033905061176887828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250612de6915050565b61025e546000908082036119ec57505061025d54919050565b600061025e6119fc6001846169e8565b81548110611a0c57611a0c6168cf565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b03169282019290925291508410611a6257602001516001600160e01b03169392505050565b611a77611a6e856138ce565b61025e90613937565b6001600160e01b0316949350505050565b611a90610edb565b6001600160a01b0316336001600160a01b031614611ac05760405162461bcd60e51b81526004016104539061685e565b30611ac9610edb565b6001600160a01b031614611b075760008036604051611ae992919061684e565b604051809103902090505b80611b00610164612e4f565b03611af457505b6111d1816139ea565b600080339050611b5886828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061340292505050565b9695505050505050565b6000805462010000900460ff1615611b8d57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615611bbe5760405163b1d02c3d60e01b815260040160405180910390fd5b611bc6613a2d565b3360009081526102c360205260409020548015611c3b576000611be882611773565b90506001816007811115611bfe57611bfe6162eb565b1480611c1b57506000816007811115611c1957611c196162eb565b145b15611c395760405163867f3ee560e01b815260040160405180910390fd5b505b825160208401206000611c5088888885612a27565b3360009081526102c3602052604090208190559050611c7188888888613ad8565b98975050505050505050565b600054610100900460ff1615808015611c9d5750600054600160ff909116105b80611cb75750303b158015611cb7575060005460ff166001145b611d1a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610453565b6000805460ff191660011790558015611d3d576000805461ff0019166101001790555b334114611d5d5760405163022d8c9560e31b815260040160405180910390fd5b3a15611d7c576040516383f1b1d360e01b815260040160405180910390fd5b611da86040518060400160405280600b81526020016a2129a1a3b7bb32b93737b960a91b815250613b40565b611dd2611db76003603c616a11565b611dc360036078616a11565b680ad78ebc5ac6200000613b97565b611dda613bce565b611de5612005613bf5565b611df0612006613c25565b611dfa600a613c55565b611e0e611e096003603c616a11565b613c85565b6110076000526102c16020527f2f832952f0ef896b8c8edd6d16a2e4f2591a90375e33021e3b9ff197f3793fc0805460ff19166001179055611e6373df87f0e2b8519ea2dd4abd8b639cdd628497ed25613cb5565b80156111d1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b600054630100000090046001600160a01b03163314611edd576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1615611f0757604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b6000606080600080600060606098546000801b148015611f615750609954155b611fa55760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606401610453565b611fad613d08565b611fb5613d17565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6101f854604080516324776b7d60e21b815290516000926001600160a01b0316916391ddadf49160048083019260209291908290030181865afa925050508015612046575060408051601f3d908101601f1916820190925261204391810190616a33565b60015b61195b57610ef043613d26565b6000612060848484613d8d565b90505b9392505050565b61025e546000901561208f5761208161025e613e04565b6001600160e01b0316905090565b5061025d5490565b61209f610edb565b6001600160a01b0316336001600160a01b0316146120cf5760405162461bcd60e51b81526004016104539061685e565b306120d8610edb565b6001600160a01b03161461211657600080366040516120f892919061684e565b604051809103902090505b8061210f610164612e4f565b0361210357505b6111d181613e34565b61022b54600082815261022c602052604080822054905163d45c443560e01b81526004810191909152909182916001600160a01b039091169063d45c443590602401602060405180830381865afa15801561217e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a29190616a5b565b9050806001146121b25780612063565b60009392505050565b33611007146121e157604051630f22c43960e41b81526110076004820152602401610453565b6122476040518060400160405280600b81526020016a766f74696e6744656c617960a81b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613e9f9050565b156122fc57602081146122755783838383604051630a5a604160e01b81526004016104539493929190616a9d565b604080516020601f84018190048102820181019092528281526000916122b6918585808385018382808284376000920191909152509293925050613ef89050565b90508015806122c757506201518081115b156122ed5784848484604051630a5a604160e01b81526004016104539493929190616a9d565b6122f6816139ea565b506128bd565b6123636040518060400160405280600c81526020016b1d9bdd1a5b99d4195c9a5bd960a21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613e9f9050565b1561241257602081146123915783838383604051630a5a604160e01b81526004016104539493929190616a9d565b604080516020601f84018190048102820181019092528281526000916123d2918585808385018382808284376000920191909152509293925050613ef89050565b90508015806123e3575062278d0081115b156124095784848484604051630a5a604160e01b81526004016104539493929190616a9d565b6122f681613efd565b61247e604051806040016040528060118152602001701c1c9bdc1bdcd85b151a1c995cda1bdb19607a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613e9f9050565b1561253457602081146124ac5783838383604051630a5a604160e01b81526004016104539493929190616a9d565b604080516020601f84018190048102820181019092528281526000916124ed918585808385018382808284376000920191909152509293925050613ef89050565b9050801580612505575069021e19e0c9bab240000081115b1561252b5784848484604051630a5a604160e01b81526004016104539493929190616a9d565b6122f681613fa0565b61259e6040518060400160405280600f81526020016e38bab7b93ab6a73ab6b2b930ba37b960891b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613e9f9050565b1561264d57602081146125cc5783838383604051630a5a604160e01b81526004016104539493929190616a9d565b604080516020601f840181900481028201810190925282815260009161260d918585808385018382808284376000920191909152509293925050613ef89050565b9050600581108061261e5750601481115b156126445784848484604051630a5a604160e01b81526004016104539493929190616a9d565b6122f681612ece565b6126bc604051806040016040528060148152602001736d696e506572696f64416674657251756f72756d60601b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613e9f9050565b1561278257600881146126ea5783838383604051630a5a604160e01b81526004016104539493929190616a9d565b6000612730600884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ef89050565b90506001600160401b038116158061275357506202a300816001600160401b0316115b156127795784848484604051630a5a604160e01b81526004016104539493929190616a9d565b6122f681613fe3565b6127ee6040518060400160405280601181526020017033b7bb32b93737b9283937ba32b1ba37b960791b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613e9f9050565b1561289c576014811461281c5783838383604051630a5a604160e01b81526004016104539493929190616a9d565b6000612862601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ef89050565b90506001600160a01b0381166128935784848484604051630a5a604160e01b81526004016104539493929190616a9d565b6122f68161404f565b838383836040516325ee20d560e21b81526004016104539493929190616a9d565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516128f29493929190616a9d565b60405180910390a150505050565b6000610ef06101965490565b6000610fbb826140bb565b61291f610edb565b6001600160a01b0316336001600160a01b03161461294f5760405162461bcd60e51b81526004016104539061685e565b30612958610edb565b6001600160a01b031614612996576000803660405161297892919061684e565b604051809103902090505b8061298f610164612e4f565b0361298357505b600080856001600160a01b03168585856040516129b492919061684e565b60006040518083038185875af1925050503d80600081146129f1576040519150601f19603f3d011682016040523d82523d6000602084013e6129f6565b606091505b5091509150612a1e8282604051806060016040528060288152602001616efa602891396140f9565b50505050505050565b600084848484604051602001612a409493929190616ac4565b60408051601f19818403018152919052805160209091012095945050505050565b612a69610edb565b6001600160a01b0316336001600160a01b031614612a995760405162461bcd60e51b81526004016104539061685e565b30612aa2610edb565b6001600160a01b031614612ae05760008036604051612ac292919061684e565b604051809103902090505b80612ad9610164612e4f565b03612acd57505b6111d181613fe3565b60008251845114612b4d5760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72427261766f3a20696e76616c6964207369676e61747572656044820152670e640d8cadccee8d60c31b6064820152608401610453565b612b5b338787878787614112565b611b588686612b6a87876141d0565b85611b62565b600080600080612b7f85613572565b93509350935093506117a184848484611267565b612b9b610edb565b6001600160a01b0316336001600160a01b031614612bcb5760405162461bcd60e51b81526004016104539061685e565b30612bd4610edb565b6001600160a01b031614612c125760008036604051612bf492919061684e565b604051809103902090505b80612c0b610164612e4f565b03612bff57505b6111d181613efd565b60006120638383612c3760408051602081019091526000815290565b613d8d565b612c44610edb565b6001600160a01b0316336001600160a01b031614612c745760405162461bcd60e51b81526004016104539061685e565b30612c7d610edb565b6001600160a01b031614612cbb5760008036604051612c9d92919061684e565b604051809103902090505b80612cb4610164612e4f565b03612ca857505b6111d181613fa0565b60006064612cd1836119d3565b6101f854604051632394e7a360e21b8152600481018690526001600160a01b0390911690638e539e8c90602401602060405180830381865afa158015612d1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3f9190616a5b565b612d499190616b0f565b610fbb9190616a11565b600080600080612d6285613572565b93509350935093506117a184848484611378565b60006001600160e01b03198216636e665ced60e01b1480610fbb5750610fbb82614302565b6000610fbb612da861439e565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000612dd9878787876143a8565b915091506114618161446c565b6000805462010000900460ff1615612e1157604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615612e425760405163b1d02c3d60e01b815260040160405180910390fd5b611b5886868686866145b6565b6000612e6a8254600f81810b600160801b909204900b131590565b15612e8857604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b6064811115612f515760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610453565b6000612f5b61206a565b90508015801590612f6d575061025e54155b15612fd257604080518082019091526000815261025e9060208101612f91846146b9565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b613000612fed612fe0611fdf565b65ffffffffffff166138ce565b612ff6846146b9565b61025e9190614722565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60008061304e86868686612a27565b9050600461305b82611773565b600781111561306c5761306c6162eb565b146130895760405162461bcd60e51b81526004016104539061693a565b61022b546040805163793d064960e11b815290516000926001600160a01b03169163f27a0c929160048083019260209291908290030181865afa1580156130d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f89190616a5b565b61022b5460405163b1c5f42760e01b81529192506001600160a01b03169063b1c5f42790613133908a908a908a906000908b90600401616b26565b602060405180830381865afa158015613150573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131749190616a5b565b600083815261022c60205260408082209290925561022b5491516308f2a0bb60e41b81526001600160a01b0390921691638f2a0bb0916131c1918b918b918b91908b908990600401616b74565b600060405180830381600087803b1580156131db57600080fd5b505af11580156131ef573d6000803e3d6000fd5b505050507f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda28928282426132219190616bcc565b604080519283526020830191909152015b60405180910390a15095945050505050565b3061324d610edb565b6001600160a01b0316146132de5760005b84518110156117a157306001600160a01b0316858281518110613283576132836168cf565b60200260200101516001600160a01b0316036132ce576132ce8382815181106132ae576132ae6168cf565b60200260200101518051906020012061016461473d90919063ffffffff16565b6132d7816168fb565b905061325e565b5050505050565b60005462010000900460ff161561330f57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156133405760405163b1d02c3d60e01b815260040160405180910390fd5b60005b84518110156133b9576102c16000868381518110613363576133636168cf565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff166133a757604051630b094f2760e31b815260040160405180910390fd5b806133b1816168fb565b915050613343565b506132de8585858585614779565b306133d0610edb565b6001600160a01b0316146132de5761016454600f81810b600160801b909204900b13156132de576000610164556132de565b60006113498585858561342060408051602081019091526000815290565b612de6565b600080613431836147ee565b90506004816007811115613447576134476162eb565b146134525792915050565b600083815261022c60205260409020548061346e575092915050565b61022b54604051632ab0f52960e01b8152600481018390526001600160a01b0390911690632ab0f52990602401602060405180830381865afa1580156134b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134dc9190616bdf565b156134eb575060079392505050565b61022b54604051632c258a9f60e11b8152600481018390526001600160a01b039091169063584b153e90602401602060405180830381865afa158015613535573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135599190616bdf565b15613568575060059392505050565b5060029392505050565b60608060606000806101c660008781526020019081526020016000209050806001018160020161374483600301805480602002602001604051908101604052809291908181526020016000905b8282101561366b5783829060005260206000200180546135de90616895565b80601f016020809104026020016040519081016040528092919081815260200182805461360a90616895565b80156136575780601f1061362c57610100808354040283529160200191613657565b820191906000526020600020905b81548152906001019060200180831161363a57829003601f168201915b5050505050815260200190600101906135bf565b50505060048601805460408051602080840282018101909252828152935060009084015b8282101561373b5783829060005260206000200180546136ae90616895565b80601f01602080910402602001604051908101604052809291908181526020018280546136da90616895565b80156137275780601f106136fc57610100808354040283529160200191613727565b820191906000526020600020905b81548152906001019060200180831161370a57829003601f168201915b50505050508152602001906001019061368f565b505050506141d0565b600984015483546040805160208084028201810190925282815291869183018282801561379a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161377c575b50505050509350828054806020026020016040519081016040528092919081815260200182805480156137ec57602002820191906000526020600020905b8154815260200190600101908083116137d8575b505050505092509450945094509450509193509193565b60008061381286868686612a27565b60008181526101c660205260409020549091506001600160a01b031633811480613866575061383f612900565b61386482600161384d611fdf565b6138579190616914565b65ffffffffffff16612c1b565b105b6138c25760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72427261766f3a2070726f706f7365722061626f76652074686044820152661c995cda1bdb1960ca1b6064820152608401610453565b61176887878787614926565b600063ffffffff8211156139335760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610453565b5090565b81546000908181600581111561399457600061395284614934565b61395c90856169e8565b60008881526020902090915081015463ffffffff908116908716101561398457809150613992565b61398f816001616bcc565b92505b505b60006139a287878585614a1c565b905080156139dd576139c7876139b96001846169e8565b600091825260209091200190565b54600160201b90046001600160e01b0316611768565b6000979650505050505050565b6101945460408051918252602082018390527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a93910160405180910390a161019455565b6102c25460ff16613ad6576a084595161401484a0000006120056001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aa89190616a5b565b1015613ac7576040516311b6707f60e01b815260040160405180910390fd5b6102c2805460ff191660011790555b565b6000613b3433868686516001600160401b03811115613af957613af9615d23565b604051908082528060200260200182016040528015613b2c57816020015b6060815260200190600190039081613b175790505b508787614112565b61134985858585614a72565b600054610100900460ff16613b675760405162461bcd60e51b815260040161045390616c01565b613b8e81613b896040805180820190915260018152603160f81b602082015290565b614e51565b6111d181614ea0565b600054610100900460ff16613bbe5760405162461bcd60e51b815260040161045390616c01565b613bc9838383614ed8565b505050565b600054610100900460ff16613ad65760405162461bcd60e51b815260040161045390616c01565b600054610100900460ff16613c1c5760405162461bcd60e51b815260040161045390616c01565b6111d181614f1a565b600054610100900460ff16613c4c5760405162461bcd60e51b815260040161045390616c01565b6111d181614f64565b600054610100900460ff16613c7c5760405162461bcd60e51b815260040161045390616c01565b6111d181614f8b565b600054610100900460ff16613cac5760405162461bcd60e51b815260040161045390616c01565b6111d181614fb2565b600054610100900460ff16613cdc5760405162461bcd60e51b815260040161045390616c01565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b6060609a80546111e490616895565b6060609b80546111e490616895565b600065ffffffffffff8211156139335760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610453565b6101f854604051630748d63560e31b81526001600160a01b038581166004830152602482018590526000921690633a46b1a890604401602060405180830381865afa158015613de0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190616a5b565b805460009080156121b257613e1e836139b96001846169e8565b54600160201b90046001600160e01b0316612063565b61022b54604080516001600160a01b03928316815291831660208301527f08f74ea46ef7894f65eabfb5e6e695de773a000b47c529ab559178069b226401910160405180910390a161022b80546001600160a01b0319166001600160a01b0392909216919091179055565b600081604051602001613eb29190616c4c565b6040516020818303038152906040528051906020012083604051602001613ed99190616c4c565b6040516020818303038152906040528051906020012014905092915050565b015190565b60008111613f5d5760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253657474696e67733a20766f74696e6720706572696f6420604482015266746f6f206c6f7760c81b6064820152608401610453565b6101955460408051918252602082018390527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828910160405180910390a161019555565b6101965460408051918252602082018390527fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc05461910160405180910390a161019655565b61028f54604080516001600160401b03928316815291831660208301527f7ca4ac117ed3cdce75c1161d8207c440389b1a15d69d096831664657c07dafc2910160405180910390a161028f805467ffffffffffffffff19166001600160401b0392909216919091179055565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008181526101636020526040812060010154610fbb906001600160401b0316600084815261029060205260409020546001600160401b0316614fd9565b60608315614108575081612063565b6120638383614fef565b805160208201206000614130878761412a88886141d0565b85612a27565b60008181526101c6602052604090206009810154919250906141c55780546001600160a01b0319166001600160a01b038a16178155875161417a90600183019060208b0190615abe565b50865161419090600283019060208a0190615b1f565b5085516141a69060038301906020890190615b5a565b5084516141bc9060048301906020880190615bac565b50600981018390555b505050505050505050565b6060600082516001600160401b038111156141ed576141ed615d23565b60405190808252806020026020018201604052801561422057816020015b606081526020019060019003908161420b5790505b50905060005b81518110156142fa57848181518110614241576142416168cf565b6020026020010151516000146142b157848181518110614263576142636168cf565b602002602001015180519060200120848281518110614284576142846168cf565b602002602001015160405160200161429d929190616c68565b6040516020818303038152906040526142cc565b8381815181106142c3576142c36168cf565b60200260200101515b8282815181106142de576142de6168cf565b6020026020010181905250806142f3906168fb565b9050614226565b509392505050565b600063288ace0360e11b6318df743f60e31b63bf26d89760e01b6379dd796f60e01b6001600160e01b0319861682148061434857506001600160e01b0319868116908216145b8061435f57506001600160e01b0319868116908516145b8061437a57506001600160e01b03198616630271189760e51b145b80611b5857506301ffc9a760e01b6001600160e01b03198716149695505050505050565b6000610ef0615019565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143df5750600090506003614463565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614433573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661445c57600060019250925050614463565b9150600090505b94509492505050565b6000816004811115614480576144806162eb565b036144885750565b600181600481111561449c5761449c6162eb565b036144e95760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610453565b60028160048111156144fd576144fd6162eb565b0361454a5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610453565b600381600481111561455e5761455e6162eb565b036111d15760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610453565b6000806145c6878787878761508d565b600088815261029060205260409020549091506001600160401b03161580156145f357506145f3876151e3565b15611b5857600061460d61028f546001600160401b031690565b614615611fdf565b65ffffffffffff166146279190616c99565b90506146328861290c565b816001600160401b03161115614681576040516001600160401b038216815288907f541f725fb9f7c98a30cc9c0ff32fbb14358cd7159c847a3aa20a2bdc442ba5119060200160405180910390a25b600088815261029060205260409020805467ffffffffffffffff19166001600160401b03929092169190911790559695505050505050565b60006001600160e01b038211156139335760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610453565b600080614730858585615223565b915091505b935093915050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b61022b5460405163e38335e560e01b81526001600160a01b039091169063e38335e59034906147b5908890889088906000908990600401616b26565b6000604051808303818588803b1580156147ce57600080fd5b505af11580156147e2573d6000803e3d6000fd5b50505050505050505050565b600081815261016360205260408120600281015460ff16156148135750600792915050565b6002810154610100900460ff161561482e5750600292915050565b600083815261016360205260408120546001600160401b0316908190036148975760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610453565b60006148a1611fdf565b65ffffffffffff1690508082106148bd57506000949350505050565b60006148c88661290c565b90508181106148dd5750600195945050505050565b6148e6866151e3565b8015614909575060008681526101c6602052604090206006810154600590910154115b1561491a5750600495945050505050565b50600395945050505050565b6000611349858585856153c2565b60008160000361494657506000919050565b6000600161495384615478565b901c6001901b9050600181848161496c5761496c6169fb565b048201901c90506001818481614984576149846169fb565b048201901c9050600181848161499c5761499c6169fb565b048201901c905060018184816149b4576149b46169fb565b048201901c905060018184816149cc576149cc6169fb565b048201901c905060018184816149e4576149e46169fb565b048201901c905060018184816149fc576149fc6169fb565b048201901c905061206381828581614a1657614a166169fb565b0461550c565b60005b818310156142fa576000614a33848461551b565b60008781526020902090915063ffffffff86169082015463ffffffff161115614a5e57809250614a6c565b614a69816001616bcc565b93505b50614a1f565b600033614a7f8184615536565b614acb5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73657220726573747269637465640000006044820152606401610453565b6000614ad5611fdf565b65ffffffffffff169050614ae7612900565b614af683610e216001856169e8565b1015614b5e5760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610453565b6000614b738888888880519060200120612a27565b90508651885114614b965760405162461bcd60e51b815260040161045390616cb9565b8551885114614bb75760405162461bcd60e51b815260040161045390616cb9565b6000885111614c085760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610453565b600081815261016360205260409020546001600160401b031615614c785760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610453565b6000614c846101945490565b614c8e9084616bcc565b90506000614c9c6101955490565b614ca69083616bcc565b90506040518060e00160405280614cbc84615627565b6001600160401b031681526001600160a01b038716602082015260006040820152606001614ce983615627565b6001600160401b03908116825260006020808401829052604080850183905260609485018390528883526101638252918290208551815492870151878501519186166001600160e01b031990941693909317600160401b6001600160a01b039094168402176001600160e01b0316600160e01b60e09290921c91909102178155938501516080860151908416921c0217600183015560a08301516002909201805460c09094015161ffff1990941692151561ff00191692909217610100931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e91811115614dee57614dee615d23565b604051908082528060200260200182016040528015614e2157816020015b6060815260200190600190039081614e0c5790505b508d88888f604051614e3b99989796959493929190616cfa565b60405180910390a1509098975050505050505050565b600054610100900460ff16614e785760405162461bcd60e51b815260040161045390616c01565b609a614e848382616dd8565b50609b614e918282616dd8565b50506000609881905560995550565b600054610100900460ff16614ec75760405162461bcd60e51b815260040161045390616c01565b610162614ed48282616dd8565b5050565b600054610100900460ff16614eff5760405162461bcd60e51b815260040161045390616c01565b614f08836139ea565b614f1182613efd565b613bc981613fa0565b600054610100900460ff16614f415760405162461bcd60e51b815260040161045390616c01565b6101f880546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166121165760405162461bcd60e51b815260040161045390616c01565b600054610100900460ff166111c85760405162461bcd60e51b815260040161045390616c01565b600054610100900460ff16612ae05760405162461bcd60e51b815260040161045390616c01565b6000818311614fe85781612063565b5090919050565b815115614fff5781518083602001fd5b8060405162461bcd60e51b81526004016104539190615edc565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61504461568f565b61504c6156e8565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60008581526101636020526040812060016150a788611773565b60078111156150b8576150b86162eb565b146151115760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610453565b805460009061512b9088906001600160401b031686613d8d565b905061513a8888888488615719565b835160000361518f57866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda4898884896040516151829493929190616e97565b60405180910390a2611768565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb871289888489896040516151d0959493929190616ebf565b60405180910390a2979650505050505050565b60008181526101c660205260408120600581015461521a610ea285600090815261016360205260409020546001600160401b031690565b11159392505050565b825460009081908015615369576000615241876139b96001856169e8565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090871610156152c25760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610453565b805163ffffffff80881691160361530a57846152e3886139b96001866169e8565b80546001600160e01b0392909216600160201b0263ffffffff909216919091179055615359565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b6020015192508391506147359050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b029190931617920191909155905081614735565b6000806153d1868686866158b7565b600081815261022c6020526040902054909150156113495761022b54600082815261022c60205260409081902054905163c4d252f560e01b81526001600160a01b039092169163c4d252f59161542d9160040190815260200190565b600060405180830381600087803b15801561544757600080fd5b505af115801561545b573d6000803e3d6000fd5b505050600082815261022c60205260408120555095945050505050565b600080608083901c1561548d57608092831c92015b604083901c1561549f57604092831c92015b602083901c156154b157602092831c92015b601083901c156154c357601092831c92015b600883901c156154d557600892831c92015b600483901c156154e757600492831c92015b600283901c156154f957600292831c92015b600183901c15610fbb5760010192915050565b6000818310614fe85781612063565b600061552a6002848418616a11565b61206390848416616bcc565b8051600090603481101561554e576001915050610fbb565b82810160131901516001600160a01b031981166b046e0e4dee0dee6cae47a60f60a31b1461558157600192505050610fbb565b60008061558f6028856169e8565b90505b83811015615606576000806155c68884815181106155b2576155b26168cf565b01602001516001600160f81b0319166159c4565b91509150816155de5760019650505050505050610fbb565b8060ff166004856001600160a01b0316901b1793505050806155ff906168fb565b9050615592565b50856001600160a01b0316816001600160a01b031614935050505092915050565b60006001600160401b038211156139335760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610453565b60008061569a613d08565b8051909150156156b1578051602090910120919050565b60985480156156c05792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b6000806156f3613d17565b80519091501561570a578051602090910120919050565b60995480156156c05792915050565b60008581526101c6602090815260408083206001600160a01b038816845260088101909252909120805460ff16156157a95760405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20766f746560448201526c08185b1c9958591e4818d85cdd609a1b6064820152608401610453565b805460ff86166101000261ffff199091161760011781556157c984615a56565b81546001600160601b039190911662010000026dffffffffffffffffffffffff00001990911617815560ff8516615819578382600601600082825461580e9190616bcc565b90915550612a1e9050565b60001960ff861601615839578382600501600082825461580e9190616bcc565b60011960ff861601615859578382600701600082825461580e9190616bcc565b60405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20696e766160448201526c6c696420766f7465207479706560981b6064820152608401610453565b6000806158c686868686612a27565b905060006158d382611773565b905060028160078111156158e9576158e96162eb565b1415801561590957506006816007811115615906576159066162eb565b14155b801561592757506007816007811115615924576159246162eb565b14155b6159735760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610453565b6000828152610163602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c906132329084815260200190565b60008060f883901c602f811180156159df5750603a8160ff16105b156159f457600194602f199091019350915050565b8060ff166040108015615a0a575060478160ff16105b15615a1f576001946036199091019350915050565b8060ff166060108015615a35575060678160ff16105b15615a4a576001946056199091019350915050565b50600093849350915050565b60006001600160601b038211156139335760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610453565b828054828255906000526020600020908101928215615b13579160200282015b82811115615b1357825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615ade565b50613933929150615bfe565b828054828255906000526020600020908101928215615b13579160200282015b82811115615b13578251825591602001919060010190615b3f565b828054828255906000526020600020908101928215615ba0579160200282015b82811115615ba05782518290615b909082616dd8565b5091602001919060010190615b7a565b50613933929150615c13565b828054828255906000526020600020908101928215615bf2579160200282015b82811115615bf25782518290615be29082616dd8565b5091602001919060010190615bcc565b50613933929150615c30565b5b808211156139335760008155600101615bff565b80821115613933576000615c278282615c4d565b50600101615c13565b80821115613933576000615c448282615c4d565b50600101615c30565b508054615c5990616895565b6000825580601f10615c69575050565b601f0160209004906000526020600020908101906111d19190615bfe565b600060208284031215615c9957600080fd5b5035919050565b600060208284031215615cb257600080fd5b81356001600160e01b03198116811461206357600080fd5b803560ff8116811461195b57600080fd5b60008083601f840112615ced57600080fd5b5081356001600160401b03811115615d0457600080fd5b602083019150836020828501011115615d1c57600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715615d6157615d61615d23565b604052919050565b60006001600160401b03821115615d8257615d82615d23565b50601f01601f191660200190565b600082601f830112615da157600080fd5b8135615db4615daf82615d69565b615d39565b818152846020838601011115615dc957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060e0898b031215615e0257600080fd5b88359750615e1260208a01615cca565b965060408901356001600160401b0380821115615e2e57600080fd5b615e3a8c838d01615cdb565b909850965060608b0135915080821115615e5357600080fd5b50615e608b828c01615d90565b945050615e6f60808a01615cca565b925060a0890135915060c089013590509295985092959890939650565b60005b83811015615ea7578181015183820152602001615e8f565b50506000910152565b60008151808452615ec8816020860160208601615e8c565b601f01601f19169290920160200192915050565b6020815260006120636020830184615eb0565b6001600160a01b03811681146111d157600080fd5b60008060008060808587031215615f1a57600080fd5b8435615f2581615eef565b93506020850135615f3581615eef565b92506040850135915060608501356001600160401b03811115615f5757600080fd5b615f6387828801615d90565b91505092959194509250565b60006001600160401b03821115615f8857615f88615d23565b5060051b60200190565b600082601f830112615fa357600080fd5b81356020615fb3615daf83615f6f565b82815260059290921b84018101918181019086841115615fd257600080fd5b8286015b84811015615ff6578035615fe981615eef565b8352918301918301615fd6565b509695505050505050565b600082601f83011261601257600080fd5b81356020616022615daf83615f6f565b82815260059290921b8401810191818101908684111561604157600080fd5b8286015b84811015615ff65780358352918301918301616045565b600082601f83011261606d57600080fd5b8135602061607d615daf83615f6f565b82815260059290921b8401810191818101908684111561609c57600080fd5b8286015b84811015615ff65780356001600160401b038111156160bf5760008081fd5b6160cd8986838b0101615d90565b8452509183019183016160a0565b600080600080608085870312156160f157600080fd5b84356001600160401b038082111561610857600080fd5b61611488838901615f92565b9550602087013591508082111561612a57600080fd5b61613688838901616001565b9450604087013591508082111561614c57600080fd5b506161598782880161605c565b949793965093946060013593505050565b60006020828403121561617c57600080fd5b813561206381615eef565b600081518084526020808501945080840160005b838110156161c05781516001600160a01b03168752958201959082019060010161619b565b509495945050505050565b600081518084526020808501945080840160005b838110156161c0578151875295820195908201906001016161df565b600081518084526020808501808196508360051b8101915082860160005b85811015616243578284038952616231848351615eb0565b98850198935090840190600101616219565b5091979650505050505050565b6080815260006162636080830187616187565b828103602084015261627581876161cb565b9050828103604084015261628981866161fb565b9050828103606084015261176881856161fb565b600080600080600060a086880312156162b557600080fd5b853594506162c560208701615cca565b93506162d360408701615cca565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b602081016008831061632357634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561633c57600080fd5b82359150602083013561634e81615eef565b809150509250929050565b6000806040838503121561636c57600080fd5b8235915061637c60208401615cca565b90509250929050565b60008060008060006080868803121561639d57600080fd5b853594506163ad60208701615cca565b935060408601356001600160401b03808211156163c957600080fd5b6163d589838a01615cdb565b909550935060608801359150808211156163ee57600080fd5b506163fb88828901615d90565b9150509295509295909350565b6000806000806060858703121561641e57600080fd5b8435935061642e60208601615cca565b925060408501356001600160401b0381111561644957600080fd5b61645587828801615cdb565b95989497509550505050565b6000806000806080858703121561647757600080fd5b84356001600160401b038082111561648e57600080fd5b61649a88838901615f92565b955060208701359150808211156164b057600080fd5b6164bc88838901616001565b945060408701359150808211156164d257600080fd5b6164de8883890161605c565b935060608701359150808211156164f457600080fd5b50615f6387828801615d90565b60ff60f81b8816815260e06020820152600061652060e0830189615eb0565b82810360408401526165328189615eb0565b606084018890526001600160a01b038716608085015260a0840186905283810360c085015290506110ab81856161cb565b60008060006060848603121561657857600080fd5b833561658381615eef565b92506020840135915060408401356001600160401b038111156165a557600080fd5b6165b186828701615d90565b9150509250925092565b600080600080604085870312156165d157600080fd5b84356001600160401b03808211156165e857600080fd5b6165f488838901615cdb565b9096509450602087013591508082111561660d57600080fd5b5061645587828801615cdb565b600080600080600060a0868803121561663257600080fd5b853561663d81615eef565b9450602086013561664d81615eef565b935060408601356001600160401b038082111561666957600080fd5b61667589838a01616001565b9450606088013591508082111561668b57600080fd5b61669789838a01616001565b935060808801359150808211156163ee57600080fd5b600080600080606085870312156166c357600080fd5b84356166ce81615eef565b93506020850135925060408501356001600160401b0381111561644957600080fd5b60006020828403121561670257600080fd5b81356001600160401b038116811461206357600080fd5b600080600080600060a0868803121561673157600080fd5b85356001600160401b038082111561674857600080fd5b61675489838a01615f92565b9650602088013591508082111561676a57600080fd5b61677689838a01616001565b9550604088013591508082111561678c57600080fd5b61679889838a0161605c565b945060608801359150808211156167ae57600080fd5b61669789838a0161605c565b600080604083850312156167cd57600080fd5b82356167d881615eef565b946020939093013593505050565b600080600080600060a086880312156167fe57600080fd5b853561680981615eef565b9450602086013561681981615eef565b9350604086013592506060860135915060808601356001600160401b0381111561684257600080fd5b6163fb88828901615d90565b8183823760009101908152919050565b60208082526018908201527f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000604082015260600190565b600181811c908216806168a957607f821691505b6020821081036168c957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161690d5761690d6168e5565b5060010190565b65ffffffffffff828116828216039080821115616933576169336168e5565b5092915050565b60208082526021908201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756040820152601b60fa1b606082015260800190565b60006020828403121561698d57600080fd5b81516001600160401b038111156169a357600080fd5b8201601f810184136169b457600080fd5b80516169c2615daf82615d69565b8181528560208385010111156169d757600080fd5b611349826020830160208601615e8c565b81810381811115610fbb57610fbb6168e5565b634e487b7160e01b600052601260045260246000fd5b600082616a2e57634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215616a4557600080fd5b815165ffffffffffff8116811461206357600080fd5b600060208284031215616a6d57600080fd5b5051919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000616ab1604083018688616a74565b8281036020840152611768818587616a74565b608081526000616ad76080830187616187565b8281036020840152616ae981876161cb565b90508281036040840152616afd81866161fb565b91505082606083015295945050505050565b8082028115828204841417610fbb57610fbb6168e5565b60a081526000616b3960a0830188616187565b8281036020840152616b4b81886161cb565b90508281036040840152616b5f81876161fb565b60608401959095525050608001529392505050565b60c081526000616b8760c0830189616187565b8281036020840152616b9981896161cb565b90508281036040840152616bad81886161fb565b60608401969096525050608081019290925260a0909101529392505050565b80820180821115610fbb57610fbb6168e5565b600060208284031215616bf157600080fd5b8151801515811461206357600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251616c5e818460208701615e8c565b9190910192915050565b6001600160e01b0319831681528151600090616c8b816004850160208701615e8c565b919091016004019392505050565b6001600160401b03818116838216019080821115616933576169336168e5565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b8981526001600160a01b038916602082015261012060408201819052600090616d258382018b616187565b90508281036060840152616d39818a6161cb565b90508281036080840152616d4d81896161fb565b905082810360a0840152616d6181886161fb565b90508560c08401528460e0840152828103610100840152616d828185615eb0565b9c9b505050505050505050505050565b601f821115613bc957600081815260208120601f850160051c81016020861015616db95750805b601f850160051c820191505b818110156117a157828155600101616dc5565b81516001600160401b03811115616df157616df1615d23565b616e0581616dff8454616895565b84616d92565b602080601f831160018114616e3a5760008415616e225750858301515b600019600386901b1c1916600185901b1785556117a1565b600085815260208120601f198616915b82811015616e6957888601518255948401946001909101908401616e4a565b5085821015616e875787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b84815260ff84166020820152826040820152608060608201526000611b586080830184615eb0565b85815260ff8516602082015283604082015260a060608201526000616ee760a0830185615eb0565b8281036080840152611c718185615eb056fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765a164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(GovTokenContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b50600436106102065760003560e01c806370a082311161011a5780639ab24eb0116100ad578063d505accf1161007c578063d505accf1461049d578063dd62ed3e146104b0578063e5ed5b1e146104c3578063f1127ed8146104d6578063f1fad1041461051357600080fd5b80639ab24eb014610451578063a457c2d714610464578063a9059cbb14610477578063c3cda5201461048a57600080fd5b806384b0196e116100e957806384b0196e146103fc5780638e539e8c1461041757806391ddadf41461042a57806395d89b411461044957600080fd5b806370a08231146103aa57806379cc6790146103d35780637ecebe00146103e15780638129fc1c146103f457600080fd5b8063395093511161019d5780634bf5d7e91161016c5780634bf5d7e91461031b5780634bf6c88214610323578063587cde1e1461032b5780635c19a95c1461036f5780636fcfff451461038257600080fd5b806339509351146102cf5780633a46b1a8146102e257806342966c68146102f5578063448407751461030857600080fd5b806323b872dd116101d957806323b872dd1461028a5780633041949b1461029d578063313ce567146102b25780633644e515146102c757600080fd5b8063039c91fc1461020b57806306fdde031461024a578063095ea7b31461025f57806318160ddd14610282575b600080fd5b6102376102193660046120c7565b61013060209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b61025261051b565b6040516102419190612140565b61027261026d366004612153565b6105ad565b6040519015158152602001610241565b603554610237565b61027261029836600461217d565b6105c7565b6102b06102ab3660046120c7565b6105eb565b005b60125b60405160ff9091168152602001610241565b610237610624565b6102726102dd366004612153565b610633565b6102376102f0366004612153565b610655565b6102b06103033660046121b9565b6106da565b6102b06103163660046121d2565b6106f3565b61025261076c565b6102b5600881565b610357610339366004612256565b6001600160a01b03908116600090815260fe60205260409020541690565b6040516001600160a01b039091168152602001610241565b6102b061037d366004612256565b610804565b610395610390366004612256565b610811565b60405163ffffffff9091168152602001610241565b6102376103b8366004612256565b6001600160a01b031660009081526033602052604090205490565b6102b0610303366004612153565b6102376103ef366004612256565b610833565b6102b0610851565b610404610a31565b6040516102419796959493929190612271565b6102376104253660046121b9565b610acf565b610432610b37565b60405165ffffffffffff9091168152602001610241565b610252610b42565b61023761045f366004612256565b610b51565b610272610472366004612153565b610bd3565b610272610485366004612153565b610c4e565b6102b0610498366004612318565b610c5c565b6102b06104ab366004612370565b610d92565b6102376104be3660046120c7565b610ef6565b6102b06104d13660046120c7565b610f21565b6104e96104e43660046123da565b610f51565b60408051825163ffffffff1681526020928301516001600160e01b03169281019290925201610241565b6102b5601181565b60606036805461052a9061241a565b80601f01602080910402602001604051908101604052809291908181526020018280546105569061241a565b80156105a35780601f10610578576101008083540402835291602001916105a3565b820191906000526020600020905b81548152906001019060200180831161058657829003601f168201915b5050505050905090565b6000336105bb818585610fd5565b60019150505b92915050565b6000336105d5858285610fee565b6105e0858585611068565b506001949350505050565b336120021461061657604051630f22c43960e41b815261200260048201526024015b60405180910390fd5b6106208282611081565b5050565b600061062e6111b1565b905090565b6000336105bb8185856106468383610ef6565b6106509190612464565b610fd5565b600061065f610b37565b65ffffffffffff1682106106b15760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b604482015260640161060d565b6001600160a01b038316600090815260ff602052604090206106d390836111bb565b9392505050565b60405163e5d8776760e01b815260040160405180910390fd5b336120021461071957604051630f22c43960e41b8152612002600482015260240161060d565b8160005b818110156107655761075585858381811061073a5761073a612477565b905060200201602081019061074f9190612256565b84611081565b61075e8161248d565b905061071d565b5050505050565b606043610777610b37565b65ffffffffffff16146107cc5760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a2062726f6b656e20636c6f636b206d6f6465000000604482015260640161060d565b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b61080e33826112a4565b50565b6001600160a01b038116600090815260ff60205260408120546105c19061131e565b6001600160a01b038116600090815260cb60205260408120546105c1565b600054610100900460ff16158080156108715750600054600160ff909116105b8061088b5750303b15801561088b575060005460ff166001145b6108ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161060d565b6000805460ff191660011790558015610911576000805461ff0019166101001790555b3341146109315760405163022d8c9560e31b815260040160405180910390fd5b3a15610950576040516383f1b1d360e01b815260040160405180910390fd5b6109a4604051806040016040528060148152602001732129a19023b7bb32b93730b731b2902a37b5b2b760611b8152506040518060400160405280600681526020016533b7bb21272160d11b815250611387565b6109ac6113b8565b6109e1604051806040016040528060148152602001732129a19023b7bb32b93730b731b2902a37b5b2b760611b8152506113e1565b6109e96113b8565b801561080e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b6000606080600080600060606097546000801b148015610a515750609854155b610a955760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b604482015260640161060d565b610a9d61142b565b610aa561143a565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6000610ad9610b37565b65ffffffffffff168210610b2b5760405162461bcd60e51b815260206004820152601960248201527804552433230566f7465733a20667574757265206c6f6f6b757603c1b604482015260640161060d565b6105c1610100836111bb565b600061062e43611449565b60606037805461052a9061241a565b6001600160a01b038116600090815260ff60205260408120548015610bc0576001600160a01b038316600090815260ff6020526040902080546000198301908110610b9e57610b9e612477565b60009182526020909120015464010000000090046001600160e01b0316610bc3565b60005b6001600160e01b03169392505050565b60003381610be18286610ef6565b905083811015610c415760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161060d565b6105e08286868403610fd5565b6000336105bb818585611068565b83421115610cac5760405162461bcd60e51b815260206004820152601d60248201527f4552433230566f7465733a207369676e61747572652065787069726564000000604482015260640161060d565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090610d2690610d1e9060a001604051602081830303815290604052805190602001206114b0565b8585856114dd565b9050610d3181611505565b8614610d7f5760405162461bcd60e51b815260206004820152601960248201527f4552433230566f7465733a20696e76616c6964206e6f6e636500000000000000604482015260640161060d565b610d8981886112a4565b50505050505050565b83421115610de25760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015260640161060d565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610e118c611505565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610e6c826114b0565b90506000610e7c828787876114dd565b9050896001600160a01b0316816001600160a01b031614610edf5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015260640161060d565b610eea8a8a8a610fd5565b50505050505050505050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b3361200214610f4757604051630f22c43960e41b8152612002600482015260240161060d565b61062082826112a4565b60408051808201909152600080825260208201526001600160a01b038316600090815260ff60205260409020805463ffffffff8416908110610f9557610f95612477565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160e01b0316918101919091529392505050565b604051632028747160e01b815260040160405180910390fd5b6000610ffa8484610ef6565b9050600019811461106257818110156110555760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161060d565b6110628484848403610fd5565b50505050565b604051638cd22d1960e01b815260040160405180910390fd5b604051630913db4760e01b81526001600160a01b03828116600483015260009190841690630913db4790602401602060405180830381865afa1580156110cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ef91906124bc565b6001600160a01b03808516600090815261013060209081526040808320938716835292905220549091508181101561116857600061112d82846124d5565b6001600160a01b038087166000908152610130602090815260408083209389168352929052208490559050611162848261152d565b50611062565b8181111561106257600061117c83836124d5565b6001600160a01b0380871660009081526101306020908152604080832093891683529290522084905590506107658482611537565b600061062e611541565b8154600090818160058111156112155760006111d6846115b5565b6111e090856124d5565b600088815260209020909150869082015463ffffffff16111561120557809150611213565b611210816001612464565b92505b505b80821015611262576000611229838361169d565b600088815260209020909150869082015463ffffffff16111561124e5780915061125c565b611259816001612464565b92505b50611215565b801561128e576000868152602090208101600019015464010000000090046001600160e01b0316611291565b60005b6001600160e01b03169695505050505050565b6001600160a01b03828116600081815260fe6020818152604080842080546033845282862054949093528787166001600160a01b03198416811790915590519190951694919391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46110628284836116b8565b600063ffffffff8211156113835760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840161060d565b5090565b600054610100900460ff166113ae5760405162461bcd60e51b815260040161060d906124e8565b61062082826117f6565b600054610100900460ff166113df5760405162461bcd60e51b815260040161060d906124e8565b565b600054610100900460ff166114085760405162461bcd60e51b815260040161060d906124e8565b61080e81604051806040016040528060018152602001603160f81b815250611836565b60606099805461052a9061241a565b6060609a805461052a9061241a565b600065ffffffffffff8211156113835760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b606482015260840161060d565b60006105c16114bd6111b1565b8360405161190160f01b8152600281019290925260228201526042902090565b60008060006114ee87878787611885565b915091506114fb81611949565b5095945050505050565b6001600160a01b038116600090815260cb602052604090208054600181018255905b50919050565b6106208282611a93565b6106208282611b1e565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61156c611b37565b611574611b90565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6000816000036115c757506000919050565b600060016115d484611bc1565b901c6001901b905060018184816115ed576115ed612533565b048201901c9050600181848161160557611605612533565b048201901c9050600181848161161d5761161d612533565b048201901c9050600181848161163557611635612533565b048201901c9050600181848161164d5761164d612533565b048201901c9050600181848161166557611665612533565b048201901c9050600181848161167d5761167d612533565b048201901c90506106d38182858161169757611697612533565b04611c55565b60006116ac6002848418612549565b6106d390848416612464565b816001600160a01b0316836001600160a01b0316141580156116da5750600081115b156117f1576001600160a01b03831615611768576001600160a01b038316600090815260ff60205260408120819061171590611c6b85611c77565b91509150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724838360405161175d929190918252602082015260400190565b60405180910390a250505b6001600160a01b038216156117f1576001600160a01b038216600090815260ff60205260408120819061179e90611dec85611c77565b91509150836001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72483836040516117e6929190918252602082015260400190565b60405180910390a250505b505050565b600054610100900460ff1661181d5760405162461bcd60e51b815260040161060d906124e8565b603661182983826125b9565b5060376117f182826125b9565b600054610100900460ff1661185d5760405162461bcd60e51b815260040161060d906124e8565b609961186983826125b9565b50609a61187682826125b9565b50506000609781905560985550565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156118bc5750600090506003611940565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611910573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661193957600060019250925050611940565b9150600090505b94509492505050565b600081600481111561195d5761195d612679565b036119655750565b600181600481111561197957611979612679565b036119c65760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161060d565b60028160048111156119da576119da612679565b03611a275760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161060d565b6003816004811115611a3b57611a3b612679565b0361080e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161060d565b611a9d8282611df8565b6035546001600160e01b031015611b0f5760405162461bcd60e51b815260206004820152603060248201527f4552433230566f7465733a20746f74616c20737570706c79207269736b73206f60448201526f766572666c6f77696e6720766f74657360801b606482015260840161060d565b611062610100611dec83611c77565b611b288282611ec1565b611062610100611c6b83611c77565b600080611b4261142b565b805190915015611b59578051602090910120919050565b6097548015611b685792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b600080611b9b61143a565b805190915015611bb2578051602090910120919050565b6098548015611b685792915050565b600080608083901c15611bd657608092831c92015b604083901c15611be857604092831c92015b602083901c15611bfa57602092831c92015b601083901c15611c0c57601092831c92015b600883901c15611c1e57600892831c92015b600483901c15611c3057600492831c92015b600283901c15611c4257600292831c92015b600183901c156105c15760010192915050565b6000818310611c6457816106d3565b5090919050565b60006106d382846124d5565b82546000908190818115611cc45760008781526020902082016000190160408051808201909152905463ffffffff8116825264010000000090046001600160e01b03166020820152611cd9565b60408051808201909152600080825260208201525b905080602001516001600160e01b03169350611cf984868863ffffffff16565b9250600082118015611d235750611d0e610b37565b65ffffffffffff16816000015163ffffffff16145b15611d6857611d3183611ffc565b60008881526020902083016000190180546001600160e01b03929092166401000000000263ffffffff909216919091179055611de2565b866040518060400160405280611d8c611d7f610b37565b65ffffffffffff1661131e565b63ffffffff168152602001611da086611ffc565b6001600160e01b0390811690915282546001810184556000938452602093849020835194909301519091166401000000000263ffffffff909316929092179101555b5050935093915050565b60006106d38284612464565b6001600160a01b038216611e4e5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161060d565b8060356000828254611e609190612464565b90915550506001600160a01b0382166000818152603360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361062060008383612065565b6001600160a01b038216611f215760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161060d565b6001600160a01b03821660009081526033602052604090205481811015611f955760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161060d565b6001600160a01b03831660008181526033602090815260408083208686039055603580548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36117f183600084612065565b60006001600160e01b038211156113835760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b606482015260840161060d565b6117f18383836001600160a01b03808416600090815260fe60205260409020546117f191166001600160a01b03808516600090815260fe602052604090205416836116b8565b80356001600160a01b03811681146120c257600080fd5b919050565b600080604083850312156120da57600080fd5b6120e3836120ab565b91506120f1602084016120ab565b90509250929050565b6000815180845260005b8181101561212057602081850181015186830182015201612104565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006106d360208301846120fa565b6000806040838503121561216657600080fd5b61216f836120ab565b946020939093013593505050565b60008060006060848603121561219257600080fd5b61219b846120ab565b92506121a9602085016120ab565b9150604084013590509250925092565b6000602082840312156121cb57600080fd5b5035919050565b6000806000604084860312156121e757600080fd5b833567ffffffffffffffff808211156121ff57600080fd5b818601915086601f83011261221357600080fd5b81358181111561222257600080fd5b8760208260051b850101111561223757600080fd5b60209283019550935061224d91860190506120ab565b90509250925092565b60006020828403121561226857600080fd5b6106d3826120ab565b60ff60f81b881681526000602060e08184015261229160e084018a6120fa565b83810360408501526122a3818a6120fa565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156122f5578351835292840192918401916001016122d9565b50909c9b505050505050505050505050565b803560ff811681146120c257600080fd5b60008060008060008060c0878903121561233157600080fd5b61233a876120ab565b9550602087013594506040870135935061235660608801612307565b92506080870135915060a087013590509295509295509295565b600080600080600080600060e0888a03121561238b57600080fd5b612394886120ab565b96506123a2602089016120ab565b955060408801359450606088013593506123be60808901612307565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156123ed57600080fd5b6123f6836120ab565b9150602083013563ffffffff8116811461240f57600080fd5b809150509250929050565b600181811c9082168061242e57607f821691505b60208210810361152757634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156105c1576105c161244e565b634e487b7160e01b600052603260045260246000fd5b60006001820161249f5761249f61244e565b5060010190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156124ce57600080fd5b5051919050565b818103818111156105c1576105c161244e565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b60008261256657634e487b7160e01b600052601260045260246000fd5b500490565b601f8211156117f157600081815260208120601f850160051c810160208610156125925750805b601f850160051c820191505b818110156125b15782815560010161259e565b505050505050565b815167ffffffffffffffff8111156125d3576125d36124a6565b6125e7816125e1845461241a565b8461256b565b602080601f83116001811461261c57600084156126045750858301515b600019600386901b1c1916600185901b1785556125b1565b600085815260208120601f198616915b8281101561264b5788860151825594840194600190910190840161262c565b50858210156126695787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fdfea164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(TimelockContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "6080604052600436106101e75760003560e01c80638129fc1c11610102578063bc197c8111610095578063e38335e511610064578063e38335e5146105e1578063f1fad104146105f4578063f23a6e6114610609578063f27a0c921461063557600080fd5b8063bc197c8114610548578063c4d252f514610574578063d45c443514610594578063d547741f146105c157600080fd5b8063a217fddf116100d1578063a217fddf146104d1578063ac431751146104e6578063b08e51c014610506578063b1c5f4271461052857600080fd5b80638129fc1c1461045a5780638f2a0bb01461046f5780638f61f4f51461048f57806391d14854146104b157600080fd5b80632ab0f5291161017a5780634bf6c882116101495780634bf6c882146103d3578063584b153e146103fa57806364d623531461041a5780638065657f1461043a57600080fd5b80632ab0f529146103435780632f2ff15d1461037357806331d507501461039357806336568abe146103b357600080fd5b8063134008d3116101b6578063134008d31461029c57806313bc9f20146102af578063150b7a02146102cf578063248a9ca31461031357600080fd5b806301d5062a146101f357806301ffc9a71461021557806307bd02651461024a5780630d3cf6fc1461027a57600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061021361020e366004611aa4565b61064a565b005b34801561022157600080fd5b50610235610230366004611b18565b61070e565b60405190151581526020015b60405180910390f35b34801561025657600080fd5b5061026c60008051602061258883398151915281565b604051908152602001610241565b34801561028657600080fd5b5061026c60008051602061254883398151915281565b6102136102aa366004611b42565b610739565b3480156102bb57600080fd5b506102356102ca366004611bad565b6107dc565b3480156102db57600080fd5b506102fa6102ea366004611c7b565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610241565b34801561031f57600080fd5b5061026c61032e366004611bad565b60009081526065602052604090206001015490565b34801561034f57600080fd5b5061023561035e366004611bad565b60009081526097602052604090205460011490565b34801561037f57600080fd5b5061021361038e366004611ce2565b610802565b34801561039f57600080fd5b506102356103ae366004611bad565b61082c565b3480156103bf57600080fd5b506102136103ce366004611ce2565b610845565b3480156103df57600080fd5b506103e8600881565b60405160ff9091168152602001610241565b34801561040657600080fd5b50610235610415366004611bad565b6108c8565b34801561042657600080fd5b50610213610435366004611bad565b6108df565b34801561044657600080fd5b5061026c610455366004611b42565b610983565b34801561046657600080fd5b506102136109c2565b34801561047b57600080fd5b5061021361048a366004611d52565b610b72565b34801561049b57600080fd5b5061026c60008051602061256883398151915281565b3480156104bd57600080fd5b506102356104cc366004611ce2565b610cf3565b3480156104dd57600080fd5b5061026c600081565b3480156104f257600080fd5b50610213610501366004611e03565b610d1e565b34801561051257600080fd5b5061026c6000805160206125a883398151915281565b34801561053457600080fd5b5061026c610543366004611e6e565b610f08565b34801561055457600080fd5b506102fa610563366004611f95565b63bc197c8160e01b95945050505050565b34801561058057600080fd5b5061021361058f366004611bad565b610f4d565b3480156105a057600080fd5b5061026c6105af366004611bad565b60009081526097602052604090205490565b3480156105cd57600080fd5b506102136105dc366004611ce2565b611010565b6102136105ef366004611e6e565b611035565b34801561060057600080fd5b506103e8601181565b34801561061557600080fd5b506102fa61062436600461203e565b63f23a6e6160e01b95945050505050565b34801561064157600080fd5b5060985461026c565b600080516020612568833981519152610662816111ad565b6000610672898989898989610983565b905061067e81846111b7565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516106ba969594939291906120cb565b60405180910390a3831561070357807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387856040516106fa91815260200190565b60405180910390a25b505050505050505050565b60006001600160e01b03198216630271189760e51b14806107335750610733826112a6565b92915050565b600080516020612588833981519152610753816000610cf3565b6107615761076181336112db565b6000610771888888888888610983565b905061077d8185611334565b610789888888886113cf565b6000817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516107c19493929190612108565b60405180910390a36107d2816114a2565b5050505050505050565b6000818152609760205260408120546001811180156107fb5750428111155b9392505050565b60008281526065602052604090206001015461081d816111ad565b61082783836114db565b505050565b60008181526097602052604081205481905b1192915050565b6001600160a01b03811633146108ba5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6108c48282611561565b5050565b60008181526097602052604081205460019061083e565b3330146109425760405162461bcd60e51b815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201526a62652074696d656c6f636b60a81b60648201526084016108b1565b60985460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1609855565b60008686868686866040516020016109a0969594939291906120cb565b6040516020818303038152906040528051906020012090509695505050505050565b600054610100900460ff16158080156109e25750600054600160ff909116105b806109fc5750303b1580156109fc575060005460ff166001145b610a5f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016108b1565b6000805460ff191660011790558015610a82576000805461ff0019166101001790555b334114610aa25760405163022d8c9560e31b815260040160405180910390fd5b3a15610ac1576040516383f1b1d360e01b815260040160405180910390fd5b6040805160018082528183019092526000916020808301908036833701905050905061200481600081518110610af957610af961213a565b60200260200101906001600160a01b031690816001600160a01b031681525050610b28603c82836120046115c8565b508015610b6f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b600080516020612568833981519152610b8a816111ad565b888714610ba95760405162461bcd60e51b81526004016108b190612150565b888514610bc85760405162461bcd60e51b81526004016108b190612150565b6000610bda8b8b8b8b8b8b8b8b610f08565b9050610be681846111b7565b60005b8a811015610ca45780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c2657610c2661213a565b9050602002016020810190610c3b9190612193565b8d8d86818110610c4d57610c4d61213a565b905060200201358c8c87818110610c6657610c6661213a565b9050602002810190610c7891906121ae565b8c8b604051610c8c969594939291906120cb565b60405180910390a3610c9d8161220a565b9050610be9565b508315610ce657807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d038785604051610cdd91815260200190565b60405180910390a25b5050505050505050505050565b60009182526065602090815260408084206001600160a01b0393909316845291905290205460ff1690565b3361100714610d4457604051630f22c43960e41b815261100760048201526024016108b1565b610da7604051806040016040528060088152602001676d696e44656c617960c01b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506116019050565b15610ea45760208114610dd55783838383604051630a5a604160e01b81526004016108b19493929190612223565b604080516020601f8401819004810282018101909252828152600091610e1691858580838501838280828437600092019190915250929392505061165a9050565b9050801580610e2757506212750081115b15610e4d5784848484604051630a5a604160e01b81526004016108b19493929190612223565b6040516364d6235360e01b81526004810182905230906364d6235390602401600060405180830381600087803b158015610e8657600080fd5b505af1158015610e9a573d6000803e3d6000fd5b5050505050610ec5565b838383836040516325ee20d560e21b81526004016108b19493929190612223565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e63384848484604051610efa9493929190612223565b60405180910390a150505050565b60008888888888888888604051602001610f299897969594939291906122d8565b60405160208183030381529060405280519060200120905098975050505050505050565b6000805160206125a8833981519152610f65816111ad565b610f6e826108c8565b610fd45760405162461bcd60e51b815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e2063616044820152701b9b9bdd0818994818d85b98d95b1b1959607a1b60648201526084016108b1565b6000828152609760205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b60008281526065602052604090206001015461102b816111ad565b6108278383611561565b60008051602061258883398151915261104f816000610cf3565b61105d5761105d81336112db565b87861461107c5760405162461bcd60e51b81526004016108b190612150565b87841461109b5760405162461bcd60e51b81526004016108b190612150565b60006110ad8a8a8a8a8a8a8a8a610f08565b90506110b98185611334565b60005b898110156111975760008b8b838181106110d8576110d861213a565b90506020020160208101906110ed9190612193565b905060008a8a848181106111035761110361213a565b9050602002013590503660008a8a868181106111215761112161213a565b905060200281019061113391906121ae565b91509150611143848484846113cf565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588686868660405161117a9493929190612108565b60405180910390a350505050806111909061220a565b90506110bc565b506111a1816114a2565b50505050505050505050565b610b6f81336112db565b6111c08261082c565b156112255760405162461bcd60e51b815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201526e1c9958591e481cd8da19591d5b1959608a1b60648201526084016108b1565b6098548110156112865760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e746044820152652064656c617960d01b60648201526084016108b1565b6112908142612379565b6000928352609760205260409092209190915550565b60006001600160e01b03198216637965db0b60e01b148061073357506301ffc9a760e01b6001600160e01b0319831614610733565b6112e58282610cf3565b6108c4576112f28161165f565b6112fd836020611671565b60405160200161130e9291906123b0565b60408051601f198184030181529082905262461bcd60e51b82526108b191600401612425565b61133d826107dc565b6113595760405162461bcd60e51b81526004016108b190612458565b80158061137457506000818152609760205260409020546001145b6108c45760405162461bcd60e51b815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e6720646570656044820152656e64656e637960d01b60648201526084016108b1565b6000846001600160a01b03168484846040516113ec9291906124a2565b60006040518083038185875af1925050503d8060008114611429576040519150601f19603f3d011682016040523d82523d6000602084013e61142e565b606091505b505090508061149b5760405162461bcd60e51b815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e6720746044820152721c985b9cd858dd1a5bdb881c995d995c9d1959606a1b60648201526084016108b1565b5050505050565b6114ab816107dc565b6114c75760405162461bcd60e51b81526004016108b190612458565b600090815260976020526040902060019055565b6114e58282610cf3565b6108c45760008281526065602090815260408083206001600160a01b03851684529091529020805460ff1916600117905561151d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61156b8282610cf3565b156108c45760008281526065602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600054610100900460ff166115ef5760405162461bcd60e51b81526004016108b1906124b2565b6115fb8484848461180c565b50505050565b60008160405160200161161491906124fd565b604051602081830303815290604052805190602001208360405160200161163b91906124fd565b6040516020818303038152906040528051906020012014905092915050565b015190565b60606107336001600160a01b03831660145b60606000611680836002612519565b61168b906002612379565b6001600160401b038111156116a2576116a2611bc6565b6040519080825280601f01601f1916602001820160405280156116cc576020820181803683370190505b509050600360fc1b816000815181106116e7576116e761213a565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106117165761171661213a565b60200101906001600160f81b031916908160001a905350600061173a846002612519565b611745906001612379565b90505b60018111156117bd576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106117795761177961213a565b1a60f81b82828151811061178f5761178f61213a565b60200101906001600160f81b031916908160001a90535060049490941c936117b681612530565b9050611748565b5083156107fb5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108b1565b600054610100900460ff166118335760405162461bcd60e51b81526004016108b1906124b2565b61184b600080516020612548833981519152806119eb565b6118716000805160206125688339815191526000805160206125488339815191526119eb565b6118976000805160206125888339815191526000805160206125488339815191526119eb565b6118bd6000805160206125a88339815191526000805160206125488339815191526119eb565b6118d560008051602061254883398151915230611a36565b6001600160a01b038116156118fc576118fc60008051602061254883398151915282611a36565b60005b835181101561196d5761193960008051602061256883398151915285838151811061192c5761192c61213a565b6020026020010151611a36565b61195d6000805160206125a883398151915285838151811061192c5761192c61213a565b6119668161220a565b90506118ff565b5060005b82518110156119ae5761199e60008051602061258883398151915284838151811061192c5761192c61213a565b6119a78161220a565b9050611971565b5060988490556040805160008152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d59101610efa565b600082815260656020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6108c482826114db565b80356001600160a01b0381168114611a5757600080fd5b919050565b60008083601f840112611a6e57600080fd5b5081356001600160401b03811115611a8557600080fd5b602083019150836020828501011115611a9d57600080fd5b9250929050565b600080600080600080600060c0888a031215611abf57600080fd5b611ac888611a40565b96506020880135955060408801356001600160401b03811115611aea57600080fd5b611af68a828b01611a5c565b989b979a50986060810135976080820135975060a09091013595509350505050565b600060208284031215611b2a57600080fd5b81356001600160e01b0319811681146107fb57600080fd5b60008060008060008060a08789031215611b5b57600080fd5b611b6487611a40565b95506020870135945060408701356001600160401b03811115611b8657600080fd5b611b9289828a01611a5c565b979a9699509760608101359660809091013595509350505050565b600060208284031215611bbf57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611c0457611c04611bc6565b604052919050565b600082601f830112611c1d57600080fd5b81356001600160401b03811115611c3657611c36611bc6565b611c49601f8201601f1916602001611bdc565b818152846020838601011115611c5e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611c9157600080fd5b611c9a85611a40565b9350611ca860208601611a40565b92506040850135915060608501356001600160401b03811115611cca57600080fd5b611cd687828801611c0c565b91505092959194509250565b60008060408385031215611cf557600080fd5b82359150611d0560208401611a40565b90509250929050565b60008083601f840112611d2057600080fd5b5081356001600160401b03811115611d3757600080fd5b6020830191508360208260051b8501011115611a9d57600080fd5b600080600080600080600080600060c08a8c031215611d7057600080fd5b89356001600160401b0380821115611d8757600080fd5b611d938d838e01611d0e565b909b50995060208c0135915080821115611dac57600080fd5b611db88d838e01611d0e565b909950975060408c0135915080821115611dd157600080fd5b50611dde8c828d01611d0e565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060408587031215611e1957600080fd5b84356001600160401b0380821115611e3057600080fd5b611e3c88838901611a5c565b90965094506020870135915080821115611e5557600080fd5b50611e6287828801611a5c565b95989497509550505050565b60008060008060008060008060a0898b031215611e8a57600080fd5b88356001600160401b0380821115611ea157600080fd5b611ead8c838d01611d0e565b909a50985060208b0135915080821115611ec657600080fd5b611ed28c838d01611d0e565b909850965060408b0135915080821115611eeb57600080fd5b50611ef88b828c01611d0e565b999c989b509699959896976060870135966080013595509350505050565b600082601f830112611f2757600080fd5b813560206001600160401b03821115611f4257611f42611bc6565b8160051b611f51828201611bdc565b9283528481018201928281019087851115611f6b57600080fd5b83870192505b84831015611f8a57823582529183019190830190611f71565b979650505050505050565b600080600080600060a08688031215611fad57600080fd5b611fb686611a40565b9450611fc460208701611a40565b935060408601356001600160401b0380821115611fe057600080fd5b611fec89838a01611f16565b9450606088013591508082111561200257600080fd5b61200e89838a01611f16565b9350608088013591508082111561202457600080fd5b5061203188828901611c0c565b9150509295509295909350565b600080600080600060a0868803121561205657600080fd5b61205f86611a40565b945061206d60208701611a40565b9350604086013592506060860135915060808601356001600160401b0381111561209657600080fd5b61203188828901611c0c565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038716815285602082015260a0604082015260006120f360a0830186886120a2565b60608301949094525060800152949350505050565b60018060a01b03851681528360208201526060604082015260006121306060830184866120a2565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b60208082526023908201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d616040820152620e8c6d60eb1b606082015260800190565b6000602082840312156121a557600080fd5b6107fb82611a40565b6000808335601e198436030181126121c557600080fd5b8301803591506001600160401b038211156121df57600080fd5b602001915036819003821315611a9d57600080fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161221c5761221c6121f4565b5060010190565b6040815260006122376040830186886120a2565b8281036020840152611f8a8185876120a2565b818352600060208085019450848460051b86018460005b878110156122cb5783830389528135601e1988360301811261228257600080fd5b870185810190356001600160401b0381111561229d57600080fd5b8036038213156122ac57600080fd5b6122b78582846120a2565b9a87019a9450505090840190600101612261565b5090979650505050505050565b60a0808252810188905260008960c08301825b8b811015612319576001600160a01b0361230484611a40565b168252602092830192909101906001016122eb565b5083810360208501528881526001600160fb1b0389111561233957600080fd5b8860051b9150818a60208301370182810360209081016040850152612361908201878961224a565b60608401959095525050608001529695505050505050565b80820180821115610733576107336121f4565b60005b838110156123a757818101518382015260200161238f565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516123e881601785016020880161238c565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161241981602884016020880161238c565b01602801949350505050565b602081526000825180602084015261244481604085016020870161238c565b601f01601f19169190910160400192915050565b6020808252602a908201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e206973604082015269206e6f7420726561647960b01b606082015260800190565b8183823760009101908152919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000825161250f81846020870161238c565b9190910192915050565b8082028115828204841417610733576107336121f4565b60008161253f5761253f6121f4565b50600019019056fe5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63fd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783a164736f6c6343000811000a",
+ },
+ {
+ ContractAddr: common.HexToAddress(TokenRecoverPortalContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/9d09d0a3d6332460a810188261ec8195e05aa218",
+ Code: "608060405234801561001057600080fd5b506004361061010b5760003560e01c80638129fc1c116100a2578063b187bd2611610071578063b187bd261461022c578063bfb5a6a114610237578063e33f8d321461024a578063e842426a1461026d578063f1fad1041461029857600080fd5b80638129fc1c146101fc5780638456cb59146102045780639fcb50121461020c578063ac4317511461021957600080fd5b80634a49ac4c116100de5780634a49ac4c1461017c5780634bf6c8821461018f578063572c9980146101a957806374be2150146101bc57600080fd5b8063046f7da2146101105780632eb4a7ab1461011a578063417c73a7146101365780634838d16514610149575b600080fd5b6101186102a0565b005b61012360685481565b6040519081526020015b60405180910390f35b610118610144366004611696565b610328565b61016c610157366004611696565b60346020526000908152604090205460ff1681565b604051901515815260200161012d565b61011861018a366004611696565b6103a4565b610197600881565b60405160ff909116815260200161012d565b6101186101b73660046116b1565b61041d565b6101ef6040518060400160405280601481526020017342696e616e63652d436861696e2d47616e67657360601b81525081565b60405161012d919061172d565b6101186104b3565b610118610613565b60695461016c9060ff1681565b610118610227366004611789565b61069f565b60335460ff1661016c565b61011861024536600461183a565b610abe565b61016c610258366004611914565b6000908152606a602052604090205460ff1690565b606754610280906001600160a01b031681565b6040516001600160a01b03909116815260200161012d565b610197601181565b60335461010090046001600160a01b031633146102d0576040516306fbb1e360e01b815260040160405180910390fd5b60335460ff166102f357604051636cd6020160e01b815260040160405180910390fd5b6033805460ff191690556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f990600090a1565b60335461010090046001600160a01b03163314610358576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260346020526040808220805460ff19166001179055517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60335461010090046001600160a01b031633146103d4576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260346020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60335461010090046001600160a01b0316331461044d576040516306fbb1e360e01b815260040160405180910390fd5b604051638525db0360e01b8152600481018390526001600160a01b038216602482015261100490638525db0390604401600060405180830381600087803b15801561049757600080fd5b505af11580156104ab573d6000803e3d6000fd5b505050505050565b600054610100900460ff16158080156104d35750600054600160ff909116105b806104ed5750303b1580156104ed575060005460ff166001145b6105555760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610578576000805461ff0019166101001790555b3341146105985760405163022d8c9560e31b815260040160405180910390fd5b3a156105b7576040516383f1b1d360e01b815260040160405180910390fd5b6105bf610e1e565b6105ca61dead610e4b565b8015610610576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60335461010090046001600160a01b03163314610643576040516306fbb1e360e01b815260040160405180910390fd5b60335460ff161561066757604051631785c68160e01b815260040160405180910390fd5b6033805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b33611007146106c557604051630f22c43960e41b8152611007600482015260240161054c565b61072f6040518060400160405280600f81526020016e617070726f76616c4164647265737360881b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610e9a9050565b156107f9576014811461075d5783838383604051630a5a604160e01b815260040161054c9493929190611956565b60006107a3601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610ef49050565b90506001600160a01b0381166107d45784848484604051630a5a604160e01b815260040161054c9493929190611956565b606780546001600160a01b0319166001600160a01b0392909216919091179055610a7b565b61085e6040518060400160405280600a8152602001691b595c9adb19549bdbdd60b21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610e9a9050565b1561092e5760695460ff1615610887576040516379b3306f60e11b815260040160405180910390fd5b602081146108b05783838383604051630a5a604160e01b815260040161054c9493929190611956565b604080516020601f84018190048102820181019092528281526000916108f1918585808385018382808284376000920191909152509293925050610ef49050565b9050806109195784848484604051630a5a604160e01b815260040161054c9493929190611956565b6068556069805460ff19166001179055610a7b565b6109a66040518060400160405280601b81526020017f746f6b656e5265636f766572506f7274616c50726f746563746f72000000000081525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610e9a9050565b15610a5a57601481146109d45783838383604051630a5a604160e01b815260040161054c9493929190611956565b6000610a1a601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050610ef49050565b90506001600160a01b038116610a4b5784848484604051630a5a604160e01b815260040161054c9493929190611956565b610a5481610ef9565b50610a7b565b838383836040516325ee20d560e21b815260040161054c9493929190611956565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e63384848484604051610ab09493929190611956565b60405180910390a150505050565b60695460ff16610ae15760405163678f619760e11b815260040160405180910390fd5b606854610b015760405163678f619760e11b815260040160405180910390fd5b6067546001600160a01b0316610b2a57604051631a1b977b60e31b815260040160405180910390fd5b60335460ff1615610b4e57604051631785c68160e01b815260040160405180910390fd5b610b56610f60565b6000610be489898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600081840152601f19601f82011690508083019250505050505050610bdf8e8e33610fb9565b6110da565b90506000818c8c604051602001610bfd93929190611988565b604051602081830303815290604052805190602001209050610c2e816000908152606a602052604090205460ff1690565b15610c4b57604051623e493160e81b815260040160405180910390fd5b610cf33389898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a908190840183828082843760009201919091525050604080516020808c0282810182019093528b82528994509092508b918b918291908501908490808284376000920191909152506111b292505050565b610d348484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060685491508490506112bd565b610d51576040516309bde33960e01b815260040160405180910390fd5b6000818152606a602052604090819020805460ff191660011790555163799758b960e01b8152600481018d9052336024820152604481018c90526110049063799758b990606401600060405180830381600087803b158015610db257600080fd5b505af1158015610dc6573d6000803e3d6000fd5b505050507f39cc0b7297a0ef9102d75ebc4919ffec0347d50008c2b865eda4125d5812cb64828d338e604051610dff94939291906119af565b60405180910390a15050610e1260018055565b50505050505050505050565b600054610100900460ff16610e455760405162461bcd60e51b815260040161054c906119e7565b60018055565b600054610100900460ff16610e725760405162461bcd60e51b815260040161054c906119e7565b603380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600081604051602001610ead9190611a32565b6040516020818303038152906040528051906020012083604051602001610ed49190611a32565b604051602081830303815290604052805190602001201490505b92915050565b015190565b6033546040516001600160a01b0380841692610100900416907f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b90600090a3603380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600260015403610fb25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161054c565b6002600155565b600060026040518060400160405280601481526020017342696e616e63652d436861696e2d47616e67657360601b8152506110168560405160200161100091815260200190565b60405160208183030381529060405260006112d3565b6040516bffffffffffffffffffffffff19606087901b16602082015261104f9060340160405160208183030381529060405260016112d3565b6110658860405160200161100091815260200190565b6040516020016110789493929190611a4e565b60408051601f198184030181529082905261109291611a32565b602060405180830381855afa1580156110af573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906110d29190611b7d565b949350505050565b606083516021146110fe57604051638152ea1b60e01b815260040160405180910390fd5b825160401461112057604051635e4bd79760e11b815260040160405180910390fd5b604080516020808252818301909252600091602082018180368337019050509050826020820152600085858360405160200161115e93929190611bac565b60408051808303601f190181526014808452838301909252925060009190602082018180368337019050509050815160146020830182602086016069600019fa6111a757600080fd5b509695505050505050565b606060005b825181101561121057818382815181106111d3576111d3611bef565b60200260200101516040516020016111ec929190611c05565b6040516020818303038152906040529150808061120890611c3d565b9150506111b7565b5060006040518060400160405280601481526020017342696e616e63652d436861696e2d47616e67657360601b8152508787866068548660405160200161125c96959493929190611c56565b60408051601f1981840301815291905280516020909101206067549091506001600160a01b031661128d86836114a5565b6001600160a01b0316146112b4576040516356b00a4f60e11b815260040160405180910390fd5b50505050505050565b6000826112ca858461153f565b14949350505050565b60606000835160026112e59190611cc7565b67ffffffffffffffff8111156112fd576112fd611b96565b6040519080825280601f01601f191660200182016040528015611327576020820181803683370190505b5060408051808201909152601081526f181899199a1a9b1b9c1cb0b131b232b360811b602082015290915060005b855181101561146d5781825187838151811061137357611373611bef565b0160200151611385919060f81c611cf4565b8151811061139557611395611bef565b01602001516001600160f81b031916836113b0836002611cc7565b815181106113c0576113c0611bef565b60200101906001600160f81b031916908160001a9053508182518783815181106113ec576113ec611bef565b01602001516113fe919060f81c611d08565b8151811061140e5761140e611bef565b01602001516001600160f81b03191683611429836002611cc7565b611434906001611d1c565b8151811061144457611444611bef565b60200101906001600160f81b031916908160001a9053508061146581611c3d565b915050611355565b50831561149d57816040516020016114859190611d2f565b60405160208183030381529060405292505050610eee565b509392505050565b600082516041146114c9576040516356b00a4f60e11b815260040160405180910390fd5b60208301516040840151606085015160001a601b8110156114f2576114ef601b82611d59565b90505b601b8160ff1610806115075750601c8160ff16115b15611525576040516356b00a4f60e11b815260040160405180910390fd5b600061153386838686611584565b50979650505050505050565b600081815b845181101561149d576115708286838151811061156357611563611bef565b6020026020010151611648565b91508061157c81611c3d565b915050611544565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156115bb575060009050600361163f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561160f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166116385760006001925092505061163f565b9150600090505b94509492505050565b6000818310611664576000828152602084905260409020611673565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461169157600080fd5b919050565b6000602082840312156116a857600080fd5b6116738261167a565b600080604083850312156116c457600080fd5b823591506116d46020840161167a565b90509250929050565b60005b838110156116f85781810151838201526020016116e0565b50506000910152565b600081518084526117198160208601602086016116dd565b601f01601f19169290920160200192915050565b6020815260006116736020830184611701565b60008083601f84011261175257600080fd5b50813567ffffffffffffffff81111561176a57600080fd5b60208301915083602082850101111561178257600080fd5b9250929050565b6000806000806040858703121561179f57600080fd5b843567ffffffffffffffff808211156117b757600080fd5b6117c388838901611740565b909650945060208701359150808211156117dc57600080fd5b506117e987828801611740565b95989497509550505050565b60008083601f84011261180757600080fd5b50813567ffffffffffffffff81111561181f57600080fd5b6020830191508360208260051b850101111561178257600080fd5b60008060008060008060008060008060c08b8d03121561185957600080fd5b8a35995060208b0135985060408b013567ffffffffffffffff8082111561187f57600080fd5b61188b8e838f01611740565b909a50985060608d01359150808211156118a457600080fd5b6118b08e838f01611740565b909850965060808d01359150808211156118c957600080fd5b6118d58e838f01611740565b909650945060a08d01359150808211156118ee57600080fd5b506118fb8d828e016117f5565b915080935050809150509295989b9194979a5092959850565b60006020828403121561192657600080fd5b5035919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60408152600061196a60408301868861192d565b828103602084015261197d81858761192d565b979650505050505050565b6000845161199a8184602089016116dd565b91909101928352506020820152604001919050565b6080815260006119c26080830187611701565b6020830195909552506001600160a01b03929092166040830152606090910152919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251611a448184602087016116dd565b9190910192915050565b7f7b226163636f756e745f6e756d626572223a2230222c22636861696e5f6964228152611d1160f11b602082015260008551611a91816022850160208a016116dd565b7f222c2264617461223a6e756c6c2c226d656d6f223a22222c226d736773223a5b6022918401918201526a3d9130b6b7bab73a111d1160a91b60428201528551611ae281604d840160208a016116dd565b6e1116113932b1b4b834b2b73a111d1160891b604d92909101918201528451611b1281605c8401602089016116dd565b711116113a37b5b2b72fb9bcb6b137b6111d1160711b605c92909101918201528351611b4581606e8401602088016116dd565b7f227d5d2c2273657175656e6365223a2230222c22736f75726365223a2230227d606e9290910191820152608e019695505050505050565b600060208284031215611b8f57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b60008451611bbe8184602089016116dd565b845190830190611bd28183602089016116dd565b8451910190611be58183602088016116dd565b0195945050505050565b634e487b7160e01b600052603260045260246000fd5b60008351611c178184602088016116dd565b9190910191825250602001919050565b634e487b7160e01b600052601160045260246000fd5b600060018201611c4f57611c4f611c27565b5060010190565b60008751611c68818460208c016116dd565b606088901b6bffffffffffffffffffffffff19169083019081528651611c95816014840160208b016116dd565b0160148101869052603481018590528351611cb78160548401602088016116dd565b0160540198975050505050505050565b8082028115828204841417610eee57610eee611c27565b634e487b7160e01b600052601260045260246000fd5b600082611d0357611d03611cde565b500490565b600082611d1757611d17611cde565b500690565b80820180821115610eee57610eee611c27565b61060f60f31b815260008251611d4c8160028501602087016116dd565b9190910160020192915050565b60ff8181168382160190811115610eee57610eee611c2756fea164736f6c6343000811000a",
},
},
}
@@ -617,6 +731,11 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I
if config.IsOnKepler(blockNumber, lastBlockTime, blockTime) {
applySystemContractUpgrade(keplerUpgrade[network], blockNumber, statedb, logger)
}
+
+ if config.IsOnFeynman(blockNumber, lastBlockTime, blockTime) {
+ applySystemContractUpgrade(feynmanUpgrade[network], blockNumber, statedb, logger)
+ }
+
/*
apply other upgrades
*/
diff --git a/core/txindexer.go b/core/txindexer.go
new file mode 100644
index 0000000000..61de41947c
--- /dev/null
+++ b/core/txindexer.go
@@ -0,0 +1,220 @@
+// Copyright 2024 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see
+
+package core
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// TxIndexProgress is the struct describing the progress for transaction indexing.
+type TxIndexProgress struct {
+ Indexed uint64 // number of blocks whose transactions are indexed
+ Remaining uint64 // number of blocks whose transactions are not indexed yet
+}
+
+// Done returns an indicator if the transaction indexing is finished.
+func (progress TxIndexProgress) Done() bool {
+ return progress.Remaining == 0
+}
+
+// txIndexer is the module responsible for maintaining transaction indexes
+// according to the configured indexing range by users.
+type txIndexer struct {
+ // limit is the maximum number of blocks from head whose tx indexes
+ // are reserved:
+ // * 0: means the entire chain should be indexed
+ // * N: means the latest N blocks [HEAD-N+1, HEAD] should be indexed
+ // and all others shouldn't.
+ limit uint64
+ db ethdb.Database
+ progress chan chan TxIndexProgress
+ term chan chan struct{}
+ closed chan struct{}
+}
+
+// newTxIndexer initializes the transaction indexer.
+func newTxIndexer(limit uint64, chain *BlockChain) *txIndexer {
+ indexer := &txIndexer{
+ limit: limit,
+ db: chain.db,
+ progress: make(chan chan TxIndexProgress),
+ term: make(chan chan struct{}),
+ closed: make(chan struct{}),
+ }
+ go indexer.loop(chain)
+
+ var msg string
+ if limit == 0 {
+ msg = "entire chain"
+ } else {
+ msg = fmt.Sprintf("last %d blocks", limit)
+ }
+ log.Info("Initialized transaction indexer", "range", msg)
+
+ return indexer
+}
+
+// run executes the scheduled indexing/unindexing task in a separate thread.
+// If the stop channel is closed, the task should be terminated as soon as
+// possible, the done channel will be closed once the task is finished.
+func (indexer *txIndexer) run(tail *uint64, head uint64, stop chan struct{}, done chan struct{}) {
+ defer func() { close(done) }()
+
+ // Short circuit if chain is empty and nothing to index.
+ if head == 0 {
+ return
+ }
+ // The tail flag is not existent, it means the node is just initialized
+ // and all blocks in the chain (part of them may from ancient store) are
+ // not indexed yet, index the chain according to the configured limit.
+ if tail == nil {
+ from := uint64(0)
+ if indexer.limit != 0 && head >= indexer.limit {
+ from = head - indexer.limit + 1
+ }
+ rawdb.IndexTransactions(indexer.db, from, head+1, stop, true)
+ return
+ }
+ // The tail flag is existent (which means indexes in [tail, head] should be
+ // present), while the whole chain are requested for indexing.
+ if indexer.limit == 0 || head < indexer.limit {
+ if *tail > 0 {
+ // It can happen when chain is rewound to a historical point which
+ // is even lower than the indexes tail, recap the indexing target
+ // to new head to avoid reading non-existent block bodies.
+ end := *tail
+ if end > head+1 {
+ end = head + 1
+ }
+ rawdb.IndexTransactions(indexer.db, 0, end, stop, true)
+ }
+ return
+ }
+ // The tail flag is existent, adjust the index range according to configured
+ // limit and the latest chain head.
+ if head-indexer.limit+1 < *tail {
+ // Reindex a part of missing indices and rewind index tail to HEAD-limit
+ rawdb.IndexTransactions(indexer.db, head-indexer.limit+1, *tail, stop, true)
+ } else {
+ // Unindex a part of stale indices and forward index tail to HEAD-limit
+ rawdb.UnindexTransactions(indexer.db, *tail, head-indexer.limit+1, stop, false)
+ }
+}
+
+// loop is the scheduler of the indexer, assigning indexing/unindexing tasks depending
+// on the received chain event.
+func (indexer *txIndexer) loop(chain *BlockChain) {
+ defer close(indexer.closed)
+
+ // Listening to chain events and manipulate the transaction indexes.
+ var (
+ stop chan struct{} // Non-nil if background routine is active.
+ done chan struct{} // Non-nil if background routine is active.
+ lastHead uint64 // The latest announced chain head (whose tx indexes are assumed created)
+
+ headCh = make(chan ChainHeadEvent)
+ sub = chain.SubscribeChainHeadEvent(headCh)
+ )
+ defer sub.Unsubscribe()
+
+ // Launch the initial processing if chain is not empty (head != genesis).
+ // This step is useful in these scenarios that chain has no progress.
+ if head := rawdb.ReadHeadBlock(indexer.db); head != nil && head.Number().Uint64() != 0 {
+ stop = make(chan struct{})
+ done = make(chan struct{})
+ lastHead = head.Number().Uint64()
+ go indexer.run(rawdb.ReadTxIndexTail(indexer.db), head.NumberU64(), stop, done)
+ }
+ for {
+ select {
+ case head := <-headCh:
+ if done == nil {
+ stop = make(chan struct{})
+ done = make(chan struct{})
+ go indexer.run(rawdb.ReadTxIndexTail(indexer.db), head.Block.NumberU64(), stop, done)
+ }
+ lastHead = head.Block.NumberU64()
+ case <-done:
+ stop = nil
+ done = nil
+ case ch := <-indexer.progress:
+ ch <- indexer.report(lastHead)
+ case ch := <-indexer.term:
+ if stop != nil {
+ close(stop)
+ }
+ if done != nil {
+ log.Info("Waiting background transaction indexer to exit")
+ <-done
+ }
+ close(ch)
+ return
+ }
+ }
+}
+
+// report returns the tx indexing progress.
+func (indexer *txIndexer) report(head uint64) TxIndexProgress {
+ var (
+ remaining uint64
+ tail = rawdb.ReadTxIndexTail(indexer.db)
+ )
+ total := indexer.limit
+ if indexer.limit == 0 || total > head {
+ total = head + 1 // genesis included
+ }
+ var indexed uint64
+ if tail != nil {
+ indexed = head - *tail + 1
+ }
+ // The value of indexed might be larger than total if some blocks need
+ // to be unindexed, avoiding a negative remaining.
+ if indexed < total {
+ remaining = total - indexed
+ }
+ return TxIndexProgress{
+ Indexed: indexed,
+ Remaining: remaining,
+ }
+}
+
+// txIndexProgress retrieves the tx indexing progress, or an error if the
+// background tx indexer is already stopped.
+func (indexer *txIndexer) txIndexProgress() (TxIndexProgress, error) {
+ ch := make(chan TxIndexProgress, 1)
+ select {
+ case indexer.progress <- ch:
+ return <-ch, nil
+ case <-indexer.closed:
+ return TxIndexProgress{}, errors.New("indexer is closed")
+ }
+}
+
+// close shutdown the indexer. Safe to be called for multiple times.
+func (indexer *txIndexer) close() {
+ ch := make(chan struct{})
+ select {
+ case indexer.term <- ch:
+ <-ch
+ case <-indexer.closed:
+ }
+}
diff --git a/core/txindexer_test.go b/core/txindexer_test.go
new file mode 100644
index 0000000000..b18ebe6cbe
--- /dev/null
+++ b/core/txindexer_test.go
@@ -0,0 +1,243 @@
+// Copyright 2024 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see
+
+package core
+
+import (
+ "math/big"
+ "os"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// TestTxIndexer tests the functionalities for managing transaction indexes.
+func TestTxIndexer(t *testing.T) {
+ var (
+ testBankKey, _ = crypto.GenerateKey()
+ testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
+ testBankFunds = big.NewInt(1000000000000000000)
+
+ gspec = &Genesis{
+ Config: params.TestChainConfig,
+ Alloc: GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
+ BaseFee: big.NewInt(params.InitialBaseFee),
+ }
+ engine = ethash.NewFaker()
+ nonce = uint64(0)
+ chainHead = uint64(128)
+ )
+ _, blocks, receipts := GenerateChainWithGenesis(gspec, engine, int(chainHead), func(i int, gen *BlockGen) {
+ tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xdeadbeef"), big.NewInt(1000), params.TxGas, big.NewInt(10*params.InitialBaseFee), nil), types.HomesteadSigner{}, testBankKey)
+ gen.AddTx(tx)
+ nonce += 1
+ })
+
+ // verifyIndexes checks if the transaction indexes are present or not
+ // of the specified block.
+ verifyIndexes := func(db ethdb.Database, number uint64, exist bool) {
+ if number == 0 {
+ return
+ }
+ block := blocks[number-1]
+ for _, tx := range block.Transactions() {
+ lookup := rawdb.ReadTxLookupEntry(db, tx.Hash())
+ if exist && lookup == nil {
+ t.Fatalf("missing %d %x", number, tx.Hash().Hex())
+ }
+ if !exist && lookup != nil {
+ t.Fatalf("unexpected %d %x", number, tx.Hash().Hex())
+ }
+ }
+ }
+ verify := func(db ethdb.Database, expTail uint64, indexer *txIndexer) {
+ tail := rawdb.ReadTxIndexTail(db)
+ if tail == nil {
+ t.Fatal("Failed to write tx index tail")
+ }
+ if *tail != expTail {
+ t.Fatalf("Unexpected tx index tail, want %v, got %d", expTail, *tail)
+ }
+ if *tail != 0 {
+ for number := uint64(0); number < *tail; number += 1 {
+ verifyIndexes(db, number, false)
+ }
+ }
+ for number := *tail; number <= chainHead; number += 1 {
+ verifyIndexes(db, number, true)
+ }
+ progress := indexer.report(chainHead)
+ if !progress.Done() {
+ t.Fatalf("Expect fully indexed")
+ }
+ }
+
+ var cases = []struct {
+ limitA uint64
+ tailA uint64
+ limitB uint64
+ tailB uint64
+ limitC uint64
+ tailC uint64
+ }{
+ {
+ // LimitA: 0
+ // TailA: 0
+ //
+ // all blocks are indexed
+ limitA: 0,
+ tailA: 0,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ {
+ // LimitA: 64
+ // TailA: 65
+ //
+ // block [65, 128] are indexed
+ limitA: 64,
+ tailA: 65,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ {
+ // LimitA: 127
+ // TailA: 2
+ //
+ // block [2, 128] are indexed
+ limitA: 127,
+ tailA: 2,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ {
+ // LimitA: 128
+ // TailA: 1
+ //
+ // block [2, 128] are indexed
+ limitA: 128,
+ tailA: 1,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ {
+ // LimitA: 129
+ // TailA: 0
+ //
+ // block [0, 128] are indexed
+ limitA: 129,
+ tailA: 0,
+
+ // LimitB: 1
+ // TailB: 128
+ //
+ // block-128 is indexed
+ limitB: 1,
+ tailB: 128,
+
+ // LimitB: 64
+ // TailB: 65
+ //
+ // block [65, 128] are indexed
+ limitC: 64,
+ tailC: 65,
+ },
+ }
+ for _, c := range cases {
+ frdir := t.TempDir()
+ db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false, false)
+ rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), big.NewInt(0))
+
+ // Index the initial blocks from ancient store
+ indexer := &txIndexer{
+ limit: c.limitA,
+ db: db,
+ progress: make(chan chan TxIndexProgress),
+ }
+ indexer.run(nil, 128, make(chan struct{}), make(chan struct{}))
+ verify(db, c.tailA, indexer)
+
+ indexer.limit = c.limitB
+ indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{}))
+ verify(db, c.tailB, indexer)
+
+ indexer.limit = c.limitC
+ indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{}))
+ verify(db, c.tailC, indexer)
+
+ // Recover all indexes
+ indexer.limit = 0
+ indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{}))
+ verify(db, 0, indexer)
+
+ db.Close()
+ os.RemoveAll(frdir)
+ }
+}
diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go
index 71cb2cb53f..c9f72b5ea8 100644
--- a/core/txpool/blobpool/blobpool.go
+++ b/core/txpool/blobpool/blobpool.go
@@ -19,6 +19,7 @@ package blobpool
import (
"container/heap"
+ "errors"
"fmt"
"math"
"math/big"
@@ -35,7 +36,6 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
@@ -53,7 +53,7 @@ const (
// maxBlobsPerTransaction is the maximum number of blobs a single transaction
// is allowed to contain. Whilst the spec states it's unlimited, the block
// data slots are protocol bound, which implicitly also limit this.
- maxBlobsPerTransaction = params.BlobTxMaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob
+ maxBlobsPerTransaction = params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob
// txAvgSize is an approximate byte size of a transaction metadata to avoid
// tiny overflows causing all txs to move a shelf higher, wasting disk space.
@@ -83,16 +83,6 @@ const (
limboedTransactionStore = "limbo"
)
-// blobTx is a wrapper around types.BlobTx which also contains the literal blob
-// data along with all the transaction metadata.
-type blobTx struct {
- Tx *types.Transaction
-
- Blobs []kzg4844.Blob
- Commits []kzg4844.Commitment
- Proofs []kzg4844.Proof
-}
-
// blobTxMeta is the minimal subset of types.BlobTx necessary to validate and
// schedule the blob transactions into the following blocks. Only ever add the
// bare minimum needed fields to keep the size down (and thus number of entries
@@ -107,6 +97,8 @@ type blobTxMeta struct {
execTipCap *uint256.Int // Needed to prioritize inclusion order across accounts and validate replacement price bump
execFeeCap *uint256.Int // Needed to validate replacement price bump
blobFeeCap *uint256.Int // Needed to validate replacement price bump
+ execGas uint64 // Needed to check inclusion validity before reading the blob
+ blobGas uint64 // Needed to check inclusion validity before reading the blob
basefeeJumps float64 // Absolute number of 1559 fee adjustments needed to reach the tx's fee cap
blobfeeJumps float64 // Absolute number of 4844 fee adjustments needed to reach the tx's blob fee cap
@@ -128,6 +120,8 @@ func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta {
execTipCap: uint256.MustFromBig(tx.GasTipCap()),
execFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
blobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()),
+ execGas: tx.Gas(),
+ blobGas: tx.BlobGas(),
}
meta.basefeeJumps = dynamicFeeJumps(meta.execFeeCap)
meta.blobfeeJumps = dynamicFeeJumps(meta.blobFeeCap)
@@ -317,8 +311,10 @@ type BlobPool struct {
spent map[common.Address]*uint256.Int // Expenditure tracking for individual accounts
evict *evictHeap // Heap of cheapest accounts for eviction when full
- eventFeed event.Feed // Event feed to send out new tx events on pool inclusion
- eventScope event.SubscriptionScope // Event scope to track and mass unsubscribe on termination
+ discoverFeed event.Feed // Event feed to send out new tx events on pool discovery (reorg excluded)
+ insertFeed event.Feed // Event feed to send out new tx events on pool inclusion (reorg included)
+ reannoTxFeed event.Feed // Event feed for announcing transactions again
+ scope event.SubscriptionScope
lock sync.RWMutex // Mutex protecting the pool during reorg handling
}
@@ -365,7 +361,13 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
return err
}
}
+ // Initialize the state with head block, or fallback to empty one in
+ // case the head state is not available(might occur when node is not
+ // fully synced).
state, err := p.chain.StateAt(head.Root)
+ if err != nil {
+ state, err = p.chain.StateAt(types.EmptyRootHash)
+ }
if err != nil {
return err
}
@@ -440,8 +442,6 @@ func (p *BlobPool) Close() error {
if err := p.store.Close(); err != nil {
errs = append(errs, err)
}
- p.eventScope.Close()
-
switch {
case errs == nil:
return nil
@@ -455,22 +455,27 @@ func (p *BlobPool) Close() error {
// parseTransaction is a callback method on pool creation that gets called for
// each transaction on disk to create the in-memory metadata index.
func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error {
- item := new(blobTx)
- if err := rlp.DecodeBytes(blob, item); err != nil {
+ tx := new(types.Transaction)
+ if err := rlp.DecodeBytes(blob, tx); err != nil {
// This path is impossible unless the disk data representation changes
// across restarts. For that ever unprobable case, recover gracefully
// by ignoring this data entry.
log.Error("Failed to decode blob pool entry", "id", id, "err", err)
return err
}
- meta := newBlobTxMeta(id, size, item.Tx)
+ if tx.BlobTxSidecar() == nil {
+ log.Error("Missing sidecar in blob pool entry", "id", id, "hash", tx.Hash())
+ return errors.New("missing blob sidecar")
+ }
+
+ meta := newBlobTxMeta(id, size, tx)
- sender, err := p.signer.Sender(item.Tx)
+ sender, err := p.signer.Sender(tx)
if err != nil {
// This path is impossible unless the signature validity changes across
// restarts. For that ever unprobable case, recover gracefully by ignoring
// this data entry.
- log.Error("Failed to recover blob tx sender", "id", id, "hash", item.Tx.Hash(), "err", err)
+ log.Error("Failed to recover blob tx sender", "id", id, "hash", tx.Hash(), "err", err)
return err
}
if _, ok := p.index[sender]; !ok {
@@ -580,7 +585,7 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
txs[0].evictionBlobFeeJumps = txs[0].blobfeeJumps
for i := 1; i < len(txs); i++ {
- // If there's no nonce gap, initialize the evicion thresholds as the
+ // If there's no nonce gap, initialize the eviction thresholds as the
// minimum between the cumulative thresholds and the current tx fees
if txs[i].nonce == txs[i-1].nonce+1 {
txs[i].evictionExecTip = txs[i-1].evictionExecTip
@@ -629,7 +634,7 @@ func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint6
// Ensure that there's no over-draft, this is expected to happen when some
// transactions get included without publishing on the network
var (
- balance = uint256.MustFromBig(p.state.GetBalance(addr))
+ balance = p.state.GetBalance(addr)
spent = p.spent[addr]
)
if spent.Cmp(balance) > 0 {
@@ -718,24 +723,24 @@ func (p *BlobPool) offload(addr common.Address, nonce uint64, id uint64, inclusi
log.Error("Blobs missing for included transaction", "from", addr, "nonce", nonce, "id", id, "err", err)
return
}
- item := new(blobTx)
- if err = rlp.DecodeBytes(data, item); err != nil {
+ var tx types.Transaction
+ if err = rlp.DecodeBytes(data, &tx); err != nil {
log.Error("Blobs corrupted for included transaction", "from", addr, "nonce", nonce, "id", id, "err", err)
return
}
- block, ok := inclusions[item.Tx.Hash()]
+ block, ok := inclusions[tx.Hash()]
if !ok {
log.Warn("Blob transaction swapped out by signer", "from", addr, "nonce", nonce, "id", id)
return
}
- if err := p.limbo.push(item.Tx.Hash(), block, item.Blobs, item.Commits, item.Proofs); err != nil {
+ if err := p.limbo.push(&tx, block); err != nil {
log.Warn("Failed to offload blob tx into limbo", "err", err)
return
}
}
// Reset implements txpool.SubPool, allowing the blob pool's internal state to be
-// kept in sync with the main transacion pool's internal state.
+// kept in sync with the main transaction pool's internal state.
func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
waitStart := time.Now()
p.lock.Lock()
@@ -757,15 +762,21 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
// Run the reorg between the old and new head and figure out which accounts
// need to be rechecked and which transactions need to be readded
if reinject, inclusions := p.reorg(oldHead, newHead); reinject != nil {
+ var adds []*types.Transaction
for addr, txs := range reinject {
// Blindly push all the lost transactions back into the pool
for _, tx := range txs {
- p.reinject(addr, tx)
+ if err := p.reinject(addr, tx.Hash()); err == nil {
+ adds = append(adds, tx.WithoutBlobTxSidecar())
+ }
}
// Recheck the account's pooled transactions to drop included and
// invalidated one
p.recheck(addr, inclusions)
}
+ if len(adds) > 0 {
+ p.insertFeed.Send(core.NewTxsEvent{Txs: adds})
+ }
}
// Flush out any blobs from limbo that are older than the latest finality
if p.chain.Config().IsCancun(p.head.Number, p.head.Time) {
@@ -920,32 +931,35 @@ func (p *BlobPool) reorg(oldHead, newHead *types.Header) (map[common.Address][]*
// Note, the method will not initialize the eviction cache values as those will
// be done once for all transactions belonging to an account after all individual
// transactions are injected back into the pool.
-func (p *BlobPool) reinject(addr common.Address, tx *types.Transaction) {
+func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error {
// Retrieve the associated blob from the limbo. Without the blobs, we cannot
// add the transaction back into the pool as it is not mineable.
- blobs, commits, proofs, err := p.limbo.pull(tx.Hash())
+ tx, err := p.limbo.pull(txhash)
if err != nil {
log.Error("Blobs unavailable, dropping reorged tx", "err", err)
- return
+ return err
}
- // Serialize the transaction back into the primary datastore
- blob, err := rlp.EncodeToBytes(&blobTx{Tx: tx, Blobs: blobs, Commits: commits, Proofs: proofs})
+ // TODO: seems like an easy optimization here would be getting the serialized tx
+ // from limbo instead of re-serializing it here.
+
+ // Serialize the transaction back into the primary datastore.
+ blob, err := rlp.EncodeToBytes(tx)
if err != nil {
log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err)
- return
+ return err
}
id, err := p.store.Put(blob)
if err != nil {
log.Error("Failed to write transaction into storage", "hash", tx.Hash(), "err", err)
- return
+ return err
}
+
// Update the indixes and metrics
meta := newBlobTxMeta(id, p.store.Size(id), tx)
-
if _, ok := p.index[addr]; !ok {
if err := p.reserve(addr, true); err != nil {
log.Warn("Failed to reserve account for blob pool", "tx", tx.Hash(), "from", addr, "err", err)
- return
+ return err
}
p.index[addr] = []*blobTxMeta{meta}
p.spent[addr] = meta.costCap
@@ -956,10 +970,11 @@ func (p *BlobPool) reinject(addr common.Address, tx *types.Transaction) {
}
p.lookup[meta.hash] = meta.id
p.stored += uint64(meta.size)
+ return nil
}
// SetGasTip implements txpool.SubPool, allowing the blob pool's gas requirements
-// to be kept in sync with the main transacion pool's gas requirements.
+// to be kept in sync with the main transaction pool's gas requirements.
func (p *BlobPool) SetGasTip(tip *big.Int) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -1023,7 +1038,7 @@ func (p *BlobPool) SetGasTip(tip *big.Int) {
// validateTx checks whether a transaction is valid according to the consensus
// rules and adheres to some heuristic limits of the local node (price and size).
-func (p *BlobPool) validateTx(tx *types.Transaction, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof) error {
+func (p *BlobPool) validateTx(tx *types.Transaction) error {
// Ensure the transaction adheres to basic pool filters (type, size, tip) and
// consensus rules
baseOpts := &txpool.ValidationOptions{
@@ -1032,7 +1047,7 @@ func (p *BlobPool) validateTx(tx *types.Transaction, blobs []kzg4844.Blob, commi
MaxSize: txMaxSize,
MinTip: p.gasTip.ToBig(),
}
- if err := txpool.ValidateTransaction(tx, blobs, commits, proofs, p.head, p.signer, baseOpts); err != nil {
+ if err := txpool.ValidateTransaction(tx, p.head, p.signer, baseOpts); err != nil {
return err
}
// Ensure the transaction adheres to the stateful pool filters (nonce, balance)
@@ -1117,7 +1132,7 @@ func (p *BlobPool) Has(hash common.Hash) bool {
}
// Get returns a transaction if it is contained in the pool, or nil otherwise.
-func (p *BlobPool) Get(hash common.Hash) *txpool.Transaction {
+func (p *BlobPool) Get(hash common.Hash) *types.Transaction {
// Track the amount of time waiting to retrieve a fully resolved blob tx from
// the pool and the amount of time actually spent on pulling the data from disk.
getStart := time.Now()
@@ -1139,32 +1154,37 @@ func (p *BlobPool) Get(hash common.Hash) *txpool.Transaction {
log.Error("Tracked blob transaction missing from store", "hash", hash, "id", id, "err", err)
return nil
}
- item := new(blobTx)
+ item := new(types.Transaction)
if err = rlp.DecodeBytes(data, item); err != nil {
log.Error("Blobs corrupted for traced transaction", "hash", hash, "id", id, "err", err)
return nil
}
- return &txpool.Transaction{
- Tx: item.Tx,
- BlobTxBlobs: item.Blobs,
- BlobTxCommits: item.Commits,
- BlobTxProofs: item.Proofs,
- }
+ return item
}
// Add inserts a set of blob transactions into the pool if they pass validation (both
// consensus validity and pool restictions).
-func (p *BlobPool) Add(txs []*txpool.Transaction, local bool, sync bool) []error {
- errs := make([]error, len(txs))
+func (p *BlobPool) Add(txs []*types.Transaction, local bool, sync bool) []error {
+ var (
+ adds = make([]*types.Transaction, 0, len(txs))
+ errs = make([]error, len(txs))
+ )
for i, tx := range txs {
- errs[i] = p.add(tx.Tx, tx.BlobTxBlobs, tx.BlobTxCommits, tx.BlobTxProofs)
+ errs[i] = p.add(tx)
+ if errs[i] == nil {
+ adds = append(adds, tx.WithoutBlobTxSidecar())
+ }
+ }
+ if len(adds) > 0 {
+ p.discoverFeed.Send(core.NewTxsEvent{Txs: adds})
+ p.insertFeed.Send(core.NewTxsEvent{Txs: adds})
}
return errs
}
// Add inserts a new blob transaction into the pool if it passes validation (both
// consensus validity and pool restictions).
-func (p *BlobPool) add(tx *types.Transaction, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof) (err error) {
+func (p *BlobPool) add(tx *types.Transaction) (err error) {
// The blob pool blocks on adding a transaction. This is because blob txs are
// only even pulled form the network, so this method will act as the overload
// protection for fetches.
@@ -1178,7 +1198,7 @@ func (p *BlobPool) add(tx *types.Transaction, blobs []kzg4844.Blob, commits []kz
}(time.Now())
// Ensure the transaction is valid from all perspectives
- if err := p.validateTx(tx, blobs, commits, proofs); err != nil {
+ if err := p.validateTx(tx); err != nil {
log.Trace("Transaction validation failed", "hash", tx.Hash(), "err", err)
return err
}
@@ -1203,7 +1223,7 @@ func (p *BlobPool) add(tx *types.Transaction, blobs []kzg4844.Blob, commits []kz
}
// Transaction permitted into the pool from a nonce and cost perspective,
// insert it into the database and update the indices
- blob, err := rlp.EncodeToBytes(&blobTx{Tx: tx, Blobs: blobs, Commits: commits, Proofs: proofs})
+ blob, err := rlp.EncodeToBytes(tx)
if err != nil {
log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err)
return err
@@ -1337,7 +1357,7 @@ func (p *BlobPool) drop() {
p.stored -= uint64(drop.size)
delete(p.lookup, drop.hash)
- // Remove the transaction from the pool's evicion heap:
+ // Remove the transaction from the pool's eviction heap:
// - If the entire account was dropped, pop off the address
// - Otherwise, if the new tail has better eviction caps, fix the heap
if last {
@@ -1385,6 +1405,8 @@ func (p *BlobPool) Pending(enforceTips bool) map[common.Address][]*txpool.LazyTr
Time: time.Now(), // TODO(karalabe): Maybe save these and use that?
GasFeeCap: tx.execFeeCap.ToBig(),
GasTipCap: tx.execTipCap.ToBig(),
+ Gas: tx.execGas,
+ BlobGas: tx.blobGas,
})
}
if len(lazies) > 0 {
@@ -1469,16 +1491,20 @@ func (p *BlobPool) updateLimboMetrics() {
limboSlotusedGauge.Update(int64(slotused))
}
-// SubscribeTransactions registers a subscription of NewTxsEvent and
-// starts sending event to the given channel.
-func (p *BlobPool) SubscribeTransactions(ch chan<- core.NewTxsEvent) event.Subscription {
- return p.eventScope.Track(p.eventFeed.Subscribe(ch))
+// SubscribeTransactions registers a subscription for new transaction events,
+// supporting feeding only newly seen or also resurrected transactions.
+func (p *BlobPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription {
+ if reorgs {
+ return p.insertFeed.Subscribe(ch)
+ } else {
+ return p.discoverFeed.Subscribe(ch)
+ }
}
// SubscribeReannoTxsEvent registers a subscription of ReannoTxsEvent and
// starts sending event to the given channel.
func (pool *BlobPool) SubscribeReannoTxsEvent(ch chan<- core.ReannoTxsEvent) event.Subscription {
- panic("not supported")
+ return pool.scope.Track(pool.reannoTxFeed.Subscribe(ch))
}
// Nonce returns the next nonce of an account, with all transactions executable
diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go
index f8ddcc0c10..e4fc67f352 100644
--- a/core/txpool/blobpool/blobpool_test.go
+++ b/core/txpool/blobpool/blobpool_test.go
@@ -51,21 +51,9 @@ var (
emptyBlob = kzg4844.Blob{}
emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
- emptyBlobVHash = blobHash(emptyBlobCommit)
+ emptyBlobVHash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit)
)
-func blobHash(commit kzg4844.Commitment) common.Hash {
- hasher := sha256.New()
- hasher.Write(commit[:])
- hash := hasher.Sum(nil)
-
- var vhash common.Hash
- vhash[0] = params.BlobTxHashVersion
- copy(vhash[1:], hash[1:])
-
- return vhash
-}
-
// Chain configuration with Cancun enabled.
//
// TODO(karalabe): replace with params.MainnetChainConfig after Cancun.
@@ -193,8 +181,8 @@ func makeAddressReserver() txpool.AddressReserver {
// with a valid key, only setting the interesting fields from the perspective of
// the blob pool.
func makeTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64, key *ecdsa.PrivateKey) *types.Transaction {
- tx, _ := types.SignNewTx(key, types.LatestSigner(testChainConfig), makeUnsignedTx(nonce, gasTipCap, gasFeeCap, blobFeeCap))
- return tx
+ blobtx := makeUnsignedTx(nonce, gasTipCap, gasFeeCap, blobFeeCap)
+ return types.MustSignNewTx(key, types.LatestSigner(testChainConfig), blobtx)
}
// makeUnsignedTx is a utility method to construct a random blob tranasaction
@@ -209,6 +197,11 @@ func makeUnsignedTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap
BlobFeeCap: uint256.NewInt(blobFeeCap),
BlobHashes: []common.Hash{emptyBlobVHash},
Value: uint256.NewInt(100),
+ Sidecar: &types.BlobTxSidecar{
+ Blobs: []kzg4844.Blob{emptyBlob},
+ Commitments: []kzg4844.Commitment{emptyBlobCommit},
+ Proofs: []kzg4844.Proof{emptyBlobProof},
+ },
}
}
@@ -314,7 +307,7 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
// - 3. All transactions after a nonce gap must be dropped
// - 4. All transactions after an underpriced one (including it) must be dropped
func TestOpenDrops(t *testing.T) {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
// Create a temporary folder for the persistent backend
storage, _ := os.MkdirTemp("", "blobpool-")
@@ -341,7 +334,7 @@ func TestOpenDrops(t *testing.T) {
R: new(uint256.Int),
S: new(uint256.Int),
})
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
badsig, _ := store.Put(blob)
// Insert a sequence of transactions with a nonce gap in between to verify
@@ -354,7 +347,7 @@ func TestOpenDrops(t *testing.T) {
)
for _, nonce := range []uint64{0, 1, 3, 4, 6, 7} { // first gap at #2, another at #5
tx := makeTx(nonce, 1, 1, 1, gapper)
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
id, _ := store.Put(blob)
if nonce < 2 {
@@ -371,7 +364,7 @@ func TestOpenDrops(t *testing.T) {
)
for _, nonce := range []uint64{1, 2, 3} { // first gap at #0, all set dangling
tx := makeTx(nonce, 1, 1, 1, dangler)
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
id, _ := store.Put(blob)
dangling[id] = struct{}{}
@@ -384,7 +377,7 @@ func TestOpenDrops(t *testing.T) {
)
for _, nonce := range []uint64{0, 1, 2} { // account nonce at 3, all set filled
tx := makeTx(nonce, 1, 1, 1, filler)
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
id, _ := store.Put(blob)
filled[id] = struct{}{}
@@ -397,7 +390,7 @@ func TestOpenDrops(t *testing.T) {
)
for _, nonce := range []uint64{0, 1, 2, 3} { // account nonce at 2, half filled
tx := makeTx(nonce, 1, 1, 1, overlapper)
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
id, _ := store.Put(blob)
if nonce >= 2 {
@@ -419,7 +412,7 @@ func TestOpenDrops(t *testing.T) {
} else {
tx = makeTx(uint64(i), 1, 1, 1, underpayer)
}
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
id, _ := store.Put(blob)
underpaid[id] = struct{}{}
@@ -438,7 +431,7 @@ func TestOpenDrops(t *testing.T) {
} else {
tx = makeTx(uint64(i), 1, 1, 1, outpricer)
}
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
id, _ := store.Put(blob)
if i < 2 {
@@ -460,7 +453,7 @@ func TestOpenDrops(t *testing.T) {
} else {
tx = makeTx(nonce, 1, 1, 1, exceeder)
}
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
id, _ := store.Put(blob)
exceeded[id] = struct{}{}
@@ -478,7 +471,7 @@ func TestOpenDrops(t *testing.T) {
} else {
tx = makeTx(nonce, 1, 1, 1, overdrafter)
}
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
id, _ := store.Put(blob)
if nonce < 1 {
@@ -494,7 +487,7 @@ func TestOpenDrops(t *testing.T) {
overcapped = make(map[uint64]struct{})
)
for nonce := uint64(0); nonce < maxTxsPerAccount+3; nonce++ {
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: makeTx(nonce, 1, 1, 1, overcapper)})
+ blob, _ := rlp.EncodeToBytes(makeTx(nonce, 1, 1, 1, overcapper))
id, _ := store.Put(blob)
if nonce < maxTxsPerAccount {
@@ -507,17 +500,17 @@ func TestOpenDrops(t *testing.T) {
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
- statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), big.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000))
statedb.SetNonce(crypto.PubkeyToAddress(filler.PublicKey), 3)
- statedb.AddBalance(crypto.PubkeyToAddress(overlapper.PublicKey), big.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(overlapper.PublicKey), uint256.NewInt(1000000))
statedb.SetNonce(crypto.PubkeyToAddress(overlapper.PublicKey), 2)
- statedb.AddBalance(crypto.PubkeyToAddress(underpayer.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(outpricer.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(overdrafter.PublicKey), big.NewInt(1000000))
- statedb.AddBalance(crypto.PubkeyToAddress(overcapper.PublicKey), big.NewInt(10000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(underpayer.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(outpricer.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(overdrafter.PublicKey), uint256.NewInt(1000000))
+ statedb.AddBalance(crypto.PubkeyToAddress(overcapper.PublicKey), uint256.NewInt(10000000))
statedb.Finalise(true)
statedb.AccountsIntermediateRoot()
statedb.Commit(0, nil)
@@ -591,13 +584,13 @@ func TestOpenDrops(t *testing.T) {
verifyPoolInternals(t, pool)
}
-// Tests that transactions loaded from disk are indexed corrently.
+// Tests that transactions loaded from disk are indexed correctly.
//
// - 1. Transactions must be groupped by sender, sorted by nonce
// - 2. Eviction thresholds are calculated correctly for the sequences
// - 3. Balance usage of an account is totals across all transactions
func TestOpenIndex(t *testing.T) {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
// Create a temporary folder for the persistent backend
storage, _ := os.MkdirTemp("", "blobpool-")
@@ -627,14 +620,14 @@ func TestOpenIndex(t *testing.T) {
)
for _, i := range []int{5, 3, 4, 2, 0, 1} { // Randomize the tx insertion order to force sorting on load
tx := makeTx(uint64(i), txExecTipCaps[i], txExecFeeCaps[i], txBlobFeeCaps[i], key)
- blob, _ := rlp.EncodeToBytes(&blobTx{Tx: tx})
+ blob, _ := rlp.EncodeToBytes(tx)
store.Put(blob)
}
store.Close()
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
- statedb.AddBalance(addr, big.NewInt(1_000_000_000))
+ statedb.AddBalance(addr, uint256.NewInt(1_000_000_000))
statedb.Finalise(true)
statedb.AccountsIntermediateRoot()
statedb.Commit(0, nil)
@@ -688,7 +681,7 @@ func TestOpenIndex(t *testing.T) {
// Tests that after indexing all the loaded transactions from disk, a price heap
// is correctly constructed based on the head basefee and blobfee.
func TestOpenHeap(t *testing.T) {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
// Create a temporary folder for the persistent backend
storage, _ := os.MkdirTemp("", "blobpool-")
@@ -722,9 +715,9 @@ func TestOpenHeap(t *testing.T) {
tx2 = makeTx(0, 1, 800, 70, key2)
tx3 = makeTx(0, 1, 1500, 110, key3)
- blob1, _ = rlp.EncodeToBytes(&blobTx{Tx: tx1})
- blob2, _ = rlp.EncodeToBytes(&blobTx{Tx: tx2})
- blob3, _ = rlp.EncodeToBytes(&blobTx{Tx: tx3})
+ blob1, _ = rlp.EncodeToBytes(tx1)
+ blob2, _ = rlp.EncodeToBytes(tx2)
+ blob3, _ = rlp.EncodeToBytes(tx3)
heapOrder = []common.Address{addr2, addr1, addr3}
heapIndex = map[common.Address]int{addr2: 0, addr1: 1, addr3: 2}
@@ -736,9 +729,9 @@ func TestOpenHeap(t *testing.T) {
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
- statedb.AddBalance(addr1, big.NewInt(1_000_000_000))
- statedb.AddBalance(addr2, big.NewInt(1_000_000_000))
- statedb.AddBalance(addr3, big.NewInt(1_000_000_000))
+ statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000))
+ statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000))
+ statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000))
statedb.Finalise(true)
statedb.AccountsIntermediateRoot()
statedb.Commit(0, nil)
@@ -777,7 +770,7 @@ func TestOpenHeap(t *testing.T) {
// Tests that after the pool's previous state is loaded back, any transactions
// over the new storage cap will get dropped.
func TestOpenCap(t *testing.T) {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
// Create a temporary folder for the persistent backend
storage, _ := os.MkdirTemp("", "blobpool-")
@@ -800,9 +793,9 @@ func TestOpenCap(t *testing.T) {
tx2 = makeTx(0, 1, 800, 70, key2)
tx3 = makeTx(0, 1, 1500, 110, key3)
- blob1, _ = rlp.EncodeToBytes(&blobTx{Tx: tx1, Blobs: []kzg4844.Blob{emptyBlob}, Commits: []kzg4844.Commitment{emptyBlobCommit}, Proofs: []kzg4844.Proof{emptyBlobProof}})
- blob2, _ = rlp.EncodeToBytes(&blobTx{Tx: tx2, Blobs: []kzg4844.Blob{emptyBlob}, Commits: []kzg4844.Commitment{emptyBlobCommit}, Proofs: []kzg4844.Proof{emptyBlobProof}})
- blob3, _ = rlp.EncodeToBytes(&blobTx{Tx: tx3, Blobs: []kzg4844.Blob{emptyBlob}, Commits: []kzg4844.Commitment{emptyBlobCommit}, Proofs: []kzg4844.Proof{emptyBlobProof}})
+ blob1, _ = rlp.EncodeToBytes(tx1)
+ blob2, _ = rlp.EncodeToBytes(tx2)
+ blob3, _ = rlp.EncodeToBytes(tx3)
keep = []common.Address{addr1, addr3}
drop = []common.Address{addr2}
@@ -818,9 +811,9 @@ func TestOpenCap(t *testing.T) {
for _, datacap := range []uint64{2 * (txAvgSize + blobSize), 100 * (txAvgSize + blobSize)} {
// Create a blob pool out of the pre-seeded data, but cap it to 2 blob transaction
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
- statedb.AddBalance(addr1, big.NewInt(1_000_000_000))
- statedb.AddBalance(addr2, big.NewInt(1_000_000_000))
- statedb.AddBalance(addr3, big.NewInt(1_000_000_000))
+ statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000))
+ statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000))
+ statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000))
statedb.Finalise(true)
statedb.AccountsIntermediateRoot()
statedb.Commit(0, nil)
@@ -871,7 +864,7 @@ func TestOpenCap(t *testing.T) {
// specific to the blob pool. It does not do an exhaustive transaction validity
// check.
func TestAdd(t *testing.T) {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
// seed is a helper tumpe to seed an initial state db and pool
type seed struct {
@@ -1213,15 +1206,13 @@ func TestAdd(t *testing.T) {
addrs[acc] = crypto.PubkeyToAddress(keys[acc].PublicKey)
// Seed the state database with this acocunt
- statedb.AddBalance(addrs[acc], new(big.Int).SetUint64(seed.balance))
+ statedb.AddBalance(addrs[acc], new(uint256.Int).SetUint64(seed.balance))
statedb.SetNonce(addrs[acc], seed.nonce)
// Sign the seed transactions and store them in the data store
for _, tx := range seed.txs {
- var (
- signed, _ = types.SignNewTx(keys[acc], types.LatestSigner(testChainConfig), tx)
- blob, _ = rlp.EncodeToBytes(&blobTx{Tx: signed, Blobs: []kzg4844.Blob{emptyBlob}, Commits: []kzg4844.Commitment{emptyBlobCommit}, Proofs: []kzg4844.Proof{emptyBlobProof}})
- )
+ signed := types.MustSignNewTx(keys[acc], types.LatestSigner(testChainConfig), tx)
+ blob, _ := rlp.EncodeToBytes(signed)
store.Put(blob)
}
}
@@ -1246,7 +1237,7 @@ func TestAdd(t *testing.T) {
// Add each transaction one by one, verifying the pool internals in between
for j, add := range tt.adds {
signed, _ := types.SignNewTx(keys[add.from], types.LatestSigner(testChainConfig), add.tx)
- if err := pool.add(signed, []kzg4844.Blob{emptyBlob}, []kzg4844.Commitment{emptyBlobCommit}, []kzg4844.Proof{emptyBlobProof}); !errors.Is(err, add.err) {
+ if err := pool.add(signed); !errors.Is(err, add.err) {
t.Errorf("test %d, tx %d: adding transaction error mismatch: have %v, want %v", i, j, err, add.err)
}
verifyPoolInternals(t, pool)
diff --git a/core/txpool/blobpool/evictheap.go b/core/txpool/blobpool/evictheap.go
index 7607a911c1..df594099f7 100644
--- a/core/txpool/blobpool/evictheap.go
+++ b/core/txpool/blobpool/evictheap.go
@@ -44,7 +44,7 @@ type evictHeap struct {
index map[common.Address]int // Indices into the heap for replacements
}
-// newPriceHeap creates a new heap of cheapets accounts in the blob pool to evict
+// newPriceHeap creates a new heap of cheapest accounts in the blob pool to evict
// from in case of over saturation.
func newPriceHeap(basefee *uint256.Int, blobfee *uint256.Int, index *map[common.Address][]*blobTxMeta) *evictHeap {
heap := &evictHeap{
diff --git a/core/txpool/blobpool/limbo.go b/core/txpool/blobpool/limbo.go
index 4cb5042c2b..d1fe9c7394 100644
--- a/core/txpool/blobpool/limbo.go
+++ b/core/txpool/blobpool/limbo.go
@@ -21,7 +21,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/holiman/billy"
@@ -31,12 +30,9 @@ import (
// to which it belongs as well as the block number in which it was included for
// finality eviction.
type limboBlob struct {
- Owner common.Hash // Owner transaction's hash to support resurrecting reorged txs
- Block uint64 // Block in which the blob transaction was included
-
- Blobs []kzg4844.Blob // The opaque blobs originally part of the transaction
- Commits []kzg4844.Commitment // The commitments for the original blobs
- Proofs []kzg4844.Proof // The proofs verifying the commitments
+ TxHash common.Hash // Owner transaction's hash to support resurrecting reorged txs
+ Block uint64 // Block in which the blob transaction was included
+ Tx *types.Transaction
}
// limbo is a light, indexed database to temporarily store recently included
@@ -98,19 +94,19 @@ func (l *limbo) parseBlob(id uint64, data []byte) error {
log.Error("Failed to decode blob limbo entry", "id", id, "err", err)
return err
}
- if _, ok := l.index[item.Owner]; ok {
+ if _, ok := l.index[item.TxHash]; ok {
// This path is impossible, unless due to a programming error a blob gets
// inserted into the limbo which was already part of if. Recover gracefully
// by ignoring this data entry.
- log.Error("Dropping duplicate blob limbo entry", "owner", item.Owner, "id", id)
+ log.Error("Dropping duplicate blob limbo entry", "owner", item.TxHash, "id", id)
return errors.New("duplicate blob")
}
- l.index[item.Owner] = id
+ l.index[item.TxHash] = id
if _, ok := l.groups[item.Block]; !ok {
l.groups[item.Block] = make(map[uint64]common.Hash)
}
- l.groups[item.Block][id] = item.Owner
+ l.groups[item.Block][id] = item.TxHash
return nil
}
@@ -139,15 +135,15 @@ func (l *limbo) finalize(final *types.Header) {
// push stores a new blob transaction into the limbo, waiting until finality for
// it to be automatically evicted.
-func (l *limbo) push(tx common.Hash, block uint64, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof) error {
+func (l *limbo) push(tx *types.Transaction, block uint64) error {
// If the blobs are already tracked by the limbo, consider it a programming
// error. There's not much to do against it, but be loud.
- if _, ok := l.index[tx]; ok {
+ if _, ok := l.index[tx.Hash()]; ok {
log.Error("Limbo cannot push already tracked blobs", "tx", tx)
return errors.New("already tracked blob transaction")
}
- if err := l.setAndIndex(tx, block, blobs, commits, proofs); err != nil {
- log.Error("Failed to set and index liboed blobs", "tx", tx, "err", err)
+ if err := l.setAndIndex(tx, block); err != nil {
+ log.Error("Failed to set and index limboed blobs", "tx", tx, "err", err)
return err
}
return nil
@@ -156,21 +152,21 @@ func (l *limbo) push(tx common.Hash, block uint64, blobs []kzg4844.Blob, commits
// pull retrieves a previously pushed set of blobs back from the limbo, removing
// it at the same time. This method should be used when a previously included blob
// transaction gets reorged out.
-func (l *limbo) pull(tx common.Hash) ([]kzg4844.Blob, []kzg4844.Commitment, []kzg4844.Proof, error) {
+func (l *limbo) pull(tx common.Hash) (*types.Transaction, error) {
// If the blobs are not tracked by the limbo, there's not much to do. This
// can happen for example if a blob transaction is mined without pushing it
// into the network first.
id, ok := l.index[tx]
if !ok {
log.Trace("Limbo cannot pull non-tracked blobs", "tx", tx)
- return nil, nil, nil, errors.New("unseen blob transaction")
+ return nil, errors.New("unseen blob transaction")
}
item, err := l.getAndDrop(id)
if err != nil {
log.Error("Failed to get and drop limboed blobs", "tx", tx, "id", id, "err", err)
- return nil, nil, nil, err
+ return nil, err
}
- return item.Blobs, item.Commits, item.Proofs, nil
+ return item.Tx, nil
}
// update changes the block number under which a blob transaction is tracked. This
@@ -180,33 +176,33 @@ func (l *limbo) pull(tx common.Hash) ([]kzg4844.Blob, []kzg4844.Commitment, []kz
// any of it since there's no clear error case. Some errors may be due to coding
// issues, others caused by signers mining MEV stuff or swapping transactions. In
// all cases, the pool needs to continue operating.
-func (l *limbo) update(tx common.Hash, block uint64) {
+func (l *limbo) update(txhash common.Hash, block uint64) {
// If the blobs are not tracked by the limbo, there's not much to do. This
// can happen for example if a blob transaction is mined without pushing it
// into the network first.
- id, ok := l.index[tx]
+ id, ok := l.index[txhash]
if !ok {
- log.Trace("Limbo cannot update non-tracked blobs", "tx", tx)
+ log.Trace("Limbo cannot update non-tracked blobs", "tx", txhash)
return
}
// If there was no change in the blob's inclusion block, don't mess around
// with heavy database operations.
if _, ok := l.groups[block][id]; ok {
- log.Trace("Blob transaction unchanged in limbo", "tx", tx, "block", block)
+ log.Trace("Blob transaction unchanged in limbo", "tx", txhash, "block", block)
return
}
- // Retrieve the old blobs from the data store and write tehm back with a new
+ // Retrieve the old blobs from the data store and write them back with a new
// block number. IF anything fails, there's not much to do, go on.
item, err := l.getAndDrop(id)
if err != nil {
- log.Error("Failed to get and drop limboed blobs", "tx", tx, "id", id, "err", err)
+ log.Error("Failed to get and drop limboed blobs", "tx", txhash, "id", id, "err", err)
return
}
- if err := l.setAndIndex(tx, block, item.Blobs, item.Commits, item.Proofs); err != nil {
- log.Error("Failed to set and index limboed blobs", "tx", tx, "err", err)
+ if err := l.setAndIndex(item.Tx, block); err != nil {
+ log.Error("Failed to set and index limboed blobs", "tx", txhash, "err", err)
return
}
- log.Trace("Blob transaction updated in limbo", "tx", tx, "old-block", item.Block, "new-block", block)
+ log.Trace("Blob transaction updated in limbo", "tx", txhash, "old-block", item.Block, "new-block", block)
}
// getAndDrop retrieves a blob item from the limbo store and deletes it both from
@@ -220,7 +216,7 @@ func (l *limbo) getAndDrop(id uint64) (*limboBlob, error) {
if err = rlp.DecodeBytes(data, item); err != nil {
return nil, err
}
- delete(l.index, item.Owner)
+ delete(l.index, item.TxHash)
delete(l.groups[item.Block], id)
if len(l.groups[item.Block]) == 0 {
delete(l.groups, item.Block)
@@ -233,13 +229,12 @@ func (l *limbo) getAndDrop(id uint64) (*limboBlob, error) {
// setAndIndex assembles a limbo blob database entry and stores it, also updating
// the in-memory indices.
-func (l *limbo) setAndIndex(tx common.Hash, block uint64, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof) error {
+func (l *limbo) setAndIndex(tx *types.Transaction, block uint64) error {
+ txhash := tx.Hash()
item := &limboBlob{
- Owner: tx,
- Block: block,
- Blobs: blobs,
- Commits: commits,
- Proofs: proofs,
+ TxHash: txhash,
+ Block: block,
+ Tx: tx,
}
data, err := rlp.EncodeToBytes(item)
if err != nil {
@@ -249,10 +244,10 @@ func (l *limbo) setAndIndex(tx common.Hash, block uint64, blobs []kzg4844.Blob,
if err != nil {
return err
}
- l.index[tx] = id
+ l.index[txhash] = id
if _, ok := l.groups[block]; !ok {
l.groups[block] = make(map[uint64]common.Hash)
}
- l.groups[block][id] = tx
+ l.groups[block][id] = txhash
return nil
}
diff --git a/core/txpool/blobpool/metrics.go b/core/txpool/blobpool/metrics.go
index 070cc5ca47..587804cc61 100644
--- a/core/txpool/blobpool/metrics.go
+++ b/core/txpool/blobpool/metrics.go
@@ -65,7 +65,7 @@ var (
pooltipGauge = metrics.NewRegisteredGauge("blobpool/pooltip", nil)
// addwait/time, resetwait/time and getwait/time track the rough health of
- // the pool and wether or not it's capable of keeping up with the load from
+ // the pool and whether or not it's capable of keeping up with the load from
// the network.
addwaitHist = metrics.NewRegisteredHistogram("blobpool/addwait", nil, metrics.NewExpDecaySample(1028, 0.015))
addtimeHist = metrics.NewRegisteredHistogram("blobpool/addtime", nil, metrics.NewExpDecaySample(1028, 0.015))
diff --git a/core/txpool/blobpool/priority.go b/core/txpool/blobpool/priority.go
index 18e545c2a8..a8332bd9b0 100644
--- a/core/txpool/blobpool/priority.go
+++ b/core/txpool/blobpool/priority.go
@@ -27,7 +27,7 @@ import (
var log2_1_125 = math.Log2(1.125)
// evictionPriority calculates the eviction priority based on the algorithm
-// described in the BlobPool docs for a both fee components.
+// described in the BlobPool docs for both fee components.
//
// This method takes about 8ns on a very recent laptop CPU, recalculating about
// 125 million transaction priority values per second.
diff --git a/core/txpool/blobpool/slotter_test.go b/core/txpool/blobpool/slotter_test.go
index 2751a18725..a7b43b4d22 100644
--- a/core/txpool/blobpool/slotter_test.go
+++ b/core/txpool/blobpool/slotter_test.go
@@ -38,14 +38,16 @@ func TestNewSlotter(t *testing.T) {
2*blobSize + txAvgSize, // 2 blob + some expected tx infos (could be fewer blobs and more tx data)
3*blobSize + txAvgSize, // 3 blob + some expected tx infos (could be fewer blobs and more tx data)
4*blobSize + txAvgSize, // 4 blob + some expected tx infos (could be fewer blobs and more tx data)
- 5*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
- 6*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
- 7*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
- 8*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
- 9*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
- 10*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
- 11*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
- 12*blobSize + txAvgSize, // 1-4 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size
+ 5*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 6*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 7*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 8*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 9*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 10*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 11*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 12*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 13*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size
+ 14*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size
}
if len(shelves) != len(want) {
t.Errorf("shelves count mismatch: have %d, want %d", len(shelves), len(want))
diff --git a/core/txpool/errors.go b/core/txpool/errors.go
index bc26550f78..61daa999ff 100644
--- a/core/txpool/errors.go
+++ b/core/txpool/errors.go
@@ -52,6 +52,6 @@ var (
ErrOversizedData = errors.New("oversized data")
// ErrFutureReplacePending is returned if a future transaction replaces a pending
- // transaction. Future transactions should only be able to replace other future transactions.
+ // one. Future transactions should only be able to replace other future transactions.
ErrFutureReplacePending = errors.New("future transaction tries to replace pending")
)
diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go
index 08e629074f..b67abaa2b7 100644
--- a/core/txpool/legacypool/legacypool.go
+++ b/core/txpool/legacypool/legacypool.go
@@ -307,7 +307,20 @@ func (pool *LegacyPool) Init(gasTip *big.Int, head *types.Header, reserve txpool
// Set the basic pool parameters
pool.gasTip.Store(gasTip)
- pool.reset(nil, head)
+
+ // Initialize the state with head block, or fallback to empty one in
+ // case the head state is not available(might occur when node is not
+ // fully synced).
+ statedb, err := pool.chain.StateAt(head.Root)
+ if err != nil {
+ statedb, err = pool.chain.StateAt(types.EmptyRootHash)
+ }
+ if err != nil {
+ return err
+ }
+ pool.currentHead.Store(head)
+ pool.currentState = statedb
+ pool.pendingNonces = newNoncer(statedb)
// Start the reorg loop early, so it can handle requests generated during
// journal loading.
@@ -429,9 +442,6 @@ func (pool *LegacyPool) loop() {
// Close terminates the transaction pool.
func (pool *LegacyPool) Close() error {
- // Unsubscribe all subscriptions registered from txpool
- pool.scope.Close()
-
// Terminate the pool reorger and return
close(pool.reorgShutdownCh)
pool.wg.Wait()
@@ -444,16 +454,20 @@ func (pool *LegacyPool) Close() error {
}
// Reset implements txpool.SubPool, allowing the legacy pool's internal state to be
-// kept in sync with the main transacion pool's internal state.
+// kept in sync with the main transaction pool's internal state.
func (pool *LegacyPool) Reset(oldHead, newHead *types.Header) {
wait := pool.requestReset(oldHead, newHead)
<-wait
}
-// SubscribeTransactions registers a subscription of NewTxsEvent and
-// starts sending event to the given channel.
-func (pool *LegacyPool) SubscribeTransactions(ch chan<- core.NewTxsEvent) event.Subscription {
- return pool.scope.Track(pool.txFeed.Subscribe(ch))
+// SubscribeTransactions registers a subscription for new transaction events,
+// supporting feeding only newly seen or also resurrected transactions.
+func (pool *LegacyPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription {
+ // The legacy pool has a very messed up internal shuffling, so it's kind of
+ // hard to separate newly discovered transaction from resurrected ones. This
+ // is because the new txs are added to the queue, resurrected ones too and
+ // reorgs run lazily, so separating the two would need a marker.
+ return pool.txFeed.Subscribe(ch)
}
// SubscribeReannoTxsEvent registers a subscription of ReannoTxsEvent and
@@ -579,10 +593,12 @@ func (pool *LegacyPool) Pending(enforceTips bool) map[common.Address][]*txpool.L
lazies[i] = &txpool.LazyTransaction{
Pool: pool,
Hash: txs[i].Hash(),
- Tx: &txpool.Transaction{Tx: txs[i]},
+ Tx: txs[i],
Time: txs[i].Time(),
GasFeeCap: txs[i].GasFeeCap(),
GasTipCap: txs[i].GasTipCap(),
+ Gas: txs[i].Gas(),
+ BlobGas: txs[i].BlobGas(),
}
}
pending[addr] = lazies
@@ -643,7 +659,7 @@ func (pool *LegacyPool) validateTxBasics(tx *types.Transaction, local bool) erro
if local {
opts.MinTip = new(big.Int)
}
- if err := txpool.ValidateTransaction(tx, nil, nil, nil, pool.currentHead.Load(), pool.signer, opts); err != nil {
+ if err := txpool.ValidateTransaction(tx, pool.currentHead.Load(), pool.signer, opts); err != nil {
return err
}
return nil
@@ -703,7 +719,7 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction, local bool) error {
// pending or queued one, it overwrites the previous transaction if its price is higher.
//
// If a newly added transaction is marked as local, its sending account will be
-// be added to the allowlist, preventing any associated transaction from being dropped
+// added to the allowlist, preventing any associated transaction from being dropped
// out of the pool due to pricing constraints.
func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, err error) {
// If the transaction is already known, discard it
@@ -966,33 +982,19 @@ func (pool *LegacyPool) promoteTx(addr common.Address, hash common.Hash, tx *typ
return true
}
-// Add enqueues a batch of transactions into the pool if they are valid. Depending
-// on the local flag, full pricing contraints will or will not be applied.
-//
-// If sync is set, the method will block until all internal maintenance related
-// to the add is finished. Only use this during tests for determinism!
-func (pool *LegacyPool) Add(txs []*txpool.Transaction, local bool, sync bool) []error {
- unwrapped := make([]*types.Transaction, len(txs))
- for i, tx := range txs {
- unwrapped[i] = tx.Tx
- }
- return pool.addTxs(unwrapped, local, sync)
-}
-
// addLocals enqueues a batch of transactions into the pool if they are valid, marking the
-// senders as a local ones, ensuring they go around the local pricing constraints.
+// senders as local ones, ensuring they go around the local pricing constraints.
//
// This method is used to add transactions from the RPC API and performs synchronous pool
// reorganization and event propagation.
func (pool *LegacyPool) addLocals(txs []*types.Transaction) []error {
- return pool.addTxs(txs, !pool.config.NoLocals, true)
+ return pool.Add(txs, !pool.config.NoLocals, true)
}
// addLocal enqueues a single local transaction into the pool if it is valid. This is
// a convenience wrapper around addLocals.
func (pool *LegacyPool) addLocal(tx *types.Transaction) error {
- errs := pool.addLocals([]*types.Transaction{tx})
- return errs[0]
+ return pool.addLocals([]*types.Transaction{tx})[0]
}
// addRemotes enqueues a batch of transactions into the pool if they are valid. If the
@@ -1001,28 +1003,31 @@ func (pool *LegacyPool) addLocal(tx *types.Transaction) error {
// This method is used to add transactions from the p2p network and does not wait for pool
// reorganization and internal event propagation.
func (pool *LegacyPool) addRemotes(txs []*types.Transaction) []error {
- return pool.addTxs(txs, false, false)
+ return pool.Add(txs, false, false)
}
// addRemote enqueues a single transaction into the pool if it is valid. This is a convenience
// wrapper around addRemotes.
func (pool *LegacyPool) addRemote(tx *types.Transaction) error {
- errs := pool.addRemotes([]*types.Transaction{tx})
- return errs[0]
+ return pool.addRemotes([]*types.Transaction{tx})[0]
}
// addRemotesSync is like addRemotes, but waits for pool reorganization. Tests use this method.
func (pool *LegacyPool) addRemotesSync(txs []*types.Transaction) []error {
- return pool.addTxs(txs, false, true)
+ return pool.Add(txs, false, true)
}
// This is like addRemotes with a single transaction, but waits for pool reorganization. Tests use this method.
func (pool *LegacyPool) addRemoteSync(tx *types.Transaction) error {
- return pool.addTxs([]*types.Transaction{tx}, false, true)[0]
+ return pool.Add([]*types.Transaction{tx}, false, true)[0]
}
-// addTxs attempts to queue a batch of transactions if they are valid.
-func (pool *LegacyPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
+// Add enqueues a batch of transactions into the pool if they are valid. Depending
+// on the local flag, full pricing constraints will or will not be applied.
+//
+// If sync is set, the method will block until all internal maintenance related
+// to the add is finished. Only use this during tests for determinism!
+func (pool *LegacyPool) Add(txs []*types.Transaction, local, sync bool) []error {
// Do not treat as local if local transactions have been disabled
local = local && !pool.config.NoLocals
@@ -1043,6 +1048,7 @@ func (pool *LegacyPool) addTxs(txs []*types.Transaction, local, sync bool) []err
// in transactions before obtaining lock
if err := pool.validateTxBasics(tx, local); err != nil {
errs[i] = err
+ log.Trace("Discarding invalid transaction", "hash", tx.Hash(), "err", err)
invalidTxMeter.Mark(1)
continue
}
@@ -1111,12 +1117,12 @@ func (pool *LegacyPool) Status(hash common.Hash) txpool.TxStatus {
}
// Get returns a transaction if it is contained in the pool and nil otherwise.
-func (pool *LegacyPool) Get(hash common.Hash) *txpool.Transaction {
+func (pool *LegacyPool) Get(hash common.Hash) *types.Transaction {
tx := pool.get(hash)
if tx == nil {
return nil
}
- return &txpool.Transaction{Tx: tx}
+ return tx
}
// get returns a transaction if it is contained in the pool and nil otherwise.
@@ -1506,7 +1512,7 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T
}
log.Trace("Removed old queued transactions", "count", len(forwards))
// Drop all transactions that are too costly (low balance or out of gas)
- drops, _ := list.Filter(pool.currentState.GetBalance(addr), gasLimit)
+ drops, _ := list.Filter(pool.currentState.GetBalance(addr).ToBig(), gasLimit)
for _, tx := range drops {
hash := tx.Hash()
pool.all.Remove(hash)
@@ -1707,7 +1713,7 @@ func (pool *LegacyPool) demoteUnexecutables() {
log.Trace("Removed old pending transaction", "hash", hash)
}
// Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later
- drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit)
+ drops, invalids := list.Filter(pool.currentState.GetBalance(addr).ToBig(), gasLimit)
for _, tx := range drops {
hash := tx.Hash()
log.Trace("Removed unpayable pending transaction", "hash", hash)
diff --git a/core/txpool/legacypool/legacypool2_test.go b/core/txpool/legacypool/legacypool2_test.go
index a73c1bb8a7..0f53000b3d 100644
--- a/core/txpool/legacypool/legacypool2_test.go
+++ b/core/txpool/legacypool/legacypool2_test.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
+ "github.com/holiman/uint256"
)
func pricedValuedTransaction(nonce uint64, value int64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
@@ -49,7 +50,7 @@ func fillPool(t testing.TB, pool *LegacyPool) {
nonExecutableTxs := types.Transactions{}
for i := 0; i < 384; i++ {
key, _ := crypto.GenerateKey()
- pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000))
+ pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(10000000000))
// Add executable ones
for j := 0; j < int(pool.config.AccountSlots); j++ {
executableTxs = append(executableTxs, pricedTransaction(uint64(j), 100000, big.NewInt(300), key))
@@ -91,7 +92,7 @@ func TestTransactionFutureAttack(t *testing.T) {
// Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops
{
key, _ := crypto.GenerateKey()
- pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000))
+ pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000))
futureTxs := types.Transactions{}
for j := 0; j < int(pool.config.GlobalSlots+pool.config.GlobalQueue); j++ {
futureTxs = append(futureTxs, pricedTransaction(1000+uint64(j), 100000, big.NewInt(500), key))
@@ -128,7 +129,7 @@ func TestTransactionFuture1559(t *testing.T) {
// Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops
{
key, _ := crypto.GenerateKey()
- pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000))
+ pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000))
futureTxs := types.Transactions{}
for j := 0; j < int(pool.config.GlobalSlots+pool.config.GlobalQueue); j++ {
futureTxs = append(futureTxs, dynamicFeeTx(1000+uint64(j), 100000, big.NewInt(200), big.NewInt(101), key))
@@ -161,7 +162,7 @@ func TestTransactionZAttack(t *testing.T) {
var ivpendingNum int
pendingtxs, _ := pool.Content()
for account, txs := range pendingtxs {
- cur_balance := new(big.Int).Set(pool.currentState.GetBalance(account))
+ cur_balance := new(big.Int).Set(pool.currentState.GetBalance(account).ToBig())
for _, tx := range txs {
if cur_balance.Cmp(tx.Value()) <= 0 {
ivpendingNum++
@@ -182,7 +183,7 @@ func TestTransactionZAttack(t *testing.T) {
for j := 0; j < int(pool.config.GlobalQueue); j++ {
futureTxs := types.Transactions{}
key, _ := crypto.GenerateKey()
- pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000))
+ pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000))
futureTxs = append(futureTxs, pricedTransaction(1000+uint64(j), 21000, big.NewInt(500), key))
pool.addRemotesSync(futureTxs)
}
@@ -190,7 +191,7 @@ func TestTransactionZAttack(t *testing.T) {
overDraftTxs := types.Transactions{}
{
key, _ := crypto.GenerateKey()
- pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000))
+ pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000))
for j := 0; j < int(pool.config.GlobalSlots); j++ {
overDraftTxs = append(overDraftTxs, pricedValuedTransaction(uint64(j), 600000000000, 21000, big.NewInt(500), key))
}
@@ -227,7 +228,7 @@ func BenchmarkFutureAttack(b *testing.B) {
fillPool(b, pool)
key, _ := crypto.GenerateKey()
- pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(100000000000))
+ pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000))
futureTxs := types.Transactions{}
for n := 0; n < b.N; n++ {
diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go
index 05ff64aed1..7823e31650 100644
--- a/core/txpool/legacypool/legacypool_test.go
+++ b/core/txpool/legacypool/legacypool_test.go
@@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
var (
@@ -255,7 +256,7 @@ func (c *testChain) State() (*state.StateDB, error) {
c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
// simulate that the new head block included tx0 and tx1
c.statedb.SetNonce(c.address, 2)
- c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether))
+ c.statedb.SetBalance(c.address, new(uint256.Int).SetUint64(params.Ether))
*c.trigger = false
}
return stdb, nil
@@ -275,7 +276,7 @@ func TestStateChangeDuringReset(t *testing.T) {
)
// setup pool with 2 transaction in it
- statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether))
+ statedb.SetBalance(address, new(uint256.Int).SetUint64(params.Ether))
blockchain := &testChain{newTestBlockChain(params.TestChainConfig, 1000000000, statedb, new(event.Feed)), address, &trigger}
tx0 := transaction(0, 100000, key)
@@ -309,7 +310,7 @@ func TestStateChangeDuringReset(t *testing.T) {
func testAddBalance(pool *LegacyPool, addr common.Address, amount *big.Int) {
pool.mu.Lock()
- pool.currentState.AddBalance(addr, amount)
+ pool.currentState.AddBalance(addr, uint256.MustFromBig(amount))
pool.mu.Unlock()
}
@@ -470,7 +471,7 @@ func TestChainFork(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
- statedb.AddBalance(addr, big.NewInt(100000000000000))
+ statedb.AddBalance(addr, uint256.NewInt(100000000000000))
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
<-pool.requestReset(nil, nil)
@@ -499,7 +500,7 @@ func TestDoubleNonce(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
- statedb.AddBalance(addr, big.NewInt(100000000000000))
+ statedb.AddBalance(addr, uint256.NewInt(100000000000000))
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
<-pool.requestReset(nil, nil)
@@ -1492,6 +1493,50 @@ func TestRepricing(t *testing.T) {
}
}
+func TestMinGasPriceEnforced(t *testing.T) {
+ t.Parallel()
+
+ // Create the pool to test the pricing enforcement with
+ statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
+ blockchain := newTestBlockChain(eip1559Config, 10000000, statedb, new(event.Feed))
+
+ txPoolConfig := DefaultConfig
+ txPoolConfig.NoLocals = true
+ pool := New(txPoolConfig, blockchain)
+ pool.Init(new(big.Int).SetUint64(txPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
+ defer pool.Close()
+
+ key, _ := crypto.GenerateKey()
+ testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000))
+
+ tx := pricedTransaction(0, 100000, big.NewInt(2), key)
+ pool.SetGasTip(big.NewInt(tx.GasPrice().Int64() + 1))
+
+ if err := pool.addLocal(tx); !errors.Is(err, txpool.ErrUnderpriced) {
+ t.Fatalf("Min tip not enforced")
+ }
+
+ if err := pool.Add([]*types.Transaction{tx}, true, false)[0]; !errors.Is(err, txpool.ErrUnderpriced) {
+ t.Fatalf("Min tip not enforced")
+ }
+
+ tx = dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), key)
+ pool.SetGasTip(big.NewInt(tx.GasTipCap().Int64() + 1))
+
+ if err := pool.addLocal(tx); !errors.Is(err, txpool.ErrUnderpriced) {
+ t.Fatalf("Min tip not enforced")
+ }
+
+ if err := pool.Add([]*types.Transaction{tx}, true, false)[0]; !errors.Is(err, txpool.ErrUnderpriced) {
+ t.Fatalf("Min tip not enforced")
+ }
+ // Make sure the tx is accepted if locals are enabled
+ pool.config.NoLocals = false
+ if err := pool.Add([]*types.Transaction{tx}, true, false)[0]; err != nil {
+ t.Fatalf("Min tip enforced with locals enabled, error: %v", err)
+ }
+}
+
// Tests that setting the transaction pool gas price to a higher value correctly
// discards everything cheaper (legacy & dynamic fee) than that and moves any
// gapped transactions back from the pending pool to the queue.
@@ -2509,7 +2554,7 @@ func TestTransactionPendingReannouce(t *testing.T) {
key, _ := crypto.GenerateKey()
account := crypto.PubkeyToAddress(key.PublicKey)
- pool.currentState.AddBalance(account, big.NewInt(1000000))
+ pool.currentState.AddBalance(account, uint256.NewInt(1000000))
events := make(chan core.ReannoTxsEvent, testTxPoolConfig.AccountQueue)
sub := pool.reannoTxFeed.Subscribe(events)
@@ -2660,7 +2705,7 @@ func BenchmarkMultiAccountBatchInsert(b *testing.B) {
for i := 0; i < b.N; i++ {
key, _ := crypto.GenerateKey()
account := crypto.PubkeyToAddress(key.PublicKey)
- pool.currentState.AddBalance(account, big.NewInt(1000000))
+ pool.currentState.AddBalance(account, uint256.NewInt(1000000))
tx := transaction(uint64(0), 100000, key)
batches[i] = tx
}
diff --git a/core/txpool/legacypool/list.go b/core/txpool/legacypool/list.go
index 8cd71f21c5..f412a21989 100644
--- a/core/txpool/legacypool/list.go
+++ b/core/txpool/legacypool/list.go
@@ -61,9 +61,10 @@ func (h *nonceHeap) Pop() interface{} {
// sortedMap is a nonce->transaction hash map with a heap based index to allow
// iterating over the contents in a nonce-incrementing way.
type sortedMap struct {
- items map[uint64]*types.Transaction // Hash map storing the transaction data
- index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
- cache types.Transactions // Cache of the transactions already sorted
+ items map[uint64]*types.Transaction // Hash map storing the transaction data
+ index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
+ cache types.Transactions // Cache of the transactions already sorted
+ cacheMu sync.Mutex // Mutex covering the cache
}
// newSortedMap creates a new nonce-sorted transaction map.
@@ -86,10 +87,12 @@ func (m *sortedMap) Put(tx *types.Transaction) {
if m.items[nonce] == nil {
heap.Push(m.index, nonce)
}
+ m.cacheMu.Lock()
if m.cache != nil {
txSortedMapPool.Put(m.cache)
}
m.items[nonce], m.cache = tx, nil
+ m.cacheMu.Unlock()
}
// Forward removes all transactions from the map with a nonce lower than the
@@ -105,9 +108,11 @@ func (m *sortedMap) Forward(threshold uint64) types.Transactions {
delete(m.items, nonce)
}
// If we had a cached order, shift the front
+ m.cacheMu.Lock()
if m.cache != nil {
m.cache = m.cache[len(removed):]
}
+ m.cacheMu.Unlock()
return removed
}
@@ -131,7 +136,9 @@ func (m *sortedMap) reheap() {
*m.index = append(*m.index, nonce)
}
heap.Init(m.index)
+ m.cacheMu.Lock()
m.cache = nil
+ m.cacheMu.Unlock()
}
// filter is identical to Filter, but **does not** regenerate the heap. This method
@@ -147,10 +154,12 @@ func (m *sortedMap) filter(filter func(*types.Transaction) bool) types.Transacti
}
}
if len(removed) > 0 {
+ m.cacheMu.Lock()
if m.cache != nil {
txSortedMapPool.Put(m.cache)
m.cache = nil
}
+ m.cacheMu.Unlock()
}
return removed
}
@@ -174,9 +183,11 @@ func (m *sortedMap) Cap(threshold int) types.Transactions {
heap.Init(m.index)
// If we had a cache, shift the back
+ m.cacheMu.Lock()
if m.cache != nil {
m.cache = m.cache[:len(m.cache)-len(drops)]
}
+ m.cacheMu.Unlock()
return drops
}
@@ -196,10 +207,12 @@ func (m *sortedMap) Remove(nonce uint64) bool {
}
}
delete(m.items, nonce)
+ m.cacheMu.Lock()
if m.cache != nil {
txSortedMapPool.Put(m.cache)
m.cache = nil
}
+ m.cacheMu.Unlock()
return true
}
@@ -209,7 +222,7 @@ func (m *sortedMap) Remove(nonce uint64) bool {
// removed from the list.
//
// Note, all transactions with nonces lower than start will also be returned to
-// prevent getting into and invalid state. This is not something that should ever
+// prevent getting into an invalid state. This is not something that should ever
// happen but better to be self correcting than failing!
func (m *sortedMap) Ready(start uint64) types.Transactions {
// Short circuit if no transactions are available
@@ -223,10 +236,12 @@ func (m *sortedMap) Ready(start uint64) types.Transactions {
delete(m.items, next)
heap.Pop(m.index)
}
+ m.cacheMu.Lock()
if m.cache != nil {
txSortedMapPool.Put(m.cache)
m.cache = nil
}
+ m.cacheMu.Unlock()
return ready
}
@@ -237,6 +252,8 @@ func (m *sortedMap) Len() int {
}
func (m *sortedMap) flatten() types.Transactions {
+ m.cacheMu.Lock()
+ defer m.cacheMu.Unlock()
// If the sorting was not cached yet, create and cache it
if m.cache == nil {
cache := txSortedMapPool.Get()
@@ -258,8 +275,8 @@ func (m *sortedMap) flatten() types.Transactions {
// sorted internal representation. The result of the sorting is cached in case
// it's requested again before any modifications are made to the contents.
func (m *sortedMap) Flatten() types.Transactions {
- // Copy the cache to prevent accidental modifications
cache := m.flatten()
+ // Copy the cache to prevent accidental modification
txs := make(types.Transactions, len(cache))
copy(txs, cache)
return txs
@@ -430,7 +447,7 @@ func (l *list) Remove(tx *types.Transaction) (bool, types.Transactions) {
// removed from the list.
//
// Note, all transactions with nonces lower than start will also be returned to
-// prevent getting into and invalid state. This is not something that should ever
+// prevent getting into an invalid state. This is not something that should ever
// happen but better to be self correcting than failing!
func (l *list) Ready(start uint64) types.Transactions {
txs := l.txs.Ready(start)
diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go
index f1a89c5719..3f644c88cf 100644
--- a/core/txpool/subpool.go
+++ b/core/txpool/subpool.go
@@ -23,42 +23,42 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/event"
)
-// Transaction is a helper struct to group together a canonical transaction with
-// satellite data items that are needed by the pool but are not part of the chain.
-type Transaction struct {
- Tx *types.Transaction // Canonical transaction
-
- BlobTxBlobs []kzg4844.Blob // Blobs needed by the blob pool
- BlobTxCommits []kzg4844.Commitment // Commitments needed by the blob pool
- BlobTxProofs []kzg4844.Proof // Proofs needed by the blob pool
-}
-
// LazyTransaction contains a small subset of the transaction properties that is
// enough for the miner and other APIs to handle large batches of transactions;
// and supports pulling up the entire transaction when really needed.
type LazyTransaction struct {
- Pool SubPool // Transaction subpool to pull the real transaction up
- Hash common.Hash // Transaction hash to pull up if needed
- Tx *Transaction // Transaction if already resolved
+ Pool LazyResolver // Transaction resolver to pull the real transaction up
+ Hash common.Hash // Transaction hash to pull up if needed
+ Tx *types.Transaction // Transaction if already resolved
Time time.Time // Time when the transaction was first seen
GasFeeCap *big.Int // Maximum fee per gas the transaction may consume
GasTipCap *big.Int // Maximum miner tip per gas the transaction can pay
+
+ Gas uint64 // Amount of gas required by the transaction
+ BlobGas uint64 // Amount of blob gas required by the transaction
}
// Resolve retrieves the full transaction belonging to a lazy handle if it is still
// maintained by the transaction pool.
-func (ltx *LazyTransaction) Resolve() *Transaction {
+func (ltx *LazyTransaction) Resolve() *types.Transaction {
if ltx.Tx == nil {
ltx.Tx = ltx.Pool.Get(ltx.Hash)
}
return ltx.Tx
}
+// LazyResolver is a minimal interface needed for a transaction pool to satisfy
+// resolving lazy transactions. It's mostly a helper to avoid the entire sub-
+// pool being injected into the lazy transaction.
+type LazyResolver interface {
+ // Get returns a transaction if it is contained in the pool, or nil otherwise.
+ Get(hash common.Hash) *types.Transaction
+}
+
// AddressReserver is passed by the main transaction pool to subpools, so they
// may request (and relinquish) exclusive access to certain addresses.
type AddressReserver func(addr common.Address, reserve bool) error
@@ -99,19 +99,21 @@ type SubPool interface {
Has(hash common.Hash) bool
// Get returns a transaction if it is contained in the pool, or nil otherwise.
- Get(hash common.Hash) *Transaction
+ Get(hash common.Hash) *types.Transaction
// Add enqueues a batch of transactions into the pool if they are valid. Due
// to the large transaction churn, add may postpone fully integrating the tx
// to a later point to batch multiple ones together.
- Add(txs []*Transaction, local bool, sync bool) []error
+ Add(txs []*types.Transaction, local bool, sync bool) []error
// Pending retrieves all currently processable transactions, grouped by origin
// account and sorted by nonce.
Pending(enforceTips bool) map[common.Address][]*LazyTransaction
- // SubscribeTransactions subscribes to new transaction events.
- SubscribeTransactions(ch chan<- core.NewTxsEvent) event.Subscription
+ // SubscribeTransactions subscribes to new transaction events. The subscriber
+ // can decide whether to receive notifications only for newly seen transactions
+ // or also for reorged out ones.
+ SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription
// SubscribeReannoTxsEvent should return an event subscription of
// ReannoTxsEvent and send events to the given channel.
diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go
index 7d9c2d4e92..46c90fe2fb 100644
--- a/core/txpool/txpool.go
+++ b/core/txpool/txpool.go
@@ -70,8 +70,11 @@ type TxPool struct {
reservations map[common.Address]SubPool // Map with the account to pool reservations
reserveLock sync.Mutex // Lock protecting the account reservations
- subs event.SubscriptionScope // Subscription scope to unscubscribe all on shutdown
+ subs event.SubscriptionScope // Subscription scope to unsubscribe all on shutdown
quit chan chan error // Quit channel to tear down the head updater
+ term chan struct{} // Termination channel to detect a closed pool
+
+ sync chan chan error // Testing / simulator channel to block until internal reset is done
}
// New creates a new transaction pool to gather, sort and filter inbound
@@ -86,6 +89,8 @@ func New(gasTip *big.Int, chain BlockChain, subpools []SubPool) (*TxPool, error)
subpools: subpools,
reservations: make(map[common.Address]SubPool),
quit: make(chan chan error),
+ term: make(chan struct{}),
+ sync: make(chan chan error),
}
for i, subpool := range subpools {
if err := subpool.Init(gasTip, head, pool.reserver(i, subpool)); err != nil {
@@ -155,13 +160,15 @@ func (p *TxPool) Close() error {
if err := <-errc; err != nil {
errs = append(errs, err)
}
-
// Terminate each subpool
for _, subpool := range p.subpools {
if err := subpool.Close(); err != nil {
errs = append(errs, err)
}
}
+ // Unsubscribe anyone still listening for tx events
+ p.subs.Close()
+
if len(errs) > 0 {
return fmt.Errorf("subpool close errors: %v", errs)
}
@@ -172,6 +179,9 @@ func (p *TxPool) Close() error {
// outside blockchain events as well as for various reporting and transaction
// eviction events.
func (p *TxPool) loop(head *types.Header, chain BlockChain) {
+ // Close the termination marker when the pool stops
+ defer close(p.term)
+
// Subscribe to chain head events to trigger subpool resets
var (
newHeadCh = make(chan core.ChainHeadEvent)
@@ -188,13 +198,23 @@ func (p *TxPool) loop(head *types.Header, chain BlockChain) {
var (
resetBusy = make(chan struct{}, 1) // Allow 1 reset to run concurrently
resetDone = make(chan *types.Header)
+
+ resetForced bool // Whether a forced reset was requested, only used in simulator mode
+ resetWaiter chan error // Channel waiting on a forced reset, only used in simulator mode
)
+ // Notify the live reset waiter to not block if the txpool is closed.
+ defer func() {
+ if resetWaiter != nil {
+ resetWaiter <- errors.New("pool already terminated")
+ resetWaiter = nil
+ }
+ }()
var errc chan error
for errc == nil {
// Something interesting might have happened, run a reset if there is
// one needed but none is running. The resetter will run on its own
// goroutine to allow chain head events to be consumed contiguously.
- if newHead != oldHead {
+ if newHead != oldHead || resetForced {
// Try to inject a busy marker and start a reset if successful
select {
case resetBusy <- struct{}{}:
@@ -206,8 +226,17 @@ func (p *TxPool) loop(head *types.Header, chain BlockChain) {
resetDone <- newHead
}(oldHead, newHead)
+ // If the reset operation was explicitly requested, consider it
+ // being fulfilled and drop the request marker. If it was not,
+ // this is a noop.
+ resetForced = false
+
default:
- // Reset already running, wait until it finishes
+ // Reset already running, wait until it finishes.
+ //
+ // Note, this will not drop any forced reset request. If a forced
+ // reset was requested, but we were busy, then when the currently
+ // running reset finishes, a new one will be spun up.
}
}
// Wait for the next chain head event or a previous reset finish
@@ -221,8 +250,26 @@ func (p *TxPool) loop(head *types.Header, chain BlockChain) {
oldHead = head
<-resetBusy
+ // If someone is waiting for a reset to finish, notify them, unless
+ // the forced op is still pending. In that case, wait another round
+ // of resets.
+ if resetWaiter != nil && !resetForced {
+ resetWaiter <- nil
+ resetWaiter = nil
+ }
+
case errc = <-p.quit:
// Termination requested, break out on the next loop round
+
+ case syncc := <-p.sync:
+ // Transaction pool is running inside a simulator, and we are about
+ // to create a new block. Request a forced sync operation to ensure
+ // that any running reset operation finishes to make block imports
+ // deterministic. On top of that, run a new reset operation to make
+ // transaction insertions deterministic instead of being stuck in a
+ // queue waiting for a reset.
+ resetForced = true
+ resetWaiter = syncc
}
}
// Notify the closer of termination (no error possible for now)
@@ -249,7 +296,7 @@ func (p *TxPool) Has(hash common.Hash) bool {
}
// Get returns a transaction if it is contained in the pool, or nil otherwise.
-func (p *TxPool) Get(hash common.Hash) *Transaction {
+func (p *TxPool) Get(hash common.Hash) *types.Transaction {
for _, subpool := range p.subpools {
if tx := subpool.Get(hash); tx != nil {
return tx
@@ -261,14 +308,14 @@ func (p *TxPool) Get(hash common.Hash) *Transaction {
// Add enqueues a batch of transactions into the pool if they are valid. Due
// to the large transaction churn, add may postpone fully integrating the tx
// to a later point to batch multiple ones together.
-func (p *TxPool) Add(txs []*Transaction, local bool, sync bool) []error {
+func (p *TxPool) Add(txs []*types.Transaction, local bool, sync bool) []error {
// Split the input transactions between the subpools. It shouldn't really
// happen that we receive merged batches, but better graceful than strange
// errors.
//
// We also need to track how the transactions were split across the subpools,
// so we can piece back the returned errors into the original order.
- txsets := make([][]*Transaction, len(p.subpools))
+ txsets := make([][]*types.Transaction, len(p.subpools))
splits := make([]int, len(txs))
for i, tx := range txs {
@@ -277,7 +324,7 @@ func (p *TxPool) Add(txs []*Transaction, local bool, sync bool) []error {
// Try to find a subpool that accepts the transaction
for j, subpool := range p.subpools {
- if subpool.Filter(tx.Tx) {
+ if subpool.Filter(tx) {
txsets[j] = append(txsets[j], tx)
splits[i] = j
break
@@ -316,12 +363,12 @@ func (p *TxPool) Pending(enforceTips bool) map[common.Address][]*LazyTransaction
return txs
}
-// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and starts sending
-// events to the given channel.
-func (p *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
+// SubscribeTransactions registers a subscription for new transaction events,
+// supporting feeding only newly seen or also resurrected transactions.
+func (p *TxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription {
subs := make([]event.Subscription, 0, len(p.subpools))
for _, subpool := range p.subpools {
- sub := subpool.SubscribeTransactions(ch)
+ sub := subpool.SubscribeTransactions(ch, reorgs)
if sub != nil { // sub will be nil when subpool have been shut down
subs = append(subs, sub)
}
@@ -329,7 +376,7 @@ func (p *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscrip
return p.subs.Track(event.JoinSubscriptions(subs...))
}
-// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and starts sending
+// SubscribeReannoTxsEvent registers a subscription of ReannoTxsEvent and starts sending
// events to the given channel.
func (p *TxPool) SubscribeReannoTxsEvent(ch chan<- core.ReannoTxsEvent) event.Subscription {
subs := make([]event.Subscription, 0, len(p.subpools))
@@ -420,7 +467,7 @@ func (p *TxPool) Locals() []common.Address {
}
// Status returns the known status (unknown/pending/queued) of a transaction
-// identified by their hashes.
+// identified by its hash.
func (p *TxPool) Status(hash common.Hash) TxStatus {
for _, subpool := range p.subpools {
if status := subpool.Status(hash); status != TxStatusUnknown {
@@ -429,3 +476,20 @@ func (p *TxPool) Status(hash common.Hash) TxStatus {
}
return TxStatusUnknown
}
+
+// Sync is a helper method for unit tests or simulator runs where the chain events
+// are arriving in quick succession, without any time in between them to run the
+// internal background reset operations. This method will run an explicit reset
+// operation to ensure the pool stabilises, thus avoiding flakey behavior.
+//
+// Note, do not use this in production / live code. In live code, the pool is
+// meant to reset on a separate thread to avoid DoS vectors.
+func (p *TxPool) Sync() error {
+ sync := make(chan error)
+ select {
+ case p.sync <- sync:
+ return <-sync
+ case <-p.term:
+ return errors.New("pool already terminated")
+ }
+}
diff --git a/core/txpool/validation.go b/core/txpool/validation.go
index cc9c82cfcd..a9bd14020b 100644
--- a/core/txpool/validation.go
+++ b/core/txpool/validation.go
@@ -46,7 +46,7 @@ type ValidationOptions struct {
//
// This check is public to allow different transaction pools to check the basic
// rules without duplicating code and running the risk of missed updates.
-func ValidateTransaction(tx *types.Transaction, blobs []kzg4844.Blob, commits []kzg4844.Commitment, proofs []kzg4844.Proof, head *types.Header, signer types.Signer, opts *ValidationOptions) error {
+func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types.Signer, opts *ValidationOptions) error {
// Ensure transactions not implemented by the calling pool are rejected
if opts.Accept&(1< params.BlobTxMaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob {
- return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.BlobTxMaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob)
- }
- if len(blobs) != len(hashes) {
- return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(blobs), len(hashes))
+ if len(hashes) > params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob {
+ return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob)
}
- if len(commits) != len(hashes) {
- return fmt.Errorf("invalid number of %d blob commitments compared to %d blob hashes", len(commits), len(hashes))
+ if err := validateBlobSidecar(hashes, sidecar); err != nil {
+ return err
}
- if len(proofs) != len(hashes) {
- return fmt.Errorf("invalid number of %d blob proofs compared to %d blob hashes", len(proofs), len(hashes))
- }
- // Blob quantities match up, validate that the provers match with the
- // transaction hash before getting to the cryptography
- hasher := sha256.New()
- for i, want := range hashes {
- hasher.Write(commits[i][:])
- hash := hasher.Sum(nil)
- hasher.Reset()
-
- var vhash common.Hash
- vhash[0] = params.BlobTxHashVersion
- copy(vhash[1:], hash[1:])
+ }
+ return nil
+}
- if vhash != want {
- return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, vhash, want)
- }
+func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobTxSidecar) error {
+ if len(sidecar.Blobs) != len(hashes) {
+ return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(sidecar.Blobs), len(hashes))
+ }
+ if len(sidecar.Commitments) != len(hashes) {
+ return fmt.Errorf("invalid number of %d blob commitments compared to %d blob hashes", len(sidecar.Commitments), len(hashes))
+ }
+ if len(sidecar.Proofs) != len(hashes) {
+ return fmt.Errorf("invalid number of %d blob proofs compared to %d blob hashes", len(sidecar.Proofs), len(hashes))
+ }
+ // Blob quantities match up, validate that the provers match with the
+ // transaction hash before getting to the cryptography
+ hasher := sha256.New()
+ for i, vhash := range hashes {
+ computed := kzg4844.CalcBlobHashV1(hasher, &sidecar.Commitments[i])
+ if vhash != computed {
+ return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, computed, vhash)
}
- // Blob commitments match with the hashes in the transaction, verify the
- // blobs themselves via KZG
- for i := range blobs {
- if err := kzg4844.VerifyBlobProof(blobs[i], commits[i], proofs[i]); err != nil {
- return fmt.Errorf("invalid blob %d: %v", i, err)
- }
+ }
+ // Blob commitments match with the hashes in the transaction, verify the
+ // blobs themselves via KZG
+ for i := range sidecar.Blobs {
+ if err := kzg4844.VerifyBlobProof(sidecar.Blobs[i], sidecar.Commitments[i], sidecar.Proofs[i]); err != nil {
+ return fmt.Errorf("invalid blob %d: %v", i, err)
}
}
return nil
@@ -171,7 +175,7 @@ type ValidationOptionsWithState struct {
// be rejected once the number of remaining slots reaches zero.
UsedAndLeftSlots func(addr common.Address) (int, int)
- // ExistingExpenditure is a mandatory callback to retrieve the cummulative
+ // ExistingExpenditure is a mandatory callback to retrieve the cumulative
// cost of the already pooled transactions to check for overdrafts.
ExistingExpenditure func(addr common.Address) *big.Int
@@ -205,7 +209,7 @@ func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, op
}
// Ensure the transactor has enough funds to cover the transaction costs
var (
- balance = opts.State.GetBalance(from)
+ balance = opts.State.GetBalance(from).ToBig()
cost = tx.Cost()
)
if balance.Cmp(cost) < 0 {
diff --git a/core/types/bid.go b/core/types/bid.go
new file mode 100644
index 0000000000..6d7796acfc
--- /dev/null
+++ b/core/types/bid.go
@@ -0,0 +1,184 @@
+package types
+
+import (
+ "fmt"
+ "math/big"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+const TxDecodeConcurrencyForPerBid = 5
+
+// BidArgs represents the arguments to submit a bid.
+type BidArgs struct {
+ // RawBid from builder directly
+ RawBid *RawBid
+ // Signature of the bid from builder
+ Signature hexutil.Bytes `json:"signature"`
+
+ // PayBidTx is a payment tx to builder from sentry, which is optional
+ PayBidTx hexutil.Bytes `json:"payBidTx"`
+ PayBidTxGasUsed uint64 `json:"payBidTxGasUsed"`
+}
+
+func (b *BidArgs) EcrecoverSender() (common.Address, error) {
+ pk, err := crypto.SigToPub(b.RawBid.Hash().Bytes(), b.Signature)
+ if err != nil {
+ return common.Address{}, err
+ }
+
+ return crypto.PubkeyToAddress(*pk), nil
+}
+
+func (b *BidArgs) ToBid(builder common.Address, signer Signer) (*Bid, error) {
+ txs, err := b.RawBid.DecodeTxs(signer)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(b.PayBidTx) != 0 {
+ var payBidTx = new(Transaction)
+ err = payBidTx.UnmarshalBinary(b.PayBidTx)
+ if err != nil {
+ return nil, err
+ }
+
+ txs = append(txs, payBidTx)
+ }
+
+ bid := &Bid{
+ Builder: builder,
+ BlockNumber: b.RawBid.BlockNumber,
+ ParentHash: b.RawBid.ParentHash,
+ Txs: txs,
+ GasUsed: b.RawBid.GasUsed + b.PayBidTxGasUsed,
+ GasFee: b.RawBid.GasFee,
+ BuilderFee: b.RawBid.BuilderFee,
+ rawBid: *b.RawBid,
+ }
+
+ if bid.BuilderFee == nil {
+ bid.BuilderFee = big.NewInt(0)
+ }
+
+ return bid, nil
+}
+
+// RawBid represents a raw bid from builder directly.
+type RawBid struct {
+ BlockNumber uint64 `json:"blockNumber"`
+ ParentHash common.Hash `json:"parentHash"`
+ Txs []hexutil.Bytes `json:"txs"`
+ GasUsed uint64 `json:"gasUsed"`
+ GasFee *big.Int `json:"gasFee"`
+ BuilderFee *big.Int `json:"builderFee"`
+
+ hash atomic.Value
+}
+
+func (b *RawBid) DecodeTxs(signer Signer) ([]*Transaction, error) {
+ if len(b.Txs) == 0 {
+ return []*Transaction{}, nil
+ }
+
+ txChan := make(chan int, len(b.Txs))
+ bidTxs := make([]*Transaction, len(b.Txs))
+ decode := func(txBytes hexutil.Bytes) (*Transaction, error) {
+ tx := new(Transaction)
+ err := tx.UnmarshalBinary(txBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ _, err = Sender(signer, tx)
+ if err != nil {
+ return nil, err
+ }
+
+ return tx, nil
+ }
+
+ errChan := make(chan error, TxDecodeConcurrencyForPerBid)
+ for i := 0; i < TxDecodeConcurrencyForPerBid; i++ {
+ go func() {
+ for {
+ txIndex, ok := <-txChan
+ if !ok {
+ errChan <- nil
+ return
+ }
+
+ txBytes := b.Txs[txIndex]
+ tx, err := decode(txBytes)
+ if err != nil {
+ errChan <- err
+ return
+ }
+
+ bidTxs[txIndex] = tx
+ }
+ }()
+ }
+
+ for i := 0; i < len(b.Txs); i++ {
+ txChan <- i
+ }
+
+ close(txChan)
+
+ for i := 0; i < TxDecodeConcurrencyForPerBid; i++ {
+ err := <-errChan
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode tx, %v", err)
+ }
+ }
+
+ return bidTxs, nil
+}
+
+// Hash returns the hash of the bid.
+func (b *RawBid) Hash() common.Hash {
+ if hash := b.hash.Load(); hash != nil {
+ return hash.(common.Hash)
+ }
+
+ h := rlpHash(b)
+ b.hash.Store(h)
+
+ return h
+}
+
+// Bid represents a bid.
+type Bid struct {
+ Builder common.Address
+ BlockNumber uint64
+ ParentHash common.Hash
+ Txs Transactions
+ GasUsed uint64
+ GasFee *big.Int
+ BuilderFee *big.Int
+
+ rawBid RawBid
+}
+
+// Hash returns the bid hash.
+func (b *Bid) Hash() common.Hash {
+ return b.rawBid.Hash()
+}
+
+// BidIssue represents a bid issue.
+type BidIssue struct {
+ Validator common.Address
+ Builder common.Address
+ BidHash common.Hash
+ Message string
+}
+
+type MevParams struct {
+ ValidatorCommission uint64 // 100 means 1%
+ BidSimulationLeftOver time.Duration
+}
diff --git a/core/types/bid_error.go b/core/types/bid_error.go
new file mode 100644
index 0000000000..6b543ae64f
--- /dev/null
+++ b/core/types/bid_error.go
@@ -0,0 +1,45 @@
+package types
+
+import "errors"
+
+const (
+ InvalidBidParamError = -38001
+ InvalidPayBidTxError = -38002
+ MevNotRunningError = -38003
+ MevBusyError = -38004
+ MevNotInTurnError = -38005
+)
+
+var (
+ ErrMevNotRunning = newBidError(errors.New("the validator stop accepting bids for now, try again later"), MevNotRunningError)
+ ErrMevBusy = newBidError(errors.New("the validator is working on too many bids, try again later"), MevBusyError)
+ ErrMevNotInTurn = newBidError(errors.New("the validator is not in-turn to propose currently, try again later"), MevNotInTurnError)
+)
+
+// bidError is an API error that encompasses an invalid bid with JSON error
+// code and a binary data blob.
+type bidError struct {
+ error
+ code int
+}
+
+// ErrorCode returns the JSON error code for an invalid bid.
+// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
+func (e *bidError) ErrorCode() int {
+ return e.code
+}
+
+func NewInvalidBidError(message string) *bidError {
+ return newBidError(errors.New(message), InvalidBidParamError)
+}
+
+func NewInvalidPayBidTxError(message string) *bidError {
+ return newBidError(errors.New(message), InvalidPayBidTxError)
+}
+
+func newBidError(err error, code int) *bidError {
+ return &bidError{
+ error: err,
+ code: code,
+ }
+}
diff --git a/core/types/block.go b/core/types/block.go
index 0ce5b4d068..ac6066dd9b 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -26,6 +26,8 @@ import (
"sync/atomic"
"time"
+ "golang.org/x/crypto/sha3"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rlp"
@@ -116,6 +118,9 @@ type Header struct {
// ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers.
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
+
+ // ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
+ ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
}
// field type overrides for gencodec
@@ -323,6 +328,10 @@ func CopyHeader(h *Header) *Header {
cpy.BlobGasUsed = new(uint64)
*cpy.BlobGasUsed = *h.BlobGasUsed
}
+ if h.ParentBeaconRoot != nil {
+ cpy.ParentBeaconRoot = new(common.Hash)
+ *cpy.ParentBeaconRoot = *h.ParentBeaconRoot
+ }
return &cpy
}
@@ -402,6 +411,8 @@ func (b *Block) BaseFee() *big.Int {
return new(big.Int).Set(b.header.BaseFee)
}
+func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot }
+
func (b *Block) ExcessBlobGas() *uint64 {
var excessBlobGas *uint64
if b.header.ExcessBlobGas != nil {
@@ -560,8 +571,7 @@ func (d *DiffLayer) DecodeRLP(s *rlp.Stream) error {
if err := s.Decode(&ed); err != nil {
return err
}
- d.BlockHash, d.Number, d.Codes, d.Destructs, d.Accounts, d.Storages =
- ed.BlockHash, ed.Number, ed.Codes, ed.Destructs, ed.Accounts, ed.Storages
+ d.BlockHash, d.Number, d.Codes, d.Destructs, d.Accounts, d.Storages = ed.BlockHash, ed.Number, ed.Codes, ed.Destructs, ed.Accounts, ed.Storages
d.Receipts = make([]*Receipt, len(ed.Receipts))
for i, storageReceipt := range ed.Receipts {
@@ -608,6 +618,7 @@ func (storage *DiffStorage) Swap(i, j int) {
storage.Keys[i], storage.Keys[j] = storage.Keys[j], storage.Keys[i]
storage.Vals[i], storage.Vals[j] = storage.Vals[j], storage.Vals[i]
}
+
func (storage *DiffStorage) Less(i, j int) bool {
return string(storage.Keys[i][:]) < string(storage.Keys[j][:])
}
@@ -622,3 +633,64 @@ type DiffAccountsInBlock struct {
BlockHash common.Hash
Transactions []DiffAccountsInTx
}
+
+var (
+ extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
+ extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
+)
+
+// SealHash returns the hash of a block prior to it being sealed.
+func SealHash(header *Header, chainId *big.Int) (hash common.Hash) {
+ hasher := sha3.NewLegacyKeccak256()
+ EncodeSigHeader(hasher, header, chainId)
+ hasher.Sum(hash[:0])
+ return hash
+}
+
+func EncodeSigHeader(w io.Writer, header *Header, chainId *big.Int) {
+ err := rlp.Encode(w, []interface{}{
+ chainId,
+ header.ParentHash,
+ header.UncleHash,
+ header.Coinbase,
+ header.Root,
+ header.TxHash,
+ header.ReceiptHash,
+ header.Bloom,
+ header.Difficulty,
+ header.Number,
+ header.GasLimit,
+ header.GasUsed,
+ header.Time,
+ header.Extra[:len(header.Extra)-extraSeal], // this will panic if extra is too short, should check before calling encodeSigHeader
+ header.MixDigest,
+ header.Nonce,
+ })
+ if err != nil {
+ panic("can't encode: " + err.Error())
+ }
+}
+
+func EncodeSigHeaderWithoutVoteAttestation(w io.Writer, header *Header, chainId *big.Int) {
+ err := rlp.Encode(w, []interface{}{
+ chainId,
+ header.ParentHash,
+ header.UncleHash,
+ header.Coinbase,
+ header.Root,
+ header.TxHash,
+ header.ReceiptHash,
+ header.Bloom,
+ header.Difficulty,
+ header.Number,
+ header.GasLimit,
+ header.GasUsed,
+ header.Time,
+ header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
+ header.MixDigest,
+ header.Nonce,
+ })
+ if err != nil {
+ panic("can't encode: " + err.Error())
+ }
+}
diff --git a/core/types/block_test.go b/core/types/block_test.go
index 79ee0f26fd..68b278289f 100644
--- a/core/types/block_test.go
+++ b/core/types/block_test.go
@@ -68,7 +68,7 @@ func TestBlockEncoding(t *testing.T) {
}
func TestEIP1559BlockEncoding(t *testing.T) {
- blockEnc := common.FromHex("f90303f901faa083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c480f90102f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b89f02f89c018080808301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000080a0fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b0a06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a8c0")
+ blockEnc := common.FromHex("f9030bf901fea083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4843b9aca00f90106f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b8a302f8a0018080843b9aca008301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000080a0fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b0a06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a8c0")
var block Block
if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
t.Fatal("decode error: ", err)
@@ -86,7 +86,7 @@ func TestEIP1559BlockEncoding(t *testing.T) {
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
- check("Hash", block.Hash(), common.HexToHash("0xae9d971d16de73f69f940f1bd4ce5961158781176e73abea92a2b8781403885e"))
+ check("Hash", block.Hash(), common.HexToHash("c7252048cd273fe0dac09650027d07f0e3da4ee0675ebbb26627cea92729c372"))
check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
check("Time", block.Time(), uint64(1426516743))
check("Size", block.Size(), uint64(len(blockEnc)))
diff --git a/core/types/gen_account_rlp.go b/core/types/gen_account_rlp.go
index 5181d88411..8b424493af 100644
--- a/core/types/gen_account_rlp.go
+++ b/core/types/gen_account_rlp.go
@@ -1,8 +1,5 @@
// Code generated by rlpgen. DO NOT EDIT.
-//go:build !norlpgen
-// +build !norlpgen
-
package types
import "github.com/ethereum/go-ethereum/rlp"
@@ -15,10 +12,7 @@ func (obj *StateAccount) EncodeRLP(_w io.Writer) error {
if obj.Balance == nil {
w.Write(rlp.EmptyString)
} else {
- if obj.Balance.Sign() == -1 {
- return rlp.ErrNegativeBigInt
- }
- w.WriteBigInt(obj.Balance)
+ w.WriteUint256(obj.Balance)
}
w.WriteBytes(obj.Root[:])
w.WriteBytes(obj.CodeHash)
diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go
index bac475959d..fb1f915d01 100644
--- a/core/types/gen_header_json.go
+++ b/core/types/gen_header_json.go
@@ -16,26 +16,27 @@ var _ = (*headerMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (h Header) MarshalJSON() ([]byte, error) {
type Header struct {
- ParentHash common.Hash `json:"parentHash" gencodec:"required"`
- UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
- Coinbase common.Address `json:"miner"`
- Root common.Hash `json:"stateRoot" gencodec:"required"`
- TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
- ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
- Bloom Bloom `json:"logsBloom" gencodec:"required"`
- Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
- Number *hexutil.Big `json:"number" gencodec:"required"`
- GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
- Time hexutil.Uint64 `json:"timestamp" gencodec:"required"`
- Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
- MixDigest common.Hash `json:"mixHash"`
- Nonce BlockNonce `json:"nonce"`
- BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
- WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
- BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
- ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
- Hash common.Hash `json:"hash"`
+ ParentHash common.Hash `json:"parentHash" gencodec:"required"`
+ UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
+ Coinbase common.Address `json:"miner"`
+ Root common.Hash `json:"stateRoot" gencodec:"required"`
+ TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
+ ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
+ Bloom Bloom `json:"logsBloom" gencodec:"required"`
+ Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
+ Number *hexutil.Big `json:"number" gencodec:"required"`
+ GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
+ Time hexutil.Uint64 `json:"timestamp" gencodec:"required"`
+ Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
+ MixDigest common.Hash `json:"mixHash"`
+ Nonce BlockNonce `json:"nonce"`
+ BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
+ WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
+ BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
+ ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
+ ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
+ Hash common.Hash `json:"hash"`
}
var enc Header
enc.ParentHash = h.ParentHash
@@ -57,6 +58,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
enc.WithdrawalsHash = h.WithdrawalsHash
enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed)
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
+ enc.ParentBeaconRoot = h.ParentBeaconRoot
enc.Hash = h.Hash()
return json.Marshal(&enc)
}
@@ -64,25 +66,26 @@ func (h Header) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON.
func (h *Header) UnmarshalJSON(input []byte) error {
type Header struct {
- ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
- UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
- Coinbase *common.Address `json:"miner"`
- Root *common.Hash `json:"stateRoot" gencodec:"required"`
- TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
- ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
- Bloom *Bloom `json:"logsBloom" gencodec:"required"`
- Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
- Number *hexutil.Big `json:"number" gencodec:"required"`
- GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
- Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
- Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
- MixDigest *common.Hash `json:"mixHash"`
- Nonce *BlockNonce `json:"nonce"`
- BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
- WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
- BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
- ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
+ ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
+ UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
+ Coinbase *common.Address `json:"miner"`
+ Root *common.Hash `json:"stateRoot" gencodec:"required"`
+ TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
+ ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
+ Bloom *Bloom `json:"logsBloom" gencodec:"required"`
+ Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
+ Number *hexutil.Big `json:"number" gencodec:"required"`
+ GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
+ Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
+ Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
+ MixDigest *common.Hash `json:"mixHash"`
+ Nonce *BlockNonce `json:"nonce"`
+ BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
+ WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
+ BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
+ ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
+ ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
}
var dec Header
if err := json.Unmarshal(input, &dec); err != nil {
@@ -157,5 +160,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
if dec.ExcessBlobGas != nil {
h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
}
+ if dec.ParentBeaconRoot != nil {
+ h.ParentBeaconRoot = dec.ParentBeaconRoot
+ }
return nil
}
diff --git a/core/types/gen_header_rlp.go b/core/types/gen_header_rlp.go
index a5ed5cd150..ed6a1a002c 100644
--- a/core/types/gen_header_rlp.go
+++ b/core/types/gen_header_rlp.go
@@ -1,8 +1,5 @@
// Code generated by rlpgen. DO NOT EDIT.
-//go:build !norlpgen
-// +build !norlpgen
-
package types
import "github.com/ethereum/go-ethereum/rlp"
@@ -44,7 +41,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
_tmp2 := obj.WithdrawalsHash != nil
_tmp3 := obj.BlobGasUsed != nil
_tmp4 := obj.ExcessBlobGas != nil
- if _tmp1 || _tmp2 || _tmp3 || _tmp4 {
+ _tmp5 := obj.ParentBeaconRoot != nil
+ if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 {
if obj.BaseFee == nil {
w.Write(rlp.EmptyString)
} else {
@@ -54,27 +52,34 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
w.WriteBigInt(obj.BaseFee)
}
}
- if _tmp2 || _tmp3 || _tmp4 {
+ if _tmp2 || _tmp3 || _tmp4 || _tmp5 {
if obj.WithdrawalsHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.WithdrawalsHash[:])
}
}
- if _tmp3 || _tmp4 {
+ if _tmp3 || _tmp4 || _tmp5 {
if obj.BlobGasUsed == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.BlobGasUsed))
}
}
- if _tmp4 {
+ if _tmp4 || _tmp5 {
if obj.ExcessBlobGas == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.ExcessBlobGas))
}
}
+ if _tmp5 {
+ if obj.ParentBeaconRoot == nil {
+ w.Write([]byte{0x80})
+ } else {
+ w.WriteBytes(obj.ParentBeaconRoot[:])
+ }
+ }
w.ListEnd(_tmp0)
return w.Flush()
}
diff --git a/core/types/gen_log_json.go b/core/types/gen_log_json.go
index 90e1c14d90..3ffa9c2feb 100644
--- a/core/types/gen_log_json.go
+++ b/core/types/gen_log_json.go
@@ -18,12 +18,12 @@ func (l Log) MarshalJSON() ([]byte, error) {
Address common.Address `json:"address" gencodec:"required"`
Topics []common.Hash `json:"topics" gencodec:"required"`
Data hexutil.Bytes `json:"data" gencodec:"required"`
- BlockNumber hexutil.Uint64 `json:"blockNumber"`
- TxHash common.Hash `json:"transactionHash" gencodec:"required"`
- TxIndex hexutil.Uint `json:"transactionIndex"`
- BlockHash common.Hash `json:"blockHash"`
- Index hexutil.Uint `json:"logIndex"`
- Removed bool `json:"removed"`
+ BlockNumber hexutil.Uint64 `json:"blockNumber" rlp:"-"`
+ TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"`
+ TxIndex hexutil.Uint `json:"transactionIndex" rlp:"-"`
+ BlockHash common.Hash `json:"blockHash" rlp:"-"`
+ Index hexutil.Uint `json:"logIndex" rlp:"-"`
+ Removed bool `json:"removed" rlp:"-"`
}
var enc Log
enc.Address = l.Address
@@ -44,12 +44,12 @@ func (l *Log) UnmarshalJSON(input []byte) error {
Address *common.Address `json:"address" gencodec:"required"`
Topics []common.Hash `json:"topics" gencodec:"required"`
Data *hexutil.Bytes `json:"data" gencodec:"required"`
- BlockNumber *hexutil.Uint64 `json:"blockNumber"`
- TxHash *common.Hash `json:"transactionHash" gencodec:"required"`
- TxIndex *hexutil.Uint `json:"transactionIndex"`
- BlockHash *common.Hash `json:"blockHash"`
- Index *hexutil.Uint `json:"logIndex"`
- Removed *bool `json:"removed"`
+ BlockNumber *hexutil.Uint64 `json:"blockNumber" rlp:"-"`
+ TxHash *common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"`
+ TxIndex *hexutil.Uint `json:"transactionIndex" rlp:"-"`
+ BlockHash *common.Hash `json:"blockHash" rlp:"-"`
+ Index *hexutil.Uint `json:"logIndex" rlp:"-"`
+ Removed *bool `json:"removed" rlp:"-"`
}
var dec Log
if err := json.Unmarshal(input, &dec); err != nil {
diff --git a/core/types/gen_log_rlp.go b/core/types/gen_log_rlp.go
index 4a6c6b0094..7e89629668 100644
--- a/core/types/gen_log_rlp.go
+++ b/core/types/gen_log_rlp.go
@@ -1,14 +1,11 @@
// Code generated by rlpgen. DO NOT EDIT.
-//go:build !norlpgen
-// +build !norlpgen
-
package types
import "github.com/ethereum/go-ethereum/rlp"
import "io"
-func (obj *rlpLog) EncodeRLP(_w io.Writer) error {
+func (obj *Log) EncodeRLP(_w io.Writer) error {
w := rlp.NewEncoderBuffer(_w)
_tmp0 := w.List()
w.WriteBytes(obj.Address[:])
diff --git a/core/types/gen_withdrawal_rlp.go b/core/types/gen_withdrawal_rlp.go
index d0b4e0147a..6a97c04c81 100644
--- a/core/types/gen_withdrawal_rlp.go
+++ b/core/types/gen_withdrawal_rlp.go
@@ -1,8 +1,5 @@
// Code generated by rlpgen. DO NOT EDIT.
-//go:build !norlpgen
-// +build !norlpgen
-
package types
import "github.com/ethereum/go-ethereum/rlp"
diff --git a/core/types/hashes.go b/core/types/hashes.go
index 3a787aa136..43e9130fd1 100644
--- a/core/types/hashes.go
+++ b/core/types/hashes.go
@@ -23,7 +23,7 @@ import (
)
var (
- // EmptyRootHash is the known root hash of an empty trie.
+ // EmptyRootHash is the known root hash of an empty merkle trie.
EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// EmptyUncleHash is the known hash of the empty uncle set.
@@ -40,6 +40,9 @@ var (
// EmptyWithdrawalsHash is the known hash of the empty withdrawal set.
EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
+
+ // EmptyVerkleHash is the known hash of an empty verkle trie.
+ EmptyVerkleHash = common.Hash{}
)
// TrieRootHash returns the hash itself if it's non-empty or the predefined
diff --git a/core/types/hashing.go b/core/types/hashing.go
index fbdeaf0d07..224d7a87ea 100644
--- a/core/types/hashing.go
+++ b/core/types/hashing.go
@@ -18,6 +18,8 @@ package types
import (
"bytes"
+ "fmt"
+ "math"
"sync"
"github.com/ethereum/go-ethereum/common"
@@ -36,6 +38,22 @@ var encodeBufferPool = sync.Pool{
New: func() interface{} { return new(bytes.Buffer) },
}
+// getPooledBuffer retrieves a buffer from the pool and creates a byte slice of the
+// requested size from it.
+//
+// The caller should return the *bytes.Buffer object back into encodeBufferPool after use!
+// The returned byte slice must not be used after returning the buffer.
+func getPooledBuffer(size uint64) ([]byte, *bytes.Buffer, error) {
+ if size > math.MaxInt {
+ return nil, nil, fmt.Errorf("can't get buffer of size %d", size)
+ }
+ buf := encodeBufferPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ buf.Grow(int(size))
+ b := buf.Bytes()[:int(size)]
+ return b, buf, nil
+}
+
// rlpHash encodes x and hashes the encoded bytes.
func rlpHash(x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState)
@@ -77,7 +95,7 @@ type DerivableList interface {
func encodeForDerive(list DerivableList, i int, buf *bytes.Buffer) []byte {
buf.Reset()
list.EncodeIndex(i, buf)
- // It's really unfortunate that we need to do perform this copy.
+ // It's really unfortunate that we need to perform this copy.
// StackTrie holds onto the values until Hash is called, so the values
// written to it must not alias.
return common.CopyBytes(buf.Bytes())
diff --git a/core/types/log.go b/core/types/log.go
index e489191368..54c7ff6372 100644
--- a/core/types/log.go
+++ b/core/types/log.go
@@ -17,13 +17,11 @@
package types
import (
- "io"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/rlp"
)
+//go:generate go run ../../rlp/rlpgen -type Log -out gen_log_rlp.go
//go:generate go run github.com/fjl/gencodec -type Log -field-override logMarshaling -out gen_log_json.go
// Log represents a contract log event. These events are generated by the LOG opcode and
@@ -40,19 +38,19 @@ type Log struct {
// Derived fields. These fields are filled in by the node
// but not secured by consensus.
// block in which the transaction was included
- BlockNumber uint64 `json:"blockNumber"`
+ BlockNumber uint64 `json:"blockNumber" rlp:"-"`
// hash of the transaction
- TxHash common.Hash `json:"transactionHash" gencodec:"required"`
+ TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"`
// index of the transaction in the block
- TxIndex uint `json:"transactionIndex"`
+ TxIndex uint `json:"transactionIndex" rlp:"-"`
// hash of the block in which the transaction was included
- BlockHash common.Hash `json:"blockHash"`
+ BlockHash common.Hash `json:"blockHash" rlp:"-"`
// index of the log in the block
- Index uint `json:"logIndex"`
+ Index uint `json:"logIndex" rlp:"-"`
// The Removed field is true if this log was reverted due to a chain reorganisation.
// You must pay attention to this field if you receive logs through a filter query.
- Removed bool `json:"removed"`
+ Removed bool `json:"removed" rlp:"-"`
}
type logMarshaling struct {
@@ -61,28 +59,3 @@ type logMarshaling struct {
TxIndex hexutil.Uint
Index hexutil.Uint
}
-
-//go:generate go run ../../rlp/rlpgen -type rlpLog -out gen_log_rlp.go
-
-// rlpLog is used to RLP-encode both the consensus and storage formats.
-type rlpLog struct {
- Address common.Address
- Topics []common.Hash
- Data []byte
-}
-
-// EncodeRLP implements rlp.Encoder.
-func (l *Log) EncodeRLP(w io.Writer) error {
- rl := rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data}
- return rlp.Encode(w, &rl)
-}
-
-// DecodeRLP implements rlp.Decoder.
-func (l *Log) DecodeRLP(s *rlp.Stream) error {
- var dec rlpLog
- err := s.Decode(&dec)
- if err == nil {
- l.Address, l.Topics, l.Data = dec.Address, dec.Topics, dec.Data
- }
- return err
-}
diff --git a/core/types/receipt.go b/core/types/receipt.go
index e4716f55c7..d1eeda7d87 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -159,7 +159,7 @@ func (r *Receipt) MarshalBinary() ([]byte, error) {
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
// from an RLP stream.
func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
- kind, _, err := s.Kind()
+ kind, size, err := s.Kind()
switch {
case err != nil:
return err
@@ -171,12 +171,18 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
}
r.Type = LegacyTxType
return r.setFromRLP(dec)
+ case kind == rlp.Byte:
+ return errShortTypedReceipt
default:
// It's an EIP-2718 typed tx receipt.
- b, err := s.Bytes()
+ b, buf, err := getPooledBuffer(size)
if err != nil {
return err
}
+ defer encodeBufferPool.Put(buf)
+ if err := s.ReadBytes(b); err != nil {
+ return err
+ }
return r.decodeTyped(b)
}
}
@@ -270,7 +276,7 @@ func (r *ReceiptForStorage) EncodeRLP(_w io.Writer) error {
w.WriteUint64(r.CumulativeGasUsed)
logList := w.List()
for _, log := range r.Logs {
- if err := rlp.Encode(w, log); err != nil {
+ if err := log.EncodeRLP(w); err != nil {
return err
}
}
diff --git a/core/types/rlp_fuzzer_test.go b/core/types/rlp_fuzzer_test.go
new file mode 100644
index 0000000000..a3b9f72436
--- /dev/null
+++ b/core/types/rlp_fuzzer_test.go
@@ -0,0 +1,147 @@
+// Copyright 2019 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package types
+
+import (
+ "bytes"
+ "fmt"
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/holiman/uint256"
+)
+
+func decodeEncode(input []byte, val interface{}) error {
+ if err := rlp.DecodeBytes(input, val); err != nil {
+ // not valid rlp, nothing to do
+ return nil
+ }
+ // If it _were_ valid rlp, we can encode it again
+ output, err := rlp.EncodeToBytes(val)
+ if err != nil {
+ return err
+ }
+ if !bytes.Equal(input, output) {
+ return fmt.Errorf("encode-decode is not equal, \ninput : %x\noutput: %x", input, output)
+ }
+ return nil
+}
+
+func FuzzRLP(f *testing.F) {
+ f.Fuzz(fuzzRlp)
+}
+
+func fuzzRlp(t *testing.T, input []byte) {
+ if len(input) == 0 || len(input) > 500*1024 {
+ return
+ }
+ rlp.Split(input)
+ if elems, _, err := rlp.SplitList(input); err == nil {
+ rlp.CountValues(elems)
+ }
+ rlp.NewStream(bytes.NewReader(input), 0).Decode(new(interface{}))
+ if err := decodeEncode(input, new(interface{})); err != nil {
+ t.Fatal(err)
+ }
+ {
+ var v struct {
+ Int uint
+ String string
+ Bytes []byte
+ }
+ if err := decodeEncode(input, &v); err != nil {
+ t.Fatal(err)
+ }
+ }
+ {
+ type Types struct {
+ Bool bool
+ Raw rlp.RawValue
+ Slice []*Types
+ Iface []interface{}
+ }
+ var v Types
+ if err := decodeEncode(input, &v); err != nil {
+ t.Fatal(err)
+ }
+ }
+ {
+ type AllTypes struct {
+ Int uint
+ String string
+ Bytes []byte
+ Bool bool
+ Raw rlp.RawValue
+ Slice []*AllTypes
+ Array [3]*AllTypes
+ Iface []interface{}
+ }
+ var v AllTypes
+ if err := decodeEncode(input, &v); err != nil {
+ t.Fatal(err)
+ }
+ }
+ {
+ if err := decodeEncode(input, [10]byte{}); err != nil {
+ t.Fatal(err)
+ }
+ }
+ {
+ var v struct {
+ Byte [10]byte
+ Rool [10]bool
+ }
+ if err := decodeEncode(input, &v); err != nil {
+ t.Fatal(err)
+ }
+ }
+ {
+ var h Header
+ if err := decodeEncode(input, &h); err != nil {
+ t.Fatal(err)
+ }
+ var b Block
+ if err := decodeEncode(input, &b); err != nil {
+ t.Fatal(err)
+ }
+ var tx Transaction
+ if err := decodeEncode(input, &tx); err != nil {
+ t.Fatal(err)
+ }
+ var txs Transactions
+ if err := decodeEncode(input, &txs); err != nil {
+ t.Fatal(err)
+ }
+ var rs Receipts
+ if err := decodeEncode(input, &rs); err != nil {
+ t.Fatal(err)
+ }
+ }
+ {
+ var v struct {
+ AnIntPtr *big.Int
+ AnInt big.Int
+ AnU256Ptr *uint256.Int
+ AnU256 uint256.Int
+ NotAnU256 [4]uint64
+ }
+ if err := decodeEncode(input, &v); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/core/types/state_account.go b/core/types/state_account.go
index 314f4943ec..52ef843b35 100644
--- a/core/types/state_account.go
+++ b/core/types/state_account.go
@@ -18,10 +18,10 @@ package types
import (
"bytes"
- "math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/holiman/uint256"
)
//go:generate go run ../../rlp/rlpgen -type StateAccount -out gen_account_rlp.go
@@ -30,7 +30,7 @@ import (
// These objects are stored in the main account trie.
type StateAccount struct {
Nonce uint64
- Balance *big.Int
+ Balance *uint256.Int
Root common.Hash // merkle root of the storage trie
CodeHash []byte
}
@@ -38,7 +38,7 @@ type StateAccount struct {
// NewEmptyStateAccount constructs an empty state account.
func NewEmptyStateAccount() *StateAccount {
return &StateAccount{
- Balance: new(big.Int),
+ Balance: new(uint256.Int),
Root: EmptyRootHash,
CodeHash: EmptyCodeHash.Bytes(),
}
@@ -46,9 +46,9 @@ func NewEmptyStateAccount() *StateAccount {
// Copy returns a deep-copied state account object.
func (acct *StateAccount) Copy() *StateAccount {
- var balance *big.Int
+ var balance *uint256.Int
if acct.Balance != nil {
- balance = new(big.Int).Set(acct.Balance)
+ balance = new(uint256.Int).Set(acct.Balance)
}
return &StateAccount{
Nonce: acct.Nonce,
@@ -63,7 +63,7 @@ func (acct *StateAccount) Copy() *StateAccount {
// or slim format which replaces the empty root and code hash as nil byte slice.
type SlimAccount struct {
Nonce uint64
- Balance *big.Int
+ Balance *uint256.Int
Root []byte // Nil if root equals to types.EmptyRootHash
CodeHash []byte // Nil if hash equals to types.EmptyCodeHash
}
@@ -87,7 +87,7 @@ func SlimAccountRLP(account StateAccount) []byte {
return data
}
-// FullAccount decodes the data on the 'slim RLP' format and return
+// FullAccount decodes the data on the 'slim RLP' format and returns
// the consensus format account.
func FullAccount(data []byte) (*StateAccount, error) {
var slim SlimAccount
diff --git a/core/types/transaction.go b/core/types/transaction.go
index c723962604..9a844158c0 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -37,6 +37,9 @@ var (
ErrTxTypeNotSupported = errors.New("transaction type not supported")
ErrGasFeeCapTooLow = errors.New("fee cap less than base fee")
errShortTypedTx = errors.New("typed transaction too short")
+ errInvalidYParity = errors.New("'yParity' field must be 0 or 1")
+ errVYParityMismatch = errors.New("'v' and 'yParity' fields do not match")
+ errVYParityMissing = errors.New("missing 'yParity' or 'v' field in transaction")
)
// Transaction types.
@@ -82,9 +85,6 @@ type TxData interface {
value() *big.Int
nonce() uint64
to() *common.Address
- blobGas() uint64
- blobGasFeeCap() *big.Int
- blobHashes() []common.Hash
rawSignatureValues() (v, r, s *big.Int)
setSignatureValues(chainID, v, r, s *big.Int)
@@ -96,6 +96,9 @@ type TxData interface {
// copy of the computed value, i.e. callers are allowed to mutate the result.
// Method implementations can use 'dst' to store the result.
effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int
+
+ encode(*bytes.Buffer) error
+ decode([]byte) error
}
// EncodeRLP implements rlp.Encoder
@@ -116,7 +119,7 @@ func (tx *Transaction) EncodeRLP(w io.Writer) error {
// encodeTyped writes the canonical encoding of a typed transaction to w.
func (tx *Transaction) encodeTyped(w *bytes.Buffer) error {
w.WriteByte(tx.Type())
- return rlp.Encode(w, tx.inner)
+ return tx.inner.encode(w)
}
// MarshalBinary returns the canonical encoding of the transaction.
@@ -145,22 +148,30 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
tx.setDecoded(&inner, rlp.ListSize(size))
}
return err
+ case kind == rlp.Byte:
+ return errShortTypedTx
default:
// It's an EIP-2718 typed TX envelope.
- var b []byte
- if b, err = s.Bytes(); err != nil {
+ // First read the tx payload bytes into a temporary buffer.
+ b, buf, err := getPooledBuffer(size)
+ if err != nil {
return err
}
+ defer encodeBufferPool.Put(buf)
+ if err := s.ReadBytes(b); err != nil {
+ return err
+ }
+ // Now decode the inner transaction.
inner, err := tx.decodeTyped(b)
if err == nil {
- tx.setDecoded(inner, uint64(len(b)))
+ tx.setDecoded(inner, size)
}
return err
}
}
// UnmarshalBinary decodes the canonical encoding of transactions.
-// It supports legacy RLP transactions and EIP2718 typed transactions.
+// It supports legacy RLP transactions and EIP-2718 typed transactions.
func (tx *Transaction) UnmarshalBinary(b []byte) error {
if len(b) > 0 && b[0] > 0x7f {
// It's a legacy transaction.
@@ -172,7 +183,7 @@ func (tx *Transaction) UnmarshalBinary(b []byte) error {
tx.setDecoded(&data, uint64(len(b)))
return nil
}
- // It's an EIP2718 typed transaction envelope.
+ // It's an EIP-2718 typed transaction envelope.
inner, err := tx.decodeTyped(b)
if err != nil {
return err
@@ -186,22 +197,19 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
if len(b) <= 1 {
return nil, errShortTypedTx
}
+ var inner TxData
switch b[0] {
case AccessListTxType:
- var inner AccessListTx
- err := rlp.DecodeBytes(b[1:], &inner)
- return &inner, err
+ inner = new(AccessListTx)
case DynamicFeeTxType:
- var inner DynamicFeeTx
- err := rlp.DecodeBytes(b[1:], &inner)
- return &inner, err
+ inner = new(DynamicFeeTx)
case BlobTxType:
- var inner BlobTx
- err := rlp.DecodeBytes(b[1:], &inner)
- return &inner, err
+ inner = new(BlobTx)
default:
return nil, ErrTxTypeNotSupported
}
+ err := inner.decode(b[1:])
+ return inner, err
}
// setDecoded sets the inner transaction and size after decoding.
@@ -288,15 +296,6 @@ func (tx *Transaction) GasTipCap() *big.Int { return new(big.Int).Set(tx.inner.g
// GasFeeCap returns the fee cap per gas of the transaction.
func (tx *Transaction) GasFeeCap() *big.Int { return new(big.Int).Set(tx.inner.gasFeeCap()) }
-// BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise.
-func (tx *Transaction) BlobGas() uint64 { return tx.inner.blobGas() }
-
-// BlobGasFeeCap returns the blob gas fee cap per blob gas of the transaction for blob transactions, nil otherwise.
-func (tx *Transaction) BlobGasFeeCap() *big.Int { return tx.inner.blobGasFeeCap() }
-
-// BlobHashes returns the hases of the blob commitments for blob transactions, nil otherwise.
-func (tx *Transaction) BlobHashes() []common.Hash { return tx.inner.blobHashes() }
-
// Value returns the ether amount of the transaction.
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.inner.value()) }
@@ -393,14 +392,66 @@ func (tx *Transaction) EffectiveGasTipIntCmp(other *big.Int, baseFee *big.Int) i
return tx.EffectiveGasTipValue(baseFee).Cmp(other)
}
+// BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise.
+func (tx *Transaction) BlobGas() uint64 {
+ if blobtx, ok := tx.inner.(*BlobTx); ok {
+ return blobtx.blobGas()
+ }
+ return 0
+}
+
+// BlobGasFeeCap returns the blob gas fee cap per blob gas of the transaction for blob transactions, nil otherwise.
+func (tx *Transaction) BlobGasFeeCap() *big.Int {
+ if blobtx, ok := tx.inner.(*BlobTx); ok {
+ return blobtx.BlobFeeCap.ToBig()
+ }
+ return nil
+}
+
+// BlobHashes returns the hashes of the blob commitments for blob transactions, nil otherwise.
+func (tx *Transaction) BlobHashes() []common.Hash {
+ if blobtx, ok := tx.inner.(*BlobTx); ok {
+ return blobtx.BlobHashes
+ }
+ return nil
+}
+
+// BlobTxSidecar returns the sidecar of a blob transaction, nil otherwise.
+func (tx *Transaction) BlobTxSidecar() *BlobTxSidecar {
+ if blobtx, ok := tx.inner.(*BlobTx); ok {
+ return blobtx.Sidecar
+ }
+ return nil
+}
+
// BlobGasFeeCapCmp compares the blob fee cap of two transactions.
func (tx *Transaction) BlobGasFeeCapCmp(other *Transaction) int {
- return tx.inner.blobGasFeeCap().Cmp(other.inner.blobGasFeeCap())
+ return tx.BlobGasFeeCap().Cmp(other.BlobGasFeeCap())
}
// BlobGasFeeCapIntCmp compares the blob fee cap of the transaction against the given blob fee cap.
func (tx *Transaction) BlobGasFeeCapIntCmp(other *big.Int) int {
- return tx.inner.blobGasFeeCap().Cmp(other)
+ return tx.BlobGasFeeCap().Cmp(other)
+}
+
+// WithoutBlobTxSidecar returns a copy of tx with the blob sidecar removed.
+func (tx *Transaction) WithoutBlobTxSidecar() *Transaction {
+ blobtx, ok := tx.inner.(*BlobTx)
+ if !ok {
+ return tx
+ }
+ cpy := &Transaction{
+ inner: blobtx.withoutSidecar(),
+ time: tx.time,
+ }
+ // Note: tx.size cache not carried over because the sidecar is included in size!
+ if h := tx.hash.Load(); h != nil {
+ cpy.hash.Store(h)
+ }
+ if f := tx.from.Load(); f != nil {
+ cpy.from.Store(f)
+ }
+ return cpy
}
// SetTime sets the decoding time of a transaction. This is used by tests to set
@@ -438,13 +489,24 @@ func (tx *Transaction) Size() uint64 {
if size := tx.size.Load(); size != nil {
return size.(uint64)
}
+
+ // Cache miss, encode and cache.
+ // Note we rely on the assumption that all tx.inner values are RLP-encoded!
c := writeCounter(0)
rlp.Encode(&c, &tx.inner)
-
size := uint64(c)
+
+ // For blob transactions, add the size of the blob content and the outer list of the
+ // tx + sidecar encoding.
+ if sc := tx.BlobTxSidecar(); sc != nil {
+ size += rlp.ListSize(sc.encodedSize())
+ }
+
+ // For typed transactions, the encoding also includes the leading type byte.
if tx.Type() != LegacyTxType {
- size += 1 // type byte
+ size += 1
}
+
tx.size.Store(size)
return size
}
diff --git a/core/types/transaction_marshalling.go b/core/types/transaction_marshalling.go
index 1378cb4014..08ce80b07c 100644
--- a/core/types/transaction_marshalling.go
+++ b/core/types/transaction_marshalling.go
@@ -57,18 +57,18 @@ func (tx *txJSON) yParityValue() (*big.Int, error) {
if tx.YParity != nil {
val := uint64(*tx.YParity)
if val != 0 && val != 1 {
- return nil, errors.New("'yParity' field must be 0 or 1")
+ return nil, errInvalidYParity
}
bigval := new(big.Int).SetUint64(val)
if tx.V != nil && tx.V.ToInt().Cmp(bigval) != 0 {
- return nil, errors.New("'v' and 'yParity' fields do not match")
+ return nil, errVYParityMismatch
}
return bigval, nil
}
if tx.V != nil {
return tx.V.ToInt(), nil
}
- return nil, errors.New("missing 'yParity' or 'v' field in transaction")
+ return nil, errVYParityMissing
}
// MarshalJSON marshals as JSON with a hash.
@@ -294,9 +294,6 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'input' in transaction")
}
itx.Data = *dec.Input
- if dec.V == nil {
- return errors.New("missing required field 'v' in transaction")
- }
if dec.AccessList != nil {
itx.AccessList = *dec.AccessList
}
@@ -361,9 +358,6 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'input' in transaction")
}
itx.Data = *dec.Input
- if dec.V == nil {
- return errors.New("missing required field 'v' in transaction")
- }
if dec.AccessList != nil {
itx.AccessList = *dec.AccessList
}
@@ -373,20 +367,20 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
itx.BlobHashes = dec.BlobVersionedHashes
// signature R
- var ok bool
+ var overflow bool
if dec.R == nil {
return errors.New("missing required field 'r' in transaction")
}
- itx.R, ok = uint256.FromBig((*big.Int)(dec.R))
- if !ok {
+ itx.R, overflow = uint256.FromBig((*big.Int)(dec.R))
+ if overflow {
return errors.New("'r' value overflows uint256")
}
// signature S
if dec.S == nil {
return errors.New("missing required field 's' in transaction")
}
- itx.S, ok = uint256.FromBig((*big.Int)(dec.S))
- if !ok {
+ itx.S, overflow = uint256.FromBig((*big.Int)(dec.S))
+ if overflow {
return errors.New("'s' value overflows uint256")
}
// signature V
@@ -394,8 +388,8 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
if err != nil {
return err
}
- itx.V, ok = uint256.FromBig(vbig)
- if !ok {
+ itx.V, overflow = uint256.FromBig(vbig)
+ if overflow {
return errors.New("'v' value overflows uint256")
}
if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 {
diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go
index 8633440824..9e26642f75 100644
--- a/core/types/transaction_signing.go
+++ b/core/types/transaction_signing.go
@@ -57,7 +57,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int, blockTime uint
}
// LatestSigner returns the 'most permissive' Signer available for the given chain
-// configuration. Specifically, this enables support of all types of transacrions
+// configuration. Specifically, this enables support of all types of transactions
// when their respective forks are scheduled to occur at any block number (or time)
// in the chain config.
//
@@ -331,11 +331,7 @@ func (s eip2930Signer) Sender(tx *Transaction) (common.Address, error) {
V, R, S := tx.RawSignatureValues()
switch tx.Type() {
case LegacyTxType:
- if !tx.Protected() {
- return HomesteadSigner{}.Sender(tx)
- }
- V = new(big.Int).Sub(V, s.chainIdMul)
- V.Sub(V, big8)
+ return s.EIP155Signer.Sender(tx)
case AccessListTxType:
// AL txs are defined to use 0 and 1 as their recovery
// id, add 27 to become equivalent to unprotected Homestead signatures.
@@ -372,15 +368,7 @@ func (s eip2930Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *bi
func (s eip2930Signer) Hash(tx *Transaction) common.Hash {
switch tx.Type() {
case LegacyTxType:
- return rlpHash([]interface{}{
- tx.Nonce(),
- tx.GasPrice(),
- tx.Gas(),
- tx.To(),
- tx.Value(),
- tx.Data(),
- s.chainId, uint(0), uint(0),
- })
+ return s.EIP155Signer.Hash(tx)
case AccessListTxType:
return prefixedRlpHash(
tx.Type(),
diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go
index a984a9c709..76a010d2e5 100644
--- a/core/types/transaction_test.go
+++ b/core/types/transaction_test.go
@@ -214,7 +214,7 @@ func TestEIP2718TransactionEncode(t *testing.T) {
func decodeTx(data []byte) (*Transaction, error) {
var tx Transaction
- t, err := &tx, rlp.Decode(bytes.NewReader(data), &tx)
+ t, err := &tx, rlp.DecodeBytes(data, &tx)
return t, err
}
@@ -451,3 +451,97 @@ func TestTransactionSizes(t *testing.T) {
}
}
}
+
+func TestYParityJSONUnmarshalling(t *testing.T) {
+ baseJson := map[string]interface{}{
+ // type is filled in by the test
+ "chainId": "0x7",
+ "nonce": "0x0",
+ "to": "0x1b442286e32ddcaa6e2570ce9ed85f4b4fc87425",
+ "gas": "0x124f8",
+ "gasPrice": "0x693d4ca8",
+ "maxPriorityFeePerGas": "0x3b9aca00",
+ "maxFeePerGas": "0x6fc23ac00",
+ "maxFeePerBlobGas": "0x3b9aca00",
+ "value": "0x0",
+ "input": "0x",
+ "accessList": []interface{}{},
+ "blobVersionedHashes": []string{
+ "0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014",
+ },
+
+ // v and yParity are filled in by the test
+ "r": "0x2a922afc784d07e98012da29f2f37cae1f73eda78aa8805d3df6ee5dbb41ec1",
+ "s": "0x4f1f75ae6bcdf4970b4f305da1a15d8c5ddb21f555444beab77c9af2baab14",
+ }
+
+ tests := []struct {
+ name string
+ v string
+ yParity string
+ wantErr error
+ }{
+ // Valid v and yParity
+ {"valid v and yParity, 0x0", "0x0", "0x0", nil},
+ {"valid v and yParity, 0x1", "0x1", "0x1", nil},
+
+ // Valid v, missing yParity
+ {"valid v, missing yParity, 0x0", "0x0", "", nil},
+ {"valid v, missing yParity, 0x1", "0x1", "", nil},
+
+ // Valid yParity, missing v
+ {"valid yParity, missing v, 0x0", "", "0x0", nil},
+ {"valid yParity, missing v, 0x1", "", "0x1", nil},
+
+ // Invalid yParity
+ {"invalid yParity, 0x2", "", "0x2", errInvalidYParity},
+
+ // Conflicting v and yParity
+ {"conflicting v and yParity", "0x1", "0x0", errVYParityMismatch},
+
+ // Missing v and yParity
+ {"missing v and yParity", "", "", errVYParityMissing},
+ }
+
+ // Run for all types that accept yParity
+ t.Parallel()
+ for _, txType := range []uint64{
+ AccessListTxType,
+ DynamicFeeTxType,
+ BlobTxType,
+ } {
+ txType := txType
+ for _, test := range tests {
+ test := test
+ t.Run(fmt.Sprintf("txType=%d: %s", txType, test.name), func(t *testing.T) {
+ // Copy the base json
+ testJson := make(map[string]interface{})
+ for k, v := range baseJson {
+ testJson[k] = v
+ }
+
+ // Set v, yParity and type
+ if test.v != "" {
+ testJson["v"] = test.v
+ }
+ if test.yParity != "" {
+ testJson["yParity"] = test.yParity
+ }
+ testJson["type"] = fmt.Sprintf("0x%x", txType)
+
+ // Marshal the JSON
+ jsonBytes, err := json.Marshal(testJson)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Unmarshal the tx
+ var tx Transaction
+ err = tx.UnmarshalJSON(jsonBytes)
+ if err != test.wantErr {
+ t.Fatalf("wrong error: got %v, want %v", err, test.wantErr)
+ }
+ })
+ }
+ }
+}
diff --git a/core/types/tx_access_list.go b/core/types/tx_access_list.go
index 7ce9da73ec..730a77b752 100644
--- a/core/types/tx_access_list.go
+++ b/core/types/tx_access_list.go
@@ -17,9 +17,11 @@
package types
import (
+ "bytes"
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
)
//go:generate go run github.com/fjl/gencodec -type AccessTuple -out gen_access_tuple.go
@@ -94,20 +96,17 @@ func (tx *AccessListTx) copy() TxData {
}
// accessors for innerTx.
-func (tx *AccessListTx) txType() byte { return AccessListTxType }
-func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID }
-func (tx *AccessListTx) accessList() AccessList { return tx.AccessList }
-func (tx *AccessListTx) data() []byte { return tx.Data }
-func (tx *AccessListTx) gas() uint64 { return tx.Gas }
-func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice }
-func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice }
-func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice }
-func (tx *AccessListTx) value() *big.Int { return tx.Value }
-func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
-func (tx *AccessListTx) to() *common.Address { return tx.To }
-func (tx *AccessListTx) blobGas() uint64 { return 0 }
-func (tx *AccessListTx) blobGasFeeCap() *big.Int { return nil }
-func (tx *AccessListTx) blobHashes() []common.Hash { return nil }
+func (tx *AccessListTx) txType() byte { return AccessListTxType }
+func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID }
+func (tx *AccessListTx) accessList() AccessList { return tx.AccessList }
+func (tx *AccessListTx) data() []byte { return tx.Data }
+func (tx *AccessListTx) gas() uint64 { return tx.Gas }
+func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice }
+func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice }
+func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice }
+func (tx *AccessListTx) value() *big.Int { return tx.Value }
+func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
+func (tx *AccessListTx) to() *common.Address { return tx.To }
func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
return dst.Set(tx.GasPrice)
@@ -120,3 +119,11 @@ func (tx *AccessListTx) rawSignatureValues() (v, r, s *big.Int) {
func (tx *AccessListTx) setSignatureValues(chainID, v, r, s *big.Int) {
tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s
}
+
+func (tx *AccessListTx) encode(b *bytes.Buffer) error {
+ return rlp.Encode(b, tx)
+}
+
+func (tx *AccessListTx) decode(input []byte) error {
+ return rlp.DecodeBytes(input, tx)
+}
diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go
index a08121bf14..caede7cc53 100644
--- a/core/types/tx_blob.go
+++ b/core/types/tx_blob.go
@@ -17,10 +17,14 @@
package types
import (
+ "bytes"
+ "crypto/sha256"
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/holiman/uint256"
)
@@ -38,12 +42,57 @@ type BlobTx struct {
BlobFeeCap *uint256.Int // a.k.a. maxFeePerBlobGas
BlobHashes []common.Hash
+ // A blob transaction can optionally contain blobs. This field must be set when BlobTx
+ // is used to create a transaction for sigining.
+ Sidecar *BlobTxSidecar `rlp:"-"`
+
// Signature values
V *uint256.Int `json:"v" gencodec:"required"`
R *uint256.Int `json:"r" gencodec:"required"`
S *uint256.Int `json:"s" gencodec:"required"`
}
+// BlobTxSidecar contains the blobs of a blob transaction.
+type BlobTxSidecar struct {
+ Blobs []kzg4844.Blob // Blobs needed by the blob pool
+ Commitments []kzg4844.Commitment // Commitments needed by the blob pool
+ Proofs []kzg4844.Proof // Proofs needed by the blob pool
+}
+
+// BlobHashes computes the blob hashes of the given blobs.
+func (sc *BlobTxSidecar) BlobHashes() []common.Hash {
+ hasher := sha256.New()
+ h := make([]common.Hash, len(sc.Commitments))
+ for i := range sc.Blobs {
+ h[i] = kzg4844.CalcBlobHashV1(hasher, &sc.Commitments[i])
+ }
+ return h
+}
+
+// encodedSize computes the RLP size of the sidecar elements. This does NOT return the
+// encoded size of the BlobTxSidecar, it's just a helper for tx.Size().
+func (sc *BlobTxSidecar) encodedSize() uint64 {
+ var blobs, commitments, proofs uint64
+ for i := range sc.Blobs {
+ blobs += rlp.BytesSize(sc.Blobs[i][:])
+ }
+ for i := range sc.Commitments {
+ commitments += rlp.BytesSize(sc.Commitments[i][:])
+ }
+ for i := range sc.Proofs {
+ proofs += rlp.BytesSize(sc.Proofs[i][:])
+ }
+ return rlp.ListSize(blobs) + rlp.ListSize(commitments) + rlp.ListSize(proofs)
+}
+
+// blobTxWithBlobs is used for encoding of transactions when blobs are present.
+type blobTxWithBlobs struct {
+ BlobTx *BlobTx
+ Blobs []kzg4844.Blob
+ Commitments []kzg4844.Commitment
+ Proofs []kzg4844.Proof
+}
+
// copy creates a deep copy of the transaction data and initializes all fields.
func (tx *BlobTx) copy() TxData {
cpy := &BlobTx{
@@ -90,24 +139,29 @@ func (tx *BlobTx) copy() TxData {
if tx.S != nil {
cpy.S.Set(tx.S)
}
+ if tx.Sidecar != nil {
+ cpy.Sidecar = &BlobTxSidecar{
+ Blobs: append([]kzg4844.Blob(nil), tx.Sidecar.Blobs...),
+ Commitments: append([]kzg4844.Commitment(nil), tx.Sidecar.Commitments...),
+ Proofs: append([]kzg4844.Proof(nil), tx.Sidecar.Proofs...),
+ }
+ }
return cpy
}
// accessors for innerTx.
-func (tx *BlobTx) txType() byte { return BlobTxType }
-func (tx *BlobTx) chainID() *big.Int { return tx.ChainID.ToBig() }
-func (tx *BlobTx) accessList() AccessList { return tx.AccessList }
-func (tx *BlobTx) data() []byte { return tx.Data }
-func (tx *BlobTx) gas() uint64 { return tx.Gas }
-func (tx *BlobTx) gasFeeCap() *big.Int { return tx.GasFeeCap.ToBig() }
-func (tx *BlobTx) gasTipCap() *big.Int { return tx.GasTipCap.ToBig() }
-func (tx *BlobTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() }
-func (tx *BlobTx) value() *big.Int { return tx.Value.ToBig() }
-func (tx *BlobTx) nonce() uint64 { return tx.Nonce }
-func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp }
-func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) }
-func (tx *BlobTx) blobGasFeeCap() *big.Int { return tx.BlobFeeCap.ToBig() }
-func (tx *BlobTx) blobHashes() []common.Hash { return tx.BlobHashes }
+func (tx *BlobTx) txType() byte { return BlobTxType }
+func (tx *BlobTx) chainID() *big.Int { return tx.ChainID.ToBig() }
+func (tx *BlobTx) accessList() AccessList { return tx.AccessList }
+func (tx *BlobTx) data() []byte { return tx.Data }
+func (tx *BlobTx) gas() uint64 { return tx.Gas }
+func (tx *BlobTx) gasFeeCap() *big.Int { return tx.GasFeeCap.ToBig() }
+func (tx *BlobTx) gasTipCap() *big.Int { return tx.GasTipCap.ToBig() }
+func (tx *BlobTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() }
+func (tx *BlobTx) value() *big.Int { return tx.Value.ToBig() }
+func (tx *BlobTx) nonce() uint64 { return tx.Nonce }
+func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp }
+func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) }
func (tx *BlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
if baseFee == nil {
@@ -130,3 +184,55 @@ func (tx *BlobTx) setSignatureValues(chainID, v, r, s *big.Int) {
tx.R.SetFromBig(r)
tx.S.SetFromBig(s)
}
+
+func (tx *BlobTx) withoutSidecar() *BlobTx {
+ cpy := *tx
+ cpy.Sidecar = nil
+ return &cpy
+}
+
+func (tx *BlobTx) encode(b *bytes.Buffer) error {
+ if tx.Sidecar == nil {
+ return rlp.Encode(b, tx)
+ }
+ inner := &blobTxWithBlobs{
+ BlobTx: tx,
+ Blobs: tx.Sidecar.Blobs,
+ Commitments: tx.Sidecar.Commitments,
+ Proofs: tx.Sidecar.Proofs,
+ }
+ return rlp.Encode(b, inner)
+}
+
+func (tx *BlobTx) decode(input []byte) error {
+ // Here we need to support two formats: the network protocol encoding of the tx (with
+ // blobs) or the canonical encoding without blobs.
+ //
+ // The two encodings can be distinguished by checking whether the first element of the
+ // input list is itself a list.
+
+ outerList, _, err := rlp.SplitList(input)
+ if err != nil {
+ return err
+ }
+ firstElemKind, _, _, err := rlp.Split(outerList)
+ if err != nil {
+ return err
+ }
+
+ if firstElemKind != rlp.List {
+ return rlp.DecodeBytes(input, tx)
+ }
+ // It's a tx with blobs.
+ var inner blobTxWithBlobs
+ if err := rlp.DecodeBytes(input, &inner); err != nil {
+ return err
+ }
+ *tx = *inner.BlobTx
+ tx.Sidecar = &BlobTxSidecar{
+ Blobs: inner.Blobs,
+ Commitments: inner.Commitments,
+ Proofs: inner.Proofs,
+ }
+ return nil
+}
diff --git a/core/types/tx_blob_test.go b/core/types/tx_blob_test.go
new file mode 100644
index 0000000000..44ac48cc6f
--- /dev/null
+++ b/core/types/tx_blob_test.go
@@ -0,0 +1,90 @@
+package types
+
+import (
+ "crypto/ecdsa"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
+ "github.com/holiman/uint256"
+)
+
+// This test verifies that tx.Hash() is not affected by presence of a BlobTxSidecar.
+func TestBlobTxHashing(t *testing.T) {
+ key, _ := crypto.GenerateKey()
+ withBlobs := createEmptyBlobTx(key, true)
+ withBlobsStripped := withBlobs.WithoutBlobTxSidecar()
+ withoutBlobs := createEmptyBlobTx(key, false)
+
+ hash := withBlobs.Hash()
+ t.Log("tx hash:", hash)
+
+ if h := withBlobsStripped.Hash(); h != hash {
+ t.Fatal("wrong tx hash after WithoutBlobTxSidecar:", h)
+ }
+ if h := withoutBlobs.Hash(); h != hash {
+ t.Fatal("wrong tx hash on tx created without sidecar:", h)
+ }
+}
+
+// This test verifies that tx.Size() takes BlobTxSidecar into account.
+func TestBlobTxSize(t *testing.T) {
+ key, _ := crypto.GenerateKey()
+ withBlobs := createEmptyBlobTx(key, true)
+ withBlobsStripped := withBlobs.WithoutBlobTxSidecar()
+ withoutBlobs := createEmptyBlobTx(key, false)
+
+ withBlobsEnc, _ := withBlobs.MarshalBinary()
+ withoutBlobsEnc, _ := withoutBlobs.MarshalBinary()
+
+ size := withBlobs.Size()
+ t.Log("size with blobs:", size)
+
+ sizeNoBlobs := withoutBlobs.Size()
+ t.Log("size without blobs:", sizeNoBlobs)
+
+ if size != uint64(len(withBlobsEnc)) {
+ t.Error("wrong size with blobs:", size, "encoded length:", len(withBlobsEnc))
+ }
+ if sizeNoBlobs != uint64(len(withoutBlobsEnc)) {
+ t.Error("wrong size without blobs:", sizeNoBlobs, "encoded length:", len(withoutBlobsEnc))
+ }
+ if sizeNoBlobs >= size {
+ t.Error("size without blobs >= size with blobs")
+ }
+ if sz := withBlobsStripped.Size(); sz != sizeNoBlobs {
+ t.Fatal("wrong size on tx after WithoutBlobTxSidecar:", sz)
+ }
+}
+
+var (
+ emptyBlob = kzg4844.Blob{}
+ emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
+ emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
+)
+
+func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
+ sidecar := &BlobTxSidecar{
+ Blobs: []kzg4844.Blob{emptyBlob},
+ Commitments: []kzg4844.Commitment{emptyBlobCommit},
+ Proofs: []kzg4844.Proof{emptyBlobProof},
+ }
+ blobtx := &BlobTx{
+ ChainID: uint256.NewInt(1),
+ Nonce: 5,
+ GasTipCap: uint256.NewInt(22),
+ GasFeeCap: uint256.NewInt(5),
+ Gas: 25000,
+ To: common.Address{0x03, 0x04, 0x05},
+ Value: uint256.NewInt(99),
+ Data: make([]byte, 50),
+ BlobFeeCap: uint256.NewInt(15),
+ BlobHashes: sidecar.BlobHashes(),
+ }
+ if withSidecar {
+ blobtx.Sidecar = sidecar
+ }
+ signer := NewCancunSigner(blobtx.ChainID.ToBig())
+ return MustSignNewTx(key, signer, blobtx)
+}
diff --git a/core/types/tx_dynamic_fee.go b/core/types/tx_dynamic_fee.go
index 47b870abbf..8b5b514fde 100644
--- a/core/types/tx_dynamic_fee.go
+++ b/core/types/tx_dynamic_fee.go
@@ -17,9 +17,11 @@
package types
import (
+ "bytes"
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
)
// DynamicFeeTx represents an EIP-1559 transaction.
@@ -83,20 +85,17 @@ func (tx *DynamicFeeTx) copy() TxData {
}
// accessors for innerTx.
-func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType }
-func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID }
-func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList }
-func (tx *DynamicFeeTx) data() []byte { return tx.Data }
-func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas }
-func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap }
-func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap }
-func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap }
-func (tx *DynamicFeeTx) value() *big.Int { return tx.Value }
-func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce }
-func (tx *DynamicFeeTx) to() *common.Address { return tx.To }
-func (tx *DynamicFeeTx) blobGas() uint64 { return 0 }
-func (tx *DynamicFeeTx) blobGasFeeCap() *big.Int { return nil }
-func (tx *DynamicFeeTx) blobHashes() []common.Hash { return nil }
+func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType }
+func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID }
+func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList }
+func (tx *DynamicFeeTx) data() []byte { return tx.Data }
+func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas }
+func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap }
+func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap }
+func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap }
+func (tx *DynamicFeeTx) value() *big.Int { return tx.Value }
+func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce }
+func (tx *DynamicFeeTx) to() *common.Address { return tx.To }
func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
if baseFee == nil {
@@ -116,3 +115,11 @@ func (tx *DynamicFeeTx) rawSignatureValues() (v, r, s *big.Int) {
func (tx *DynamicFeeTx) setSignatureValues(chainID, v, r, s *big.Int) {
tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s
}
+
+func (tx *DynamicFeeTx) encode(b *bytes.Buffer) error {
+ return rlp.Encode(b, tx)
+}
+
+func (tx *DynamicFeeTx) decode(input []byte) error {
+ return rlp.DecodeBytes(input, tx)
+}
diff --git a/core/types/tx_legacy.go b/core/types/tx_legacy.go
index 902e70cf94..71025b78fc 100644
--- a/core/types/tx_legacy.go
+++ b/core/types/tx_legacy.go
@@ -17,6 +17,7 @@
package types
import (
+ "bytes"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -91,20 +92,17 @@ func (tx *LegacyTx) copy() TxData {
}
// accessors for innerTx.
-func (tx *LegacyTx) txType() byte { return LegacyTxType }
-func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) }
-func (tx *LegacyTx) accessList() AccessList { return nil }
-func (tx *LegacyTx) data() []byte { return tx.Data }
-func (tx *LegacyTx) gas() uint64 { return tx.Gas }
-func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice }
-func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice }
-func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice }
-func (tx *LegacyTx) value() *big.Int { return tx.Value }
-func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
-func (tx *LegacyTx) to() *common.Address { return tx.To }
-func (tx *LegacyTx) blobGas() uint64 { return 0 }
-func (tx *LegacyTx) blobGasFeeCap() *big.Int { return nil }
-func (tx *LegacyTx) blobHashes() []common.Hash { return nil }
+func (tx *LegacyTx) txType() byte { return LegacyTxType }
+func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) }
+func (tx *LegacyTx) accessList() AccessList { return nil }
+func (tx *LegacyTx) data() []byte { return tx.Data }
+func (tx *LegacyTx) gas() uint64 { return tx.Gas }
+func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice }
+func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice }
+func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice }
+func (tx *LegacyTx) value() *big.Int { return tx.Value }
+func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
+func (tx *LegacyTx) to() *common.Address { return tx.To }
func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
return dst.Set(tx.GasPrice)
@@ -117,3 +115,11 @@ func (tx *LegacyTx) rawSignatureValues() (v, r, s *big.Int) {
func (tx *LegacyTx) setSignatureValues(chainID, v, r, s *big.Int) {
tx.V, tx.R, tx.S = v, r, s
}
+
+func (tx *LegacyTx) encode(*bytes.Buffer) error {
+ panic("encode called on LegacyTx")
+}
+
+func (tx *LegacyTx) decode([]byte) error {
+ panic("decode called on LegacyTx)")
+}
diff --git a/core/vm/contract.go b/core/vm/contract.go
index 7575c85f19..eab3a17447 100644
--- a/core/vm/contract.go
+++ b/core/vm/contract.go
@@ -17,12 +17,9 @@
package vm
import (
- "math/big"
-
- lru "github.com/hashicorp/golang-lru"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/metrics"
+ lru "github.com/hashicorp/golang-lru"
"github.com/holiman/uint256"
)
@@ -43,13 +40,13 @@ type ContractRef interface {
// AccountRef implements ContractRef.
//
// Account references are used during EVM initialisation and
-// it's primary use is to fetch addresses. Removing this object
+// its primary use is to fetch addresses. Removing this object
// proves difficult because of the cached jump destinations which
// are fetched from the parent contract (i.e. the caller), which
// is a ContractRef.
type AccountRef common.Address
-// Address casts AccountRef to a Address
+// Address casts AccountRef to an Address
func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }
// Contract represents an ethereum contract in the state database. It contains
@@ -71,11 +68,11 @@ type Contract struct {
Input []byte
Gas uint64
- value *big.Int
+ value *uint256.Int
}
// NewContract returns a new contract environment for the execution of EVM.
-func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract {
+func NewContract(caller ContractRef, object ContractRef, value *uint256.Int, gas uint64) *Contract {
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object}
if parent, ok := caller.(*Contract); ok {
@@ -192,7 +189,7 @@ func (c *Contract) Address() common.Address {
}
// Value returns the contract's value (sent to it from it's caller)
-func (c *Contract) Value() *big.Int {
+func (c *Contract) Value() *uint256.Int {
return c.value
}
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index 482c020a67..f9eea9f5cc 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -17,23 +17,28 @@
package vm
import (
+ "bytes"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"math/big"
+ "github.com/prysmaticlabs/prysm/v4/crypto/bls"
+ "golang.org/x/crypto/ripemd160"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/blake2b"
"github.com/ethereum/go-ethereum/crypto/bls12381"
"github.com/ethereum/go-ethereum/crypto/bn256"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
+ "github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
- "github.com/prysmaticlabs/prysm/v4/crypto/bls"
- "golang.org/x/crypto/ripemd160"
+ "github.com/ethereum/go-ethereum/rlp"
)
// PrecompiledContract is the basic interface for native Go contracts. The implementation
@@ -217,6 +222,29 @@ var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{},
+ common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
+ common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
+}
+
+// PrecompiledContractsFeynman contains the default set of pre-compiled Ethereum
+// contracts used in the Feynman release.
+var PrecompiledContractsFeynman = map[common.Address]PrecompiledContract{
+ common.BytesToAddress([]byte{1}): &ecrecover{},
+ common.BytesToAddress([]byte{2}): &sha256hash{},
+ common.BytesToAddress([]byte{3}): &ripemd160hash{},
+ common.BytesToAddress([]byte{4}): &dataCopy{},
+ common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
+ common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
+ common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
+ common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
+ common.BytesToAddress([]byte{9}): &blake2F{},
+
+ common.BytesToAddress([]byte{100}): &tmHeaderValidate{},
+ common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{},
+ common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
+ common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidateHertz{},
+ common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
+ common.BytesToAddress([]byte{105}): &secp256k1SignatureRecover{},
}
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
@@ -245,6 +273,7 @@ var (
PrecompiledAddressesIstanbul []common.Address
PrecompiledAddressesByzantium []common.Address
PrecompiledAddressesHomestead []common.Address
+ PrecompiledAddressesFeynman []common.Address
)
func init() {
@@ -281,6 +310,9 @@ func init() {
for k := range PrecompiledContractsCancun {
PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k)
}
+ for k := range PrecompiledContractsFeynman {
+ PrecompiledAddressesFeynman = append(PrecompiledAddressesFeynman, k)
+ }
}
// ActivePrecompiles returns the precompiles enabled with the current configuration.
@@ -288,6 +320,8 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
switch {
case rules.IsCancun:
return PrecompiledAddressesCancun
+ case rules.IsFeynman:
+ return PrecompiledAddressesFeynman
case rules.IsHertz:
return PrecompiledAddressesHertz
case rules.IsPlato:
@@ -418,7 +452,6 @@ type bigModExp struct {
}
var (
- big0 = big.NewInt(0)
big1 = big.NewInt(1)
big3 = big.NewInt(3)
big4 = big.NewInt(4)
@@ -561,7 +594,7 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
// Modulo 0 is undefined, return zero
return common.LeftPadBytes([]byte{}, int(modLen)), nil
case base.BitLen() == 1: // a bit length of 1 means it's 1 (or -1).
- //If base == 1, then we can just return base % mod (if mod >= 1, which it is)
+ // If base == 1, then we can just return base % mod (if mod >= 1, which it is)
v = base.Mod(base, mod).Bytes()
default:
v = base.Exp(base, exp, mod).Bytes()
@@ -1281,11 +1314,11 @@ func (c *blsSignatureVerify) Run(input []byte) ([]byte, error) {
if pubKeyNumber > 1 {
if !sig.FastAggregateVerify(pubKeys, msg) {
- return big0.Bytes(), nil
+ return common.Big0.Bytes(), nil
}
} else {
if !sig.Verify(pubKeys[0], msgBytes) {
- return big0.Bytes(), nil
+ return common.Big0.Bytes(), nil
}
}
@@ -1355,3 +1388,95 @@ func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash {
return h
}
+
+// verifyDoubleSignEvidence implements bsc header verification precompile.
+type verifyDoubleSignEvidence struct{}
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *verifyDoubleSignEvidence) RequiredGas(input []byte) uint64 {
+ return params.DoubleSignEvidenceVerifyGas
+}
+
+type DoubleSignEvidence struct {
+ ChainId *big.Int
+ HeaderBytes1 []byte
+ HeaderBytes2 []byte
+}
+
+const (
+ extraSeal = 65
+)
+
+var (
+ errInvalidEvidence = errors.New("invalid double sign evidence")
+)
+
+// Run input: rlp encoded DoubleSignEvidence
+// return:
+// signer address| evidence height|
+// 20 bytes | 32 bytes |
+func (c *verifyDoubleSignEvidence) Run(input []byte) ([]byte, error) {
+ evidence := &DoubleSignEvidence{}
+ err := rlp.DecodeBytes(input, evidence)
+ if err != nil {
+ return nil, ErrExecutionReverted
+ }
+
+ header1 := &types.Header{}
+ err = rlp.DecodeBytes(evidence.HeaderBytes1, header1)
+ if err != nil {
+ return nil, ErrExecutionReverted
+ }
+
+ header2 := &types.Header{}
+ err = rlp.DecodeBytes(evidence.HeaderBytes2, header2)
+ if err != nil {
+ return nil, ErrExecutionReverted
+ }
+
+ // basic check
+ if len(header1.Number.Bytes()) > 32 || len(header2.Number.Bytes()) > 32 { // block number should be less than 2^256
+ return nil, errInvalidEvidence
+ }
+ if header1.Number.Cmp(header2.Number) != 0 {
+ return nil, errInvalidEvidence
+ }
+ if header1.ParentHash != header2.ParentHash {
+ return nil, errInvalidEvidence
+ }
+
+ if len(header1.Extra) < extraSeal || len(header2.Extra) < extraSeal {
+ return nil, errInvalidEvidence
+ }
+ sig1 := header1.Extra[len(header1.Extra)-extraSeal:]
+ sig2 := header2.Extra[len(header2.Extra)-extraSeal:]
+ if bytes.Equal(sig1, sig2) {
+ return nil, errInvalidEvidence
+ }
+
+ // check sig
+ msgHash1 := types.SealHash(header1, evidence.ChainId)
+ msgHash2 := types.SealHash(header2, evidence.ChainId)
+ if bytes.Equal(msgHash1.Bytes(), msgHash2.Bytes()) {
+ return nil, errInvalidEvidence
+ }
+ pubkey1, err := secp256k1.RecoverPubkey(msgHash1.Bytes(), sig1)
+ if err != nil {
+ return nil, ErrExecutionReverted
+ }
+ pubkey2, err := secp256k1.RecoverPubkey(msgHash2.Bytes(), sig2)
+ if err != nil {
+ return nil, ErrExecutionReverted
+ }
+ if !bytes.Equal(pubkey1, pubkey2) {
+ return nil, errInvalidEvidence
+ }
+
+ returnBz := make([]byte, 52) // 20 + 32
+ signerAddr := crypto.Keccak256(pubkey1[1:])[12:]
+ evidenceHeightBz := header1.Number.Bytes()
+ copy(returnBz[:20], signerAddr)
+ copy(returnBz[52-len(evidenceHeightBz):], evidenceHeightBz)
+
+ return returnBz, nil
+}
diff --git a/tests/fuzzers/runtime/runtime_fuzz.go b/core/vm/contracts_fuzz_test.go
similarity index 55%
rename from tests/fuzzers/runtime/runtime_fuzz.go
rename to core/vm/contracts_fuzz_test.go
index b30e9243d8..87c1fff7cc 100644
--- a/tests/fuzzers/runtime/runtime_fuzz.go
+++ b/core/vm/contracts_fuzz_test.go
@@ -1,4 +1,4 @@
-// Copyright 2017 The go-ethereum Authors
+// Copyright 2023 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
@@ -14,23 +14,31 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package runtime
+package vm
import (
- "github.com/ethereum/go-ethereum/core/vm/runtime"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
)
-// Fuzz is the basic entry point for the go-fuzz tool
-//
-// This returns 1 for valid parse:able/runnable code, 0
-// for invalid opcode.
-func Fuzz(input []byte) int {
- _, _, err := runtime.Execute(input, input, &runtime.Config{
- GasLimit: 12000000,
- })
- // invalid opcode
- if err != nil && len(err.Error()) > 6 && err.Error()[:7] == "invalid" {
- return 0
+func FuzzPrecompiledContracts(f *testing.F) {
+ // Create list of addresses
+ var addrs []common.Address
+ for k := range allPrecompiles {
+ addrs = append(addrs, k)
}
- return 1
+ f.Fuzz(func(t *testing.T, addr uint8, input []byte) {
+ a := addrs[int(addr)%len(addrs)]
+ p := allPrecompiles[a]
+ gas := p.RequiredGas(input)
+ if gas > 10_000_000 {
+ return
+ }
+ inWant := string(input)
+ RunPrecompiledContract(p, input, gas)
+ if inHave := string(input); inWant != inHave {
+ t.Errorf("Precompiled %v modified input data", a)
+ }
+ })
}
diff --git a/core/vm/contracts_lightclient.go b/core/vm/contracts_lightclient.go
index 4ac985f644..286250b1d8 100644
--- a/core/vm/contracts_lightclient.go
+++ b/core/vm/contracts_lightclient.go
@@ -8,8 +8,10 @@ import (
"github.com/tendermint/iavl"
"github.com/tendermint/tendermint/crypto/merkle"
+ "github.com/tendermint/tendermint/crypto/secp256k1"
cmn "github.com/tendermint/tendermint/libs/common"
+ //nolint:staticcheck
v1 "github.com/ethereum/go-ethereum/core/vm/lightclient/v1"
v2 "github.com/ethereum/go-ethereum/core/vm/lightclient/v2"
"github.com/ethereum/go-ethereum/params"
@@ -104,7 +106,7 @@ func (c *tmHeaderValidate) Run(input []byte) (result []byte, err error) {
return result, nil
}
-//------------------------------------------------------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------------------------------------------------------
// iavlMerkleProofValidate implemented as a native contract.
type iavlMerkleProofValidate struct {
@@ -397,3 +399,40 @@ type cometBFTLightBlockValidateHertz struct {
func (c *cometBFTLightBlockValidateHertz) Run(input []byte) (result []byte, err error) {
return c.run(input, true)
}
+
+// secp256k1SignatureRecover implemented as a native contract.
+type secp256k1SignatureRecover struct{}
+
+func (c *secp256k1SignatureRecover) RequiredGas(input []byte) uint64 {
+ return params.EcrecoverGas
+}
+
+const (
+ secp256k1PubKeyLength uint8 = 33
+ secp256k1SignatureLength uint8 = 64
+ secp256k1SignatureMsgHashLength uint8 = 32
+)
+
+// input:
+// | PubKey | Signature | SignatureMsgHash |
+// | 33 bytes | 64 bytes | 32 bytes |
+func (c *secp256k1SignatureRecover) Run(input []byte) (result []byte, err error) {
+ if len(input) != int(secp256k1PubKeyLength)+int(secp256k1SignatureLength)+int(secp256k1SignatureMsgHashLength) {
+ return nil, fmt.Errorf("invalid input")
+ }
+
+ return c.runTMSecp256k1Signature(
+ input[:secp256k1PubKeyLength],
+ input[secp256k1PubKeyLength:secp256k1PubKeyLength+secp256k1SignatureLength],
+ input[secp256k1PubKeyLength+secp256k1SignatureLength:],
+ )
+}
+
+func (c *secp256k1SignatureRecover) runTMSecp256k1Signature(pubkey, signatureStr, msgHash []byte) (result []byte, err error) {
+ tmPubKey := secp256k1.PubKeySecp256k1(pubkey)
+ ok := tmPubKey.VerifyBytesWithMsgHash(msgHash, signatureStr)
+ if !ok {
+ return nil, fmt.Errorf("invalid signature")
+ }
+ return tmPubKey.Address().Bytes(), nil
+}
diff --git a/core/vm/contracts_lightclient_test.go b/core/vm/contracts_lightclient_test.go
index bc99d88fa1..e669fbaea7 100644
--- a/core/vm/contracts_lightclient_test.go
+++ b/core/vm/contracts_lightclient_test.go
@@ -373,3 +373,42 @@ func TestCometBFTLightBlockValidateHertz(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expectOutputStr, hex.EncodeToString(res))
}
+
+func TestSecp256k1SignatureRecover(t *testing.T) {
+ // local key
+ {
+ pubKey, err := hex.DecodeString("0278caa4d6321aa856d6341dd3e8bcdfe0b55901548871c63c3f5cec43c2ae88a9")
+ require.NoError(t, err)
+ sig, err := hex.DecodeString("0cb78be0d8eaeab991907b06c61240c04f4ca83f54b7799ce77cf029b837988038c4b3b7f5df231695b0d14499b716e1fd6504860eb3c9244ecb4e569d44c062")
+ require.NoError(t, err)
+ msghash, err := hex.DecodeString("b6ac827edff4bbbf23579720782dbef40b65780af292cc66849e7e5944f1230f")
+ require.NoError(t, err)
+ expectedAddr, err := hex.DecodeString("fa3B227adFf8EA1706098928715076D76959Ae6c")
+ require.NoError(t, err)
+
+ input := append(append(pubKey, sig...), msghash...)
+ contract := &secp256k1SignatureRecover{}
+ res, err := contract.Run(input)
+ require.NoError(t, err)
+
+ require.Equal(t, expectedAddr, res)
+ }
+ // ledger
+ {
+ pubKey, err := hex.DecodeString("02d63ee39adb1779353b4393dd5ea9d6d2b6df63b71d168571803cc7b9a0a20e98")
+ require.NoError(t, err)
+ sig, err := hex.DecodeString("66bdb5d381b2773c0f569858c7ee143959522d7c1f46dc656c325cb7353ec40c28ec22dff3650b34c096c5b12e702d7237d409f1ebaaa6dd1128a8f2d401fd5b")
+ require.NoError(t, err)
+ msghash, err := hex.DecodeString("c45e8f0dc7c054c31912beeffd6f10f1c585606d61e252e97968cd66661c2571")
+ require.NoError(t, err)
+ expectedAddr, err := hex.DecodeString("65a284146b84210a01add088954bb52d88b230af")
+ require.NoError(t, err)
+
+ input := append(append(pubKey, sig...), msghash...)
+ contract := &secp256k1SignatureRecover{}
+ res, err := contract.Run(input)
+ require.NoError(t, err)
+
+ require.Equal(t, expectedAddr, res)
+ }
+}
diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go
index b0ebef86e5..f9b48e132b 100644
--- a/core/vm/contracts_test.go
+++ b/core/vm/contracts_test.go
@@ -67,6 +67,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{0x0f, 0x11}): &bls12381MapG1{},
common.BytesToAddress([]byte{0x0f, 0x12}): &bls12381MapG2{},
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
+ common.BytesToAddress([]byte{104}): &verifyDoubleSignEvidence{},
}
// EIP-152 test vectors
@@ -405,3 +406,24 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
}
benchmarkPrecompiled("0f", testcase, b)
}
+
+func TestDoubleSignSlash(t *testing.T) {
+ tc := precompiledTest{
+ Input: "f906278202cab9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494976ea74026e726554db657fa54763abd0c3a0aa9a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a804ae755e0fe64b59753f4db6308a1f679747bce186aa2c62b95fa6eeff3fbd08f3b0667e45428a54ade15bad19f49641c499b431b36f65803ea71b379e6b61de501a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094976ea74026e726554db657fa54763abd0c3a0aa9a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a80c0b17bfe88534296ff064cb7156548f6deba2d6310d5044ed6485f087dc6ef232e051c28e1909c2b50a3b4f29345d66681c319bef653e52e5d746480d5a3983b00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000",
+ Expected: "15d34aaf54267db7d7c367839aaf71a00a2c6a650000000000000000000000000000000000000000000000000000000000000cdf",
+ Gas: 10000,
+ Name: "",
+ }
+
+ testPrecompiled("68", tc, t)
+}
+
+func TestDoubleSignSlashFailure(t *testing.T) {
+ tc := precompiledFailureTest{
+ Input: "f9066b38b90332f9032fa01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494df87f0e2b8519ea2dd4abd8b639cdd628497ed25a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a1010000000000000000000000000000000000000000000000000000000000000000830f4240830f42408465bc6996b90115d983010306846765746889676f312e32302e3131856c696e7578000053474aa9f8b25fb860b0844a5082bfaa2299d2a23f076e2f6b17b15f839cc3e7d5a875656f6733fd4b87ba3401f906d15f3dea263cd9a6076107c7db620a4630dd3832c4a4b57eb8f497e28a3d69e5c03b30205c4b45675747d513e1accd66329770f3c35b18c9d023f84c84023a5ad6a086a28d985d9a6c8e7f9a4feadd5ace0adba9818e1e1727edca755fcc0bd8344684023a5ad7a0bc3492196b2e68b8e6ceea87cfa7588b4d590089eb885c4f2c1e9d9fb450f7b980988e1b9d0beb91dab063e04879a24c43d33baae3759dee41fd62ffa83c77fd202bea27a829b49e8025bdd198393526dd12b223ab16052fd26a43f3aabf63e76901a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b90332f9032fa01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094df87f0e2b8519ea2dd4abd8b639cdd628497ed25a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a1010000000000000000000000000000000000000000000000000000000000000000830f4240830f42408465bc6996b90115d983010306846765746889676f312e32302e3131856c696e7578000053474aa9f8b25fb860b0844a5082bfaa2299d2a23f076e2f6b17b15f839cc3e7d5a875656f6733fd4b87ba3401f906d15f3dea263cd9a6076107c7db620a4630dd3832c4a4b57eb8f497e28a3d69e5c03b30205c4b45675747d513e1accd66329770f3c35b18c9d023f84c84023a5ad6a086a28d985d9a6c8e7f9a4feadd5ace0adba9818e1e1727edca755fcc0bd8344684023a5ad7a0bc3492196b2e68b8e6ceea87cfa7588b4d590089eb885c4f2c1e9d9fb450f7b9804c71ed015dd0c5c2d7393b68c2927f83f0a5da4c66f761f09e2f950cc610832c7876144599368404096ddef0eadacfde57717e2c7d23982b927285b797d41bfa00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000",
+ ExpectedError: errInvalidEvidence.Error(),
+ Name: "",
+ }
+
+ testPrecompiledFailure("68", tc, t)
+}
diff --git a/core/vm/eips.go b/core/vm/eips.go
index 704c1ce127..9f06b2818f 100644
--- a/core/vm/eips.go
+++ b/core/vm/eips.go
@@ -85,7 +85,7 @@ func enable1884(jt *JumpTable) {
}
func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- balance, _ := uint256.FromBig(interpreter.evm.StateDB.GetBalance(scope.Contract.Address()))
+ balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
scope.Stack.push(balance)
return nil, nil
}
@@ -282,9 +282,15 @@ func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
return nil, nil
}
-// enable4844 applies EIP-4844 (DATAHASH opcode)
+// opBlobBaseFee implements BLOBBASEFEE opcode
+func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ blobBaseFee, _ := uint256.FromBig(interpreter.evm.Context.BlobBaseFee)
+ scope.Stack.push(blobBaseFee)
+ return nil, nil
+}
+
+// enable4844 applies EIP-4844 (BLOBHASH opcode)
func enable4844(jt *JumpTable) {
- // New opcode
jt[BLOBHASH] = &operation{
execute: opBlobHash,
constantGas: GasFastestStep,
@@ -293,6 +299,16 @@ func enable4844(jt *JumpTable) {
}
}
+// enable7516 applies EIP-7516 (BLOBBASEFEE opcode)
+func enable7516(jt *JumpTable) {
+ jt[BLOBBASEFEE] = &operation{
+ execute: opBlobBaseFee,
+ constantGas: GasQuickStep,
+ minStack: minStack(0, 1),
+ maxStack: maxStack(0, 1),
+ }
+}
+
// enable6780 applies EIP-6780 (deactivate SELFDESTRUCT)
func enable6780(jt *JumpTable) {
jt[SELFDESTRUCT] = &operation{
diff --git a/core/vm/evm.go b/core/vm/evm.go
index a1d427360d..30c9eb0f78 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -37,9 +37,9 @@ var EvmPool = sync.Pool{
type (
// CanTransferFunc is the signature of a transfer guard function
- CanTransferFunc func(StateDB, common.Address, *big.Int) bool
+ CanTransferFunc func(StateDB, common.Address, *uint256.Int) bool
// TransferFunc is the signature of a transfer function
- TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
+ TransferFunc func(StateDB, common.Address, common.Address, *uint256.Int)
// GetHashFunc returns the n'th block hash in the blockchain
// and is used by the BLOCKHASH EVM op code.
GetHashFunc func(uint64) common.Hash
@@ -50,6 +50,8 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
switch {
case evm.chainRules.IsCancun:
precompiles = PrecompiledContractsCancun
+ case evm.chainRules.IsFeynman:
+ precompiles = PrecompiledContractsFeynman
case evm.chainRules.IsHertz:
precompiles = PrecompiledContractsHertz
case evm.chainRules.IsPlato:
@@ -87,14 +89,14 @@ type BlockContext struct {
GetHash GetHashFunc
// Block information
- Coinbase common.Address // Provides information for COINBASE
- GasLimit uint64 // Provides information for GASLIMIT
- BlockNumber *big.Int // Provides information for NUMBER
- Time uint64 // Provides information for TIME
- Difficulty *big.Int // Provides information for DIFFICULTY
- BaseFee *big.Int // Provides information for BASEFEE
- Random *common.Hash // Provides information for PREVRANDAO
- ExcessBlobGas *uint64 // ExcessBlobGas field in the header, needed to compute the data
+ Coinbase common.Address // Provides information for COINBASE
+ GasLimit uint64 // Provides information for GASLIMIT
+ BlockNumber *big.Int // Provides information for NUMBER
+ Time uint64 // Provides information for TIME
+ Difficulty *big.Int // Provides information for DIFFICULTY
+ 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
}
// TxContext provides the EVM with information about a transaction.
@@ -102,8 +104,9 @@ type BlockContext struct {
type TxContext struct {
// Message information
Origin common.Address // Provides information for ORIGIN
- GasPrice *big.Int // Provides information for GASPRICE
+ GasPrice *big.Int // Provides information for GASPRICE (and is used to zero the basefee if NoBaseFee is set)
BlobHashes []common.Hash // Provides information for BLOBHASH
+ BlobFeeCap *big.Int // Is used to zero the blobbasefee if NoBaseFee is set
}
// EVM is the Ethereum Virtual Machine base object and provides
@@ -145,6 +148,18 @@ type EVM struct {
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
+ // If basefee tracking is disabled (eth_call, eth_estimateGas, etc), and no
+ // gas prices were specified, lower the basefee to 0 to avoid breaking EVM
+ // invariants (basefee < feecap)
+ if config.NoBaseFee {
+ if txCtx.GasPrice.BitLen() == 0 {
+ blockCtx.BaseFee = new(big.Int)
+ }
+ if txCtx.BlobFeeCap != nil && txCtx.BlobFeeCap.BitLen() == 0 {
+ blockCtx.BlobBaseFee = new(big.Int)
+ }
+ }
+
evm := EvmPool.Get().(*EVM)
evm.Context = blockCtx
evm.TxContext = txCtx
@@ -184,19 +199,11 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
return evm.interpreter
}
-// SetBlockContext updates the block context of the EVM.
-func (evm *EVM) SetBlockContext(blockCtx BlockContext) {
- evm.Context = blockCtx
- num := blockCtx.BlockNumber
- timestamp := blockCtx.Time
- evm.chainRules = evm.chainConfig.Rules(num, blockCtx.Random != nil, timestamp)
-}
-
// Call executes the contract associated with the addr with the given input as
// parameters. It also handles any necessary value transfer required and takes
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
-func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
+func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, ErrDepth
@@ -214,10 +221,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// Calling a non existing account, don't do anything, but ping the tracer
if debug {
if evm.depth == 0 {
- evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value.ToBig())
evm.Config.Tracer.CaptureEnd(ret, 0, nil)
} else {
- evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
+ evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value.ToBig())
evm.Config.Tracer.CaptureExit(ret, 0, nil)
}
}
@@ -230,13 +237,13 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// Capture the tracer start/end events in debug mode
if debug {
if evm.depth == 0 {
- evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value.ToBig())
defer func(startGas uint64) { // Lazy evaluation of the parameters
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err)
}(gas)
} else {
// Handle tracer events for entering and exiting a call frame
- evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
+ evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value.ToBig())
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
}(gas)
@@ -283,7 +290,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
//
// CallCode differs from Call in the sense that it executes the given address'
// code with the caller as context.
-func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
+func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, ErrDepth
@@ -299,7 +306,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil {
- evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
+ evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value.ToBig())
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
}(gas)
@@ -344,7 +351,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// that caller is something other than a Contract.
parent := caller.(*Contract)
// DELEGATECALL inherits value from parent call
- evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value)
+ evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value.ToBig())
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
}(gas)
@@ -390,7 +397,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
// but is the correct thing to do and matters on other networks, in tests, and potential
// future scenarios
- evm.StateDB.AddBalance(addr, big0)
+ evm.StateDB.AddBalance(addr, new(uint256.Int))
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil {
@@ -409,7 +416,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
addrCopy := addr
// 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.
- contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas)
+ contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas)
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
@@ -439,7 +446,7 @@ func (c *codeAndHash) Hash() common.Hash {
}
// create creates a new contract using code as deployment code.
-func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
+func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if evm.depth > int(params.CallCreateDepth) {
@@ -478,9 +485,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if evm.Config.Tracer != nil {
if evm.depth == 0 {
- evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
+ evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value.ToBig())
} else {
- evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
+ evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value.ToBig())
}
}
@@ -530,7 +537,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
}
// Create creates a new contract using code as deployment code.
-func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE)
}
@@ -539,7 +546,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
//
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
-func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
codeAndHash := &codeAndHash{code: code}
contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes())
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index 5153c8b7a3..4b141d8f9a 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -104,7 +104,7 @@ func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySi
// Legacy rules should be applied if we are in Petersburg (removal of EIP-1283)
// OR Constantinople is not active
if evm.chainRules.IsPetersburg || !evm.chainRules.IsConstantinople {
- // This checks for 3 scenario's and calculates gas accordingly:
+ // This checks for 3 scenarios and calculates gas accordingly:
//
// 1. From a zero-value address to a non-zero value (NEW VALUE)
// 2. From a non-zero value address to a zero-value address (DELETE)
diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go
index 4a5259a262..4a2545b6ed 100644
--- a/core/vm/gas_table_test.go
+++ b/core/vm/gas_table_test.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
func TestMemoryGasCost(t *testing.T) {
@@ -91,12 +92,12 @@ func TestEIP2200(t *testing.T) {
statedb.Finalise(true) // Push the state into the "original" slot
vmctx := BlockContext{
- CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
- Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
+ Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
}
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
- _, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
+ _, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int))
if err != tt.failure {
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
}
@@ -141,8 +142,8 @@ func TestCreateGas(t *testing.T) {
statedb.SetCode(address, hexutil.MustDecode(tt.code))
statedb.Finalise(true)
vmctx := BlockContext{
- CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
- Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
+ Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
BlockNumber: big.NewInt(0),
}
config := Config{}
@@ -152,7 +153,7 @@ func TestCreateGas(t *testing.T) {
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, config)
var startGas = uint64(testGas)
- ret, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, startGas, new(big.Int))
+ ret, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int))
if err != nil {
return false
}
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 2105201fce..ff78833ed9 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -251,6 +251,7 @@ func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
size.SetBytes(interpreter.hasherBuf[:])
return nil, nil
}
+
func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes()))
return nil, nil
@@ -259,7 +260,7 @@ func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
slot := scope.Stack.peek()
address := common.Address(slot.Bytes20())
- slot.SetFromBig(interpreter.evm.StateDB.GetBalance(address))
+ slot.Set(interpreter.evm.StateDB.GetBalance(address))
return nil, nil
}
@@ -267,14 +268,14 @@ func opOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes()))
return nil, nil
}
+
func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Caller().Bytes()))
return nil, nil
}
func opCallValue(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- v, _ := uint256.FromBig(scope.Contract.value)
- scope.Stack.push(v)
+ scope.Stack.push(scope.Contract.value)
return nil, nil
}
@@ -590,13 +591,8 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
stackvalue := size
scope.Contract.UseGas(gas)
- //TODO: use uint256.Int instead of converting with toBig()
- var bigVal = big0
- if !value.IsZero() {
- bigVal = value.ToBig()
- }
- res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, bigVal)
+ res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, &value)
// Push item on the stack based on the returned error. If the ruleset is
// homestead we must check for CodeStoreOutOfGasError (homestead only
// rule) and treat as an error, if the ruleset is frontier we must
@@ -635,13 +631,8 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
scope.Contract.UseGas(gas)
// reuse size int for stackvalue
stackvalue := size
- //TODO: use uint256.Int instead of converting with toBig()
- bigEndowment := big0
- if !endowment.IsZero() {
- bigEndowment = endowment.ToBig()
- }
res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract, input, gas,
- bigEndowment, &salt)
+ &endowment, &salt)
// Push item on the stack based on the returned error.
if suberr != nil {
stackvalue.Clear()
@@ -674,16 +665,10 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
if interpreter.readOnly && !value.IsZero() {
return nil, ErrWriteProtection
}
- var bigVal = big0
- //TODO: use uint256.Int instead of converting with toBig()
- // By using big0 here, we save an alloc for the most common case (non-ether-transferring contract calls),
- // but it would make more sense to extend the usage of uint256.Int
if !value.IsZero() {
gas += params.CallStipend
- bigVal = value.ToBig()
}
-
- ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, bigVal)
+ ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, &value)
if err != nil {
temp.Clear()
@@ -712,14 +697,11 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
// Get arguments from the memory.
args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
- //TODO: use uint256.Int instead of converting with toBig()
- var bigVal = big0
if !value.IsZero() {
gas += params.CallStipend
- bigVal = value.ToBig()
}
- ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, bigVal)
+ ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, &value)
if err != nil {
temp.Clear()
} else {
@@ -823,7 +805,7 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
interpreter.evm.StateDB.SelfDestruct(scope.Contract.Address())
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
- tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
+ tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
tracer.CaptureExit([]byte{}, 0, nil)
}
return nil, errStopToken
@@ -839,7 +821,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
interpreter.evm.StateDB.Selfdestruct6780(scope.Contract.Address())
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
- tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
+ tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
tracer.CaptureExit([]byte{}, 0, nil)
}
return nil, errStopToken
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index 807073336d..8653864d11 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -590,7 +590,7 @@ func TestOpTstore(t *testing.T) {
caller = common.Address{}
to = common.Address{1}
contractRef = contractRef{caller}
- contract = NewContract(contractRef, AccountRef(to), new(big.Int), 0)
+ contract = NewContract(contractRef, AccountRef(to), new(uint256.Int), 0)
scopeContext = ScopeContext{mem, stack, contract}
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
)
diff --git a/core/vm/interface.go b/core/vm/interface.go
index 26814d3d2f..25bfa06720 100644
--- a/core/vm/interface.go
+++ b/core/vm/interface.go
@@ -22,15 +22,16 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
// StateDB is an EVM database for full state querying.
type StateDB interface {
CreateAccount(common.Address)
- SubBalance(common.Address, *big.Int)
- AddBalance(common.Address, *big.Int)
- GetBalance(common.Address) *big.Int
+ SubBalance(common.Address, *uint256.Int)
+ AddBalance(common.Address, *uint256.Int)
+ GetBalance(common.Address) *uint256.Int
GetNonce(common.Address) uint64
SetNonce(common.Address, uint64)
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index e119983438..bcb9edb5a8 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -54,7 +54,7 @@ type EVMInterpreter struct {
table *JumpTable
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
- hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes
+ hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes
readOnly bool // Whether to throw on stateful modifications
returnData []byte // Last CALL's return data for subsequent reuse
diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go
index 96e681fccd..ff4977d728 100644
--- a/core/vm/interpreter_test.go
+++ b/core/vm/interpreter_test.go
@@ -17,7 +17,6 @@
package vm
import (
- "math/big"
"testing"
"time"
@@ -27,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
var loopInterruptTests = []string{
@@ -39,7 +39,7 @@ var loopInterruptTests = []string{
func TestLoopInterrupt(t *testing.T) {
address := common.BytesToAddress([]byte("contract"))
vmctx := BlockContext{
- Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
}
for i, tt := range loopInterruptTests {
@@ -54,7 +54,7 @@ func TestLoopInterrupt(t *testing.T) {
timeout := make(chan bool)
go func(evm *EVM) {
- _, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(big.Int))
+ _, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int))
errChannel <- err
}(evm)
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 38a0a76539..70c543f14d 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -82,7 +82,8 @@ func validate(jt JumpTable) JumpTable {
func newCancunInstructionSet() JumpTable {
instructionSet := newShanghaiInstructionSet()
- enable4844(&instructionSet) // EIP-4844 (DATAHASH opcode)
+ enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode)
+ enable7516(&instructionSet) // EIP-7516 (BLOBBASEFEE opcode)
enable1153(&instructionSet) // EIP-1153 "Transient Storage"
enable5656(&instructionSet) // EIP-5656 (MCOPY opcode)
enable6780(&instructionSet) // EIP-6780 SELFDESTRUCT only in same transaction
@@ -121,7 +122,7 @@ func newLondonInstructionSet() JumpTable {
// constantinople, istanbul, petersburg and berlin instructions.
func newBerlinInstructionSet() JumpTable {
instructionSet := newIstanbulInstructionSet()
- enable2929(&instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
+ enable2929(&instructionSet) // Gas cost increases for state access opcodes https://eips.ethereum.org/EIPS/eip-2929
return validate(instructionSet)
}
diff --git a/core/vm/jump_table_export.go b/core/vm/jump_table_export.go
index 6ea47d63a2..b74109da0a 100644
--- a/core/vm/jump_table_export.go
+++ b/core/vm/jump_table_export.go
@@ -22,7 +22,7 @@ import (
"github.com/ethereum/go-ethereum/params"
)
-// LookupInstructionSet returns the instructionset for the fork configured by
+// LookupInstructionSet returns the instruction set for the fork configured by
// the rules.
func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
switch {
@@ -56,7 +56,7 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
return newFrontierInstructionSet(), nil
}
-// Stack returns the mininum and maximum stack requirements.
+// Stack returns the minimum and maximum stack requirements.
func (op *operation) Stack() (int, int) {
return op.minStack, op.maxStack
}
diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go
index 2929b8ce92..2b9231fe1a 100644
--- a/core/vm/opcodes.go
+++ b/core/vm/opcodes.go
@@ -25,7 +25,7 @@ type OpCode byte
// IsPush specifies if an opcode is a PUSH opcode.
func (op OpCode) IsPush() bool {
- return PUSH1 <= op && op <= PUSH32
+ return PUSH0 <= op && op <= PUSH32
}
// 0x0 range - arithmetic ops.
@@ -101,6 +101,7 @@ const (
SELFBALANCE OpCode = 0x47
BASEFEE OpCode = 0x48
BLOBHASH OpCode = 0x49
+ BLOBBASEFEE OpCode = 0x4a
)
// 0x50 range - 'storage' and execution.
@@ -223,8 +224,7 @@ const (
SELFDESTRUCT OpCode = 0xff
)
-// Since the opcodes aren't all in order we can't use a regular slice.
-var opCodeToString = map[OpCode]string{
+var opCodeToString = [256]string{
// 0x0 range - arithmetic ops.
STOP: "STOP",
ADD: "ADD",
@@ -287,6 +287,7 @@ var opCodeToString = map[OpCode]string{
SELFBALANCE: "SELFBALANCE",
BASEFEE: "BASEFEE",
BLOBHASH: "BLOBHASH",
+ BLOBBASEFEE: "BLOBBASEFEE",
// 0x50 range - 'storage' and execution.
POP: "POP",
@@ -397,12 +398,10 @@ var opCodeToString = map[OpCode]string{
}
func (op OpCode) String() string {
- str := opCodeToString[op]
- if len(str) == 0 {
- return fmt.Sprintf("opcode %#x not defined", int(op))
+ if s := opCodeToString[op]; s != "" {
+ return s
}
-
- return str
+ return fmt.Sprintf("opcode %#x not defined", int(op))
}
var stringToOp = map[string]OpCode{
@@ -444,6 +443,7 @@ var stringToOp = map[string]OpCode{
"CHAINID": CHAINID,
"BASEFEE": BASEFEE,
"BLOBHASH": BLOBHASH,
+ "BLOBBASEFEE": BLOBBASEFEE,
"DELEGATECALL": DELEGATECALL,
"STATICCALL": STATICCALL,
"CODESIZE": CODESIZE,
diff --git a/core/vm/operations_acl.go b/core/vm/operations_acl.go
index 04c6409ebd..bca6d1e83b 100644
--- a/core/vm/operations_acl.go
+++ b/core/vm/operations_acl.go
@@ -197,7 +197,7 @@ var (
gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929(gasStaticCall)
gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929(gasCallCode)
gasSelfdestructEIP2929 = makeSelfdestructGasFn(true)
- // gasSelfdestructEIP3529 implements the changes in EIP-2539 (no refunds)
+ // gasSelfdestructEIP3529 implements the changes in EIP-3529 (no refunds)
gasSelfdestructEIP3529 = makeSelfdestructGasFn(false)
// gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929
@@ -214,12 +214,12 @@ var (
// see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified
gasSStoreEIP2929 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP2200)
- // gasSStoreEIP2539 implements gas cost for SSTORE according to EIP-2539
+ // gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529
// Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
)
-// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-2539
+// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-3529
func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go
index ffc631a90c..34335b8e9e 100644
--- a/core/vm/runtime/env.go
+++ b/core/vm/runtime/env.go
@@ -26,6 +26,7 @@ func NewEnv(cfg *Config) *vm.EVM {
Origin: cfg.Origin,
GasPrice: cfg.GasPrice,
BlobHashes: cfg.BlobHashes,
+ BlobFeeCap: cfg.BlobFeeCap,
}
blockContext := vm.BlockContext{
CanTransfer: core.CanTransfer,
@@ -37,6 +38,8 @@ func NewEnv(cfg *Config) *vm.EVM {
Difficulty: cfg.Difficulty,
GasLimit: cfg.GasLimit,
BaseFee: cfg.BaseFee,
+ BlobBaseFee: cfg.BlobBaseFee,
+ Random: cfg.Random,
}
return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index a3e75c6721..46f2bb5d5f 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
// Config is a basic type specifying certain configuration flags for running
@@ -44,7 +45,10 @@ type Config struct {
Debug bool
EVMConfig vm.Config
BaseFee *big.Int
+ BlobBaseFee *big.Int
BlobHashes []common.Hash
+ BlobFeeCap *big.Int
+ Random *common.Hash
State *state.StateDB
GetHashFn func(n uint64) common.Hash
@@ -94,6 +98,9 @@ func setDefaults(cfg *Config) {
if cfg.BaseFee == nil {
cfg.BaseFee = big.NewInt(params.InitialBaseFee)
}
+ if cfg.BlobBaseFee == nil {
+ cfg.BlobBaseFee = big.NewInt(params.BlobTxMinBlobGasprice)
+ }
}
// Execute executes the code using the input as call data during the execution.
@@ -129,7 +136,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
common.BytesToAddress([]byte("contract")),
input,
cfg.GasLimit,
- cfg.Value,
+ uint256.MustFromBig(cfg.Value),
)
return ret, cfg.State, err
}
@@ -158,7 +165,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
sender,
input,
cfg.GasLimit,
- cfg.Value,
+ uint256.MustFromBig(cfg.Value),
)
return code, address, leftOverGas, err
}
@@ -173,7 +180,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
var (
vmenv = NewEnv(cfg)
- sender = cfg.State.GetOrNewStateObject(cfg.Origin)
+ sender = vm.AccountRef(cfg.Origin)
statedb = cfg.State
rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
)
@@ -188,7 +195,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
address,
input,
cfg.GasLimit,
- cfg.Value,
+ uint256.MustFromBig(cfg.Value),
)
return ret, leftOverGas, err
}
diff --git a/tests/fuzzers/snap/debug/main.go b/core/vm/runtime/runtime_fuzz_test.go
similarity index 64%
rename from tests/fuzzers/snap/debug/main.go
rename to core/vm/runtime/runtime_fuzz_test.go
index df46bb1e22..8a4d31d819 100644
--- a/tests/fuzzers/snap/debug/main.go
+++ b/core/vm/runtime/runtime_fuzz_test.go
@@ -1,4 +1,4 @@
-// Copyright 2020 The go-ethereum Authors
+// Copyright 2023 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
@@ -14,25 +14,16 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package main
+package runtime
import (
- "fmt"
- "os"
-
- "github.com/ethereum/go-ethereum/tests/fuzzers/snap"
+ "testing"
)
-func main() {
- if len(os.Args) != 2 {
- fmt.Fprintf(os.Stderr, "Usage: debug \n")
- os.Exit(1)
- }
- crasher := os.Args[1]
- data, err := os.ReadFile(crasher)
- if err != nil {
- fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
- os.Exit(1)
- }
- snap.FuzzTrieNodes(data)
+func FuzzVmRuntime(f *testing.F) {
+ f.Fuzz(func(t *testing.T, code, input []byte) {
+ Execute(code, input, &Config{
+ GasLimit: 12000000,
+ })
+ })
}
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go
index 796d3b4434..b9e3c8ed66 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/runtime/runtime_test.go
@@ -38,6 +38,7 @@ import (
// force-load js tracers to trigger registration
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
+ "github.com/holiman/uint256"
)
func TestDefaults(t *testing.T) {
@@ -362,12 +363,12 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
//cfg.State.CreateAccount(cfg.Origin)
// set the receiver's (the executing contract) code for execution.
cfg.State.SetCode(destination, code)
- vmenv.Call(sender, destination, nil, gas, cfg.Value)
+ vmenv.Call(sender, destination, nil, gas, uint256.MustFromBig(cfg.Value))
b.Run(name, func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- vmenv.Call(sender, destination, nil, gas, cfg.Value)
+ vmenv.Call(sender, destination, nil, gas, uint256.MustFromBig(cfg.Value))
}
})
}
@@ -671,7 +672,7 @@ func TestColdAccountAccessCost(t *testing.T) {
for ii, op := range tracer.StructLogs() {
t.Logf("%d: %v %d", ii, op.OpName(), op.GasCost)
}
- t.Fatalf("tescase %d, gas report wrong, step %d, have %d want %d", i, tc.step, have, want)
+ t.Fatalf("testcase %d, gas report wrong, step %d, have %d want %d", i, tc.step, have, want)
}
}
}
diff --git a/crypto/blake2b/blake2b_f_fuzz.go b/crypto/blake2b/blake2b_f_fuzz_test.go
similarity index 55%
rename from crypto/blake2b/blake2b_f_fuzz.go
rename to crypto/blake2b/blake2b_f_fuzz_test.go
index b2f4057074..1de9a62de9 100644
--- a/crypto/blake2b/blake2b_f_fuzz.go
+++ b/crypto/blake2b/blake2b_f_fuzz_test.go
@@ -1,16 +1,24 @@
-//go:build gofuzz
-// +build gofuzz
+// Only enable fuzzer on platforms with AVX enabled
+//go:build go1.7 && amd64 && !gccgo && !appengine
+// +build go1.7,amd64,!gccgo,!appengine
package blake2b
import (
"encoding/binary"
+ "testing"
)
-func Fuzz(data []byte) int {
+func Fuzz(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(data)
+ })
+}
+
+func fuzz(data []byte) {
// Make sure the data confirms to the input model
if len(data) != 211 {
- return 0
+ return
}
// Parse everything and call all the implementations
var (
@@ -21,6 +29,7 @@ func Fuzz(data []byte) int {
t [2]uint64
f uint64
)
+
for i := 0; i < 8; i++ {
offset := 2 + i*8
h[i] = binary.LittleEndian.Uint64(data[offset : offset+8])
@@ -35,24 +44,32 @@ func Fuzz(data []byte) int {
if data[210]%2 == 1 { // Avoid spinning the fuzzer to hit 0/1
f = 0xFFFFFFFFFFFFFFFF
}
+
// Run the blake2b compression on all instruction sets and cross reference
want := h
fGeneric(&want, &m, t[0], t[1], f, uint64(rounds))
have := h
- fSSE4(&have, &m, t[0], t[1], f, uint64(rounds))
- if have != want {
- panic("SSE4 mismatches generic algo")
+ if useSSE4 {
+ fSSE4(&have, &m, t[0], t[1], f, uint64(rounds))
+ if have != want {
+ panic("SSE4 mismatches generic algo")
+ }
}
- have = h
- fAVX(&have, &m, t[0], t[1], f, uint64(rounds))
- if have != want {
- panic("AVX mismatches generic algo")
+
+ if useAVX {
+ have = h
+ fAVX(&have, &m, t[0], t[1], f, uint64(rounds))
+ if have != want {
+ panic("AVX mismatches generic algo")
+ }
}
- have = h
- fAVX2(&have, &m, t[0], t[1], f, uint64(rounds))
- if have != want {
- panic("AVX2 mismatches generic algo")
+
+ if useAVX2 {
+ have = h
+ fAVX2(&have, &m, t[0], t[1], f, uint64(rounds))
+ if have != want {
+ panic("AVX2 mismatches generic algo")
+ }
}
- return 1
}
diff --git a/crypto/bls12381/g2.go b/crypto/bls12381/g2.go
index 4d6f1ff11d..e5fe75af20 100644
--- a/crypto/bls12381/g2.go
+++ b/crypto/bls12381/g2.go
@@ -121,7 +121,7 @@ func (g *G2) FromBytes(in []byte) (*PointG2, error) {
return p, nil
}
-// DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G1 Point.
+// DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G2 Point.
func (g *G2) DecodePoint(in []byte) (*PointG2, error) {
if len(in) != 256 {
return nil, errors.New("invalid g2 point length")
diff --git a/crypto/kzg4844/kzg4844.go b/crypto/kzg4844/kzg4844.go
index 5969d1c2ce..4561ef9de9 100644
--- a/crypto/kzg4844/kzg4844.go
+++ b/crypto/kzg4844/kzg4844.go
@@ -20,6 +20,7 @@ package kzg4844
import (
"embed"
"errors"
+ "hash"
"sync/atomic"
)
@@ -108,3 +109,21 @@ func VerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
}
return gokzgVerifyBlobProof(blob, commitment, proof)
}
+
+// CalcBlobHashV1 calculates the 'versioned blob hash' of a commitment.
+// The given hasher must be a sha256 hash instance, otherwise the result will be invalid!
+func CalcBlobHashV1(hasher hash.Hash, commit *Commitment) (vh [32]byte) {
+ if hasher.Size() != 32 {
+ panic("wrong hash size")
+ }
+ hasher.Reset()
+ hasher.Write(commit[:])
+ hasher.Sum(vh[:0])
+ vh[0] = 0x01 // version
+ return vh
+}
+
+// IsValidVersionedHash checks that h is a structurally-valid versioned blob hash.
+func IsValidVersionedHash(h []byte) bool {
+ return len(h) == 32 && h[0] == 0x01
+}
diff --git a/crypto/secp256k1/secp256_test.go b/crypto/secp256k1/secp256_test.go
index 8656b9179c..a135291a79 100644
--- a/crypto/secp256k1/secp256_test.go
+++ b/crypto/secp256k1/secp256_test.go
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
+//go:build !gofuzz && cgo
+// +build !gofuzz,cgo
+
package secp256k1
import (
diff --git a/eth/api_admin.go b/eth/api_admin.go
index 88d8f5a14d..76a0d087bb 100644
--- a/eth/api_admin.go
+++ b/eth/api_admin.go
@@ -24,6 +24,7 @@ import (
"os"
"strings"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
@@ -118,6 +119,10 @@ func (api *AdminAPI) ImportChain(file string) (bool, error) {
} else if err != nil {
return false, fmt.Errorf("block %d: failed to parse: %v", index, err)
}
+ // ignore the genesis block when importing blocks
+ if block.NumberU64() == 0 {
+ continue
+ }
blocks = append(blocks, block)
index++
}
@@ -137,3 +142,31 @@ func (api *AdminAPI) ImportChain(file string) (bool, error) {
}
return true, nil
}
+
+// MevRunning returns true if the validator accept bids from builder
+func (api *AdminAPI) MevRunning() bool {
+ return api.eth.APIBackend.MevRunning()
+}
+
+// StartMev starts mev. It notifies the miner to start to receive bids.
+func (api *AdminAPI) StartMev() {
+ api.eth.APIBackend.StartMev()
+}
+
+// StopMev stops mev. It notifies the miner to stop receiving bids from this moment,
+// but the bids before this moment would still been taken into consideration by mev.
+func (api *AdminAPI) StopMev() {
+ api.eth.APIBackend.StopMev()
+}
+
+// AddBuilder adds a builder to the bid simulator.
+// url is the endpoint of the builder, for example, "https://mev-builder.amazonaws.com",
+// if validator is equipped with sentry, ignore the url.
+func (api *AdminAPI) AddBuilder(builder common.Address, url string) error {
+ return api.eth.APIBackend.AddBuilder(builder, url)
+}
+
+// RemoveBuilder removes a builder from the bid simulator.
+func (api *AdminAPI) RemoveBuilder(builder common.Address) error {
+ return api.eth.APIBackend.RemoveBuilder(builder)
+}
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 3192823148..5df2b32f49 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -80,17 +80,17 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
}
if number == rpc.FinalizedBlockNumber {
block := b.eth.blockchain.CurrentFinalBlock()
- if block != nil {
- return block, nil
+ if block == nil {
+ return nil, errors.New("finalized block not found")
}
- return nil, errors.New("finalized block not found")
+ return block, nil
}
if number == rpc.SafeBlockNumber {
block := b.eth.blockchain.CurrentSafeBlock()
- if block != nil {
- return block, nil
+ if block == nil {
+ return nil, errors.New("safe block not found")
}
- return nil, errors.New("safe block not found")
+ return block, nil
}
return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil
}
@@ -205,7 +205,10 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
return nil, nil, errors.New("header not found")
}
stateDb, err := b.eth.BlockChain().StateAt(header.Root)
- return stateDb, header, err
+ if err != nil {
+ return nil, nil, err
+ }
+ return stateDb, header, nil
}
func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
@@ -224,7 +227,10 @@ func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockN
return nil, nil, errors.New("hash is not currently canonical")
}
stateDb, err := b.eth.BlockChain().StateAt(header.Root)
- return stateDb, header, err
+ if err != nil {
+ return nil, nil, err
+ }
+ return stateDb, header, nil
}
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
}
@@ -234,7 +240,7 @@ func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (type
}
func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
- return rawdb.ReadLogs(b.eth.chainDb, hash, number, b.ChainConfig()), nil
+ return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil
}
func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
@@ -244,7 +250,7 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
return nil
}
-func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) {
+func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
if vmConfig == nil {
vmConfig = b.eth.blockchain.GetVMConfig()
}
@@ -255,7 +261,7 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *st
} else {
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
}
- return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error
+ return vm.NewEVM(context, txContext, state, b.ChainConfig(), *vmConfig)
}
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
@@ -287,7 +293,7 @@ func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscri
}
func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
- return b.eth.txPool.Add([]*txpool.Transaction{{Tx: signedTx}}, true, false)[0]
+ return b.eth.txPool.Add([]*types.Transaction{signedTx}, true, false)[0]
}
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
@@ -296,7 +302,7 @@ func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
for _, batch := range pending {
for _, lazy := range batch {
if tx := lazy.Resolve(); tx != nil {
- txs = append(txs, tx.Tx)
+ txs = append(txs, tx)
}
}
}
@@ -304,15 +310,28 @@ func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
}
func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction {
- if tx := b.eth.txPool.Get(hash); tx != nil {
- return tx.Tx
- }
- return nil
+ return b.eth.txPool.Get(hash)
}
-func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
- tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash)
- return tx, blockHash, blockNumber, index, nil
+// GetTransaction retrieves the lookup along with the transaction itself associate
+// with the given transaction hash.
+//
+// An error will be returned if the transaction is not found, and background
+// indexing for transactions is still in progress. The error is used to indicate the
+// scenario explicitly that the transaction might be reachable shortly.
+//
+// A null will be returned in the transaction is not found and background transaction
+// indexing is already finished. The transaction is not existent from the perspective
+// of node.
+func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
+ lookup, tx, err := b.eth.blockchain.GetTransactionLookup(txHash)
+ if err != nil {
+ return false, nil, common.Hash{}, 0, 0, err
+ }
+ if lookup == nil || tx == nil {
+ return false, nil, common.Hash{}, 0, 0, nil
+ }
+ return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index, nil
}
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
@@ -336,7 +355,7 @@ func (b *EthAPIBackend) TxPool() *txpool.TxPool {
}
func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
- return b.eth.txPool.SubscribeNewTxsEvent(ch)
+ return b.eth.txPool.SubscribeTransactions(ch, true)
}
func (b *EthAPIBackend) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription {
@@ -351,7 +370,12 @@ func (b *EthAPIBackend) Downloader() *downloader.Downloader {
}
func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress {
- return b.eth.Downloader().Progress()
+ prog := b.eth.Downloader().Progress()
+ if txProg, err := b.eth.blockchain.TxIndexProgress(); err == nil {
+ prog.TxIndexFinishedBlocks = txProg.Indexed
+ prog.TxIndexRemainingBlocks = txProg.Remaining
+ }
+ return prog
}
func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
@@ -432,3 +456,39 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
}
+
+func (b *EthAPIBackend) MevRunning() bool {
+ return b.Miner().MevRunning()
+}
+
+func (b *EthAPIBackend) MevParams() *types.MevParams {
+ return b.Miner().MevParams()
+}
+
+func (b *EthAPIBackend) StartMev() {
+ b.Miner().StartMev()
+}
+
+func (b *EthAPIBackend) StopMev() {
+ b.Miner().StopMev()
+}
+
+func (b *EthAPIBackend) AddBuilder(builder common.Address, url string) error {
+ return b.Miner().AddBuilder(builder, url)
+}
+
+func (b *EthAPIBackend) RemoveBuilder(builder common.Address) error {
+ return b.Miner().RemoveBuilder(builder)
+}
+
+func (b *EthAPIBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) {
+ return b.Miner().SendBid(ctx, bid)
+}
+
+func (b *EthAPIBackend) BestBidGasFee(parentHash common.Hash) *big.Int {
+ return b.Miner().BestPackedBlockReward(parentHash)
+}
+
+func (b *EthAPIBackend) MinerInTurn() bool {
+ return b.Miner().InTurn()
+}
diff --git a/eth/api_debug.go b/eth/api_debug.go
index 8d6f454634..baedd2632f 100644
--- a/eth/api_debug.go
+++ b/eth/api_debug.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
@@ -134,7 +135,7 @@ func (api *DebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error)
const AccountRangeMaxResults = 256
// AccountRange enumerates all accounts in the given block and start point in paging request
-func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hexutil.Bytes, maxResults int, nocode, nostorage, incompletes bool) (state.IteratorDump, error) {
+func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hexutil.Bytes, maxResults int, nocode, nostorage, incompletes bool) (state.Dump, error) {
var stateDb *state.StateDB
var err error
@@ -145,7 +146,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
// the miner and operate on those
_, stateDb = api.eth.miner.Pending()
if stateDb == nil {
- return state.IteratorDump{}, errors.New("pending state is not available")
+ return state.Dump{}, errors.New("pending state is not available")
}
} else {
var header *types.Header
@@ -159,29 +160,29 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
default:
block := api.eth.blockchain.GetBlockByNumber(uint64(number))
if block == nil {
- return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
+ return state.Dump{}, fmt.Errorf("block #%d not found", number)
}
header = block.Header()
}
if header == nil {
- return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
+ return state.Dump{}, fmt.Errorf("block #%d not found", number)
}
stateDb, err = api.eth.BlockChain().StateAt(header.Root)
if err != nil {
- return state.IteratorDump{}, err
+ return state.Dump{}, err
}
}
} else if hash, ok := blockNrOrHash.Hash(); ok {
block := api.eth.blockchain.GetBlockByHash(hash)
if block == nil {
- return state.IteratorDump{}, fmt.Errorf("block %s not found", hash.Hex())
+ return state.Dump{}, fmt.Errorf("block %s not found", hash.Hex())
}
stateDb, err = api.eth.BlockChain().StateAt(block.Root())
if err != nil {
- return state.IteratorDump{}, err
+ return state.Dump{}, err
}
} else {
- return state.IteratorDump{}, errors.New("either block number or block hash must be specified")
+ return state.Dump{}, errors.New("either block number or block hash must be specified")
}
opts := &state.DumpConfig{
@@ -195,7 +196,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
if maxResults > AccountRangeMaxResults || maxResults <= 0 {
opts.Max = AccountRangeMaxResults
}
- return stateDb.IteratorDump(opts), nil
+ return stateDb.RawDump(opts), nil
}
// StorageRangeResult is the result of a debug_storageRangeAt API call.
@@ -219,7 +220,6 @@ func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockNrOrHash rpc.Block
if err != nil {
return StorageRangeResult{}, err
}
-
if block == nil {
return StorageRangeResult{}, fmt.Errorf("block %v not found", blockNrOrHash)
}
@@ -229,18 +229,20 @@ func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockNrOrHash rpc.Block
}
defer release()
- st, err := statedb.StorageTrie(contractAddress)
+ return storageRangeAt(statedb, block.Root(), contractAddress, keyStart, maxResult)
+}
+
+func storageRangeAt(statedb *state.StateDB, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) {
+ storageRoot := statedb.GetStorageRoot(address)
+ if storageRoot == types.EmptyRootHash || storageRoot == (common.Hash{}) {
+ return StorageRangeResult{}, nil // empty storage
+ }
+ id := trie.StorageTrieID(root, crypto.Keccak256Hash(address.Bytes()), storageRoot)
+ tr, err := trie.NewStateTrie(id, statedb.Database().TrieDB())
if err != nil {
return StorageRangeResult{}, err
}
- if st == nil {
- return StorageRangeResult{}, fmt.Errorf("account %x doesn't exist", contractAddress)
- }
- return storageRangeAt(st, keyStart, maxResult)
-}
-
-func storageRangeAt(st state.Trie, start []byte, maxResult int) (StorageRangeResult, error) {
- trieIt, err := st.NodeIterator(start)
+ trieIt, err := tr.NodeIterator(start)
if err != nil {
return StorageRangeResult{}, err
}
@@ -252,7 +254,7 @@ func storageRangeAt(st state.Trie, start []byte, maxResult int) (StorageRangeRes
return StorageRangeResult{}, err
}
e := storageEntry{Value: common.BytesToHash(content)}
- if preimage := st.GetKey(it.Key); preimage != nil {
+ if preimage := tr.GetKey(it.Key); preimage != nil {
preimage := common.BytesToHash(preimage)
e.Key = &preimage
}
@@ -363,6 +365,9 @@ func (api *DebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]c
// The (from, to) parameters are the sequence of blocks to search, which can go
// either forwards or backwards
func (api *DebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error) {
+ if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme {
+ return 0, errors.New("state history is not yet available in path-based scheme")
+ }
db := api.eth.ChainDb()
var pivot uint64
if p := rawdb.ReadLastPivotNumber(db); p != nil {
@@ -423,6 +428,9 @@ func (api *DebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error
// If the value is shorter than the block generation time, or even 0 or negative,
// the node will flush trie after processing each block (effectively archive mode).
func (api *DebugAPI) SetTrieFlushInterval(interval string) error {
+ if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme {
+ return errors.New("trie flush interval is undefined for path-based scheme")
+ }
t, err := time.ParseDuration(interval)
if err != nil {
return err
@@ -432,6 +440,9 @@ func (api *DebugAPI) SetTrieFlushInterval(interval string) error {
}
// GetTrieFlushInterval gets the current value of in-memory trie flush interval
-func (api *DebugAPI) GetTrieFlushInterval() string {
- return api.eth.blockchain.GetTrieFlushInterval().String()
+func (api *DebugAPI) GetTrieFlushInterval() (string, error) {
+ if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme {
+ return "", errors.New("trie flush interval is undefined for path-based scheme")
+ }
+ return api.eth.blockchain.GetTrieFlushInterval().String(), nil
}
diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go
index de82521455..d3296e745b 100644
--- a/eth/api_debug_test.go
+++ b/eth/api_debug_test.go
@@ -19,8 +19,8 @@ package eth
import (
"bytes"
"fmt"
- "math/big"
"reflect"
+ "strings"
"testing"
"github.com/davecgh/go-spew/spew"
@@ -30,13 +30,14 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
"golang.org/x/exp/slices"
)
var dumper = spew.ConfigState{Indent: " "}
-func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.IteratorDump {
- result := statedb.IteratorDump(&state.DumpConfig{
+func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.Dump {
+ result := statedb.RawDump(&state.DumpConfig{
SkipCode: true,
SkipStorage: true,
OnlyWithAddresses: false,
@@ -47,12 +48,12 @@ func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, st
if len(result.Accounts) != expectedNum {
t.Fatalf("expected %d results, got %d", expectedNum, len(result.Accounts))
}
- for address := range result.Accounts {
- if address == (common.Address{}) {
- t.Fatalf("empty address returned")
+ for addr, acc := range result.Accounts {
+ if strings.HasSuffix(addr, "pre") || acc.Address == nil {
+ t.Fatalf("account without prestate (address) returned: %v", addr)
}
- if !statedb.Exist(address) {
- t.Fatalf("account not found in state %s", address.Hex())
+ if !statedb.Exist(*acc.Address) {
+ t.Fatalf("account not found in state %s", acc.Address.Hex())
}
}
return result
@@ -72,7 +73,7 @@ func TestAccountRange(t *testing.T) {
hash := common.HexToHash(fmt.Sprintf("%x", i))
addr := common.BytesToAddress(crypto.Keccak256Hash(hash.Bytes()).Bytes())
addrs[i] = addr
- sdb.SetBalance(addrs[i], big.NewInt(1))
+ sdb.SetBalance(addrs[i], uint256.NewInt(1))
if _, ok := m[addr]; ok {
t.Fatalf("bad")
} else {
@@ -94,16 +95,16 @@ func TestAccountRange(t *testing.T) {
secondResult := accountRangeTest(t, &trie, sdb, common.BytesToHash(firstResult.Next), AccountRangeMaxResults, AccountRangeMaxResults)
hList := make([]common.Hash, 0)
- for addr1 := range firstResult.Accounts {
- // If address is empty, then it makes no sense to compare
+ for addr1, acc := range firstResult.Accounts {
+ // If address is non-available, then it makes no sense to compare
// them as they might be two different accounts.
- if addr1 == (common.Address{}) {
+ if acc.Address == nil {
continue
}
if _, duplicate := secondResult.Accounts[addr1]; duplicate {
t.Fatalf("pagination test failed: results should not overlap")
}
- hList = append(hList, crypto.Keccak256Hash(addr1.Bytes()))
+ hList = append(hList, crypto.Keccak256Hash(acc.Address.Bytes()))
}
// Test to see if it's possible to recover from the middle of the previous
// set and get an even split between the first and second sets.
@@ -139,11 +140,11 @@ func TestEmptyAccountRange(t *testing.T) {
st, _ = state.New(types.EmptyRootHash, statedb, nil)
)
// Commit(although nothing to flush) and re-init the statedb
- st.Commit(0, nil)
st.IntermediateRoot(true)
+ st.Commit(0, nil)
st, _ = state.New(types.EmptyRootHash, statedb, nil)
- results := st.IteratorDump(&state.DumpConfig{
+ results := st.RawDump(&state.DumpConfig{
SkipCode: true,
SkipStorage: true,
OnlyWithAddresses: true,
@@ -162,9 +163,10 @@ func TestStorageRangeAt(t *testing.T) {
// Create a state where account 0x010000... has a few storage entries.
var (
- state, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
- addr = common.Address{0x01}
- keys = []common.Hash{ // hashes of Keys of storage
+ db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: true})
+ sdb, _ = state.New(types.EmptyRootHash, db, nil)
+ addr = common.Address{0x01}
+ keys = []common.Hash{ // hashes of Keys of storage
common.HexToHash("340dd630ad21bf010b4e676dbfa9ba9a02175262d1fa356232cfde6cb5b47ef2"),
common.HexToHash("426fcb404ab2d5d8e61a3d918108006bbb0a9be65e92235bb10eefbdb6dcd053"),
common.HexToHash("48078cfed56339ea54962e72c37c7f588fc4f8e5bc173827ba75cb10a63a96a5"),
@@ -178,8 +180,12 @@ func TestStorageRangeAt(t *testing.T) {
}
)
for _, entry := range storage {
- state.SetState(addr, *entry.Key, entry.Value)
+ sdb.SetState(addr, *entry.Key, entry.Value)
}
+ sdb.Finalise(false)
+ sdb.AccountsIntermediateRoot()
+ root, _, _ := sdb.Commit(0, nil)
+ sdb, _ = state.New(root, db, nil)
// Check a few combinations of limit and start/end.
tests := []struct {
@@ -209,11 +215,7 @@ func TestStorageRangeAt(t *testing.T) {
},
}
for _, test := range tests {
- tr, err := state.StorageTrie(addr)
- if err != nil {
- t.Error(err)
- }
- result, err := storageRangeAt(tr, test.start, test.limit)
+ result, err := storageRangeAt(sdb, root, addr, test.start, test.limit)
if err != nil {
t.Error(err)
}
diff --git a/eth/backend.go b/eth/backend.go
index 25791aeca3..d60e24605c 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/pruner"
"github.com/ethereum/go-ethereum/core/txpool"
+ "github.com/ethereum/go-ethereum/core/txpool/blobpool"
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -189,7 +190,15 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
chainConfig.VerkleTime = config.OverrideVerkle
overrides.OverrideVerkle = config.OverrideVerkle
}
+ if config.OverrideFeynman != nil {
+ chainConfig.FeynmanTime = config.OverrideFeynman
+ overrides.OverrideFeynman = config.OverrideFeynman
+ }
+ networkID := config.NetworkId
+ if networkID == 0 {
+ networkID = chainConfig.ChainID.Uint64()
+ }
eth := &Ethereum{
config: config,
merger: consensus.NewMerger(chainDb),
@@ -197,7 +206,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
eventMux: stack.EventMux(),
accountManager: stack.AccountManager(),
closeBloomHandler: make(chan struct{}),
- networkID: config.NetworkId,
+ networkID: networkID,
gasPrice: config.Miner.GasPrice,
etherbase: config.Miner.Etherbase,
bloomRequests: make(chan chan *bloombits.Retrieval),
@@ -221,7 +230,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if bcVersion != nil {
dbVer = fmt.Sprintf("%d", *bcVersion)
}
- log.Info("Initialising Ethereum protocol", "network", config.NetworkId, "dbversion", dbVer)
+ log.Info("Initialising Ethereum protocol", "network", networkID, "dbversion", dbVer)
if !config.SkipBcVersionCheck {
if bcVersion != nil && *bcVersion > core.BlockChainVersion {
@@ -274,16 +283,14 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if config.BlobPool.Datadir != "" {
config.BlobPool.Datadir = stack.ResolvePath(config.BlobPool.Datadir)
}
- // TODO(Nathan): blob is not ready now, it will cause panic.
- // blobPool := blobpool.New(config.BlobPool, eth.blockchain)
+ blobPool := blobpool.New(config.BlobPool, eth.blockchain)
if config.TxPool.Journal != "" {
config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal)
}
legacyPool := legacypool.New(config.TxPool, eth.blockchain)
- // TODO(Nathan): eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool, blobPool})
- eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool})
+ eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool, blobPool})
if err != nil {
return nil, err
}
@@ -294,7 +301,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
Chain: eth.blockchain,
TxPool: eth.txPool,
Merger: eth.merger,
- Network: config.NetworkId,
+ Network: networkID,
Sync: config.SyncMode,
BloomCache: uint64(cacheLimit),
EventMux: eth.eventMux,
@@ -368,7 +375,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}
// Start the RPC service
- eth.netRPCService = ethapi.NewNetAPI(eth.p2pServer, config.NetworkId)
+ eth.netRPCService = ethapi.NewNetAPI(eth.p2pServer, networkID)
// Register the backend on the node
stack.RegisterAPIs(eth.APIs())
@@ -416,7 +423,7 @@ func (s *Ethereum) APIs() []rpc.API {
Service: NewMinerAPI(s),
}, {
Namespace: "eth",
- Service: downloader.NewDownloaderAPI(s.handler.downloader, s.eventMux),
+ Service: downloader.NewDownloaderAPI(s.handler.downloader, s.blockchain, s.eventMux),
}, {
Namespace: "eth",
Service: filters.NewFilterAPI(filters.NewFilterSystem(s.APIBackend, filters.Config{}), s.config.RangeLimit),
@@ -492,7 +499,7 @@ func (s *Ethereum) shouldPreserve(header *types.Header) bool {
// r5 A [X] F G
// r6 [X]
//
- // In the round5, the inturn signer E is offline, so the worst case
+ // In the round5, the in-turn signer E is offline, so the worst case
// is A, F and G sign the block of round5 and reject the block of opponents
// and in the round6, the last available signer B is offline, the whole
// network is stuck.
@@ -596,7 +603,7 @@ func (s *Ethereum) Engine() consensus.Engine { return s.engine }
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
func (s *Ethereum) IsListening() bool { return true } // Always listening
func (s *Ethereum) Downloader() *downloader.Downloader { return s.handler.downloader }
-func (s *Ethereum) Synced() bool { return s.handler.acceptTxs.Load() }
+func (s *Ethereum) Synced() bool { return s.handler.synced.Load() }
func (s *Ethereum) SetSynced() { s.handler.enableSyncedFeatures() }
func (s *Ethereum) ArchiveMode() bool { return s.config.NoPruning }
func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer }
diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go
new file mode 100644
index 0000000000..8e0f81ee39
--- /dev/null
+++ b/eth/catalyst/api.go
@@ -0,0 +1,858 @@
+// Copyright 2021 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// Package catalyst implements the temporary eth1/eth2 RPC integration.
+package catalyst
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+
+ "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/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/miner"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/params/forks"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// Register adds the engine API to the full node.
+func Register(stack *node.Node, backend *eth.Ethereum) error {
+ log.Warn("Engine API enabled", "protocol", "eth")
+ stack.RegisterAPIs([]rpc.API{
+ {
+ Namespace: "engine",
+ Service: NewConsensusAPI(backend),
+ Authenticated: true,
+ },
+ })
+ return nil
+}
+
+const (
+ // invalidBlockHitEviction is the number of times an invalid block can be
+ // referenced in forkchoice update or new payload before it is attempted
+ // to be reprocessed again.
+ invalidBlockHitEviction = 128
+
+ // invalidTipsetsCap is the max number of recent block hashes tracked that
+ // have lead to some bad ancestor block. It's just an OOM protection.
+ invalidTipsetsCap = 512
+
+ // beaconUpdateStartupTimeout is the time to wait for a beacon client to get
+ // attached before starting to issue warnings.
+ beaconUpdateStartupTimeout = 30 * time.Second
+
+ // beaconUpdateConsensusTimeout is the max time allowed for a beacon client
+ // to send a consensus update before it's considered offline and the user is
+ // warned.
+ beaconUpdateConsensusTimeout = 2 * time.Minute
+
+ // beaconUpdateWarnFrequency is the frequency at which to warn the user that
+ // the beacon client is offline.
+ beaconUpdateWarnFrequency = 5 * time.Minute
+)
+
+// All methods provided over the engine endpoint.
+var caps = []string{
+ "engine_forkchoiceUpdatedV1",
+ "engine_forkchoiceUpdatedV2",
+ "engine_forkchoiceUpdatedV3",
+ "engine_exchangeTransitionConfigurationV1",
+ "engine_getPayloadV1",
+ "engine_getPayloadV2",
+ "engine_getPayloadV3",
+ "engine_newPayloadV1",
+ "engine_newPayloadV2",
+ "engine_newPayloadV3",
+ "engine_getPayloadBodiesByHashV1",
+ "engine_getPayloadBodiesByRangeV1",
+}
+
+type ConsensusAPI struct {
+ eth *eth.Ethereum
+
+ remoteBlocks *headerQueue // Cache of remote payloads received
+ localBlocks *payloadQueue // Cache of local payloads generated
+
+ // The forkchoice update and new payload method require us to return the
+ // latest valid hash in an invalid chain. To support that return, we need
+ // to track historical bad blocks as well as bad tipsets in case a chain
+ // is constantly built on it.
+ //
+ // There are a few important caveats in this mechanism:
+ // - The bad block tracking is ephemeral, in-memory only. We must never
+ // persist any bad block information to disk as a bug in Geth could end
+ // up blocking a valid chain, even if a later Geth update would accept
+ // it.
+ // - Bad blocks will get forgotten after a certain threshold of import
+ // attempts and will be retried. The rationale is that if the network
+ // really-really-really tries to feed us a block, we should give it a
+ // new chance, perhaps us being racey instead of the block being legit
+ // bad (this happened in Geth at a point with import vs. pending race).
+ // - Tracking all the blocks built on top of the bad one could be a bit
+ // problematic, so we will only track the head chain segment of a bad
+ // chain to allow discarding progressing bad chains and side chains,
+ // without tracking too much bad data.
+ invalidBlocksHits map[common.Hash]int // Ephemeral cache to track invalid blocks and their hit count
+ invalidTipsets map[common.Hash]*types.Header // Ephemeral cache to track invalid tipsets and their bad ancestor
+ invalidLock sync.Mutex // Protects the invalid maps from concurrent access
+
+ // Geth can appear to be stuck or do strange things if the beacon client is
+ // offline or is sending us strange data. Stash some update stats away so
+ // that we can warn the user and not have them open issues on our tracker.
+ lastTransitionUpdate time.Time
+ lastTransitionLock sync.Mutex
+ lastForkchoiceUpdate time.Time
+ lastForkchoiceLock sync.Mutex
+ lastNewPayloadUpdate time.Time
+ lastNewPayloadLock sync.Mutex
+
+ forkchoiceLock sync.Mutex // Lock for the forkChoiceUpdated method
+ newPayloadLock sync.Mutex // Lock for the NewPayload method
+}
+
+// NewConsensusAPI creates a new consensus api for the given backend.
+// The underlying blockchain needs to have a valid terminal total difficulty set.
+func NewConsensusAPI(eth *eth.Ethereum) *ConsensusAPI {
+ api := newConsensusAPIWithoutHeartbeat(eth)
+ go api.heartbeat()
+ return api
+}
+
+// newConsensusAPIWithoutHeartbeat creates a new consensus api for the SimulatedBeacon Node.
+func newConsensusAPIWithoutHeartbeat(eth *eth.Ethereum) *ConsensusAPI {
+ if eth.BlockChain().Config().TerminalTotalDifficulty == nil {
+ log.Warn("Engine API started but chain not configured for merge yet")
+ }
+ api := &ConsensusAPI{
+ eth: eth,
+ remoteBlocks: newHeaderQueue(),
+ localBlocks: newPayloadQueue(),
+ invalidBlocksHits: make(map[common.Hash]int),
+ invalidTipsets: make(map[common.Hash]*types.Header),
+ }
+ // eth.Downloader().SetBadBlockCallback(api.setInvalidAncestor)
+ return api
+}
+
+// ForkchoiceUpdatedV1 has several responsibilities:
+//
+// We try to set our blockchain to the headBlock.
+//
+// If the method is called with an empty head block: we return success, which can be used
+// to check if the engine API is enabled.
+//
+// If the total difficulty was not reached: we return INVALID.
+//
+// If the finalizedBlockHash is set: we check if we have the finalizedBlockHash in our db,
+// if not we start a sync.
+//
+// If there are payloadAttributes: we try to assemble a block with the payloadAttributes
+// and return its payloadID.
+func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+ if payloadAttributes != nil {
+ if payloadAttributes.Withdrawals != nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals not supported in V1"))
+ }
+ if api.eth.BlockChain().Config().IsShanghai(api.eth.BlockChain().Config().LondonBlock, payloadAttributes.Timestamp) {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai"))
+ }
+ }
+ return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, false)
+}
+
+// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload attributes.
+func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+ if params != nil {
+ if params.Withdrawals == nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing withdrawals"))
+ }
+ if params.BeaconRoot != nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("unexpected beacon root"))
+ }
+ if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Shanghai {
+ return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV2 must only be called for shanghai payloads"))
+ }
+ }
+ return api.forkchoiceUpdated(update, params, engine.PayloadV2, false)
+}
+
+// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root in the payload attributes.
+func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+ if params != nil {
+ // TODO(matt): according to https://github.com/ethereum/execution-apis/pull/498,
+ // payload attributes that are invalid should return error
+ // engine.InvalidPayloadAttributes. Once hive updates this, we should update
+ // on our end.
+ if params.Withdrawals == nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing withdrawals"))
+ }
+ if params.BeaconRoot == nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing beacon root"))
+ }
+ if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
+ return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun 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.PayloadV3, false)
+}
+
+func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, simulatorMode bool) (engine.ForkChoiceResponse, error) {
+ api.forkchoiceLock.Lock()
+ defer api.forkchoiceLock.Unlock()
+
+ log.Trace("Engine API request received", "method", "ForkchoiceUpdated", "head", update.HeadBlockHash, "finalized", update.FinalizedBlockHash, "safe", update.SafeBlockHash)
+ if update.HeadBlockHash == (common.Hash{}) {
+ log.Warn("Forkchoice requested update to zero hash")
+ return engine.STATUS_INVALID, nil // TODO(karalabe): Why does someone send us this?
+ }
+ // Stash away the last update to warn the user if the beacon client goes offline
+ api.lastForkchoiceLock.Lock()
+ api.lastForkchoiceUpdate = time.Now()
+ api.lastForkchoiceLock.Unlock()
+
+ // Check whether we have the block yet in our database or not. If not, we'll
+ // need to either trigger a sync, or to reject this forkchoice update for a
+ // reason.
+ block := api.eth.BlockChain().GetBlockByHash(update.HeadBlockHash)
+ if block == nil {
+ // If this block was previously invalidated, keep rejecting it here too
+ if res := api.checkInvalidAncestor(update.HeadBlockHash, update.HeadBlockHash); res != nil {
+ return engine.ForkChoiceResponse{PayloadStatus: *res, PayloadID: nil}, nil
+ }
+ // If the head hash is unknown (was not given to us in a newPayload request),
+ // we cannot resolve the header, so not much to do. This could be extended in
+ // the future to resolve from the `eth` network, but it's an unexpected case
+ // that should be fixed, not papered over.
+ header := api.remoteBlocks.get(update.HeadBlockHash)
+ if header == nil {
+ log.Warn("Forkchoice requested unknown head", "hash", update.HeadBlockHash)
+ return engine.STATUS_SYNCING, nil
+ }
+ // If the finalized hash is known, we can direct the downloader to move
+ // potentially more data to the freezer from the get go.
+ finalized := api.remoteBlocks.get(update.FinalizedBlockHash)
+
+ // Header advertised via a past newPayload request. Start syncing to it.
+ // Before we do however, make sure any legacy sync in switched off so we
+ // don't accidentally have 2 cycles running.
+ if merger := api.eth.Merger(); !merger.TDDReached() {
+ merger.ReachTTD()
+ api.eth.Downloader().Cancel()
+ }
+ context := []interface{}{"number", header.Number, "hash", header.Hash()}
+ if update.FinalizedBlockHash != (common.Hash{}) {
+ if finalized == nil {
+ context = append(context, []interface{}{"finalized", "unknown"}...)
+ } else {
+ context = append(context, []interface{}{"finalized", finalized.Number}...)
+ }
+ }
+ log.Info("Forkchoice requested sync to new head", context...)
+ /*if err := api.eth.Downloader().BeaconSync(api.eth.SyncMode(), header, finalized); err != nil {
+ return engine.STATUS_SYNCING, err
+ }*/
+ return engine.STATUS_SYNCING, nil
+ }
+ // Block is known locally, just sanity check that the beacon client does not
+ // attempt to push us back to before the merge.
+ if block.Difficulty().BitLen() > 0 || block.NumberU64() == 0 {
+ var (
+ td = api.eth.BlockChain().GetTd(update.HeadBlockHash, block.NumberU64())
+ ptd = api.eth.BlockChain().GetTd(block.ParentHash(), block.NumberU64()-1)
+ ttd = api.eth.BlockChain().Config().TerminalTotalDifficulty
+ )
+ if td == nil || (block.NumberU64() > 0 && ptd == nil) {
+ log.Error("TDs unavailable for TTD check", "number", block.NumberU64(), "hash", update.HeadBlockHash, "td", td, "parent", block.ParentHash(), "ptd", ptd)
+ return engine.STATUS_INVALID, errors.New("TDs unavailable for TDD check")
+ }
+ if td.Cmp(ttd) < 0 {
+ log.Error("Refusing beacon update to pre-merge", "number", block.NumberU64(), "hash", update.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)))
+ return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil
+ }
+ if block.NumberU64() > 0 && ptd.Cmp(ttd) >= 0 {
+ log.Error("Parent block is already post-ttd", "number", block.NumberU64(), "hash", update.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)))
+ return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil
+ }
+ }
+ valid := func(id *engine.PayloadID) engine.ForkChoiceResponse {
+ return engine.ForkChoiceResponse{
+ PayloadStatus: engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &update.HeadBlockHash},
+ PayloadID: id,
+ }
+ }
+ if rawdb.ReadCanonicalHash(api.eth.ChainDb(), block.NumberU64()) != update.HeadBlockHash {
+ // Block is not canonical, set head.
+ if latestValid, err := api.eth.BlockChain().SetCanonical(block); err != nil {
+ return engine.ForkChoiceResponse{PayloadStatus: engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &latestValid}}, err
+ }
+ } else if api.eth.BlockChain().CurrentBlock().Hash() == update.HeadBlockHash {
+ // If the specified head matches with our local head, do nothing and keep
+ // generating the payload. It's a special corner case that a few slots are
+ // missing and we are requested to generate the payload in slot.
+ } else {
+ // If the head block is already in our canonical chain, the beacon client is
+ // probably resyncing. Ignore the update.
+ log.Info("Ignoring beacon update to old head", "number", block.NumberU64(), "hash", update.HeadBlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)), "have", api.eth.BlockChain().CurrentBlock().Number)
+ return valid(nil), nil
+ }
+ api.eth.SetSynced()
+
+ // If the beacon client also advertised a finalized block, mark the local
+ // chain final and completely in PoS mode.
+ if update.FinalizedBlockHash != (common.Hash{}) {
+ if merger := api.eth.Merger(); !merger.PoSFinalized() {
+ merger.FinalizePoS()
+ }
+ // If the finalized block is not in our canonical tree, something is wrong
+ finalBlock := api.eth.BlockChain().GetBlockByHash(update.FinalizedBlockHash)
+ if finalBlock == nil {
+ log.Warn("Final block not available in database", "hash", update.FinalizedBlockHash)
+ return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not available in database"))
+ } else if rawdb.ReadCanonicalHash(api.eth.ChainDb(), finalBlock.NumberU64()) != update.FinalizedBlockHash {
+ log.Warn("Final block not in canonical chain", "number", block.NumberU64(), "hash", update.HeadBlockHash)
+ return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not in canonical chain"))
+ }
+ // Set the finalized block
+ // api.eth.BlockChain().SetFinalized(finalBlock.Header())
+ }
+ // Check if the safe block hash is in our canonical tree, if not something is wrong
+ if update.SafeBlockHash != (common.Hash{}) {
+ safeBlock := api.eth.BlockChain().GetBlockByHash(update.SafeBlockHash)
+ if safeBlock == nil {
+ log.Warn("Safe block not available in database")
+ return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not available in database"))
+ }
+ if rawdb.ReadCanonicalHash(api.eth.ChainDb(), safeBlock.NumberU64()) != update.SafeBlockHash {
+ log.Warn("Safe block not in canonical chain")
+ return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not in canonical chain"))
+ }
+ // Set the safe block
+ // api.eth.BlockChain().SetSafe(safeBlock.Header())
+ }
+ // If payload generation was requested, create a new block to be potentially
+ // sealed by the beacon client. The payload will be requested later, and we
+ // will replace it arbitrarily many times in between.
+ if payloadAttributes != nil {
+ args := &miner.BuildPayloadArgs{
+ Parent: update.HeadBlockHash,
+ Timestamp: payloadAttributes.Timestamp,
+ FeeRecipient: payloadAttributes.SuggestedFeeRecipient,
+ Random: payloadAttributes.Random,
+ Withdrawals: payloadAttributes.Withdrawals,
+ BeaconRoot: payloadAttributes.BeaconRoot,
+ Version: payloadVersion,
+ }
+ id := args.Id()
+ // If we already are busy generating this work, then we do not need
+ // to start a second process.
+ if api.localBlocks.has(id) {
+ return valid(&id), nil
+ }
+ // If the beacon chain is ran by a simulator, then transaction insertion,
+ // block insertion and block production will happen without any timing
+ // delay between them. This will cause flaky simulator executions due to
+ // the transaction pool running its internal reset operation on a back-
+ // ground thread. To avoid the racey behavior - in simulator mode - the
+ // pool will be explicitly blocked on its reset before continuing to the
+ // block production below.
+ if simulatorMode {
+ if err := api.eth.TxPool().Sync(); err != nil {
+ log.Error("Failed to sync transaction pool", "err", err)
+ return valid(nil), engine.InvalidPayloadAttributes.With(err)
+ }
+ }
+ payload, err := api.eth.Miner().BuildPayload(args)
+ if err != nil {
+ log.Error("Failed to build payload", "err", err)
+ return valid(nil), engine.InvalidPayloadAttributes.With(err)
+ }
+ api.localBlocks.put(id, payload)
+ return valid(&id), nil
+ }
+ return valid(nil), nil
+}
+
+// ExchangeTransitionConfigurationV1 checks the given configuration against
+// the configuration of the node.
+func (api *ConsensusAPI) ExchangeTransitionConfigurationV1(config engine.TransitionConfigurationV1) (*engine.TransitionConfigurationV1, error) {
+ log.Trace("Engine API request received", "method", "ExchangeTransitionConfiguration", "ttd", config.TerminalTotalDifficulty)
+ if config.TerminalTotalDifficulty == nil {
+ return nil, errors.New("invalid terminal total difficulty")
+ }
+ // Stash away the last update to warn the user if the beacon client goes offline
+ api.lastTransitionLock.Lock()
+ api.lastTransitionUpdate = time.Now()
+ api.lastTransitionLock.Unlock()
+
+ ttd := api.eth.BlockChain().Config().TerminalTotalDifficulty
+ if ttd == nil || ttd.Cmp(config.TerminalTotalDifficulty.ToInt()) != 0 {
+ log.Warn("Invalid TTD configured", "geth", ttd, "beacon", config.TerminalTotalDifficulty)
+ return nil, fmt.Errorf("invalid ttd: execution %v consensus %v", ttd, config.TerminalTotalDifficulty)
+ }
+ if config.TerminalBlockHash != (common.Hash{}) {
+ if hash := api.eth.BlockChain().GetCanonicalHash(uint64(config.TerminalBlockNumber)); hash == config.TerminalBlockHash {
+ return &engine.TransitionConfigurationV1{
+ TerminalTotalDifficulty: (*hexutil.Big)(ttd),
+ TerminalBlockHash: config.TerminalBlockHash,
+ TerminalBlockNumber: config.TerminalBlockNumber,
+ }, nil
+ }
+ return nil, errors.New("invalid terminal block hash")
+ }
+ return &engine.TransitionConfigurationV1{TerminalTotalDifficulty: (*hexutil.Big)(ttd)}, nil
+}
+
+// GetPayloadV1 returns a cached payload by id.
+func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.ExecutableData, error) {
+ if !payloadID.Is(engine.PayloadV1) {
+ return nil, engine.UnsupportedFork
+ }
+ data, err := api.getPayload(payloadID, false)
+ if err != nil {
+ return nil, err
+ }
+ return data.ExecutionPayload, nil
+}
+
+// GetPayloadV2 returns a cached payload by id.
+func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
+ if !payloadID.Is(engine.PayloadV1, engine.PayloadV2) {
+ return nil, engine.UnsupportedFork
+ }
+ return api.getPayload(payloadID, false)
+}
+
+// GetPayloadV3 returns a cached payload by id.
+func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
+ if !payloadID.Is(engine.PayloadV3) {
+ return nil, engine.UnsupportedFork
+ }
+ return api.getPayload(payloadID, false)
+}
+
+func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*engine.ExecutionPayloadEnvelope, error) {
+ log.Trace("Engine API request received", "method", "GetPayload", "id", payloadID)
+ data := api.localBlocks.get(payloadID, full)
+ if data == nil {
+ return nil, engine.UnknownPayload
+ }
+ return data, nil
+}
+
+// NewPayloadV1 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
+func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) {
+ if params.Withdrawals != nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1"))
+ }
+ return api.newPayload(params, nil, nil)
+}
+
+// NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
+func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) {
+ if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use new payload v2 post-shanghai"))
+ }
+ if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai {
+ if params.Withdrawals == nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
+ }
+ } else {
+ if params.Withdrawals != nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai"))
+ }
+ }
+ if params.ExcessBlobGas != nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil excessBlobGas pre-cancun"))
+ }
+ if params.BlobGasUsed != nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil params.BlobGasUsed pre-cancun"))
+ }
+ return api.newPayload(params, nil, nil)
+}
+
+// NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
+func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
+ if params.Withdrawals == nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
+ }
+ if params.ExcessBlobGas == nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun"))
+ }
+ if params.BlobGasUsed == nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil params.BlobGasUsed post-cancun"))
+ }
+
+ if versionedHashes == nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun"))
+ }
+ if beaconRoot == nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil parentBeaconBlockRoot post-cancun"))
+ }
+
+ if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 must only be called for cancun payloads"))
+ }
+ return api.newPayload(params, versionedHashes, beaconRoot)
+}
+
+func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
+ // The locking here is, strictly, not required. Without these locks, this can happen:
+ //
+ // 1. NewPayload( execdata-N ) is invoked from the CL. It goes all the way down to
+ // api.eth.BlockChain().InsertBlockWithoutSetHead, where it is blocked on
+ // e.g database compaction.
+ // 2. The call times out on the CL layer, which issues another NewPayload (execdata-N) call.
+ // Similarly, this also get stuck on the same place. Importantly, since the
+ // first call has not gone through, the early checks for "do we already have this block"
+ // will all return false.
+ // 3. When the db compaction ends, then N calls inserting the same payload are processed
+ // sequentially.
+ // Hence, we use a lock here, to be sure that the previous call has finished before we
+ // check whether we already have the block locally.
+ api.newPayloadLock.Lock()
+ defer api.newPayloadLock.Unlock()
+
+ log.Trace("Engine API request received", "method", "NewPayload", "number", params.Number, "hash", params.BlockHash)
+ block, err := engine.ExecutableDataToBlock(params, versionedHashes, beaconRoot)
+ if err != nil {
+ log.Warn("Invalid NewPayload params", "params", params, "error", err)
+ return api.invalid(err, nil), nil
+ }
+ // Stash away the last update to warn the user if the beacon client goes offline
+ api.lastNewPayloadLock.Lock()
+ api.lastNewPayloadUpdate = time.Now()
+ api.lastNewPayloadLock.Unlock()
+
+ // If we already have the block locally, ignore the entire execution and just
+ // return a fake success.
+ if block := api.eth.BlockChain().GetBlockByHash(params.BlockHash); block != nil {
+ log.Warn("Ignoring already known beacon payload", "number", params.Number, "hash", params.BlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)))
+ hash := block.Hash()
+ return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil
+ }
+ // If this block was rejected previously, keep rejecting it
+ if res := api.checkInvalidAncestor(block.Hash(), block.Hash()); res != nil {
+ return *res, nil
+ }
+ // If the parent is missing, we - in theory - could trigger a sync, but that
+ // would also entail a reorg. That is problematic if multiple sibling blocks
+ // are being fed to us, and even more so, if some semi-distant uncle shortens
+ // our live chain. As such, payload execution will not permit reorgs and thus
+ // will not trigger a sync cycle. That is fine though, if we get a fork choice
+ // update after legit payload executions.
+ parent := api.eth.BlockChain().GetBlock(block.ParentHash(), block.NumberU64()-1)
+ if parent == nil {
+ return api.delayPayloadImport(block)
+ }
+ // We have an existing parent, do some sanity checks to avoid the beacon client
+ // triggering too early
+ var (
+ ptd = api.eth.BlockChain().GetTd(parent.Hash(), parent.NumberU64())
+ ttd = api.eth.BlockChain().Config().TerminalTotalDifficulty
+ gptd = api.eth.BlockChain().GetTd(parent.ParentHash(), parent.NumberU64()-1)
+ )
+ if ptd.Cmp(ttd) < 0 {
+ log.Warn("Ignoring pre-merge payload", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd)
+ return engine.INVALID_TERMINAL_BLOCK, nil
+ }
+ if parent.Difficulty().BitLen() > 0 && gptd != nil && gptd.Cmp(ttd) >= 0 {
+ log.Error("Ignoring pre-merge parent block", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd)
+ return engine.INVALID_TERMINAL_BLOCK, nil
+ }
+ if block.Time() <= parent.Time() {
+ log.Warn("Invalid timestamp", "parent", block.Time(), "block", block.Time())
+ return api.invalid(errors.New("invalid timestamp"), parent.Header()), nil
+ }
+ // Another corner case: if the node is in snap sync mode, but the CL client
+ // tries to make it import a block. That should be denied as pushing something
+ // into the database directly will conflict with the assumptions of snap sync
+ // that it has an empty db that it can fill itself.
+ if api.eth.SyncMode() != downloader.FullSync {
+ return api.delayPayloadImport(block)
+ }
+ if !api.eth.BlockChain().HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
+ api.remoteBlocks.put(block.Hash(), block.Header())
+ log.Warn("State not available, ignoring new payload")
+ return engine.PayloadStatusV1{Status: engine.ACCEPTED}, nil
+ }
+ log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number)
+ if err := api.eth.BlockChain().InsertBlockWithoutSetHead(block); err != nil {
+ log.Warn("NewPayloadV1: inserting block failed", "error", err)
+
+ api.invalidLock.Lock()
+ api.invalidBlocksHits[block.Hash()] = 1
+ api.invalidTipsets[block.Hash()] = block.Header()
+ api.invalidLock.Unlock()
+
+ return api.invalid(err, parent.Header()), nil
+ }
+ // We've accepted a valid payload from the beacon client. Mark the local
+ // chain transitions to notify other subsystems (e.g. downloader) of the
+ // behavioral change.
+ if merger := api.eth.Merger(); !merger.TDDReached() {
+ merger.ReachTTD()
+ api.eth.Downloader().Cancel()
+ }
+ hash := block.Hash()
+ return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil
+}
+
+// delayPayloadImport stashes the given block away for import at a later time,
+// either via a forkchoice update or a sync extension. This method is meant to
+// be called by the newpayload command when the block seems to be ok, but some
+// prerequisite prevents it from being processed (e.g. no parent, or snap sync).
+func (api *ConsensusAPI) delayPayloadImport(block *types.Block) (engine.PayloadStatusV1, error) {
+ // Sanity check that this block's parent is not on a previously invalidated
+ // chain. If it is, mark the block as invalid too.
+ if res := api.checkInvalidAncestor(block.ParentHash(), block.Hash()); res != nil {
+ return *res, nil
+ }
+ // Stash the block away for a potential forced forkchoice update to it
+ // at a later time.
+ api.remoteBlocks.put(block.Hash(), block.Header())
+
+ // Although we don't want to trigger a sync, if there is one already in
+ // progress, try to extend if with the current payload request to relieve
+ // some strain from the forkchoice update.
+ // err := api.eth.Downloader().BeaconExtend(api.eth.SyncMode(), block.Header())
+ var err error
+ if err == nil {
+ log.Debug("Payload accepted for sync extension", "number", block.NumberU64(), "hash", block.Hash())
+ return engine.PayloadStatusV1{Status: engine.SYNCING}, nil
+ }
+ // Either no beacon sync was started yet, or it rejected the delivered
+ // payload as non-integratable on top of the existing sync. We'll just
+ // have to rely on the beacon client to forcefully update the head with
+ // a forkchoice update request.
+ if api.eth.SyncMode() == downloader.FullSync {
+ // In full sync mode, failure to import a well-formed block can only mean
+ // that the parent state is missing and the syncer rejected extending the
+ // current cycle with the new payload.
+ log.Warn("Ignoring payload with missing parent", "number", block.NumberU64(), "hash", block.Hash(), "parent", block.ParentHash(), "reason", err)
+ } else {
+ // In non-full sync mode (i.e. snap sync) all payloads are rejected until
+ // snap sync terminates as snap sync relies on direct database injections
+ // and cannot afford concurrent out-if-band modifications via imports.
+ log.Warn("Ignoring payload while snap syncing", "number", block.NumberU64(), "hash", block.Hash(), "reason", err)
+ }
+ return engine.PayloadStatusV1{Status: engine.SYNCING}, nil
+}
+
+// checkInvalidAncestor checks whether the specified chain end links to a known
+// bad ancestor. If yes, it constructs the payload failure response to return.
+func (api *ConsensusAPI) checkInvalidAncestor(check common.Hash, head common.Hash) *engine.PayloadStatusV1 {
+ api.invalidLock.Lock()
+ defer api.invalidLock.Unlock()
+
+ // If the hash to check is unknown, return valid
+ invalid, ok := api.invalidTipsets[check]
+ if !ok {
+ return nil
+ }
+ // If the bad hash was hit too many times, evict it and try to reprocess in
+ // the hopes that we have a data race that we can exit out of.
+ badHash := invalid.Hash()
+
+ api.invalidBlocksHits[badHash]++
+ if api.invalidBlocksHits[badHash] >= invalidBlockHitEviction {
+ log.Warn("Too many bad block import attempt, trying", "number", invalid.Number, "hash", badHash)
+ delete(api.invalidBlocksHits, badHash)
+
+ for descendant, badHeader := range api.invalidTipsets {
+ if badHeader.Hash() == badHash {
+ delete(api.invalidTipsets, descendant)
+ }
+ }
+ return nil
+ }
+ // Not too many failures yet, mark the head of the invalid chain as invalid
+ if check != head {
+ log.Warn("Marked new chain head as invalid", "hash", head, "badnumber", invalid.Number, "badhash", badHash)
+ for len(api.invalidTipsets) >= invalidTipsetsCap {
+ for key := range api.invalidTipsets {
+ delete(api.invalidTipsets, key)
+ break
+ }
+ }
+ api.invalidTipsets[head] = invalid
+ }
+ // If the last valid hash is the terminal pow block, return 0x0 for latest valid hash
+ lastValid := &invalid.ParentHash
+ if header := api.eth.BlockChain().GetHeader(invalid.ParentHash, invalid.Number.Uint64()-1); header != nil && header.Difficulty.Sign() != 0 {
+ lastValid = &common.Hash{}
+ }
+ failure := "links to previously rejected block"
+ return &engine.PayloadStatusV1{
+ Status: engine.INVALID,
+ LatestValidHash: lastValid,
+ ValidationError: &failure,
+ }
+}
+
+// invalid returns a response "INVALID" with the latest valid hash supplied by latest.
+func (api *ConsensusAPI) invalid(err error, latestValid *types.Header) engine.PayloadStatusV1 {
+ var currentHash *common.Hash
+ if latestValid != nil {
+ if latestValid.Difficulty.BitLen() != 0 {
+ // Set latest valid hash to 0x0 if parent is PoW block
+ currentHash = &common.Hash{}
+ } else {
+ // Otherwise set latest valid hash to parent hash
+ h := latestValid.Hash()
+ currentHash = &h
+ }
+ }
+ errorMsg := err.Error()
+ return engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: currentHash, ValidationError: &errorMsg}
+}
+
+// heartbeat loops indefinitely, and checks if there have been beacon client updates
+// received in the last while. If not - or if they but strange ones - it warns the
+// user that something might be off with their consensus node.
+//
+// TODO(karalabe): Spin this goroutine down somehow
+func (api *ConsensusAPI) heartbeat() {
+ // Sleep a bit on startup since there's obviously no beacon client yet
+ // attached, so no need to print scary warnings to the user.
+ time.Sleep(beaconUpdateStartupTimeout)
+
+ // If the network is not yet merged/merging, don't bother continuing.
+ if api.eth.BlockChain().Config().TerminalTotalDifficulty == nil {
+ return
+ }
+
+ var offlineLogged time.Time
+
+ for {
+ // Sleep a bit and retrieve the last known consensus updates
+ time.Sleep(5 * time.Second)
+
+ api.lastTransitionLock.Lock()
+ lastTransitionUpdate := api.lastTransitionUpdate
+ api.lastTransitionLock.Unlock()
+
+ api.lastForkchoiceLock.Lock()
+ lastForkchoiceUpdate := api.lastForkchoiceUpdate
+ api.lastForkchoiceLock.Unlock()
+
+ api.lastNewPayloadLock.Lock()
+ lastNewPayloadUpdate := api.lastNewPayloadUpdate
+ api.lastNewPayloadLock.Unlock()
+
+ // If there have been no updates for the past while, warn the user
+ // that the beacon client is probably offline
+ if api.eth.BlockChain().Config().TerminalTotalDifficultyPassed || api.eth.Merger().TDDReached() {
+ if time.Since(lastForkchoiceUpdate) <= beaconUpdateConsensusTimeout || time.Since(lastNewPayloadUpdate) <= beaconUpdateConsensusTimeout {
+ offlineLogged = time.Time{}
+ continue
+ }
+
+ if time.Since(offlineLogged) > beaconUpdateWarnFrequency {
+ if lastForkchoiceUpdate.IsZero() && lastNewPayloadUpdate.IsZero() {
+ if lastTransitionUpdate.IsZero() {
+ log.Warn("Post-merge network, but no beacon client seen. Please launch one to follow the chain!")
+ } else {
+ log.Warn("Beacon client online, but never received consensus updates. Please ensure your beacon client is operational to follow the chain!")
+ }
+ } else {
+ log.Warn("Beacon client online, but no consensus updates received in a while. Please fix your beacon client to follow the chain!")
+ }
+ offlineLogged = time.Now()
+ }
+ continue
+ }
+ }
+}
+
+// ExchangeCapabilities returns the current methods provided by this node.
+func (api *ConsensusAPI) ExchangeCapabilities([]string) []string {
+ return caps
+}
+
+// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
+// of block bodies by the engine api.
+func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 {
+ bodies := make([]*engine.ExecutionPayloadBodyV1, len(hashes))
+ for i, hash := range hashes {
+ block := api.eth.BlockChain().GetBlockByHash(hash)
+ bodies[i] = getBody(block)
+ }
+ return bodies
+}
+
+// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
+// of block bodies by the engine api.
+func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBodyV1, error) {
+ if start == 0 || count == 0 {
+ return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
+ }
+ if count > 1024 {
+ return nil, engine.TooLargeRequest.With(fmt.Errorf("requested count too large: %v", count))
+ }
+ // limit count up until current
+ current := api.eth.BlockChain().CurrentBlock().Number.Uint64()
+ last := uint64(start) + uint64(count) - 1
+ if last > current {
+ last = current
+ }
+ bodies := make([]*engine.ExecutionPayloadBodyV1, 0, uint64(count))
+ for i := uint64(start); i <= last; i++ {
+ block := api.eth.BlockChain().GetBlockByNumber(i)
+ bodies = append(bodies, getBody(block))
+ }
+ return bodies, nil
+}
+
+func getBody(block *types.Block) *engine.ExecutionPayloadBodyV1 {
+ if block == nil {
+ return nil
+ }
+
+ var (
+ body = block.Body()
+ txs = make([]hexutil.Bytes, len(body.Transactions))
+ withdrawals = body.Withdrawals
+ )
+
+ for j, tx := range body.Transactions {
+ data, _ := tx.MarshalBinary()
+ txs[j] = hexutil.Bytes(data)
+ }
+
+ // Post-shanghai withdrawals MUST be set to empty slice instead of nil
+ if withdrawals == nil && block.Header().WithdrawalsHash != nil {
+ withdrawals = make([]*types.Withdrawal, 0)
+ }
+
+ return &engine.ExecutionPayloadBodyV1{
+ TransactionData: txs,
+ Withdrawals: withdrawals,
+ }
+}
diff --git a/eth/catalyst/queue.go b/eth/catalyst/queue.go
new file mode 100644
index 0000000000..634dc1b2e6
--- /dev/null
+++ b/eth/catalyst/queue.go
@@ -0,0 +1,158 @@
+// Copyright 2022 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package catalyst
+
+import (
+ "sync"
+
+ "github.com/ethereum/go-ethereum/beacon/engine"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/miner"
+)
+
+// maxTrackedPayloads is the maximum number of prepared payloads the execution
+// engine tracks before evicting old ones. Ideally we should only ever track the
+// latest one; but have a slight wiggle room for non-ideal conditions.
+const maxTrackedPayloads = 10
+
+// maxTrackedHeaders is the maximum number of executed payloads the execution
+// engine tracks before evicting old ones. These are tracked outside the chain
+// during initial sync to allow ForkchoiceUpdate to reference past blocks via
+// hashes only. For the sync target it would be enough to track only the latest
+// header, but snap sync also needs the latest finalized height for the ancient
+// limit.
+const maxTrackedHeaders = 96
+
+// payloadQueueItem represents an id->payload tuple to store until it's retrieved
+// or evicted.
+type payloadQueueItem struct {
+ id engine.PayloadID
+ payload *miner.Payload
+}
+
+// payloadQueue tracks the latest handful of constructed payloads to be retrieved
+// by the beacon chain if block production is requested.
+type payloadQueue struct {
+ payloads []*payloadQueueItem
+ lock sync.RWMutex
+}
+
+// newPayloadQueue creates a pre-initialized queue with a fixed number of slots
+// all containing empty items.
+func newPayloadQueue() *payloadQueue {
+ return &payloadQueue{
+ payloads: make([]*payloadQueueItem, maxTrackedPayloads),
+ }
+}
+
+// put inserts a new payload into the queue at the given id.
+func (q *payloadQueue) put(id engine.PayloadID, payload *miner.Payload) {
+ q.lock.Lock()
+ defer q.lock.Unlock()
+
+ copy(q.payloads[1:], q.payloads)
+ q.payloads[0] = &payloadQueueItem{
+ id: id,
+ payload: payload,
+ }
+}
+
+// get retrieves a previously stored payload item or nil if it does not exist.
+func (q *payloadQueue) get(id engine.PayloadID, full bool) *engine.ExecutionPayloadEnvelope {
+ q.lock.RLock()
+ defer q.lock.RUnlock()
+
+ for _, item := range q.payloads {
+ if item == nil {
+ return nil // no more items
+ }
+ if item.id == id {
+ if !full {
+ return item.payload.Resolve()
+ }
+ return item.payload.ResolveFull()
+ }
+ }
+ return nil
+}
+
+// has checks if a particular payload is already tracked.
+func (q *payloadQueue) has(id engine.PayloadID) bool {
+ q.lock.RLock()
+ defer q.lock.RUnlock()
+
+ for _, item := range q.payloads {
+ if item == nil {
+ return false
+ }
+ if item.id == id {
+ return true
+ }
+ }
+ return false
+}
+
+// headerQueueItem represents an hash->header tuple to store until it's retrieved
+// or evicted.
+type headerQueueItem struct {
+ hash common.Hash
+ header *types.Header
+}
+
+// headerQueue tracks the latest handful of constructed headers to be retrieved
+// by the beacon chain if block production is requested.
+type headerQueue struct {
+ headers []*headerQueueItem
+ lock sync.RWMutex
+}
+
+// newHeaderQueue creates a pre-initialized queue with a fixed number of slots
+// all containing empty items.
+func newHeaderQueue() *headerQueue {
+ return &headerQueue{
+ headers: make([]*headerQueueItem, maxTrackedHeaders),
+ }
+}
+
+// put inserts a new header into the queue at the given hash.
+func (q *headerQueue) put(hash common.Hash, data *types.Header) {
+ q.lock.Lock()
+ defer q.lock.Unlock()
+
+ copy(q.headers[1:], q.headers)
+ q.headers[0] = &headerQueueItem{
+ hash: hash,
+ header: data,
+ }
+}
+
+// get retrieves a previously stored header item or nil if it does not exist.
+func (q *headerQueue) get(hash common.Hash) *types.Header {
+ q.lock.RLock()
+ defer q.lock.RUnlock()
+
+ for _, item := range q.headers {
+ if item == nil {
+ return nil // no more items
+ }
+ if item.hash == hash {
+ return item.header
+ }
+ }
+ return nil
+}
diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go
new file mode 100644
index 0000000000..5ad50f14c1
--- /dev/null
+++ b/eth/catalyst/simulated_beacon.go
@@ -0,0 +1,302 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package catalyst
+
+import (
+ "crypto/rand"
+ "errors"
+ "math/big"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/beacon/engine"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+const devEpochLength = 32
+
+// withdrawalQueue implements a FIFO queue which holds withdrawals that are
+// pending inclusion.
+type withdrawalQueue struct {
+ pending chan *types.Withdrawal
+}
+
+// add queues a withdrawal for future inclusion.
+func (w *withdrawalQueue) add(withdrawal *types.Withdrawal) error {
+ select {
+ case w.pending <- withdrawal:
+ break
+ default:
+ return errors.New("withdrawal queue full")
+ }
+ return nil
+}
+
+// gatherPending returns a number of queued withdrawals up to a maximum count.
+func (w *withdrawalQueue) gatherPending(maxCount int) []*types.Withdrawal {
+ withdrawals := []*types.Withdrawal{}
+ for {
+ select {
+ case withdrawal := <-w.pending:
+ withdrawals = append(withdrawals, withdrawal)
+ if len(withdrawals) == maxCount {
+ break
+ }
+ default:
+ return withdrawals
+ }
+ }
+}
+
+type SimulatedBeacon struct {
+ shutdownCh chan struct{}
+ eth *eth.Ethereum
+ period uint64
+ withdrawals withdrawalQueue
+
+ feeRecipient common.Address
+ feeRecipientLock sync.Mutex // lock gates concurrent access to the feeRecipient
+
+ engineAPI *ConsensusAPI
+ curForkchoiceState engine.ForkchoiceStateV1
+ lastBlockTime uint64
+}
+
+// NewSimulatedBeacon constructs a new simulated beacon chain.
+// Period sets the period in which blocks should be produced.
+//
+// - If period is set to 0, a block is produced on every transaction.
+// via Commit, Fork and AdjustTime.
+func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) {
+ block := eth.BlockChain().CurrentBlock()
+ current := engine.ForkchoiceStateV1{
+ HeadBlockHash: block.Hash(),
+ SafeBlockHash: block.Hash(),
+ FinalizedBlockHash: block.Hash(),
+ }
+ engineAPI := newConsensusAPIWithoutHeartbeat(eth)
+
+ // if genesis block, send forkchoiceUpdated to trigger transition to PoS
+ if block.Number.Sign() == 0 {
+ if _, err := engineAPI.ForkchoiceUpdatedV2(current, nil); err != nil {
+ return nil, err
+ }
+ }
+ return &SimulatedBeacon{
+ eth: eth,
+ period: period,
+ shutdownCh: make(chan struct{}),
+ engineAPI: engineAPI,
+ lastBlockTime: block.Time,
+ curForkchoiceState: current,
+ withdrawals: withdrawalQueue{make(chan *types.Withdrawal, 20)},
+ }, nil
+}
+
+func (c *SimulatedBeacon) setFeeRecipient(feeRecipient common.Address) {
+ c.feeRecipientLock.Lock()
+ c.feeRecipient = feeRecipient
+ c.feeRecipientLock.Unlock()
+}
+
+// Start invokes the SimulatedBeacon life-cycle function in a goroutine.
+func (c *SimulatedBeacon) Start() error {
+ if c.period == 0 {
+ // if period is set to 0, do not mine at all
+ // this is used in the simulated backend where blocks
+ // are explicitly mined via Commit, AdjustTime and Fork
+ } else {
+ go c.loop()
+ }
+ return nil
+}
+
+// Stop halts the SimulatedBeacon service.
+func (c *SimulatedBeacon) Stop() error {
+ close(c.shutdownCh)
+ return nil
+}
+
+// sealBlock initiates payload building for a new block and creates a new block
+// with the completed payload.
+func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp uint64) error {
+ if timestamp <= c.lastBlockTime {
+ timestamp = c.lastBlockTime + 1
+ }
+ c.feeRecipientLock.Lock()
+ feeRecipient := c.feeRecipient
+ c.feeRecipientLock.Unlock()
+
+ // Reset to CurrentBlock in case of the chain was rewound
+ if header := c.eth.BlockChain().CurrentBlock(); c.curForkchoiceState.HeadBlockHash != header.Hash() {
+ finalizedHash := c.finalizedBlockHash(header.Number.Uint64())
+ c.setCurrentState(header.Hash(), *finalizedHash)
+ }
+
+ var random [32]byte
+ rand.Read(random[:])
+ fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{
+ Timestamp: timestamp,
+ SuggestedFeeRecipient: feeRecipient,
+ Withdrawals: withdrawals,
+ Random: random,
+ }, engine.PayloadV2, true)
+ if err != nil {
+ return err
+ }
+ if fcResponse == engine.STATUS_SYNCING {
+ return errors.New("chain rewind prevented invocation of payload creation")
+ }
+
+ envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true)
+ if err != nil {
+ return err
+ }
+ payload := envelope.ExecutionPayload
+
+ var finalizedHash common.Hash
+ if payload.Number%devEpochLength == 0 {
+ finalizedHash = payload.BlockHash
+ } else {
+ if fh := c.finalizedBlockHash(payload.Number); fh == nil {
+ return errors.New("chain rewind interrupted calculation of finalized block hash")
+ } else {
+ finalizedHash = *fh
+ }
+ }
+
+ // Mark the payload as canon
+ if _, err = c.engineAPI.NewPayloadV2(*payload); err != nil {
+ return err
+ }
+ c.setCurrentState(payload.BlockHash, finalizedHash)
+
+ // Mark the block containing the payload as canonical
+ if _, err = c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, nil); err != nil {
+ return err
+ }
+ c.lastBlockTime = payload.Timestamp
+ return nil
+}
+
+// loop runs the block production loop for non-zero period configuration
+func (c *SimulatedBeacon) loop() {
+ timer := time.NewTimer(0)
+ for {
+ select {
+ case <-c.shutdownCh:
+ return
+ case <-timer.C:
+ withdrawals := c.withdrawals.gatherPending(10)
+ if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
+ log.Warn("Error performing sealing work", "err", err)
+ } else {
+ timer.Reset(time.Second * time.Duration(c.period))
+ }
+ }
+ }
+}
+
+// finalizedBlockHash returns the block hash of the finalized block corresponding
+// to the given number or nil if doesn't exist in the chain.
+func (c *SimulatedBeacon) finalizedBlockHash(number uint64) *common.Hash {
+ var finalizedNumber uint64
+ if number%devEpochLength == 0 {
+ finalizedNumber = number
+ } else {
+ finalizedNumber = (number - 1) / devEpochLength * devEpochLength
+ }
+ if finalizedBlock := c.eth.BlockChain().GetBlockByNumber(finalizedNumber); finalizedBlock != nil {
+ fh := finalizedBlock.Hash()
+ return &fh
+ }
+ return nil
+}
+
+// setCurrentState sets the current forkchoice state
+func (c *SimulatedBeacon) setCurrentState(headHash, finalizedHash common.Hash) {
+ c.curForkchoiceState = engine.ForkchoiceStateV1{
+ HeadBlockHash: headHash,
+ SafeBlockHash: headHash,
+ FinalizedBlockHash: finalizedHash,
+ }
+}
+
+// Commit seals a block on demand.
+func (c *SimulatedBeacon) Commit() common.Hash {
+ withdrawals := c.withdrawals.gatherPending(10)
+ if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
+ log.Warn("Error performing sealing work", "err", err)
+ }
+ return c.eth.BlockChain().CurrentBlock().Hash()
+}
+
+// Rollback un-sends previously added transactions.
+func (c *SimulatedBeacon) Rollback() {
+ // Flush all transactions from the transaction pools
+ maxUint256 := new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1)
+ c.eth.TxPool().SetGasTip(maxUint256)
+ // Set the gas tip back to accept new transactions
+ // TODO (Marius van der Wijden): set gas tip to parameter passed by config
+ c.eth.TxPool().SetGasTip(big.NewInt(params.GWei))
+}
+
+// Fork sets the head to the provided hash.
+func (c *SimulatedBeacon) Fork(parentHash common.Hash) error {
+ if len(c.eth.TxPool().Pending(false)) != 0 {
+ return errors.New("pending block dirty")
+ }
+ parent := c.eth.BlockChain().GetBlockByHash(parentHash)
+ if parent == nil {
+ return errors.New("parent not found")
+ }
+ return c.eth.BlockChain().SetHead(parent.NumberU64())
+}
+
+// AdjustTime creates a new block with an adjusted timestamp.
+func (c *SimulatedBeacon) AdjustTime(adjustment time.Duration) error {
+ if len(c.eth.TxPool().Pending(false)) != 0 {
+ return errors.New("could not adjust time on non-empty block")
+ }
+ parent := c.eth.BlockChain().CurrentBlock()
+ if parent == nil {
+ return errors.New("parent not found")
+ }
+ withdrawals := c.withdrawals.gatherPending(10)
+ return c.sealBlock(withdrawals, parent.Time+uint64(adjustment))
+}
+
+func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
+ api := &api{sim}
+ if sim.period == 0 {
+ // mine on demand if period is set to 0
+ go api.loop()
+ }
+ stack.RegisterAPIs([]rpc.API{
+ {
+ Namespace: "dev",
+ Service: api,
+ Version: "1.0",
+ },
+ })
+}
diff --git a/eth/catalyst/simulated_beacon_api.go b/eth/catalyst/simulated_beacon_api.go
new file mode 100644
index 0000000000..73d0a5921d
--- /dev/null
+++ b/eth/catalyst/simulated_beacon_api.go
@@ -0,0 +1,61 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package catalyst
+
+import (
+ "context"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+type api struct {
+ sim *SimulatedBeacon
+}
+
+func (a *api) loop() {
+ var (
+ newTxs = make(chan core.NewTxsEvent)
+ sub = a.sim.eth.TxPool().SubscribeTransactions(newTxs, true)
+ )
+ defer sub.Unsubscribe()
+
+ for {
+ select {
+ case <-a.sim.shutdownCh:
+ return
+ case w := <-a.sim.withdrawals.pending:
+ withdrawals := append(a.sim.withdrawals.gatherPending(9), w)
+ if err := a.sim.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
+ log.Warn("Error performing sealing work", "err", err)
+ }
+ case <-newTxs:
+ a.sim.Commit()
+ }
+ }
+}
+
+func (a *api) AddWithdrawal(ctx context.Context, withdrawal *types.Withdrawal) error {
+ return a.sim.withdrawals.add(withdrawal)
+}
+
+func (a *api) SetFeeRecipient(ctx context.Context, feeRecipient common.Address) {
+ a.sim.setFeeRecipient(feeRecipient)
+}
diff --git a/eth/catalyst/simulated_beacon_test.go b/eth/catalyst/simulated_beacon_test.go
new file mode 100644
index 0000000000..6fa97ad87a
--- /dev/null
+++ b/eth/catalyst/simulated_beacon_test.go
@@ -0,0 +1,141 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package catalyst
+
+import (
+ "context"
+ "math/big"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis) (*node.Node, *eth.Ethereum, *SimulatedBeacon) {
+ t.Helper()
+
+ n, err := node.New(&node.Config{
+ P2P: p2p.Config{
+ ListenAddr: "127.0.0.1:8545",
+ NoDiscovery: true,
+ MaxPeers: 0,
+ },
+ })
+ if err != nil {
+ t.Fatal("can't create node:", err)
+ }
+
+ ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256}
+ ethservice, err := eth.New(n, ethcfg)
+ if err != nil {
+ t.Fatal("can't create eth service:", err)
+ }
+
+ simBeacon, err := NewSimulatedBeacon(1, ethservice)
+ if err != nil {
+ t.Fatal("can't create simulated beacon:", err)
+ }
+
+ n.RegisterLifecycle(simBeacon)
+
+ if err := n.Start(); err != nil {
+ t.Fatal("can't start node:", err)
+ }
+
+ ethservice.SetSynced()
+ return n, ethservice, simBeacon
+}
+
+// send 20 transactions, >10 withdrawals and ensure they are included in order
+// send enough transactions to fill multiple blocks
+func TestSimulatedBeaconSendWithdrawals(t *testing.T) {
+ var withdrawals []types.Withdrawal
+ txs := make(map[common.Hash]types.Transaction)
+
+ var (
+ // testKey is a private key to use for funding a tester account.
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+
+ // testAddr is the Ethereum address of the tester account.
+ testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
+ )
+
+ // short period (1 second) for testing purposes
+ var gasLimit uint64 = 10_000_000
+ genesis := core.DeveloperGenesisBlock(gasLimit, &testAddr)
+ node, ethService, mock := startSimulatedBeaconEthService(t, genesis)
+ _ = mock
+ defer node.Close()
+
+ chainHeadCh := make(chan core.ChainHeadEvent, 10)
+ subscription := ethService.BlockChain().SubscribeChainHeadEvent(chainHeadCh)
+ defer subscription.Unsubscribe()
+
+ // generate some withdrawals
+ for i := 0; i < 20; i++ {
+ withdrawals = append(withdrawals, types.Withdrawal{Index: uint64(i)})
+ if err := mock.withdrawals.add(&withdrawals[i]); err != nil {
+ t.Fatal("addWithdrawal failed", err)
+ }
+ }
+
+ // generate a bunch of transactions
+ signer := types.NewEIP155Signer(ethService.BlockChain().Config().ChainID)
+ for i := 0; i < 20; i++ {
+ tx, err := types.SignTx(types.NewTransaction(uint64(i), common.Address{}, big.NewInt(1000), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, testKey)
+ if err != nil {
+ t.Fatalf("error signing transaction, err=%v", err)
+ }
+ txs[tx.Hash()] = *tx
+
+ if err := ethService.APIBackend.SendTx(context.Background(), tx); err != nil {
+ t.Fatal("SendTx failed", err)
+ }
+ }
+
+ includedTxs := make(map[common.Hash]struct{})
+ var includedWithdrawals []uint64
+
+ timer := time.NewTimer(12 * time.Second)
+ for {
+ select {
+ case evt := <-chainHeadCh:
+ for _, includedTx := range evt.Block.Transactions() {
+ includedTxs[includedTx.Hash()] = struct{}{}
+ }
+ for _, includedWithdrawal := range evt.Block.Withdrawals() {
+ includedWithdrawals = append(includedWithdrawals, includedWithdrawal.Index)
+ }
+
+ // ensure all withdrawals/txs included. this will take two blocks b/c number of withdrawals > 10
+ if len(includedTxs) == len(txs) && len(includedWithdrawals) == len(withdrawals) && evt.Block.Number().Cmp(big.NewInt(2)) == 0 {
+ return
+ }
+ case <-timer.C:
+ t.Fatal("timed out without including all withdrawals/txs")
+ }
+ }
+}
diff --git a/eth/downloader/api.go b/eth/downloader/api.go
index 3d9e06eba7..c1352b317b 100644
--- a/eth/downloader/api.go
+++ b/eth/downloader/api.go
@@ -19,17 +19,21 @@ package downloader
import (
"context"
"sync"
+ "time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common/gopool"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/rpc"
)
-// DownloaderAPI provides an API which gives information about the current synchronisation status.
-// It offers only methods that operates on data that can be available to anyone without security risks.
+// DownloaderAPI provides an API which gives information about the current
+// synchronisation status. It offers only methods that operates on data that
+// can be available to anyone without security risks.
type DownloaderAPI struct {
d *Downloader
+ chain *core.BlockChain
mux *event.TypeMux
installSyncSubscription chan chan interface{}
uninstallSyncSubscription chan *uninstallSyncSubscriptionRequest
@@ -39,31 +43,57 @@ type DownloaderAPI struct {
// listens for events from the downloader through the global event mux. In case it receives one of
// these events it broadcasts it to all syncing subscriptions that are installed through the
// installSyncSubscription channel.
-func NewDownloaderAPI(d *Downloader, m *event.TypeMux) *DownloaderAPI {
+func NewDownloaderAPI(d *Downloader, chain *core.BlockChain, m *event.TypeMux) *DownloaderAPI {
api := &DownloaderAPI{
d: d,
+ chain: chain,
mux: m,
installSyncSubscription: make(chan chan interface{}),
uninstallSyncSubscription: make(chan *uninstallSyncSubscriptionRequest),
}
-
go api.eventLoop()
-
return api
}
-// eventLoop runs a loop until the event mux closes. It will install and uninstall new
-// sync subscriptions and broadcasts sync status updates to the installed sync subscriptions.
+// eventLoop runs a loop until the event mux closes. It will install and uninstall
+// new sync subscriptions and broadcasts sync status updates to the installed sync
+// subscriptions.
+//
+// The sync status pushed to subscriptions can be a stream like:
+// >>> {Syncing: true, Progress: {...}}
+// >>> {false}
+//
+// If the node is already synced up, then only a single event subscribers will
+// receive is {false}.
func (api *DownloaderAPI) eventLoop() {
var (
- sub = api.mux.Subscribe(StartEvent{}, DoneEvent{}, FailedEvent{})
+ sub = api.mux.Subscribe(StartEvent{})
syncSubscriptions = make(map[chan interface{}]struct{})
+ checkInterval = time.Second * 60
+ checkTimer = time.NewTimer(checkInterval)
+
+ // status flags
+ started bool
+ done bool
+
+ getProgress = func() ethereum.SyncProgress {
+ prog := api.d.Progress()
+ if txProg, err := api.chain.TxIndexProgress(); err == nil {
+ prog.TxIndexFinishedBlocks = txProg.Indexed
+ prog.TxIndexRemainingBlocks = txProg.Remaining
+ }
+ return prog
+ }
)
+ defer checkTimer.Stop()
for {
select {
case i := <-api.installSyncSubscription:
syncSubscriptions[i] = struct{}{}
+ if done {
+ i <- false
+ }
case u := <-api.uninstallSyncSubscription:
delete(syncSubscriptions, u.c)
close(u.uninstalled)
@@ -71,21 +101,31 @@ func (api *DownloaderAPI) eventLoop() {
if event == nil {
return
}
-
- var notification interface{}
switch event.Data.(type) {
case StartEvent:
- notification = &SyncingResult{
+ started = true
+ }
+ case <-checkTimer.C:
+ if !started {
+ checkTimer.Reset(checkInterval)
+ continue
+ }
+ prog := getProgress()
+ if !prog.Done() {
+ notification := &SyncingResult{
Syncing: true,
- Status: api.d.Progress(),
+ Status: prog,
+ }
+ for c := range syncSubscriptions {
+ c <- notification
}
- case DoneEvent, FailedEvent:
- notification = false
+ checkTimer.Reset(checkInterval)
+ continue
}
- // broadcast
for c := range syncSubscriptions {
- c <- notification
+ c <- false
}
+ done = true
}
}
}
@@ -102,16 +142,15 @@ func (api *DownloaderAPI) Syncing(ctx context.Context) (*rpc.Subscription, error
gopool.Submit(func() {
statuses := make(chan interface{})
sub := api.SubscribeSyncStatus(statuses)
+ defer sub.Unsubscribe()
for {
select {
case status := <-statuses:
notifier.Notify(rpcSub.ID, status)
case <-rpcSub.Err():
- sub.Unsubscribe()
return
case <-notifier.Closed():
- sub.Unsubscribe()
return
}
}
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 14d68844eb..e524a39d78 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@@ -212,7 +211,7 @@ type BlockChain interface {
type DownloadOption func(downloader *Downloader) *Downloader
// New creates a new downloader to fetch hashes and blocks from remote peers.
-func New(stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, options ...DownloadOption) *Downloader {
+func New(stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, _ func()) *Downloader {
if lightchain == nil {
lightchain = chain
}
@@ -280,11 +279,6 @@ func (d *Downloader) Progress() ethereum.SyncProgress {
}
}
-// Synchronising returns whether the downloader is currently retrieving blocks.
-func (d *Downloader) Synchronising() bool {
- return d.synchronising.Load()
-}
-
// RegisterPeer injects a new download peer into the set of block source to be
// used for fetching hashes and blocks from.
func (d *Downloader) RegisterPeer(id string, version uint, peer Peer) error {
@@ -303,11 +297,6 @@ func (d *Downloader) RegisterPeer(id string, version uint, peer Peer) error {
return nil
}
-// RegisterLightPeer injects a light client peer, wrapping it so it appears as a regular peer.
-func (d *Downloader) RegisterLightPeer(id string, version uint, peer LightPeer) error {
- return d.RegisterPeer(id, version, &lightPeerWrapper{peer})
-}
-
// UnregisterPeer remove a peer from the known list, preventing any action from
// the specified peer. An effort is also made to return any pending fetches into
// the queue.
@@ -389,7 +378,16 @@ func (d *Downloader) synchronise(id string, hash common.Hash, td, ttd *big.Int,
log.Info("Block synchronisation started")
}
if mode == SnapSync {
- // Snap sync uses the snapshot namespace to store potentially flakey data until
+ // Snap sync will directly modify the persistent state, making the entire
+ // trie database unusable until the state is fully synced. To prevent any
+ // subsequent state reads, explicitly disable the trie database and state
+ // syncer is responsible to address and correct any state missing.
+ if d.blockchain.TrieDB().Scheme() == rawdb.PathScheme {
+ if err := d.blockchain.TrieDB().Disable(); err != nil {
+ return err
+ }
+ }
+ // Snap sync uses the snapshot namespace to store potentially flaky data until
// sync completely heals and finishes. Pause snapshot maintenance in the mean-
// time to prevent access.
if snapshots := d.blockchain.Snapshots(); snapshots != nil { // Only nil in tests
@@ -455,9 +453,6 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd *
d.mux.Post(DoneEvent{latest})
}
}()
- if p.version < eth.ETH66 {
- return fmt.Errorf("%w: advertized %d < required %d", errTooOld, p.version, eth.ETH66)
- }
mode := d.getMode()
if !beaconMode {
@@ -548,7 +543,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd *
// For non-merged networks, if there is a checkpoint available, then calculate
// the ancientLimit through that. Otherwise calculate the ancient limit through
// the advertised height of the remote peer. This most is mostly a fallback for
- // legacy networks, but should eventually be droppped. TODO(karalabe).
+ // legacy networks, but should eventually be dropped. TODO(karalabe).
// Legacy sync, use the best announcement we have from the remote peer.
// TODO(karalabe): Drop this pathway.
@@ -1228,41 +1223,13 @@ func (d *Downloader) fetchReceipts(from uint64, beaconMode bool) error {
// keeps processing and scheduling them into the header chain and downloader's
// queue until the stream ends or a failure occurs.
func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode bool) error {
- // Keep a count of uncertain headers to roll back
var (
- rollback uint64 // Zero means no rollback (fine as you can't unroll the genesis)
- rollbackErr error
- mode = d.getMode()
+ mode = d.getMode()
+ gotHeaders = false // Wait for batches of headers to process
)
- defer func() {
- if rollback > 0 {
- lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0
- if mode != LightSync {
- lastFastBlock = d.blockchain.CurrentSnapBlock().Number
- lastBlock = d.blockchain.CurrentBlock().Number
- }
- if err := d.lightchain.SetHead(rollback - 1); err != nil { // -1 to target the parent of the first uncertain block
- // We're already unwinding the stack, only print the error to make it more visible
- log.Error("Failed to roll back chain segment", "head", rollback-1, "err", err)
- }
- curFastBlock, curBlock := common.Big0, common.Big0
- if mode != LightSync {
- curFastBlock = d.blockchain.CurrentSnapBlock().Number
- curBlock = d.blockchain.CurrentBlock().Number
- }
- log.Warn("Rolled back chain segment",
- "header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number),
- "snap", fmt.Sprintf("%d->%d", lastFastBlock, curFastBlock),
- "block", fmt.Sprintf("%d->%d", lastBlock, curBlock), "reason", rollbackErr)
- }
- }()
- // Wait for batches of headers to process
- gotHeaders := false
-
for {
select {
case <-d.cancelCh:
- rollbackErr = errCanceled
return errCanceled
case task := <-d.headerProcCh:
@@ -1311,8 +1278,6 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
}
}
}
- // Disable any rollback and return
- rollback = 0
return nil
}
// Otherwise split the chunk of headers into batches and process them
@@ -1323,7 +1288,6 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
// Terminate if something failed in between processing chunks
select {
case <-d.cancelCh:
- rollbackErr = errCanceled
return errCanceled
default:
}
@@ -1339,24 +1303,9 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
if mode == SnapSync || mode == LightSync {
if len(chunkHeaders) > 0 {
if n, err := d.lightchain.InsertHeaderChain(chunkHeaders); err != nil {
- rollbackErr = err
-
- // If some headers were inserted, track them as uncertain
- if mode == SnapSync && n > 0 && rollback == 0 {
- rollback = chunkHeaders[0].Number.Uint64()
- }
log.Warn("Invalid header encountered", "number", chunkHeaders[n].Number, "hash", chunkHashes[n], "parent", chunkHeaders[n].ParentHash, "err", err)
return fmt.Errorf("%w: %v", errInvalidChain, err)
}
- // All verifications passed, track all headers within the alloted limits
- if mode == SnapSync {
- head := chunkHeaders[len(chunkHeaders)-1].Number.Uint64()
- if head-rollback > uint64(fsHeaderSafetyNet) {
- rollback = head - uint64(fsHeaderSafetyNet)
- } else {
- rollback = 1
- }
- }
}
}
// Unless we're doing light chains, schedule the headers for associated content retrieval
@@ -1365,7 +1314,6 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
for d.queue.PendingBodies() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders {
select {
case <-d.cancelCh:
- rollbackErr = errCanceled
return errCanceled
case <-time.After(time.Second):
}
@@ -1373,7 +1321,6 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
// Otherwise insert the headers for content retrieval
inserts := d.queue.Schedule(chunkHeaders, chunkHashes, origin)
if len(inserts) != len(chunkHeaders) {
- rollbackErr = fmt.Errorf("stale headers: len inserts %v len(chunk) %v", len(inserts), len(chunkHeaders))
return fmt.Errorf("%w: stale headers", errBadPeer)
}
}
@@ -1484,17 +1431,30 @@ func (d *Downloader) processSnapSyncContent() error {
// To cater for moving pivot points, track the pivot block and subsequently
// accumulated download results separately.
+ //
+ // These will be nil up to the point where we reach the pivot, and will only
+ // be set temporarily if the synced blocks are piling up, but the pivot is
+ // still busy downloading. In that case, we need to occasionally check for
+ // pivot moves, so need to unblock the loop. These fields will accumulate
+ // the results in the meantime.
+ //
+ // Note, there's no issue with memory piling up since after 64 blocks the
+ // pivot will forcefully move so these accumulators will be dropped.
var (
oldPivot *fetchResult // Locked in pivot block, might change eventually
oldTail []*fetchResult // Downloaded content after the pivot
)
for {
- // Wait for the next batch of downloaded data to be available, and if the pivot
- // block became stale, move the goalpost
- results := d.queue.Results(oldPivot == nil) // Block if we're not monitoring pivot staleness
+ // Wait for the next batch of downloaded data to be available. If we have
+ // not yet reached the pivot point, wait blockingly as there's no need to
+ // spin-loop check for pivot moves. If we reached the pivot but have not
+ // yet processed it, check for results async, so we might notice pivot
+ // moves while state syncing. If the pivot was passed fully, block again
+ // as there's no more reason to check for pivot moves at all.
+ results := d.queue.Results(oldPivot == nil)
if len(results) == 0 {
// If pivot sync is done, stop
- if oldPivot == nil {
+ if d.committed.Load() {
d.reportSnapSyncProgress(true)
return sync.Cancel()
}
@@ -1517,21 +1477,23 @@ func (d *Downloader) processSnapSyncContent() error {
pivot := d.pivotHeader
d.pivotLock.RUnlock()
- if oldPivot == nil {
- if pivot.Root != sync.root {
- sync.Cancel()
- sync = d.syncState(pivot.Root)
+ if oldPivot == nil { // no results piling up, we can move the pivot
+ if !d.committed.Load() { // not yet passed the pivot, we can move the pivot
+ if pivot.Root != sync.root { // pivot position changed, we can move the pivot
+ sync.Cancel()
+ sync = d.syncState(pivot.Root)
- go closeOnErr(sync)
+ go closeOnErr(sync)
+ }
}
- } else {
+ } else { // results already piled up, consume before handling pivot move
results = append(append([]*fetchResult{oldPivot}, oldTail...), results...)
}
// Split around the pivot block and process the two sides via snap/full sync
if !d.committed.Load() {
latest := results[len(results)-1].Header
// If the height is above the pivot block by 2 sets, it means the pivot
- // become stale in the network and it was garbage collected, move to a
+ // become stale in the network, and it was garbage collected, move to a
// new pivot.
//
// Note, we have `reorgProtHeaderDelay` number of blocks withheld, Those
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index 9c03b40229..4bdffd33a7 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -81,7 +81,7 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
chain: chain,
peers: make(map[string]*downloadTesterPeer),
}
- tester.downloader = New(db, new(event.TypeMux), tester.chain, nil, tester.dropPeer)
+ tester.downloader = New(db, new(event.TypeMux), tester.chain, nil, tester.dropPeer, success)
return tester
}
@@ -180,7 +180,7 @@ func unmarshalRlpHeaders(rlpdata []rlp.RawValue) []*types.Header {
// function can be used to retrieve batches of headers from the particular peer.
func (dlp *downloadTesterPeer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) {
// Service the header query via the live handler code
- rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, ð.GetBlockHeadersPacket{
+ rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
Hash: origin,
},
@@ -208,7 +208,7 @@ func (dlp *downloadTesterPeer) RequestHeadersByHash(origin common.Hash, amount i
}
res := ð.Response{
Req: req,
- Res: (*eth.BlockHeadersPacket)(&headers),
+ Res: (*eth.BlockHeadersRequest)(&headers),
Meta: hashes,
Time: 1,
Done: make(chan error, 1), // Ignore the returned status
@@ -224,7 +224,7 @@ func (dlp *downloadTesterPeer) RequestHeadersByHash(origin common.Hash, amount i
// function can be used to retrieve batches of headers from the particular peer.
func (dlp *downloadTesterPeer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) {
// Service the header query via the live handler code
- rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, ð.GetBlockHeadersPacket{
+ rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, ð.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{
Number: origin,
},
@@ -252,7 +252,7 @@ func (dlp *downloadTesterPeer) RequestHeadersByNumber(origin uint64, amount int,
}
res := ð.Response{
Req: req,
- Res: (*eth.BlockHeadersPacket)(&headers),
+ Res: (*eth.BlockHeadersRequest)(&headers),
Meta: hashes,
Time: 1,
Done: make(chan error, 1), // Ignore the returned status
@@ -289,7 +289,7 @@ func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *et
}
res := ð.Response{
Req: req,
- Res: (*eth.BlockBodiesPacket)(&bodies),
+ Res: (*eth.BlockBodiesResponse)(&bodies),
Meta: [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes},
Time: 1,
Done: make(chan error, 1), // Ignore the returned status
@@ -320,7 +320,7 @@ func (dlp *downloadTesterPeer) RequestReceipts(hashes []common.Hash, sink chan *
}
res := ð.Response{
Req: req,
- Res: (*eth.ReceiptsPacket)(&receipts),
+ Res: (*eth.ReceiptsResponse)(&receipts),
Meta: hashes,
Time: 1,
Done: make(chan error, 1), // Ignore the returned status
@@ -440,9 +440,9 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) {
}
}
-func TestCanonicalSynchronisation66Full(t *testing.T) { testCanonSync(t, eth.ETH66, FullSync) }
-func TestCanonicalSynchronisation66Snap(t *testing.T) { testCanonSync(t, eth.ETH66, SnapSync) }
-func TestCanonicalSynchronisation66Light(t *testing.T) { testCanonSync(t, eth.ETH66, LightSync) }
+func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) }
+func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) }
+func TestCanonicalSynchronisation68Light(t *testing.T) { testCanonSync(t, eth.ETH68, LightSync) }
func TestCanonicalSynchronisation67Full(t *testing.T) { testCanonSync(t, eth.ETH67, FullSync) }
func TestCanonicalSynchronisation67Snap(t *testing.T) { testCanonSync(t, eth.ETH67, SnapSync) }
func TestCanonicalSynchronisation67Light(t *testing.T) { testCanonSync(t, eth.ETH67, LightSync) }
@@ -464,8 +464,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 TestThrottling66Full(t *testing.T) { testThrottling(t, eth.ETH66, FullSync) }
-func TestThrottling66Snap(t *testing.T) { testThrottling(t, eth.ETH66, SnapSync) }
+func TestThrottling68Full(t *testing.T) { testThrottling(t, eth.ETH68, FullSync) }
+func TestThrottling68Snap(t *testing.T) { testThrottling(t, eth.ETH68, SnapSync) }
func TestThrottling67Full(t *testing.T) { testThrottling(t, eth.ETH67, FullSync) }
func TestThrottling67Snap(t *testing.T) { testThrottling(t, eth.ETH67, SnapSync) }
@@ -546,9 +546,9 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) {
// Tests that simple synchronization against a forked chain works correctly. In
// this test common ancestor lookup should *not* be short circuited, and a full
// binary search should be executed.
-func TestForkedSync66Full(t *testing.T) { testForkedSync(t, eth.ETH66, FullSync) }
-func TestForkedSync66Snap(t *testing.T) { testForkedSync(t, eth.ETH66, SnapSync) }
-func TestForkedSync66Light(t *testing.T) { testForkedSync(t, eth.ETH66, LightSync) }
+func TestForkedSync68Full(t *testing.T) { testForkedSync(t, eth.ETH68, FullSync) }
+func TestForkedSync68Snap(t *testing.T) { testForkedSync(t, eth.ETH68, SnapSync) }
+func TestForkedSync68Light(t *testing.T) { testForkedSync(t, eth.ETH68, LightSync) }
func TestForkedSync67Full(t *testing.T) { testForkedSync(t, eth.ETH67, FullSync) }
func TestForkedSync67Snap(t *testing.T) { testForkedSync(t, eth.ETH67, SnapSync) }
func TestForkedSync67Light(t *testing.T) { testForkedSync(t, eth.ETH67, LightSync) }
@@ -576,9 +576,9 @@ func testForkedSync(t *testing.T, protocol uint, mode SyncMode) {
// Tests that synchronising against a much shorter but much heavier fork works
// currently and is not dropped.
-func TestHeavyForkedSync66Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH66, FullSync) }
-func TestHeavyForkedSync66Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH66, SnapSync) }
-func TestHeavyForkedSync66Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH66, LightSync) }
+func TestHeavyForkedSync68Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, FullSync) }
+func TestHeavyForkedSync68Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, SnapSync) }
+func TestHeavyForkedSync68Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, LightSync) }
func TestHeavyForkedSync67Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, FullSync) }
func TestHeavyForkedSync67Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, SnapSync) }
func TestHeavyForkedSync67Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, LightSync) }
@@ -608,9 +608,9 @@ func testHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
// Tests that chain forks are contained within a certain interval of the current
// chain head, ensuring that malicious peers cannot waste resources by feeding
// long dead chains.
-func TestBoundedForkedSync66Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH66, FullSync) }
-func TestBoundedForkedSync66Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH66, SnapSync) }
-func TestBoundedForkedSync66Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH66, LightSync) }
+func TestBoundedForkedSync68Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, FullSync) }
+func TestBoundedForkedSync68Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, SnapSync) }
+func TestBoundedForkedSync68Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, LightSync) }
func TestBoundedForkedSync67Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, FullSync) }
func TestBoundedForkedSync67Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, SnapSync) }
func TestBoundedForkedSync67Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, LightSync) }
@@ -639,14 +639,14 @@ func testBoundedForkedSync(t *testing.T, protocol uint, mode SyncMode) {
// Tests that chain forks are contained within a certain interval of the current
// chain head for short but heavy forks too. These are a bit special because they
// take different ancestor lookup paths.
-func TestBoundedHeavyForkedSync66Full(t *testing.T) {
- testBoundedHeavyForkedSync(t, eth.ETH66, FullSync)
+func TestBoundedHeavyForkedSync68Full(t *testing.T) {
+ testBoundedHeavyForkedSync(t, eth.ETH68, FullSync)
}
-func TestBoundedHeavyForkedSync66Snap(t *testing.T) {
- testBoundedHeavyForkedSync(t, eth.ETH66, SnapSync)
+func TestBoundedHeavyForkedSync68Snap(t *testing.T) {
+ testBoundedHeavyForkedSync(t, eth.ETH68, SnapSync)
}
-func TestBoundedHeavyForkedSync66Light(t *testing.T) {
- testBoundedHeavyForkedSync(t, eth.ETH66, LightSync)
+func TestBoundedHeavyForkedSync68Light(t *testing.T) {
+ testBoundedHeavyForkedSync(t, eth.ETH68, LightSync)
}
func TestBoundedHeavyForkedSync67Full(t *testing.T) {
testBoundedHeavyForkedSync(t, eth.ETH67, FullSync)
@@ -681,9 +681,9 @@ func testBoundedHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
}
// Tests that a canceled download wipes all previously accumulated state.
-func TestCancel66Full(t *testing.T) { testCancel(t, eth.ETH66, FullSync) }
-func TestCancel66Snap(t *testing.T) { testCancel(t, eth.ETH66, SnapSync) }
-func TestCancel66Light(t *testing.T) { testCancel(t, eth.ETH66, LightSync) }
+func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) }
+func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) }
+func TestCancel68Light(t *testing.T) { testCancel(t, eth.ETH68, LightSync) }
func TestCancel67Full(t *testing.T) { testCancel(t, eth.ETH67, FullSync) }
func TestCancel67Snap(t *testing.T) { testCancel(t, eth.ETH67, SnapSync) }
func TestCancel67Light(t *testing.T) { testCancel(t, eth.ETH67, LightSync) }
@@ -711,9 +711,9 @@ func testCancel(t *testing.T, protocol uint, mode SyncMode) {
}
// Tests that synchronisation from multiple peers works as intended (multi thread sanity test).
-func TestMultiSynchronisation66Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH66, FullSync) }
-func TestMultiSynchronisation66Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH66, SnapSync) }
-func TestMultiSynchronisation66Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH66, LightSync) }
+func TestMultiSynchronisation68Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, FullSync) }
+func TestMultiSynchronisation68Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, SnapSync) }
+func TestMultiSynchronisation68Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, LightSync) }
func TestMultiSynchronisation67Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, FullSync) }
func TestMultiSynchronisation67Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, SnapSync) }
func TestMultiSynchronisation67Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, LightSync) }
@@ -738,9 +738,9 @@ func testMultiSynchronisation(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 TestMultiProtoSynchronisation66Full(t *testing.T) { testMultiProtoSync(t, eth.ETH66, FullSync) }
-func TestMultiProtoSynchronisation66Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH66, SnapSync) }
-func TestMultiProtoSynchronisation66Light(t *testing.T) { testMultiProtoSync(t, eth.ETH66, LightSync) }
+func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) }
+func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) }
+func TestMultiProtoSynchronisation68Light(t *testing.T) { testMultiProtoSync(t, eth.ETH68, LightSync) }
func TestMultiProtoSynchronisation67Full(t *testing.T) { testMultiProtoSync(t, eth.ETH67, FullSync) }
func TestMultiProtoSynchronisation67Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH67, SnapSync) }
func TestMultiProtoSynchronisation67Light(t *testing.T) { testMultiProtoSync(t, eth.ETH67, LightSync) }
@@ -753,7 +753,7 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
chain := testChainBase.shorten(blockCacheMaxItems - 15)
// Create peers of every type
- tester.newPeer("peer 66", eth.ETH66, chain.blocks[1:])
+ tester.newPeer("peer 68", eth.ETH68, chain.blocks[1:])
tester.newPeer("peer 67", eth.ETH67, chain.blocks[1:])
// Synchronise with the requested peer and make sure all blocks were retrieved
@@ -763,7 +763,7 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
assertOwnChain(t, tester, len(chain.blocks))
// Check that no peers have been dropped off
- for _, version := range []int{66, 67} {
+ for _, version := range []int{68, 67} {
peer := fmt.Sprintf("peer %d", version)
if _, ok := tester.peers[peer]; !ok {
t.Errorf("%s dropped", peer)
@@ -773,9 +773,9 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
// 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 TestEmptyShortCircuit66Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH66, FullSync) }
-func TestEmptyShortCircuit66Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH66, SnapSync) }
-func TestEmptyShortCircuit66Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH66, LightSync) }
+func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) }
+func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) }
+func TestEmptyShortCircuit68Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, LightSync) }
func TestEmptyShortCircuit67Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, FullSync) }
func TestEmptyShortCircuit67Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, SnapSync) }
func TestEmptyShortCircuit67Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, LightSync) }
@@ -824,9 +824,9 @@ func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
// Tests that headers are enqueued continuously, preventing malicious nodes from
// stalling the downloader by feeding gapped header chains.
-func TestMissingHeaderAttack66Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH66, FullSync) }
-func TestMissingHeaderAttack66Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH66, SnapSync) }
-func TestMissingHeaderAttack66Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH66, LightSync) }
+func TestMissingHeaderAttack68Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, FullSync) }
+func TestMissingHeaderAttack68Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, SnapSync) }
+func TestMissingHeaderAttack68Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, LightSync) }
func TestMissingHeaderAttack67Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, FullSync) }
func TestMissingHeaderAttack67Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, SnapSync) }
func TestMissingHeaderAttack67Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, LightSync) }
@@ -853,9 +853,9 @@ func testMissingHeaderAttack(t *testing.T, protocol uint, mode SyncMode) {
// Tests that if requested headers are shifted (i.e. first is missing), the queue
// detects the invalid numbering.
-func TestShiftedHeaderAttack66Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH66, FullSync) }
-func TestShiftedHeaderAttack66Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH66, SnapSync) }
-func TestShiftedHeaderAttack66Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH66, LightSync) }
+func TestShiftedHeaderAttack68Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, FullSync) }
+func TestShiftedHeaderAttack68Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, SnapSync) }
+func TestShiftedHeaderAttack68Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, LightSync) }
func TestShiftedHeaderAttack67Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, FullSync) }
func TestShiftedHeaderAttack67Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, SnapSync) }
func TestShiftedHeaderAttack67Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, LightSync) }
@@ -881,96 +881,16 @@ func testShiftedHeaderAttack(t *testing.T, protocol uint, mode SyncMode) {
assertOwnChain(t, tester, len(chain.blocks))
}
-// Tests that upon detecting an invalid header, the recent ones are rolled back
-// for various failure scenarios. Afterwards a full sync is attempted to make
-// sure no state was corrupted.
-func TestInvalidHeaderRollback66Snap(t *testing.T) { testInvalidHeaderRollback(t, eth.ETH66, SnapSync) }
-func TestInvalidHeaderRollback67Snap(t *testing.T) { testInvalidHeaderRollback(t, eth.ETH67, SnapSync) }
-
-func testInvalidHeaderRollback(t *testing.T, protocol uint, mode SyncMode) {
- tester := newTester(t)
- defer tester.terminate()
-
- // Create a small enough block chain to download
- targetBlocks := 3*fsHeaderSafetyNet + 256 + fsMinFullBlocks
- chain := testChainBase.shorten(targetBlocks)
-
- // Attempt to sync with an attacker that feeds junk during the fast sync phase.
- // This should result in the last fsHeaderSafetyNet headers being rolled back.
- missing := fsHeaderSafetyNet + MaxHeaderFetch + 1
-
- fastAttacker := tester.newPeer("fast-attack", protocol, chain.blocks[1:])
- fastAttacker.withholdHeaders[chain.blocks[missing].Hash()] = struct{}{}
-
- if err := tester.sync("fast-attack", nil, mode); err == nil {
- t.Fatalf("succeeded fast attacker synchronisation")
- }
- if head := tester.chain.CurrentHeader().Number.Int64(); int(head) > MaxHeaderFetch {
- t.Errorf("rollback head mismatch: have %v, want at most %v", head, MaxHeaderFetch)
- }
- // Attempt to sync with an attacker that feeds junk during the block import phase.
- // This should result in both the last fsHeaderSafetyNet number of headers being
- // rolled back, and also the pivot point being reverted to a non-block status.
- missing = 3*fsHeaderSafetyNet + MaxHeaderFetch + 1
-
- blockAttacker := tester.newPeer("block-attack", protocol, chain.blocks[1:])
- fastAttacker.withholdHeaders[chain.blocks[missing].Hash()] = struct{}{} // Make sure the fast-attacker doesn't fill in
- blockAttacker.withholdHeaders[chain.blocks[missing].Hash()] = struct{}{}
-
- if err := tester.sync("block-attack", nil, mode); err == nil {
- t.Fatalf("succeeded block attacker synchronisation")
- }
- if head := tester.chain.CurrentHeader().Number.Int64(); int(head) > 2*fsHeaderSafetyNet+MaxHeaderFetch {
- t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch)
- }
- if mode == SnapSync {
- if head := tester.chain.CurrentBlock().Number.Uint64(); head != 0 {
- t.Errorf("fast sync pivot block #%d not rolled back", head)
- }
- }
- // Attempt to sync with an attacker that withholds promised blocks after the
- // fast sync pivot point. This could be a trial to leave the node with a bad
- // but already imported pivot block.
- withholdAttacker := tester.newPeer("withhold-attack", protocol, chain.blocks[1:])
-
- tester.downloader.syncInitHook = func(uint64, uint64) {
- for i := missing; i < len(chain.blocks); i++ {
- withholdAttacker.withholdHeaders[chain.blocks[i].Hash()] = struct{}{}
- }
- tester.downloader.syncInitHook = nil
- }
- if err := tester.sync("withhold-attack", nil, mode); err == nil {
- t.Fatalf("succeeded withholding attacker synchronisation")
- }
- if head := tester.chain.CurrentHeader().Number.Int64(); int(head) > 2*fsHeaderSafetyNet+MaxHeaderFetch {
- t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch)
- }
- if mode == SnapSync {
- if head := tester.chain.CurrentBlock().Number.Uint64(); head != 0 {
- t.Errorf("fast sync pivot block #%d not rolled back", head)
- }
- }
- // Synchronise with the valid peer and make sure sync succeeds. Since the last rollback
- // should also disable fast syncing for this process, verify that we did a fresh full
- // sync. Note, we can't assert anything about the receipts since we won't purge the
- // database of them, hence we can't use assertOwnChain.
- tester.newPeer("valid", protocol, chain.blocks[1:])
- if err := tester.sync("valid", nil, mode); err != nil {
- t.Fatalf("failed to synchronise blocks: %v", err)
- }
- assertOwnChain(t, tester, len(chain.blocks))
-}
-
// Tests that a peer advertising a high TD doesn't get to stall the downloader
// afterwards by not sending any useful hashes.
-func TestHighTDStarvationAttack66Full(t *testing.T) {
- testHighTDStarvationAttack(t, eth.ETH66, FullSync)
+func TestHighTDStarvationAttack68Full(t *testing.T) {
+ testHighTDStarvationAttack(t, eth.ETH68, FullSync)
}
-func TestHighTDStarvationAttack66Snap(t *testing.T) {
- testHighTDStarvationAttack(t, eth.ETH66, SnapSync)
+func TestHighTDStarvationAttack68Snap(t *testing.T) {
+ testHighTDStarvationAttack(t, eth.ETH68, SnapSync)
}
-func TestHighTDStarvationAttack66Light(t *testing.T) {
- testHighTDStarvationAttack(t, eth.ETH66, LightSync)
+func TestHighTDStarvationAttack68Light(t *testing.T) {
+ testHighTDStarvationAttack(t, eth.ETH68, LightSync)
}
func TestHighTDStarvationAttack67Full(t *testing.T) {
testHighTDStarvationAttack(t, eth.ETH67, FullSync)
@@ -994,7 +914,7 @@ func testHighTDStarvationAttack(t *testing.T, protocol uint, mode SyncMode) {
}
// Tests that misbehaving peers are disconnected, whilst behaving ones are not.
-func TestBlockHeaderAttackerDropping66(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH66) }
+func TestBlockHeaderAttackerDropping68(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH68) }
func TestBlockHeaderAttackerDropping67(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH67) }
func testBlockHeaderAttackerDropping(t *testing.T, protocol uint) {
@@ -1043,9 +963,9 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol uint) {
// Tests that synchronisation progress (origin block number, current block number
// and highest block number) is tracked and updated correctly.
-func TestSyncProgress66Full(t *testing.T) { testSyncProgress(t, eth.ETH66, FullSync) }
-func TestSyncProgress66Snap(t *testing.T) { testSyncProgress(t, eth.ETH66, SnapSync) }
-func TestSyncProgress66Light(t *testing.T) { testSyncProgress(t, eth.ETH66, LightSync) }
+func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) }
+func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) }
+func TestSyncProgress68Light(t *testing.T) { testSyncProgress(t, eth.ETH68, LightSync) }
func TestSyncProgress67Full(t *testing.T) { testSyncProgress(t, eth.ETH67, FullSync) }
func TestSyncProgress67Snap(t *testing.T) { testSyncProgress(t, eth.ETH67, SnapSync) }
func TestSyncProgress67Light(t *testing.T) { testSyncProgress(t, eth.ETH67, LightSync) }
@@ -1123,9 +1043,9 @@ func checkProgress(t *testing.T, d *Downloader, stage string, want ethereum.Sync
// Tests that synchronisation progress (origin block number and highest block
// number) is tracked and updated correctly in case of a fork (or manual head
// revertal).
-func TestForkedSyncProgress66Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH66, FullSync) }
-func TestForkedSyncProgress66Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH66, SnapSync) }
-func TestForkedSyncProgress66Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH66, LightSync) }
+func TestForkedSyncProgress68Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, FullSync) }
+func TestForkedSyncProgress68Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, SnapSync) }
+func TestForkedSyncProgress68Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, LightSync) }
func TestForkedSyncProgress67Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, FullSync) }
func TestForkedSyncProgress67Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, SnapSync) }
func TestForkedSyncProgress67Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, LightSync) }
@@ -1197,9 +1117,9 @@ func testForkedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
// Tests that if synchronisation is aborted due to some failure, then the progress
// origin is not updated in the next sync cycle, as it should be considered the
// continuation of the previous sync and not a new instance.
-func TestFailedSyncProgress66Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH66, FullSync) }
-func TestFailedSyncProgress66Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH66, SnapSync) }
-func TestFailedSyncProgress66Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH66, LightSync) }
+func TestFailedSyncProgress68Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, FullSync) }
+func TestFailedSyncProgress68Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, SnapSync) }
+func TestFailedSyncProgress68Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, LightSync) }
func TestFailedSyncProgress67Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, FullSync) }
func TestFailedSyncProgress67Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, SnapSync) }
func TestFailedSyncProgress67Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, LightSync) }
@@ -1266,9 +1186,9 @@ func testFailedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
// Tests that if an attacker fakes a chain height, after the attack is detected,
// the progress height is successfully reduced at the next sync invocation.
-func TestFakedSyncProgress66Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH66, FullSync) }
-func TestFakedSyncProgress66Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH66, SnapSync) }
-func TestFakedSyncProgress66Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH66, LightSync) }
+func TestFakedSyncProgress68Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, FullSync) }
+func TestFakedSyncProgress68Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, SnapSync) }
+func TestFakedSyncProgress68Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, LightSync) }
func TestFakedSyncProgress67Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, FullSync) }
func TestFakedSyncProgress67Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, SnapSync) }
func TestFakedSyncProgress67Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, LightSync) }
@@ -1431,11 +1351,13 @@ func TestRemoteHeaderRequestSpan(t *testing.T) {
/*
// Tests that peers below a pre-configured checkpoint block are prevented from
// being fast-synced from, avoiding potential cheap eclipse attacks.
-func TestBeaconSync66Full(t *testing.T) { testBeaconSync(t, eth.ETH66, FullSync) }
-func TestBeaconSync66Snap(t *testing.T) { testBeaconSync(t, eth.ETH66, SnapSync) }
+func TestBeaconSync68Full(t *testing.T) { testBeaconSync(t, eth.ETH68, FullSync) }
+func TestBeaconSync68Snap(t *testing.T) { testBeaconSync(t, eth.ETH68, SnapSync) }
+func TestBeaconSync67Full(t *testing.T) { testBeaconSync(t, eth.ETH67, FullSync) }
+func TestBeaconSync67Snap(t *testing.T) { testBeaconSync(t, eth.ETH67, SnapSync) }
func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) {
- //log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
var cases = []struct {
name string // The name of testing scenario
diff --git a/eth/downloader/fetchers.go b/eth/downloader/fetchers.go
index 021e8c4f9b..cc4279b0da 100644
--- a/eth/downloader/fetchers.go
+++ b/eth/downloader/fetchers.go
@@ -58,14 +58,14 @@ func (d *Downloader) fetchHeadersByHash(p *peerConnection, hash common.Hash, amo
case res := <-resCh:
// Headers successfully retrieved, update the metrics
headerReqTimer.Update(time.Since(start))
- headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersPacket))))
+ headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersRequest))))
// Don't reject the packet even if it turns out to be bad, downloader will
// disconnect the peer on its own terms. Simply delivery the headers to
// be processed by the caller
res.Done <- nil
- return *res.Res.(*eth.BlockHeadersPacket), res.Meta.([]common.Hash), nil
+ return *res.Res.(*eth.BlockHeadersRequest), res.Meta.([]common.Hash), nil
}
}
@@ -103,13 +103,13 @@ func (d *Downloader) fetchHeadersByNumber(p *peerConnection, number uint64, amou
case res := <-resCh:
// Headers successfully retrieved, update the metrics
headerReqTimer.Update(time.Since(start))
- headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersPacket))))
+ headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersRequest))))
// Don't reject the packet even if it turns out to be bad, downloader will
// disconnect the peer on its own terms. Simply delivery the headers to
// be processed by the caller
res.Done <- nil
- return *res.Res.(*eth.BlockHeadersPacket), res.Meta.([]common.Hash), nil
+ return *res.Res.(*eth.BlockHeadersRequest), res.Meta.([]common.Hash), nil
}
}
diff --git a/eth/downloader/fetchers_concurrent_bodies.go b/eth/downloader/fetchers_concurrent_bodies.go
index 9440972c6d..5105fda66b 100644
--- a/eth/downloader/fetchers_concurrent_bodies.go
+++ b/eth/downloader/fetchers_concurrent_bodies.go
@@ -89,7 +89,7 @@ func (q *bodyQueue) request(peer *peerConnection, req *fetchRequest, resCh chan
// deliver is responsible for taking a generic response packet from the concurrent
// fetcher, unpacking the body data and delivering it to the downloader's queue.
func (q *bodyQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) {
- txs, uncles, withdrawals := packet.Res.(*eth.BlockBodiesPacket).Unpack()
+ txs, uncles, withdrawals := packet.Res.(*eth.BlockBodiesResponse).Unpack()
hashsets := packet.Meta.([][]common.Hash) // {txs hashes, uncle hashes, withdrawal hashes}
accepted, err := q.queue.DeliverBodies(peer.id, txs, hashsets[0], uncles, hashsets[1], withdrawals, hashsets[2])
diff --git a/eth/downloader/fetchers_concurrent_headers.go b/eth/downloader/fetchers_concurrent_headers.go
index 84c7f20986..8201f4ca74 100644
--- a/eth/downloader/fetchers_concurrent_headers.go
+++ b/eth/downloader/fetchers_concurrent_headers.go
@@ -81,7 +81,7 @@ func (q *headerQueue) request(peer *peerConnection, req *fetchRequest, resCh cha
// deliver is responsible for taking a generic response packet from the concurrent
// fetcher, unpacking the header data and delivering it to the downloader's queue.
func (q *headerQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) {
- headers := *packet.Res.(*eth.BlockHeadersPacket)
+ headers := *packet.Res.(*eth.BlockHeadersRequest)
hashes := packet.Meta.([]common.Hash)
accepted, err := q.queue.DeliverHeaders(peer.id, headers, hashes, q.headerProcCh)
diff --git a/eth/downloader/fetchers_concurrent_receipts.go b/eth/downloader/fetchers_concurrent_receipts.go
index 1c853c2184..3169f030ba 100644
--- a/eth/downloader/fetchers_concurrent_receipts.go
+++ b/eth/downloader/fetchers_concurrent_receipts.go
@@ -88,7 +88,7 @@ func (q *receiptQueue) request(peer *peerConnection, req *fetchRequest, resCh ch
// deliver is responsible for taking a generic response packet from the concurrent
// fetcher, unpacking the receipt data and delivering it to the downloader's queue.
func (q *receiptQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) {
- receipts := *packet.Res.(*eth.ReceiptsPacket)
+ receipts := *packet.Res.(*eth.ReceiptsResponse)
hashes := packet.Meta.([]common.Hash) // {receipt hashes}
accepted, err := q.queue.DeliverReceipts(peer.id, receipts, hashes)
diff --git a/eth/downloader/peer.go b/eth/downloader/peer.go
index ed57abc7a0..2184cef159 100644
--- a/eth/downloader/peer.go
+++ b/eth/downloader/peer.go
@@ -55,41 +55,17 @@ type peerConnection struct {
lock sync.RWMutex
}
-// LightPeer encapsulates the methods required to synchronise with a remote light peer.
-type LightPeer interface {
+// Peer encapsulates the methods required to synchronise with a remote full peer.
+type Peer interface {
Head() (common.Hash, *big.Int)
MarkLagging()
RequestHeadersByHash(common.Hash, int, int, bool, chan *eth.Response) (*eth.Request, error)
RequestHeadersByNumber(uint64, int, int, bool, chan *eth.Response) (*eth.Request, error)
-}
-// Peer encapsulates the methods required to synchronise with a remote full peer.
-type Peer interface {
- LightPeer
RequestBodies([]common.Hash, chan *eth.Response) (*eth.Request, error)
RequestReceipts([]common.Hash, chan *eth.Response) (*eth.Request, error)
}
-// lightPeerWrapper wraps a LightPeer struct, stubbing out the Peer-only methods.
-type lightPeerWrapper struct {
- peer LightPeer
-}
-
-func (w *lightPeerWrapper) Head() (common.Hash, *big.Int) { return w.peer.Head() }
-func (w *lightPeerWrapper) MarkLagging() { w.peer.MarkLagging() }
-func (w *lightPeerWrapper) RequestHeadersByHash(h common.Hash, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) {
- return w.peer.RequestHeadersByHash(h, amount, skip, reverse, sink)
-}
-func (w *lightPeerWrapper) RequestHeadersByNumber(i uint64, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) {
- return w.peer.RequestHeadersByNumber(i, amount, skip, reverse, sink)
-}
-func (w *lightPeerWrapper) RequestBodies([]common.Hash, chan *eth.Response) (*eth.Request, error) {
- panic("RequestBodies not supported in light client mode sync")
-}
-func (w *lightPeerWrapper) RequestReceipts([]common.Hash, chan *eth.Response) (*eth.Request, error) {
- panic("RequestReceipts not supported in light client mode sync")
-}
-
// newPeerConnection creates a new downloader peer.
func newPeerConnection(id string, version uint, peer Peer, logger log.Logger) *peerConnection {
return &peerConnection{
diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go
index 7a9f0da2d4..07c0e79d3a 100644
--- a/eth/downloader/queue.go
+++ b/eth/downloader/queue.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
@@ -800,7 +801,7 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
}
}
// Blocks must have a number of blobs corresponding to the header gas usage,
- // and zero before the Cancun hardfork
+ // and zero before the Cancun hardfork.
var blobs int
for _, tx := range txLists[index] {
// Count the number of blobs to validate against the header's blobGasUsed
@@ -812,10 +813,13 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
return errInvalidBody
}
for _, hash := range tx.BlobHashes() {
- if hash[0] != params.BlobTxHashVersion {
+ if !kzg4844.IsValidVersionedHash(hash[:]) {
return errInvalidBody
}
}
+ if tx.BlobTxSidecar() != nil {
+ return errInvalidBody
+ }
}
}
if header.BlobGasUsed != nil {
diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go
index a8b1b45e00..50b9031a27 100644
--- a/eth/downloader/queue_test.go
+++ b/eth/downloader/queue_test.go
@@ -20,6 +20,7 @@ import (
"fmt"
"math/big"
"math/rand"
+ "os"
"sync"
"testing"
"time"
@@ -31,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
+ "golang.org/x/exp/slog"
)
// makeChain creates a chain of n blocks starting at and including parent.
@@ -271,7 +273,7 @@ func XTestDelivery(t *testing.T) {
world.chain = blo
world.progress(10)
if false {
- log.Root().SetHandler(log.StdoutHandler)
+ log.SetDefault(log.NewLogger(slog.NewTextHandler(os.Stdout, nil)))
}
q := newQueue(10, 10)
var wg sync.WaitGroup
diff --git a/eth/downloader/resultstore.go b/eth/downloader/resultstore.go
index d33ee0a1fa..471a5c3f68 100644
--- a/eth/downloader/resultstore.go
+++ b/eth/downloader/resultstore.go
@@ -142,7 +142,7 @@ func (r *resultStore) HasCompletedItems() bool {
// countCompleted returns the number of items ready for delivery, stopping at
// the first non-complete item.
//
-// The mthod assumes (at least) rlock is held.
+// The method assumes (at least) rlock is held.
func (r *resultStore) countCompleted() int {
// We iterate from the already known complete point, and see
// if any more has completed since last count
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index 2742d33b44..7184f2dbe9 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -50,7 +50,7 @@ var FullNodeGPO = gasprice.Config{
// Defaults contains default settings for use on the BSC main net.
var Defaults = Config{
SyncMode: downloader.SnapSync,
- NetworkId: 56,
+ NetworkId: 0, // enable auto configuration of networkID == chainID
TxLookupLimit: 2350000,
TransactionHistory: 2350000,
StateHistory: params.FullImmutabilityThreshold,
@@ -75,14 +75,15 @@ var Defaults = Config{
//go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go
-// Config contains configuration options for of the ETH and LES protocols.
+// Config contains configuration options for ETH and LES protocols.
type Config struct {
// The genesis block, which is inserted if the database is empty.
// If nil, the Ethereum main net block is used.
Genesis *core.Genesis `toml:",omitempty"`
- // Protocol options
- NetworkId uint64 // Network ID to use for selecting peers to connect to
+ // Network ID separates blockchains on the peer-to-peer networking level. When left
+ // zero, the chain ID is used as network ID.
+ NetworkId uint64
SyncMode downloader.SyncMode
// DisablePeerTxBroadcast is an optional config and disabled by default, and usually you do not need it.
@@ -112,12 +113,11 @@ type Config struct {
TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved.
TransactionHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved.
StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved.
- PathSyncFlush bool `toml:",omitempty"` // State scheme used to store ethereum state and merkle trie nodes on top
-
// State scheme represents the scheme used to store ethereum states and trie
// nodes on top. It can be 'hash', 'path', or none which means use the scheme
// consistent with persistent state.
- StateScheme string `toml:",omitempty"`
+ StateScheme string `toml:",omitempty"` // State scheme used to store ethereum state and merkle trie nodes on top
+ PathSyncFlush bool `toml:",omitempty"` // State scheme used to store ethereum state and merkle trie nodes on top
// RequiredBlocks is a set of block number -> hash mappings which must be in the
// canonical chain of all remote peers. Setting the option makes geth verify the
@@ -197,6 +197,9 @@ type Config struct {
// OverrideVerkle (TODO: remove after the fork)
OverrideVerkle *uint64 `toml:",omitempty"`
+
+ // OverrideFeynman (TODO: remove after the fork)
+ OverrideFeynman *uint64 `toml:",omitempty"`
}
// CreateConsensusEngine creates a consensus engine for the given chain config.
@@ -211,7 +214,7 @@ func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database, ee *et
return clique.New(config.Clique, db), nil
}
// If defaulting to proof-of-work, enforce an already merged network since
- // we cannot run PoW algorithms and more, so we cannot even follow a chain
+ // we cannot run PoW algorithms anymore, so we cannot even follow a chain
// not coordinated by a beacon node.
if !config.TerminalTotalDifficultyPassed {
return nil, errors.New("ethash is only supported as a historical component of already merged networks")
diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go
index b2879cd25f..c574b80498 100644
--- a/eth/fetcher/block_fetcher.go
+++ b/eth/fetcher/block_fetcher.go
@@ -518,7 +518,7 @@ func (f *BlockFetcher) loop() {
select {
case res := <-resCh:
res.Done <- nil
- f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersPacket), time.Now().Add(res.Time))
+ f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersRequest), time.Now())
case <-timeout.C:
// The peer didn't respond in time. The request
@@ -576,7 +576,7 @@ func (f *BlockFetcher) loop() {
case res := <-resCh:
res.Done <- nil
// Ignoring withdrawals here, since the block fetcher is not used post-merge.
- txs, uncles, _ := res.Res.(*eth.BlockBodiesPacket).Unpack()
+ txs, uncles, _ := res.Res.(*eth.BlockBodiesResponse).Unpack()
f.FilterBodies(peer, txs, uncles, time.Now())
case <-timeout.C:
diff --git a/eth/fetcher/block_fetcher_test.go b/eth/fetcher/block_fetcher_test.go
index bc0f308c0e..fc0b2db8d7 100644
--- a/eth/fetcher/block_fetcher_test.go
+++ b/eth/fetcher/block_fetcher_test.go
@@ -227,7 +227,7 @@ func (f *fetcherTester) makeHeaderFetcher(peer string, blocks map[common.Hash]*t
}
res := ð.Response{
Req: req,
- Res: (*eth.BlockHeadersPacket)(&headers),
+ Res: (*eth.BlockHeadersRequest)(&headers),
Time: drift,
Done: make(chan error, 1), // Ignore the returned status
}
@@ -269,7 +269,7 @@ func (f *fetcherTester) makeBodyFetcher(peer string, blocks map[common.Hash]*typ
}
res := ð.Response{
Req: req,
- Res: (*eth.BlockBodiesPacket)(&bodies),
+ Res: (*eth.BlockBodiesResponse)(&bodies),
Time: drift,
Done: make(chan error, 1), // Ignore the returned status
}
diff --git a/eth/fetcher/tx_fetcher.go b/eth/fetcher/tx_fetcher.go
index 5f1077ffad..de472c99e8 100644
--- a/eth/fetcher/tx_fetcher.go
+++ b/eth/fetcher/tx_fetcher.go
@@ -20,6 +20,7 @@ import (
"bytes"
"errors"
"fmt"
+ "math"
mrand "math/rand"
"sort"
"time"
@@ -39,23 +40,29 @@ const (
// can announce in a short time.
maxTxAnnounces = 4096
- // maxTxRetrievals is the maximum transaction number can be fetched in one
- // request. The rationale to pick 256 is:
- // - In eth protocol, the softResponseLimit is 2MB. Nowadays according to
- // Etherscan the average transaction size is around 200B, so in theory
- // we can include lots of transaction in a single protocol packet.
- // - However the maximum size of a single transaction is raised to 128KB,
- // so pick a middle value here to ensure we can maximize the efficiency
- // of the retrieval and response size overflow won't happen in most cases.
+ // maxTxRetrievals is the maximum number of transactions that can be fetched
+ // in one request. The rationale for picking 256 is to have a reasonabe lower
+ // bound for the transferred data (don't waste RTTs, transfer more meaningful
+ // batch sizes), but also have an upper bound on the sequentiality to allow
+ // using our entire peerset for deliveries.
+ //
+ // This number also acts as a failsafe against malicious announces which might
+ // cause us to request more data than we'd expect.
maxTxRetrievals = 256
+ // maxTxRetrievalSize is the max number of bytes that delivered transactions
+ // should weigh according to the announcements. The 128KB was chosen to limit
+ // retrieving a maximum of one blob transaction at a time to minimize hogging
+ // a connection between two peers.
+ maxTxRetrievalSize = 128 * 1024
+
// maxTxUnderpricedSetSize is the size of the underpriced transaction set that
// is used to track recent transactions that have been dropped so we don't
// re-request them.
maxTxUnderpricedSetSize = 32768
// maxTxUnderpricedTimeout is the max time a transaction should be stuck in the underpriced set.
- maxTxUnderpricedTimeout = int64(5 * time.Minute)
+ maxTxUnderpricedTimeout = 5 * time.Minute
// txArriveTimeout is the time allowance before an announced transaction is
// explicitly requested.
@@ -106,6 +113,14 @@ var (
type txAnnounce struct {
origin string // Identifier of the peer originating the notification
hashes []common.Hash // Batch of transaction hashes being announced
+ metas []*txMetadata // Batch of metadatas associated with the hashes (nil before eth/68)
+}
+
+// txMetadata is a set of extra data transmitted along the announcement for better
+// fetch scheduling.
+type txMetadata struct {
+ kind byte // Transaction consensus type
+ size uint32 // Transaction size in bytes
}
// txRequest represents an in-flight transaction retrieval request destined to
@@ -121,6 +136,7 @@ type txRequest struct {
type txDelivery struct {
origin string // Identifier of the peer originating the notification
hashes []common.Hash // Batch of transaction hashes having been delivered
+ metas []txMetadata // Batch of metadatas associated with the delivered hashes
direct bool // Whether this is a direct reply or a broadcast
}
@@ -152,18 +168,18 @@ type TxFetcher struct {
drop chan *txDrop
quit chan struct{}
- underpriced *lru.Cache[common.Hash, int64] // Transactions discarded as too cheap (don't re-fetch)
+ underpriced *lru.Cache[common.Hash, time.Time] // Transactions discarded as too cheap (don't re-fetch)
// 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
- waittime map[common.Hash]mclock.AbsTime // Timestamps when transactions were added to the waitlist
- waitslots map[string]map[common.Hash]struct{} // Waiting announcements grouped by peer (DoS protection)
+ waitlist map[common.Hash]map[string]struct{} // Transactions waiting for an potential broadcast
+ waittime map[common.Hash]mclock.AbsTime // Timestamps when transactions were added to the waitlist
+ waitslots map[string]map[common.Hash]*txMetadata // Waiting announcements grouped by peer (DoS protection)
// Stage 2: Queue of transactions that waiting to be allocated to some peer
// to be retrieved directly.
- announces map[string]map[common.Hash]struct{} // Set of announced transactions, grouped by origin peer
- announced map[common.Hash]map[string]struct{} // Set of download locations, grouped by transaction hash
+ announces map[string]map[common.Hash]*txMetadata // Set of announced transactions, grouped by origin peer
+ announced map[common.Hash]map[string]struct{} // Set of download locations, grouped by transaction hash
// Stage 3: Set of transactions currently being retrieved, some which may be
// fulfilled and some rescheduled. Note, this step shares 'announces' from the
@@ -173,9 +189,10 @@ type TxFetcher struct {
alternates map[common.Hash]map[string]struct{} // In-flight transaction alternate origins if retrieval fails
// Callbacks
- hasTx func(common.Hash) bool // Retrieves a tx from the local txpool
- addTxs func(string, []*txpool.Transaction) []error // Insert a batch of transactions into local txpool
- fetchTxs func(string, []common.Hash) error // Retrieves a set of txs from a remote peer
+ hasTx func(common.Hash) bool // Retrieves a tx from the local txpool
+ addTxs func(string, []*types.Transaction) []error // Insert a batch of transactions into local txpool
+ fetchTxs func(string, []common.Hash) error // Retrieves a set of txs from a remote peer
+ dropPeer func(string) // Drops a peer in case of announcement violation
step chan struct{} // Notification channel when the fetcher loop iterates
clock mclock.Clock // Time wrapper to simulate in tests
@@ -184,14 +201,14 @@ type TxFetcher struct {
// NewTxFetcher creates a transaction fetcher to retrieve transaction
// based on hash announcements.
-func NewTxFetcher(hasTx func(common.Hash) bool, addTxs func(string, []*txpool.Transaction) []error, fetchTxs func(string, []common.Hash) error) *TxFetcher {
- return NewTxFetcherForTests(hasTx, addTxs, fetchTxs, mclock.System{}, nil)
+func NewTxFetcher(hasTx func(common.Hash) bool, addTxs func(string, []*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string)) *TxFetcher {
+ return NewTxFetcherForTests(hasTx, addTxs, fetchTxs, dropPeer, mclock.System{}, nil)
}
// NewTxFetcherForTests is a testing method to mock out the realtime clock with
// a simulated version and the internal randomness with a deterministic one.
func NewTxFetcherForTests(
- hasTx func(common.Hash) bool, addTxs func(string, []*txpool.Transaction) []error, fetchTxs func(string, []common.Hash) error,
+ hasTx func(common.Hash) bool, addTxs func(string, []*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string),
clock mclock.Clock, rand *mrand.Rand) *TxFetcher {
return &TxFetcher{
notify: make(chan *txAnnounce),
@@ -200,16 +217,17 @@ func NewTxFetcherForTests(
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]struct{}),
- announces: make(map[string]map[common.Hash]struct{}),
+ waitslots: make(map[string]map[common.Hash]*txMetadata),
+ announces: make(map[string]map[common.Hash]*txMetadata),
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, int64](maxTxUnderpricedSetSize),
+ underpriced: lru.NewCache[common.Hash, time.Time](maxTxUnderpricedSetSize),
hasTx: hasTx,
addTxs: addTxs,
fetchTxs: fetchTxs,
+ dropPeer: dropPeer,
clock: clock,
rand: rand,
}
@@ -217,7 +235,7 @@ func NewTxFetcherForTests(
// Notify announces the fetcher of the potential availability of a new batch of
// transactions in the network.
-func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error {
+func (f *TxFetcher) Notify(peer string, types []byte, sizes []uint32, hashes []common.Hash) error {
// Keep track of all the announced transactions
txAnnounceInMeter.Mark(int64(len(hashes)))
@@ -227,28 +245,35 @@ func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error {
// still valuable to check here because it runs concurrent to the internal
// loop, so anything caught here is time saved internally.
var (
- unknowns = make([]common.Hash, 0, len(hashes))
+ unknownHashes = make([]common.Hash, 0, len(hashes))
+ unknownMetas = make([]*txMetadata, 0, len(hashes))
+
duplicate int64
underpriced int64
)
- for _, hash := range hashes {
+ for i, hash := range hashes {
switch {
case f.hasTx(hash):
duplicate++
case f.isKnownUnderpriced(hash):
underpriced++
default:
- unknowns = append(unknowns, hash)
+ unknownHashes = append(unknownHashes, hash)
+ if types == nil {
+ unknownMetas = append(unknownMetas, nil)
+ } else {
+ unknownMetas = append(unknownMetas, &txMetadata{kind: types[i], size: sizes[i]})
+ }
}
}
txAnnounceKnownMeter.Mark(duplicate)
txAnnounceUnderpricedMeter.Mark(underpriced)
// If anything's left to announce, push it into the internal loop
- if len(unknowns) == 0 {
+ if len(unknownHashes) == 0 {
return nil
}
- announce := &txAnnounce{origin: peer, hashes: unknowns}
+ announce := &txAnnounce{origin: peer, hashes: unknownHashes, metas: unknownMetas}
select {
case f.notify <- announce:
return nil
@@ -260,7 +285,7 @@ func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error {
// isKnownUnderpriced reports whether a transaction hash was recently found to be underpriced.
func (f *TxFetcher) isKnownUnderpriced(hash common.Hash) bool {
prevTime, ok := f.underpriced.Peek(hash)
- if ok && prevTime+maxTxUnderpricedTimeout < time.Now().Unix() {
+ if ok && prevTime.Before(time.Now().Add(-maxTxUnderpricedTimeout)) {
f.underpriced.Remove(hash)
return false
}
@@ -291,6 +316,7 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
// re-requesting them and dropping the peer in case of malicious transfers.
var (
added = make([]common.Hash, 0, len(txs))
+ metas = make([]txMetadata, 0, len(txs))
)
// proceed in batches
for i := 0; i < len(txs); i += 128 {
@@ -305,16 +331,12 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
)
batch := txs[i:end]
- wrapped := make([]*txpool.Transaction, len(batch))
- for j, tx := range batch {
- wrapped[j] = &txpool.Transaction{Tx: tx}
- }
- for j, err := range f.addTxs(peer, wrapped) {
+ for j, err := range f.addTxs(peer, batch) {
// Track the transaction hash if the price is too low for us.
// Avoid re-request this transaction when we receive another
// announcement.
if errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced) {
- f.underpriced.Add(batch[j].Hash(), batch[j].Time().Unix())
+ f.underpriced.Add(batch[j].Hash(), batch[j].Time())
}
// Track a few interesting failure types
switch {
@@ -330,6 +352,10 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
otherreject++
}
added = append(added, batch[j].Hash())
+ metas = append(metas, txMetadata{
+ kind: batch[j].Type(),
+ size: uint32(batch[j].Size()),
+ })
}
knownMeter.Mark(duplicate)
underpricedMeter.Mark(underpriced)
@@ -342,7 +368,7 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
}
}
select {
- case f.cleanup <- &txDelivery{origin: peer, hashes: added, direct: direct}:
+ case f.cleanup <- &txDelivery{origin: peer, hashes: added, metas: metas, direct: direct}:
return nil
case <-f.quit:
return errTerminated
@@ -399,13 +425,15 @@ func (f *TxFetcher) loop() {
want := used + len(ann.hashes)
if want > maxTxAnnounces {
txAnnounceDOSMeter.Mark(int64(want - maxTxAnnounces))
+
ann.hashes = ann.hashes[:want-maxTxAnnounces]
+ ann.metas = ann.metas[:want-maxTxAnnounces]
}
// All is well, schedule the remainder of the transactions
idleWait := len(f.waittime) == 0
_, oldPeer := f.announces[ann.origin]
- for _, hash := range ann.hashes {
+ for i, hash := range ann.hashes {
// If the transaction is already downloading, add it to the list
// of possible alternates (in case the current retrieval fails) and
// also account it for the peer.
@@ -414,9 +442,9 @@ func (f *TxFetcher) loop() {
// Stage 2 and 3 share the set of origins per tx
if announces := f.announces[ann.origin]; announces != nil {
- announces[hash] = struct{}{}
+ announces[hash] = ann.metas[i]
} else {
- f.announces[ann.origin] = map[common.Hash]struct{}{hash: {}}
+ f.announces[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]}
}
continue
}
@@ -427,9 +455,9 @@ func (f *TxFetcher) loop() {
// Stage 2 and 3 share the set of origins per tx
if announces := f.announces[ann.origin]; announces != nil {
- announces[hash] = struct{}{}
+ announces[hash] = ann.metas[i]
} else {
- f.announces[ann.origin] = map[common.Hash]struct{}{hash: {}}
+ f.announces[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]}
}
continue
}
@@ -437,12 +465,18 @@ func (f *TxFetcher) loop() {
// yet downloading, add the peer as an alternate origin in the
// waiting list.
if f.waitlist[hash] != nil {
+ // Ignore double announcements from the same peer. This is
+ // especially important if metadata is also passed along to
+ // prevent malicious peers flip-flopping good/bad values.
+ if _, ok := f.waitlist[hash][ann.origin]; ok {
+ continue
+ }
f.waitlist[hash][ann.origin] = struct{}{}
if waitslots := f.waitslots[ann.origin]; waitslots != nil {
- waitslots[hash] = struct{}{}
+ waitslots[hash] = ann.metas[i]
} else {
- f.waitslots[ann.origin] = map[common.Hash]struct{}{hash: {}}
+ f.waitslots[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]}
}
continue
}
@@ -451,9 +485,9 @@ func (f *TxFetcher) loop() {
f.waittime[hash] = f.clock.Now()
if waitslots := f.waitslots[ann.origin]; waitslots != nil {
- waitslots[hash] = struct{}{}
+ waitslots[hash] = ann.metas[i]
} else {
- f.waitslots[ann.origin] = map[common.Hash]struct{}{hash: {}}
+ f.waitslots[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]}
}
}
// If a new item was added to the waitlist, schedule it into the fetcher
@@ -479,9 +513,9 @@ func (f *TxFetcher) loop() {
f.announced[hash] = f.waitlist[hash]
for peer := range f.waitlist[hash] {
if announces := f.announces[peer]; announces != nil {
- announces[hash] = struct{}{}
+ announces[hash] = f.waitslots[peer][hash]
} else {
- f.announces[peer] = map[common.Hash]struct{}{hash: {}}
+ f.announces[peer] = map[common.Hash]*txMetadata{hash: f.waitslots[peer][hash]}
}
delete(f.waitslots[peer], hash)
if len(f.waitslots[peer]) == 0 {
@@ -550,10 +584,28 @@ func (f *TxFetcher) loop() {
case delivery := <-f.cleanup:
// Independent if the delivery was direct or broadcast, remove all
- // traces of the hash from internal trackers
- for _, hash := range delivery.hashes {
+ // traces of the hash from internal trackers. That said, compare any
+ // advertised metadata with the real ones and drop bad peers.
+ for i, hash := range delivery.hashes {
if _, ok := f.waitlist[hash]; ok {
for peer, txset := range f.waitslots {
+ if meta := txset[hash]; meta != nil {
+ if delivery.metas[i].kind != meta.kind {
+ log.Warn("Announced transaction type mismatch", "peer", peer, "tx", hash, "type", delivery.metas[i].kind, "ann", meta.kind)
+ f.dropPeer(peer)
+ } else if delivery.metas[i].size != meta.size {
+ if math.Abs(float64(delivery.metas[i].size)-float64(meta.size)) > 8 {
+ log.Warn("Announced transaction size mismatch", "peer", peer, "tx", hash, "size", delivery.metas[i].size, "ann", meta.size)
+
+ // Normally we should drop a peer considering this is a protocol violation.
+ // However, due to the RLP vs consensus format messyness, allow a few bytes
+ // wiggle-room where we only warn, but don't drop.
+ //
+ // TODO(karalabe): Get rid of this relaxation when clients are proven stable.
+ f.dropPeer(peer)
+ }
+ }
+ }
delete(txset, hash)
if len(txset) == 0 {
delete(f.waitslots, peer)
@@ -563,6 +615,23 @@ func (f *TxFetcher) loop() {
delete(f.waittime, hash)
} else {
for peer, txset := range f.announces {
+ if meta := txset[hash]; meta != nil {
+ if delivery.metas[i].kind != meta.kind {
+ log.Warn("Announced transaction type mismatch", "peer", peer, "tx", hash, "type", delivery.metas[i].kind, "ann", meta.kind)
+ f.dropPeer(peer)
+ } else if delivery.metas[i].size != meta.size {
+ if math.Abs(float64(delivery.metas[i].size)-float64(meta.size)) > 8 {
+ log.Warn("Announced transaction size mismatch", "peer", peer, "tx", hash, "size", delivery.metas[i].size, "ann", meta.size)
+
+ // Normally we should drop a peer considering this is a protocol violation.
+ // However, due to the RLP vs consensus format messyness, allow a few bytes
+ // wiggle-room where we only warn, but don't drop.
+ //
+ // TODO(karalabe): Get rid of this relaxation when clients are proven stable.
+ f.dropPeer(peer)
+ }
+ }
+ }
delete(txset, hash)
if len(txset) == 0 {
delete(f.announces, peer)
@@ -799,25 +868,36 @@ func (f *TxFetcher) scheduleFetches(timer *mclock.Timer, timeout chan struct{},
if len(f.announces[peer]) == 0 {
return // continue in the for-each
}
- hashes := make([]common.Hash, 0, maxTxRetrievals)
- f.forEachHash(f.announces[peer], func(hash common.Hash) bool {
- if _, ok := f.fetching[hash]; !ok {
- // Mark the hash as fetching and stash away possible alternates
- f.fetching[hash] = peer
-
- if _, ok := f.alternates[hash]; ok {
- panic(fmt.Sprintf("alternate tracker already contains fetching item: %v", f.alternates[hash]))
- }
- f.alternates[hash] = f.announced[hash]
- delete(f.announced, hash)
+ var (
+ hashes = make([]common.Hash, 0, maxTxRetrievals)
+ bytes uint64
+ )
+ f.forEachAnnounce(f.announces[peer], func(hash common.Hash, meta *txMetadata) bool {
+ // If the transaction is already fetching, skip to the next one
+ if _, ok := f.fetching[hash]; ok {
+ return true
+ }
+ // Mark the hash as fetching and stash away possible alternates
+ f.fetching[hash] = peer
+
+ if _, ok := f.alternates[hash]; ok {
+ panic(fmt.Sprintf("alternate tracker already contains fetching item: %v", f.alternates[hash]))
+ }
+ f.alternates[hash] = f.announced[hash]
+ delete(f.announced, hash)
- // Accumulate the hash and stop if the limit was reached
- hashes = append(hashes, hash)
- if len(hashes) >= maxTxRetrievals {
- return false // break in the for-each
+ // Accumulate the hash and stop if the limit was reached
+ hashes = append(hashes, hash)
+ if len(hashes) >= maxTxRetrievals {
+ return false // break in the for-each
+ }
+ if meta != nil { // Only set eth/68 and upwards
+ bytes += uint64(meta.size)
+ if bytes >= maxTxRetrievalSize {
+ return false
}
}
- return true // continue in the for-each
+ return true // scheduled, try to add more
})
// If any hashes were allocated, request them from the peer
if len(hashes) > 0 {
@@ -862,27 +942,28 @@ func (f *TxFetcher) forEachPeer(peers map[string]struct{}, do func(peer string))
}
}
-// forEachHash does a range loop over a map of hashes in production, but during
-// testing it does a deterministic sorted random to allow reproducing issues.
-func (f *TxFetcher) forEachHash(hashes map[common.Hash]struct{}, do func(hash common.Hash) bool) {
+// forEachAnnounce does a range loop over a map of announcements in production,
+// but during testing it does a deterministic sorted random to allow reproducing
+// issues.
+func (f *TxFetcher) forEachAnnounce(announces map[common.Hash]*txMetadata, do func(hash common.Hash, meta *txMetadata) bool) {
// If we're running production, use whatever Go's map gives us
if f.rand == nil {
- for hash := range hashes {
- if !do(hash) {
+ for hash, meta := range announces {
+ if !do(hash, meta) {
return
}
}
return
}
// We're running the test suite, make iteration deterministic
- list := make([]common.Hash, 0, len(hashes))
- for hash := range hashes {
+ list := make([]common.Hash, 0, len(announces))
+ for hash := range announces {
list = append(list, hash)
}
sortHashes(list)
rotateHashes(list, f.rand.Intn(len(list)))
for _, hash := range list {
- if !do(hash) {
+ if !do(hash, announces[hash]) {
return
}
}
diff --git a/eth/fetcher/tx_fetcher_test.go b/eth/fetcher/tx_fetcher_test.go
index c4fe5ea674..d19bf8cc22 100644
--- a/eth/fetcher/tx_fetcher_test.go
+++ b/eth/fetcher/tx_fetcher_test.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
)
var (
@@ -41,9 +42,20 @@ var (
testTxsHashes = []common.Hash{testTxs[0].Hash(), testTxs[1].Hash(), testTxs[2].Hash(), testTxs[3].Hash()}
)
+type announce struct {
+ hash common.Hash
+ kind *byte
+ size *uint32
+}
+
+func typeptr(t byte) *byte { return &t }
+func sizeptr(n uint32) *uint32 { return &n }
+
type doTxNotify struct {
peer string
hashes []common.Hash
+ types []byte
+ sizes []uint32
}
type doTxEnqueue struct {
peer string
@@ -57,7 +69,14 @@ type doWait struct {
type doDrop string
type doFunc func()
+type isWaitingWithMeta map[string][]announce
type isWaiting map[string][]common.Hash
+
+type isScheduledWithMeta struct {
+ tracking map[string][]announce
+ fetching map[string][]common.Hash
+ dangling map[string][]common.Hash
+}
type isScheduled struct {
tracking map[string][]common.Hash
fetching map[string][]common.Hash
@@ -81,6 +100,7 @@ func TestTransactionFetcherWaiting(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -162,6 +182,212 @@ func TestTransactionFetcherWaiting(t *testing.T) {
})
}
+// Tests that transaction announcements with associated metadata are added to a
+// waitlist, and none of them are scheduled for retrieval until the wait expires.
+//
+// This test is an extended version of TestTransactionFetcherWaiting. It's mostly
+// to cover the metadata checks without bloating up the basic behavioral tests
+// with all the useless extra fields.
+func TestTransactionFetcherWaitingWithMeta(t *testing.T) {
+ testTransactionFetcherParallel(t, txFetcherTest{
+ init: func() *TxFetcher {
+ return NewTxFetcher(
+ func(common.Hash) bool { return false },
+ nil,
+ func(string, []common.Hash) error { return nil },
+ nil,
+ )
+ },
+ steps: []interface{}{
+ // Initial announcement to get something into the waitlist
+ doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{111, 222}},
+ isWaitingWithMeta(map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)},
+ },
+ }),
+ // Announce from a new peer to check that no overwrite happens
+ doTxNotify{peer: "B", hashes: []common.Hash{{0x03}, {0x04}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{333, 444}},
+ isWaitingWithMeta(map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)},
+ },
+ "B": {
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ }),
+ // Announce clashing hashes but unique new peer
+ doTxNotify{peer: "C", hashes: []common.Hash{{0x01}, {0x04}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{111, 444}},
+ isWaitingWithMeta(map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)},
+ },
+ "B": {
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ "C": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ }),
+ // Announce existing and clashing hashes from existing peer. Clashes
+ // should not overwrite previous announcements.
+ doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x03}, {0x05}}, types: []byte{types.LegacyTxType, types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{999, 333, 555}},
+ isWaitingWithMeta(map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)},
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)},
+ },
+ "B": {
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ "C": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ }),
+ // Announce clashing hashes with conflicting metadata. Somebody will
+ // be in the wrong, but we don't know yet who.
+ doTxNotify{peer: "D", hashes: []common.Hash{{0x01}, {0x02}}, types: []byte{types.LegacyTxType, types.BlobTxType}, sizes: []uint32{999, 222}},
+ isWaitingWithMeta(map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)},
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)},
+ },
+ "B": {
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ "C": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ "D": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)},
+ {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)},
+ },
+ }),
+ isScheduled{tracking: nil, fetching: nil},
+
+ // Wait for the arrival timeout which should move all expired items
+ // from the wait list to the scheduler
+ doWait{time: txArriveTimeout, step: true},
+ isWaiting(nil),
+ isScheduledWithMeta{
+ tracking: map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)},
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)},
+ },
+ "B": {
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ "C": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ "D": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)},
+ {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)},
+ },
+ },
+ fetching: map[string][]common.Hash{ // Depends on deterministic test randomizer
+ "A": {{0x03}, {0x05}},
+ "C": {{0x01}, {0x04}},
+ "D": {{0x02}},
+ },
+ },
+ // Queue up a non-fetchable transaction and then trigger it with a new
+ // peer (weird case to test 1 line in the fetcher)
+ doTxNotify{peer: "C", hashes: []common.Hash{{0x06}, {0x07}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{666, 777}},
+ isWaitingWithMeta(map[string][]announce{
+ "C": {
+ {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)},
+ {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)},
+ },
+ }),
+ doWait{time: txArriveTimeout, step: true},
+ isScheduledWithMeta{
+ tracking: map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)},
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)},
+ },
+ "B": {
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ "C": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)},
+ {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)},
+ },
+ "D": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)},
+ {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)},
+ },
+ },
+ fetching: map[string][]common.Hash{
+ "A": {{0x03}, {0x05}},
+ "C": {{0x01}, {0x04}},
+ "D": {{0x02}},
+ },
+ },
+ doTxNotify{peer: "E", hashes: []common.Hash{{0x06}, {0x07}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{666, 777}},
+ isScheduledWithMeta{
+ tracking: map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)},
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)},
+ },
+ "B": {
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ },
+ "C": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)},
+ {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)},
+ {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)},
+ },
+ "D": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)},
+ {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)},
+ },
+ "E": {
+ {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)},
+ {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)},
+ },
+ },
+ fetching: map[string][]common.Hash{
+ "A": {{0x03}, {0x05}},
+ "C": {{0x01}, {0x04}},
+ "D": {{0x02}},
+ "E": {{0x06}, {0x07}},
+ },
+ },
+ },
+ })
+}
+
// Tests that transaction announcements skip the waiting list if they are
// already scheduled.
func TestTransactionFetcherSkipWaiting(t *testing.T) {
@@ -171,6 +397,7 @@ func TestTransactionFetcherSkipWaiting(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -234,6 +461,7 @@ func TestTransactionFetcherSingletonRequesting(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -313,6 +541,7 @@ func TestTransactionFetcherFailedRescheduling(t *testing.T) {
<-proceed
return errors.New("peer disconnected")
},
+ nil,
)
},
steps: []interface{}{
@@ -378,10 +607,11 @@ func TestTransactionFetcherCleanup(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -417,10 +647,11 @@ func TestTransactionFetcherCleanupEmpty(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -455,10 +686,11 @@ func TestTransactionFetcherMissingRescheduling(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -501,10 +733,11 @@ func TestTransactionFetcherMissingCleanup(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -539,10 +772,11 @@ func TestTransactionFetcherBroadcasts(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -591,6 +825,7 @@ func TestTransactionFetcherWaitTimerResets(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -644,10 +879,11 @@ func TestTransactionFetcherTimeoutRescheduling(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -713,6 +949,7 @@ func TestTransactionFetcherTimeoutTimerResets(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -757,21 +994,21 @@ func TestTransactionFetcherTimeoutTimerResets(t *testing.T) {
})
}
-// Tests that if thousands of transactions are announces, only a small
+// Tests that if thousands of transactions are announced, only a small
// number of them will be requested at a time.
func TestTransactionFetcherRateLimiting(t *testing.T) {
- // Create a slew of transactions and to announce them
+ // Create a slew of transactions and announce them
var hashes []common.Hash
for i := 0; i < maxTxAnnounces; i++ {
hashes = append(hashes, common.Hash{byte(i / 256), byte(i % 256)})
}
-
testTransactionFetcherParallel(t, txFetcherTest{
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -792,6 +1029,68 @@ func TestTransactionFetcherRateLimiting(t *testing.T) {
})
}
+// Tests that if huge transactions are announced, only a small number of them will
+// be requested at a time, to keep the responses below a reasonable level.
+func TestTransactionFetcherBandwidthLimiting(t *testing.T) {
+ testTransactionFetcherParallel(t, txFetcherTest{
+ init: func() *TxFetcher {
+ return NewTxFetcher(
+ func(common.Hash) bool { return false },
+ nil,
+ func(string, []common.Hash) error { return nil },
+ nil,
+ )
+ },
+ steps: []interface{}{
+ // Announce mid size transactions from A to verify that multiple
+ // ones can be piled into a single request.
+ doTxNotify{peer: "A",
+ hashes: []common.Hash{{0x01}, {0x02}, {0x03}, {0x04}},
+ types: []byte{types.LegacyTxType, types.LegacyTxType, types.LegacyTxType, types.LegacyTxType},
+ sizes: []uint32{48 * 1024, 48 * 1024, 48 * 1024, 48 * 1024},
+ },
+ // Announce exactly on the limit transactions to see that only one
+ // gets requested
+ doTxNotify{peer: "B",
+ hashes: []common.Hash{{0x05}, {0x06}},
+ types: []byte{types.LegacyTxType, types.LegacyTxType},
+ sizes: []uint32{maxTxRetrievalSize, maxTxRetrievalSize},
+ },
+ // Announce oversized blob transactions to see that overflows are ok
+ doTxNotify{peer: "C",
+ hashes: []common.Hash{{0x07}, {0x08}},
+ types: []byte{types.BlobTxType, types.BlobTxType},
+ sizes: []uint32{params.MaxBlobGasPerBlock, params.MaxBlobGasPerBlock},
+ },
+ doWait{time: txArriveTimeout, step: true},
+ isWaiting(nil),
+ isScheduledWithMeta{
+ tracking: map[string][]announce{
+ "A": {
+ {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)},
+ {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)},
+ {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)},
+ {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)},
+ },
+ "B": {
+ {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(maxTxRetrievalSize)},
+ {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(maxTxRetrievalSize)},
+ },
+ "C": {
+ {common.Hash{0x07}, typeptr(types.BlobTxType), sizeptr(params.MaxBlobGasPerBlock)},
+ {common.Hash{0x08}, typeptr(types.BlobTxType), sizeptr(params.MaxBlobGasPerBlock)},
+ },
+ },
+ fetching: map[string][]common.Hash{
+ "A": {{0x02}, {0x03}, {0x04}},
+ "B": {{0x06}},
+ "C": {{0x08}},
+ },
+ },
+ },
+ })
+}
+
// Tests that then number of transactions a peer is allowed to announce and/or
// request at the same time is hard capped.
func TestTransactionFetcherDoSProtection(t *testing.T) {
@@ -810,6 +1109,7 @@ func TestTransactionFetcherDoSProtection(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -865,7 +1165,7 @@ func TestTransactionFetcherUnderpricedDedup(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
errs := make([]error, len(txs))
for i := 0; i < len(errs); i++ {
if i%2 == 0 {
@@ -877,6 +1177,7 @@ func TestTransactionFetcherUnderpricedDedup(t *testing.T) {
return errs
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -938,7 +1239,7 @@ func TestTransactionFetcherUnderpricedDoSProtection(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
errs := make([]error, len(txs))
for i := 0; i < len(errs); i++ {
errs[i] = txpool.ErrUnderpriced
@@ -946,6 +1247,7 @@ func TestTransactionFetcherUnderpricedDoSProtection(t *testing.T) {
return errs
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: append(steps, []interface{}{
@@ -964,10 +1266,11 @@ func TestTransactionFetcherOutOfBoundDeliveries(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -1017,10 +1320,11 @@ func TestTransactionFetcherDrop(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -1083,10 +1387,11 @@ func TestTransactionFetcherDropRescheduling(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -1120,6 +1425,74 @@ func TestTransactionFetcherDropRescheduling(t *testing.T) {
})
}
+// Tests that announced transactions with the wrong transaction type or size will
+// result in a dropped peer.
+func TestInvalidAnnounceMetadata(t *testing.T) {
+ drop := make(chan string, 2)
+ testTransactionFetcherParallel(t, txFetcherTest{
+ init: func() *TxFetcher {
+ return NewTxFetcher(
+ func(common.Hash) bool { return false },
+ func(peer string, txs []*types.Transaction) []error {
+ return make([]error, len(txs))
+ },
+ func(string, []common.Hash) error { return nil },
+ func(peer string) { drop <- peer },
+ )
+ },
+ steps: []interface{}{
+ // Initial announcement to get something into the waitlist
+ doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}, types: []byte{testTxs[0].Type(), testTxs[1].Type()}, sizes: []uint32{uint32(testTxs[0].Size()), uint32(testTxs[1].Size())}},
+ isWaitingWithMeta(map[string][]announce{
+ "A": {
+ {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))},
+ {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))},
+ },
+ }),
+ // Announce from new peers conflicting transactions
+ doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}, types: []byte{testTxs[0].Type()}, sizes: []uint32{1024 + uint32(testTxs[0].Size())}},
+ doTxNotify{peer: "C", hashes: []common.Hash{testTxsHashes[1]}, types: []byte{1 + testTxs[1].Type()}, sizes: []uint32{uint32(testTxs[1].Size())}},
+ isWaitingWithMeta(map[string][]announce{
+ "A": {
+ {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))},
+ {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))},
+ },
+ "B": {
+ {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(1024 + uint32(testTxs[0].Size()))},
+ },
+ "C": {
+ {testTxsHashes[1], typeptr(1 + testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))},
+ },
+ }),
+ // Schedule all the transactions for retrieval
+ doWait{time: txArriveTimeout, step: true},
+ isWaitingWithMeta(nil),
+ isScheduledWithMeta{
+ tracking: map[string][]announce{
+ "A": {
+ {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))},
+ {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))},
+ },
+ "B": {
+ {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(1024 + uint32(testTxs[0].Size()))},
+ },
+ "C": {
+ {testTxsHashes[1], typeptr(1 + testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))},
+ },
+ },
+ fetching: map[string][]common.Hash{
+ "A": {testTxsHashes[0]},
+ "C": {testTxsHashes[1]},
+ },
+ },
+ // Deliver the transactions and wait for B to be dropped
+ doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1]}},
+ doFunc(func() { <-drop }),
+ doFunc(func() { <-drop }),
+ },
+ })
+}
+
// This test reproduces a crash caught by the fuzzer. The root cause was a
// dangling transaction timing out and clashing on re-add with a concurrently
// announced one.
@@ -1128,10 +1501,11 @@ func TestTransactionFetcherFuzzCrash01(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -1155,10 +1529,11 @@ func TestTransactionFetcherFuzzCrash02(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -1184,10 +1559,11 @@ func TestTransactionFetcherFuzzCrash03(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
)
},
steps: []interface{}{
@@ -1217,13 +1593,14 @@ func TestTransactionFetcherFuzzCrash04(t *testing.T) {
init: func() *TxFetcher {
return NewTxFetcher(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error {
<-proceed
return errors.New("peer disconnected")
},
+ nil,
)
},
steps: []interface{}{
@@ -1274,9 +1651,34 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
// Crunch through all the test steps and execute them
for i, step := range tt.steps {
+ // Auto-expand certain steps to ones with metadata
+ switch old := step.(type) {
+ case isWaiting:
+ new := make(isWaitingWithMeta)
+ for peer, hashes := range old {
+ for _, hash := range hashes {
+ new[peer] = append(new[peer], announce{hash, nil, nil})
+ }
+ }
+ step = new
+
+ case isScheduled:
+ new := isScheduledWithMeta{
+ tracking: make(map[string][]announce),
+ fetching: old.fetching,
+ dangling: old.dangling,
+ }
+ for peer, hashes := range old.tracking {
+ for _, hash := range hashes {
+ new.tracking[peer] = append(new.tracking[peer], announce{hash, nil, nil})
+ }
+ }
+ step = new
+ }
+ // Process the original or expanded steps
switch step := step.(type) {
case doTxNotify:
- if err := fetcher.Notify(step.peer, step.hashes); err != nil {
+ if err := fetcher.Notify(step.peer, step.types, step.sizes, step.hashes); err != nil {
t.Errorf("step %d: %v", i, err)
}
<-wait // Fetcher needs to process this, wait until it's done
@@ -1307,24 +1709,34 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
case doFunc:
step()
- case isWaiting:
+ case isWaitingWithMeta:
// We need to check that the waiting list (stage 1) internals
// match with the expected set. Check the peer->hash mappings
// first.
- for peer, hashes := range step {
+ for peer, announces := range step {
waiting := fetcher.waitslots[peer]
if waiting == nil {
t.Errorf("step %d: peer %s missing from waitslots", i, peer)
continue
}
- for _, hash := range hashes {
- if _, ok := waiting[hash]; !ok {
- t.Errorf("step %d, peer %s: hash %x missing from waitslots", i, peer, hash)
+ for _, ann := range announces {
+ if meta, ok := waiting[ann.hash]; !ok {
+ t.Errorf("step %d, peer %s: hash %x missing from waitslots", i, peer, ann.hash)
+ } else {
+ if (meta == nil && (ann.kind != nil || ann.size != nil)) ||
+ (meta != nil && (ann.kind == nil || ann.size == nil)) ||
+ (meta != nil && (meta.kind != *ann.kind || meta.size != *ann.size)) {
+ t.Errorf("step %d, peer %s, hash %x: waitslot metadata mismatch: want %v, have %v/%v", i, peer, ann.hash, meta, *ann.kind, *ann.size)
+ }
}
}
- for hash := range waiting {
- if !containsHash(hashes, hash) {
- t.Errorf("step %d, peer %s: hash %x extra in waitslots", i, peer, hash)
+ for hash, meta := range waiting {
+ ann := announce{hash: hash}
+ if meta != nil {
+ ann.kind, ann.size = &meta.kind, &meta.size
+ }
+ if !containsAnnounce(announces, ann) {
+ t.Errorf("step %d, peer %s: announce %v extra in waitslots", i, peer, ann)
}
}
}
@@ -1334,13 +1746,13 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
}
}
// Peer->hash sets correct, check the hash->peer and timeout sets
- for peer, hashes := range step {
- for _, hash := range hashes {
- if _, ok := fetcher.waitlist[hash][peer]; !ok {
- t.Errorf("step %d, hash %x: peer %s missing from waitlist", i, hash, peer)
+ for peer, announces := range step {
+ for _, ann := range announces {
+ if _, ok := fetcher.waitlist[ann.hash][peer]; !ok {
+ t.Errorf("step %d, hash %x: peer %s missing from waitlist", i, ann.hash, peer)
}
- if _, ok := fetcher.waittime[hash]; !ok {
- t.Errorf("step %d: hash %x missing from waittime", i, hash)
+ if _, ok := fetcher.waittime[ann.hash]; !ok {
+ t.Errorf("step %d: hash %x missing from waittime", i, ann.hash)
}
}
}
@@ -1349,15 +1761,15 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
t.Errorf("step %d, hash %x: empty peerset in waitlist", i, hash)
}
for peer := range peers {
- if !containsHash(step[peer], hash) {
+ if !containsHashInAnnounces(step[peer], hash) {
t.Errorf("step %d, hash %x: peer %s extra in waitlist", i, hash, peer)
}
}
}
for hash := range fetcher.waittime {
var found bool
- for _, hashes := range step {
- if containsHash(hashes, hash) {
+ for _, announces := range step {
+ if containsHashInAnnounces(announces, hash) {
found = true
break
}
@@ -1367,23 +1779,33 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
}
}
- case isScheduled:
+ case isScheduledWithMeta:
// Check that all scheduled announces are accounted for and no
// extra ones are present.
- for peer, hashes := range step.tracking {
+ for peer, announces := range step.tracking {
scheduled := fetcher.announces[peer]
if scheduled == nil {
t.Errorf("step %d: peer %s missing from announces", i, peer)
continue
}
- for _, hash := range hashes {
- if _, ok := scheduled[hash]; !ok {
- t.Errorf("step %d, peer %s: hash %x missing from announces", i, peer, hash)
+ for _, ann := range announces {
+ if meta, ok := scheduled[ann.hash]; !ok {
+ t.Errorf("step %d, peer %s: hash %x missing from announces", i, peer, ann.hash)
+ } else {
+ if (meta == nil && (ann.kind != nil || ann.size != nil)) ||
+ (meta != nil && (ann.kind == nil || ann.size == nil)) ||
+ (meta != nil && (meta.kind != *ann.kind || meta.size != *ann.size)) {
+ t.Errorf("step %d, peer %s, hash %x: announce metadata mismatch: want %v, have %v/%v", i, peer, ann.hash, meta, *ann.kind, *ann.size)
+ }
}
}
- for hash := range scheduled {
- if !containsHash(hashes, hash) {
- t.Errorf("step %d, peer %s: hash %x extra in announces", i, peer, hash)
+ for hash, meta := range scheduled {
+ ann := announce{hash: hash}
+ if meta != nil {
+ ann.kind, ann.size = &meta.kind, &meta.size
+ }
+ if !containsAnnounce(announces, ann) {
+ t.Errorf("step %d, peer %s: announce %x extra in announces", i, peer, hash)
}
}
}
@@ -1483,17 +1905,17 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
// retrieval but not actively being downloaded are tracked only
// in the stage 2 `announced` map.
var queued []common.Hash
- for _, hashes := range step.tracking {
- for _, hash := range hashes {
+ for _, announces := range step.tracking {
+ for _, ann := range announces {
var found bool
for _, hs := range step.fetching {
- if containsHash(hs, hash) {
+ if containsHash(hs, ann.hash) {
found = true
break
}
}
if !found {
- queued = append(queued, hash)
+ queued = append(queued, ann.hash)
}
}
}
@@ -1526,6 +1948,42 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
}
}
+// containsAnnounce returns whether an announcement is contained within a slice
+// of announcements.
+func containsAnnounce(slice []announce, ann announce) bool {
+ for _, have := range slice {
+ if have.hash == ann.hash {
+ if have.kind == nil || ann.kind == nil {
+ if have.kind != ann.kind {
+ return false
+ }
+ } else if *have.kind != *ann.kind {
+ return false
+ }
+ if have.size == nil || ann.size == nil {
+ if have.size != ann.size {
+ return false
+ }
+ } else if *have.size != *ann.size {
+ return false
+ }
+ return true
+ }
+ }
+ return false
+}
+
+// containsHashInAnnounces returns whether a hash is contained within a slice
+// of announcements.
+func containsHashInAnnounces(slice []announce, hash common.Hash) bool {
+ for _, have := range slice {
+ if have.hash == hash {
+ return true
+ }
+ }
+ return false
+}
+
// containsHash returns whether a hash is contained within a hash slice.
func containsHash(slice []common.Hash, hash common.Hash) bool {
for _, have := range slice {
@@ -1535,3 +1993,38 @@ func containsHash(slice []common.Hash, hash common.Hash) bool {
}
return false
}
+
+// Tests that a transaction is forgotten after the timeout.
+func TestTransactionForgotten(t *testing.T) {
+ fetcher := NewTxFetcher(
+ func(common.Hash) bool { return false },
+ func(peer string, txs []*types.Transaction) []error {
+ errs := make([]error, len(txs))
+ for i := 0; i < len(errs); i++ {
+ errs[i] = txpool.ErrUnderpriced
+ }
+ return errs
+ },
+ func(string, []common.Hash) error { return nil },
+ func(string) {},
+ )
+ fetcher.Start()
+ defer fetcher.Stop()
+ // Create one TX which is 5 minutes old, and one which is recent
+ tx1 := types.NewTx(&types.LegacyTx{Nonce: 0})
+ tx1.SetTime(time.Now().Add(-maxTxUnderpricedTimeout - 1*time.Second))
+ tx2 := types.NewTx(&types.LegacyTx{Nonce: 1})
+
+ // Enqueue both in the fetcher. They will be immediately tagged as underpriced
+ if err := fetcher.Enqueue("asdf", []*types.Transaction{tx1, tx2}, false); err != nil {
+ t.Fatal(err)
+ }
+ // isKnownUnderpriced should trigger removal of the first tx (no longer be known underpriced)
+ if fetcher.isKnownUnderpriced(tx1.Hash()) {
+ t.Fatal("transaction should be forgotten by now")
+ }
+ // isKnownUnderpriced should not trigger removal of the second
+ if !fetcher.isKnownUnderpriced(tx2.Hash()) {
+ t.Fatal("transaction should be known underpriced")
+ }
+}
diff --git a/eth/filters/api.go b/eth/filters/api.go
index 18a3d64f3a..dbc7849659 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -35,10 +35,15 @@ import (
)
var (
- errInvalidTopic = errors.New("invalid topic(s)")
- errFilterNotFound = errors.New("filter not found")
+ errInvalidTopic = errors.New("invalid topic(s)")
+ errFilterNotFound = errors.New("filter not found")
+ errInvalidBlockRange = errors.New("invalid block range params")
+ errExceedMaxTopics = errors.New("exceed max topics")
)
+// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0
+const maxTopics = 4
+
// filter is a helper struct that holds meta information over the filter type
// and associated subscription in the event system.
type filter struct {
@@ -156,6 +161,8 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool)
gopool.Submit(func() {
txs := make(chan []*types.Transaction, 128)
pendingTxSub := api.events.SubscribePendingTxs(txs)
+ defer pendingTxSub.Unsubscribe()
+
chainConfig := api.sys.backend.ChainConfig()
for {
@@ -173,10 +180,8 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool)
}
}
case <-rpcSub.Err():
- pendingTxSub.Unsubscribe()
return
case <-notifier.Closed():
- pendingTxSub.Unsubscribe()
return
}
}
@@ -292,16 +297,15 @@ func (api *FilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, error) {
gopool.Submit(func() {
headers := make(chan *types.Header)
headersSub := api.events.SubscribeNewHeads(headers)
+ defer headersSub.Unsubscribe()
for {
select {
case h := <-headers:
notifier.Notify(rpcSub.ID, h)
case <-rpcSub.Err():
- headersSub.Unsubscribe()
return
case <-notifier.Closed():
- headersSub.Unsubscribe()
return
}
}
@@ -390,6 +394,7 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc
}
gopool.Submit(func() {
+ defer logsSub.Unsubscribe()
for {
select {
case logs := <-matchedLogs:
@@ -398,10 +403,8 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc
notifier.Notify(rpcSub.ID, &log)
}
case <-rpcSub.Err(): // client send an unsubscribe request
- logsSub.Unsubscribe()
return
case <-notifier.Closed(): // connection dropped
- logsSub.Unsubscribe()
return
}
}
@@ -459,6 +462,9 @@ func (api *FilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
// GetLogs returns logs matching the given argument that are stored within the state.
func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
+ if len(crit.Topics) > maxTopics {
+ return nil, errExceedMaxTopics
+ }
var filter *Filter
if crit.BlockHash != nil {
// Block filter requested, construct a single-shot filter
@@ -473,6 +479,9 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
if crit.ToBlock != nil {
end = crit.ToBlock.Int64()
}
+ if begin > 0 && end > 0 && begin > end {
+ return nil, errInvalidBlockRange
+ }
// Construct the range filter
filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics, api.rangeLimit)
}
diff --git a/eth/filters/filter.go b/eth/filters/filter.go
index acb65bc540..2fb9d7d58c 100644
--- a/eth/filters/filter.go
+++ b/eth/filters/filter.go
@@ -117,7 +117,7 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
// special case for pending logs
if beginPending && !endPending {
- return nil, errors.New("invalid block range")
+ return nil, errInvalidBlockRange
}
// Short-cut if all we care about is pending logs
@@ -350,48 +350,47 @@ func (f *Filter) pendingLogs() []*types.Log {
return nil
}
-func includes(addresses []common.Address, a common.Address) bool {
- for _, addr := range addresses {
- if addr == a {
+// includes returns true if the element is present in the list.
+func includes[T comparable](things []T, element T) bool {
+ for _, thing := range things {
+ if thing == element {
return true
}
}
-
return false
}
// filterLogs creates a slice of logs matching the given criteria.
func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []common.Address, topics [][]common.Hash) []*types.Log {
- var ret []*types.Log
-Logs:
- for _, log := range logs {
+ var check = func(log *types.Log) bool {
if fromBlock != nil && fromBlock.Int64() >= 0 && fromBlock.Uint64() > log.BlockNumber {
- continue
+ return false
}
if toBlock != nil && toBlock.Int64() >= 0 && toBlock.Uint64() < log.BlockNumber {
- continue
+ return false
}
-
if len(addresses) > 0 && !includes(addresses, log.Address) {
- continue
+ return false
}
// If the to filtered topics is greater than the amount of topics in logs, skip.
if len(topics) > len(log.Topics) {
- continue
+ return false
}
for i, sub := range topics {
- match := len(sub) == 0 // empty rule set == wildcard
- for _, topic := range sub {
- if log.Topics[i] == topic {
- match = true
- break
- }
+ if len(sub) == 0 {
+ continue // empty rule set == wildcard
}
- if !match {
- continue Logs
+ if !includes(sub, log.Topics[i]) {
+ return false
}
}
- ret = append(ret, log)
+ return true
+ }
+ var ret []*types.Log
+ for _, log := range logs {
+ if check(log) {
+ ret = append(ret, log)
+ }
}
return ret
}
diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go
index 672620327c..21f62b119d 100644
--- a/eth/filters/filter_system.go
+++ b/eth/filters/filter_system.go
@@ -20,7 +20,6 @@ package filters
import (
"context"
- "errors"
"fmt"
"sync"
"sync/atomic"
@@ -320,6 +319,9 @@ func (es *EventSystem) subscribe(sub *subscription) *Subscription {
// given criteria to the given logs channel. Default value for the from and to
// block is "latest". If the fromBlock > toBlock an error is returned.
func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) (*Subscription, error) {
+ if len(crit.Topics) > maxTopics {
+ return nil, errExceedMaxTopics
+ }
var from, to rpc.BlockNumber
if crit.FromBlock == nil {
from = rpc.LatestBlockNumber
@@ -352,7 +354,7 @@ func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*typ
if from >= 0 && to == rpc.LatestBlockNumber {
return es.subscribeLogs(crit, logs), nil
}
- return nil, errors.New("invalid from and to block combination: from > to")
+ return nil, errInvalidBlockRange
}
// subscribeMinedPendingLogs creates a subscription that returned mined and
diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go
index 23fb21975b..c3e465036d 100644
--- a/eth/filters/filter_system_test.go
+++ b/eth/filters/filter_system_test.go
@@ -117,7 +117,7 @@ func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.
}
func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
- logs := rawdb.ReadLogs(b.db, hash, number, params.TestChainConfig)
+ logs := rawdb.ReadLogs(b.db, hash, number)
return logs, nil
}
@@ -390,6 +390,8 @@ func TestLogFilterCreation(t *testing.T) {
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
// from block "higher" than to block
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, false},
+ // topics more then 4
+ {FilterCriteria{Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, false},
}
)
@@ -424,6 +426,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
0: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
1: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)},
2: {FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)},
+ 3: {Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
}
for i, test := range testCases {
@@ -433,7 +436,10 @@ func TestInvalidLogFilterCreation(t *testing.T) {
}
}
+// TestLogFilterUninstall tests invalid getLogs requests
func TestInvalidGetLogsRequest(t *testing.T) {
+ t.Parallel()
+
var (
db = rawdb.NewMemoryDatabase()
_, sys = newTestFilterSystem(t, db, Config{})
@@ -446,6 +452,7 @@ func TestInvalidGetLogsRequest(t *testing.T) {
0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)},
2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
+ 3: {BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
}
for i, test := range testCases {
@@ -455,6 +462,21 @@ func TestInvalidGetLogsRequest(t *testing.T) {
}
}
+// TestInvalidGetRangeLogsRequest tests getLogs with invalid block range
+func TestInvalidGetRangeLogsRequest(t *testing.T) {
+ t.Parallel()
+
+ var (
+ db = rawdb.NewMemoryDatabase()
+ _, sys = newTestFilterSystem(t, db, Config{})
+ api = NewFilterAPI(sys, false)
+ )
+
+ if _, err := api.GetLogs(context.Background(), FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(1)}); err != errInvalidBlockRange {
+ t.Errorf("Expected Logs for invalid range return error, but got: %v", err)
+ }
+}
+
// TestLogFilter tests whether log filters match the correct logs that are posted to the event feed.
func TestLogFilter(t *testing.T) {
t.Parallel()
@@ -782,10 +804,14 @@ func TestPendingTxFilterDeadlock(t *testing.T) {
// Create a bunch of filters that will
// timeout either in 100ms or 200ms
- fids := make([]rpc.ID, 20)
- for i := 0; i < len(fids); i++ {
+ subs := make([]*Subscription, 20)
+ for i := 0; i < len(subs); i++ {
fid := api.NewPendingTransactionFilter(nil)
- fids[i] = fid
+ f, ok := api.filters[fid]
+ if !ok {
+ t.Fatalf("Filter %s should exist", fid)
+ }
+ subs[i] = f.s
// Wait for at least one tx to arrive in filter
for {
hashes, err := api.GetFilterChanges(fid)
@@ -799,21 +825,13 @@ func TestPendingTxFilterDeadlock(t *testing.T) {
}
}
- // Wait until filters have timed out
- time.Sleep(3 * timeout)
-
- // If tx loop doesn't consume `done` after a second
- // it's hanging.
- select {
- case done <- struct{}{}:
- // Check that all filters have been uninstalled
- for _, fid := range fids {
- if _, err := api.GetFilterChanges(fid); err == nil {
- t.Errorf("Filter %s should have been uninstalled\n", fid)
- }
+ // Wait until filters have timed out and have been uninstalled.
+ for _, sub := range subs {
+ select {
+ case <-sub.Err():
+ case <-time.After(1 * time.Second):
+ t.Fatalf("Filter timeout is hanging")
}
- case <-time.After(1 * time.Second):
- t.Error("Tx sending loop hangs")
}
}
diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go
index aca70d99ed..cfb588c858 100644
--- a/eth/filters/filter_test.go
+++ b/eth/filters/filter_test.go
@@ -99,6 +99,7 @@ func BenchmarkFilters(b *testing.B) {
filter := sys.NewRangeFilter(0, -1, []common.Address{addr1, addr2, addr3, addr4}, nil, false)
for i := 0; i < b.N; i++ {
+ filter.begin = 0
logs, _ := filter.Logs(context.Background())
if len(logs) != 4 {
b.Fatal("expected 4 logs, got", len(logs))
@@ -169,7 +170,7 @@ func TestFilters(t *testing.T) {
contract: {Balance: big.NewInt(0), Code: bytecode},
contract2: {Balance: big.NewInt(0), Code: bytecode},
},
- BaseFee: big.NewInt(params.InitialBaseFeeForEthMainnet),
+ BaseFee: big.NewInt(params.InitialBaseFee),
}
)
@@ -347,15 +348,15 @@ func TestFilters(t *testing.T) {
*/
{
f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil, false),
- want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xc7245899e5817f16fa99cf5ad2d9c1e4b98443a565a673ec9c764640443ef037","logIndex":"0x0","removed":false}]`,
+ want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xd5e8d4e4eb51a2a2a6ec20ef68a4c2801240743c8deb77a6a1d118ac3eefb725","logIndex":"0x0","removed":false}]`,
},
{
f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil, false),
- want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xc7245899e5817f16fa99cf5ad2d9c1e4b98443a565a673ec9c764640443ef037","logIndex":"0x0","removed":false}]`,
+ want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xd5e8d4e4eb51a2a2a6ec20ef68a4c2801240743c8deb77a6a1d118ac3eefb725","logIndex":"0x0","removed":false}]`,
},
{
f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil, false),
- err: "invalid block range",
+ err: errInvalidBlockRange.Error(),
},
} {
logs, err := tc.f.Logs(context.Background())
diff --git a/eth/gasestimator/gasestimator.go b/eth/gasestimator/gasestimator.go
new file mode 100644
index 0000000000..f07f98956e
--- /dev/null
+++ b/eth/gasestimator/gasestimator.go
@@ -0,0 +1,235 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package gasestimator
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// Options are the contextual parameters to execute the requested call.
+//
+// Whilst it would be possible to pass a blockchain object that aggregates all
+// these together, it would be excessively hard to test. Splitting the parts out
+// allows testing without needing a proper live chain.
+type Options struct {
+ Config *params.ChainConfig // Chain configuration for hard fork selection
+ Chain core.ChainContext // Chain context to access past block hashes
+ Header *types.Header // Header defining the block context to execute in
+ State *state.StateDB // Pre-state on top of which to estimate the gas
+
+ ErrorRatio float64 // Allowed overestimation ratio for faster estimation termination
+}
+
+// Estimate returns the lowest possible gas limit that allows the transaction to
+// run successfully with the provided context options. It returns an error if the
+// transaction would always revert, or if there are unexpected failures.
+func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uint64) (uint64, []byte, error) {
+ // Binary search the gas limit, as it may need to be higher than the amount used
+ var (
+ lo uint64 // lowest-known gas limit where tx execution fails
+ hi uint64 // lowest-known gas limit where tx execution succeeds
+ )
+ // Determine the highest gas limit can be used during the estimation.
+ hi = opts.Header.GasLimit
+ if call.GasLimit >= params.TxGas {
+ hi = call.GasLimit
+ }
+ // Normalize the max fee per gas the call is willing to spend.
+ var feeCap *big.Int
+ if call.GasFeeCap != nil {
+ feeCap = call.GasFeeCap
+ } else if call.GasPrice != nil {
+ feeCap = call.GasPrice
+ } else {
+ feeCap = common.Big0
+ }
+ // Recap the highest gas limit with account's available balance.
+ if feeCap.BitLen() != 0 {
+ balance := opts.State.GetBalance(call.From).ToBig()
+
+ available := balance
+ if call.Value != nil {
+ if call.Value.Cmp(available) >= 0 {
+ return 0, nil, core.ErrInsufficientFundsForTransfer
+ }
+ available.Sub(available, call.Value)
+ }
+ allowance := new(big.Int).Div(available, feeCap)
+
+ // If the allowance is larger than maximum uint64, skip checking
+ if allowance.IsUint64() && hi > allowance.Uint64() {
+ transfer := call.Value
+ if transfer == nil {
+ transfer = new(big.Int)
+ }
+ log.Debug("Gas estimation capped by limited funds", "original", hi, "balance", balance,
+ "sent", transfer, "maxFeePerGas", feeCap, "fundable", allowance)
+ hi = allowance.Uint64()
+ }
+ }
+ // Recap the highest gas allowance with specified gascap.
+ if gasCap != 0 && hi > gasCap {
+ log.Debug("Caller gas above allowance, capping", "requested", hi, "cap", gasCap)
+ hi = gasCap
+ }
+ // If the transaction is a plain value transfer, short circuit estimation and
+ // directly try 21000. Returning 21000 without any execution is dangerous as
+ // some tx field combos might bump the price up even for plain transfers (e.g.
+ // unused access list items). Ever so slightly wasteful, but safer overall.
+ if len(call.Data) == 0 {
+ if call.To != nil && opts.State.GetCodeSize(*call.To) == 0 {
+ failed, _, err := execute(ctx, call, opts, params.TxGas)
+ if !failed && err == nil {
+ return params.TxGas, nil, nil
+ }
+ }
+ }
+ // We first execute the transaction at the highest allowable gas limit, since if this fails we
+ // can return error immediately.
+ failed, result, err := execute(ctx, call, opts, hi)
+ if err != nil {
+ return 0, nil, err
+ }
+ if failed {
+ if result != nil && !errors.Is(result.Err, vm.ErrOutOfGas) {
+ return 0, result.Revert(), result.Err
+ }
+ return 0, nil, fmt.Errorf("gas required exceeds allowance (%d)", hi)
+ }
+ // For almost any transaction, the gas consumed by the unconstrained execution
+ // above lower-bounds the gas limit required for it to succeed. One exception
+ // is those that explicitly check gas remaining in order to execute within a
+ // given limit, but we probably don't want to return the lowest possible gas
+ // limit for these cases anyway.
+ lo = result.UsedGas - 1
+
+ // There's a fairly high chance for the transaction to execute successfully
+ // with gasLimit set to the first execution's usedGas + gasRefund. Explicitly
+ // check that gas amount and use as a limit for the binary search.
+ optimisticGasLimit := (result.UsedGas + result.RefundedGas + params.CallStipend) * 64 / 63
+ if optimisticGasLimit < hi {
+ failed, _, err = execute(ctx, call, opts, optimisticGasLimit)
+ if err != nil {
+ // This should not happen under normal conditions since if we make it this far the
+ // transaction had run without error at least once before.
+ log.Error("Execution error in estimate gas", "err", err)
+ return 0, nil, err
+ }
+ if failed {
+ lo = optimisticGasLimit
+ } else {
+ hi = optimisticGasLimit
+ }
+ }
+ // Binary search for the smallest gas limit that allows the tx to execute successfully.
+ for lo+1 < hi {
+ if opts.ErrorRatio > 0 {
+ // It is a bit pointless to return a perfect estimation, as changing
+ // network conditions require the caller to bump it up anyway. Since
+ // wallets tend to use 20-25% bump, allowing a small approximation
+ // error is fine (as long as it's upwards).
+ if float64(hi-lo)/float64(hi) < opts.ErrorRatio {
+ break
+ }
+ }
+ mid := (hi + lo) / 2
+ if mid > lo*2 {
+ // Most txs don't need much higher gas limit than their gas used, and most txs don't
+ // require near the full block limit of gas, so the selection of where to bisect the
+ // range here is skewed to favor the low side.
+ mid = lo * 2
+ }
+ failed, _, err = execute(ctx, call, opts, mid)
+ if err != nil {
+ // This should not happen under normal conditions since if we make it this far the
+ // transaction had run without error at least once before.
+ log.Error("Execution error in estimate gas", "err", err)
+ return 0, nil, err
+ }
+ if failed {
+ lo = mid
+ } else {
+ hi = mid
+ }
+ }
+ return hi, nil, nil
+}
+
+// execute is a helper that executes the transaction under a given gas limit and
+// returns true if the transaction fails for a reason that might be related to
+// not enough gas. A non-nil error means execution failed due to reasons unrelated
+// to the gas limit.
+func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit uint64) (bool, *core.ExecutionResult, error) {
+ // Configure the call for this specific execution (and revert the change after)
+ defer func(gas uint64) { call.GasLimit = gas }(call.GasLimit)
+ call.GasLimit = gasLimit
+
+ // Execute the call and separate execution faults caused by a lack of gas or
+ // other non-fixable conditions
+ result, err := run(ctx, call, opts)
+ if err != nil {
+ if errors.Is(err, core.ErrIntrinsicGas) {
+ return true, nil, nil // Special case, raise gas limit
+ }
+ return true, nil, err // Bail out
+ }
+ return result.Failed(), result, nil
+}
+
+// run assembles the EVM as defined by the consensus rules and runs the requested
+// call invocation.
+func run(ctx context.Context, call *core.Message, opts *Options) (*core.ExecutionResult, error) {
+ // Assemble the call and the call context
+ var (
+ msgContext = core.NewEVMTxContext(call)
+ evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, nil)
+
+ dirtyState = opts.State.Copy()
+ evm = vm.NewEVM(evmContext, msgContext, dirtyState, opts.Config, vm.Config{NoBaseFee: true})
+ )
+ // Monitor the outer context and interrupt the EVM upon cancellation. To avoid
+ // a dangling goroutine until the outer estimation finishes, create an internal
+ // context for the lifetime of this method call.
+ ctx, cancel := context.WithCancel(ctx)
+ defer cancel()
+
+ go func() {
+ <-ctx.Done()
+ evm.Cancel()
+ }()
+ // Execute the call, returning a wrapped error or the result
+ result, err := core.ApplyMessage(evm, call, new(core.GasPool).AddGas(math.MaxUint64))
+ if vmerr := dirtyState.Error(); vmerr != nil {
+ return nil, vmerr
+ }
+ if err != nil {
+ return result, fmt.Errorf("failed with %d gas: %w", call.GasLimit, err)
+ }
+ return result, nil
+}
diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go
index 226991b24b..d657eb6d99 100644
--- a/eth/gasprice/feehistory.go
+++ b/eth/gasprice/feehistory.go
@@ -227,8 +227,8 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
if p < 0 || p > 100 {
return common.Big0, nil, nil, nil, fmt.Errorf("%w: %f", errInvalidPercentile, p)
}
- if i > 0 && p < rewardPercentiles[i-1] {
- return common.Big0, nil, nil, nil, fmt.Errorf("%w: #%d:%f > #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
+ if i > 0 && p <= rewardPercentiles[i-1] {
+ return common.Big0, nil, nil, nil, fmt.Errorf("%w: #%d:%f >= #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
}
}
var (
diff --git a/eth/handler.go b/eth/handler.go
index 7772505037..ffb80685f8 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -79,18 +79,19 @@ type txPool interface {
// Get retrieves the transaction from local txpool with given
// tx hash.
- Get(hash common.Hash) *txpool.Transaction
+ Get(hash common.Hash) *types.Transaction
// Add should add the given transactions to the pool.
- Add(txs []*txpool.Transaction, local bool, sync bool) []error
+ Add(txs []*types.Transaction, local bool, sync bool) []error
// Pending should return pending transactions.
// The slice should be modifiable by the caller.
Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction
- // SubscribeNewTxsEvent should return an event subscription of
- // NewTxsEvent and send events to the given channel.
- SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
+ // SubscribeTransactions subscribes to new transaction events. The subscriber
+ // can decide whether to receive notifications only for newly seen transactions
+ // or also for reorged out ones.
+ SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription
// SubscribeReannoTxsEvent should return an event subscription of
// ReannoTxsEvent and send events to the given channel.
@@ -132,7 +133,7 @@ type handler struct {
disablePeerTxBroadcast bool
snapSync atomic.Bool // Flag whether snap sync is enabled (gets disabled if we already have blocks)
- acceptTxs atomic.Bool // Flag whether we're considered synchronised (enables transaction processing)
+ synced atomic.Bool // Flag whether we're considered synchronised (enables transaction processing)
directBroadcast bool
database ethdb.Database
@@ -217,40 +218,28 @@ func newHandler(config *handlerConfig) (*handler, error) {
log.Crit("Fast Sync not finish, can't enable pruneancient mode")
}
h.snapSync.Store(true)
- log.Warn("Switch sync mode from full sync to snap sync")
+ log.Warn("Switch sync mode from full sync to snap sync", "reason", "snap sync incomplete")
+ } else if !h.chain.HasState(fullBlock.Root) {
+ h.snapSync.Store(true)
+ log.Warn("Switch sync mode from full sync to snap sync", "reason", "head state missing")
}
} else {
- if h.chain.CurrentBlock().Number.Uint64() > 0 {
+ head := h.chain.CurrentBlock()
+ if head.Number.Uint64() > 0 && h.chain.HasState(head.Root) {
// Print warning log if database is not empty to run snap sync.
- log.Warn("Switch sync mode from snap sync to full sync")
+ log.Warn("Switch sync mode from snap sync to full sync", "reason", "snap sync complete")
} else {
// If snap sync was requested and our database is empty, grant it
h.snapSync.Store(true)
+ log.Info("Enabled snap sync", "head", head.Number, "hash", head.Hash())
}
}
- // Construct the downloader (long sync) and its backing state bloom if snap
- // sync is requested. The downloader is responsible for deallocating the state
- // bloom when it's done.
- var downloadOptions []downloader.DownloadOption
- // If sync succeeds, pass a callback to potentially disable snap sync mode
- // and enable transaction propagation.
- // it was for beacon sync, bsc do not need it.
- /*
- success := func(dl *downloader.Downloader) *downloader.Downloader {
- // If we were running snap sync and it finished, disable doing another
- // round on next sync cycle
- if h.snapSync.Load() {
- log.Info("Snap sync complete, auto disabling")
- h.snapSync.Store(false) }
- // If we've successfully finished a sync cycle, accept transactions from
- // the network
- h.acceptTxs.Store(true)
- return dl
- }
- downloadOptions = append(downloadOptions, success)
- */
-
- h.downloader = downloader.New(config.Database, h.eventMux, h.chain, nil, h.removePeer, downloadOptions...)
+ // If snap sync is requested but snapshots are disabled, fail loudly
+ if h.snapSync.Load() && config.Chain.Snapshots() == nil {
+ return nil, errors.New("snap sync not supported with snapshots disabled")
+ }
+ // Construct the downloader (long sync)
+ h.downloader = downloader.New(config.Database, h.eventMux, h.chain, nil, h.removePeer, h.enableSyncedFeatures)
// Construct the fetcher (short sync)
validator := func(header *types.Header) error {
@@ -301,8 +290,8 @@ func newHandler(config *handlerConfig) (*handler, error) {
// accept each others' blocks until a restart. Unfortunately we haven't figured
// out a way yet where nodes can decide unilaterally whether the network is new
// or not. This should be fixed if we figure out a solution.
- if h.snapSync.Load() {
- log.Warn("Snap syncing, discarded propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash())
+ if !h.synced.Load() {
+ log.Warn("Syncing, discarded propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash())
return 0, nil
}
if h.merger.TDDReached() {
@@ -319,7 +308,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
}
td := new(big.Int).Add(ptd, block.Difficulty())
if !h.chain.Config().IsTerminalPoWBlock(ptd, td) {
- log.Info("Filtered out non-termimal pow block", "number", block.NumberU64(), "hash", block.Hash())
+ log.Info("Filtered out non-terminal pow block", "number", block.NumberU64(), "hash", block.Hash())
return 0, nil
}
if err := h.chain.InsertBlockWithoutSetHead(block); err != nil {
@@ -328,11 +317,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
}
return 0, nil
}
- n, err := h.chain.InsertChain(blocks)
- if err == nil {
- h.enableSyncedFeatures() // Mark initial sync done on any fetcher import
- }
- return n, err
+ return h.chain.InsertChain(blocks)
}
h.blockFetcher = fetcher.NewBlockFetcher(false, nil, h.chain.GetBlockByHash, validator, h.BroadcastBlock,
heighter, finalizeHeighter, nil, inserter, h.removePeer)
@@ -344,7 +329,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
}
return p.RequestTxs(hashes)
}
- addTxs := func(peer string, txs []*txpool.Transaction) []error {
+ addTxs := func(peer string, txs []*types.Transaction) []error {
errors := h.txpool.Add(txs, false, false)
for _, err := range errors {
if err == legacypool.ErrInBlackList {
@@ -360,7 +345,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
}
return errors
}
- h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx)
+ h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx, h.removePeer)
h.chainSync = newChainSyncer(h)
return h, nil
}
@@ -435,7 +420,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
number = head.Number.Uint64()
td = h.chain.GetTd(hash, number)
)
- forkID := forkid.NewID(h.chain.Config(), genesis.Hash(), number, head.Time)
+ forkID := forkid.NewID(h.chain.Config(), genesis, number, head.Time)
if err := peer.Handshake(h.networkID, td, hash, genesis.Hash(), forkID, h.forkFilter, ð.UpgradeStatusExtension{DisablePeerTxBroadcast: h.disablePeerTxBroadcast}); err != nil {
peer.Log().Debug("Ethereum handshake failed", "err", err)
return err
@@ -530,7 +515,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
select {
case res := <-resCh:
- headers := ([]*types.Header)(*res.Res.(*eth.BlockHeadersPacket))
+ headers := ([]*types.Header)(*res.Res.(*eth.BlockHeadersRequest))
if len(headers) == 0 {
// Required blocks are allowed to be missing if the remote
// node is not yet synced
@@ -577,7 +562,7 @@ func (h *handler) runSnapExtension(peer *snap.Peer, handler snap.Handler) error
snap.EgressRegistrationErrorMeter.Mark(1)
}
}
- peer.Log().Warn("Snapshot extension registration failed", "err", err)
+ peer.Log().Debug("Snapshot extension registration failed", "err", err)
return err
}
return handler(peer)
@@ -695,10 +680,10 @@ func (h *handler) unregisterPeer(id string) {
func (h *handler) Start(maxPeers int, maxPeersPerIP int) {
h.maxPeers = maxPeers
h.maxPeersPerIP = maxPeersPerIP
- // broadcast transactions
+ // broadcast and announce transactions (only new ones, not resurrected ones)
h.wg.Add(1)
h.txsCh = make(chan core.NewTxsEvent, txChanSize)
- h.txsSub = h.txpool.SubscribeNewTxsEvent(h.txsCh)
+ h.txsSub = h.txpool.SubscribeTransactions(h.txsCh, false)
go h.txBroadcastLoop()
// broadcast votes
@@ -827,26 +812,33 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) {
}
// BroadcastTransactions will propagate a batch of transactions
-// - To a square root of all peers
+// - To a square root of all peers for non-blob transactions
// - And, separately, as announcements to all peers which are not known to
// already have the given transaction.
func (h *handler) BroadcastTransactions(txs types.Transactions) {
var (
- annoCount int // Count of announcements made
- annoPeers int
- directCount int // Count of the txs sent directly to peers
- directPeers int // Count of the peers that were sent transactions directly
+ blobTxs int // Number of blob transactions to announce only
+ largeTxs int // Number of large transactions to announce only
+
+ directCount int // Number of transactions sent directly to peers (duplicates included)
+ directPeers int // Number of peers that were sent transactions directly
+ annCount int // Number of transactions announced across all peers (duplicates included)
+ annPeers int // Number of peers announced about transactions
txset = make(map[*ethPeer][]common.Hash) // Set peer->hash to transfer directly
annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce
-
)
// Broadcast transactions to a batch of peers not knowing about it
for _, tx := range txs {
peers := h.peers.peersWithoutTransaction(tx.Hash())
var numDirect int
- if tx.Size() <= txMaxBroadcastSize {
+ switch {
+ case tx.Type() == types.BlobTxType:
+ blobTxs++
+ case tx.Size() > txMaxBroadcastSize:
+ largeTxs++
+ default:
numDirect = int(math.Sqrt(float64(len(peers))))
}
// Send the tx unconditionally to a subset of our peers
@@ -864,13 +856,12 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
peer.AsyncSendTransactions(hashes)
}
for peer, hashes := range annos {
- annoPeers++
- annoCount += len(hashes)
+ annPeers++
+ annCount += len(hashes)
peer.AsyncSendPooledTransactionHashes(hashes)
}
- log.Debug("Transaction broadcast", "txs", len(txs),
- "announce packs", annoPeers, "announced hashes", annoCount,
- "tx packs", directPeers, "broadcast txs", directCount)
+ log.Debug("Distributed transactions", "plaintxs", len(txs)-blobTxs-largeTxs, "blobtxs", blobTxs, "largetxs", largeTxs,
+ "bcastpeers", directPeers, "bcastcount", directCount, "annpeers", annPeers, "anncount", annCount)
}
// ReannounceTransactions will announce a batch of local pending transactions
@@ -990,10 +981,16 @@ func (h *handler) voteBroadcastLoop() {
// enableSyncedFeatures enables the post-sync functionalities when the initial
// sync is finished.
func (h *handler) enableSyncedFeatures() {
- h.acceptTxs.Store(true)
- // In the bsc scenario, pathdb.MaxDirtyBufferSize (256MB) will be used.
- // The performance is better than DefaultDirtyBufferSize (64MB).
- //if h.chain.TrieDB().Scheme() == rawdb.PathScheme {
- // h.chain.TrieDB().SetBufferSize(pathdb.DefaultDirtyBufferSize)
- //}
+ // Mark the local node as synced.
+ h.synced.Store(true)
+
+ // If we were running snap sync and it finished, disable doing another
+ // round on next sync cycle
+ if h.snapSync.Load() {
+ log.Info("Snap sync complete, auto disabling")
+ h.snapSync.Store(false)
+ }
+ // if h.chain.TrieDB().Scheme() == rawdb.PathScheme {
+ // h.chain.TrieDB().SetBufferSize(pathdb.DefaultBufferSize)
+ // }
}
diff --git a/eth/handler_bsc_test.go b/eth/handler_bsc_test.go
index b807fa626e..842db2726f 100644
--- a/eth/handler_bsc_test.go
+++ b/eth/handler_bsc_test.go
@@ -65,11 +65,11 @@ func testSendVotes(t *testing.T, protocol uint) {
protos := []p2p.Protocol{
{
Name: "eth",
- Version: eth.ETH66,
+ Version: eth.ETH67,
},
{
Name: "eth",
- Version: eth.ETH67,
+ Version: eth.ETH68,
},
{
Name: "bsc",
@@ -79,11 +79,11 @@ func testSendVotes(t *testing.T, protocol uint) {
caps := []p2p.Cap{
{
Name: "eth",
- Version: eth.ETH66,
+ Version: eth.ETH67,
},
{
Name: "eth",
- Version: eth.ETH67,
+ Version: eth.ETH68,
},
{
Name: "bsc",
@@ -175,11 +175,11 @@ func testRecvVotes(t *testing.T, protocol uint) {
protos := []p2p.Protocol{
{
Name: "eth",
- Version: eth.ETH66,
+ Version: eth.ETH67,
},
{
Name: "eth",
- Version: eth.ETH67,
+ Version: eth.ETH68,
},
{
Name: "bsc",
@@ -189,11 +189,11 @@ func testRecvVotes(t *testing.T, protocol uint) {
caps := []p2p.Cap{
{
Name: "eth",
- Version: eth.ETH66,
+ Version: eth.ETH67,
},
{
Name: "eth",
- Version: eth.ETH67,
+ Version: eth.ETH68,
},
{
Name: "bsc",
diff --git a/eth/handler_eth.go b/eth/handler_eth.go
index 247439097b..0b3da37928 100644
--- a/eth/handler_eth.go
+++ b/eth/handler_eth.go
@@ -17,6 +17,7 @@
package eth
import (
+ "errors"
"fmt"
"math/big"
"time"
@@ -51,7 +52,7 @@ func (h *ethHandler) PeerInfo(id enode.ID) interface{} {
// AcceptTxs retrieves whether transaction processing is enabled on the node
// or if inbound transactions should simply be dropped.
func (h *ethHandler) AcceptTxs() bool {
- return h.acceptTxs.Load()
+ return h.synced.Load()
}
// Handle is invoked from a peer's message handler when it receives a new remote
@@ -66,16 +67,21 @@ func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
case *eth.NewBlockPacket:
return h.handleBlockBroadcast(peer, packet.Block, packet.TD)
- case *eth.NewPooledTransactionHashesPacket66:
- return h.txFetcher.Notify(peer.ID(), *packet)
+ case *eth.NewPooledTransactionHashesPacket67:
+ return h.txFetcher.Notify(peer.ID(), nil, nil, *packet)
case *eth.NewPooledTransactionHashesPacket68:
- return h.txFetcher.Notify(peer.ID(), packet.Hashes)
+ return h.txFetcher.Notify(peer.ID(), packet.Types, packet.Sizes, packet.Hashes)
case *eth.TransactionsPacket:
+ for _, tx := range *packet {
+ if tx.Type() == types.BlobTxType {
+ return errors.New("disallowed broadcast blob transaction")
+ }
+ }
return h.txFetcher.Enqueue(peer.ID(), *packet, false)
- case *eth.PooledTransactionsPacket:
+ case *eth.PooledTransactionsResponse:
return h.txFetcher.Enqueue(peer.ID(), *packet, true)
default:
@@ -90,9 +96,7 @@ func (h *ethHandler) handleBlockAnnounces(peer *eth.Peer, hashes []common.Hash,
// the chain already entered the pos stage and disconnect the
// remote peer.
if h.merger.PoSFinalized() {
- // TODO (MariusVanDerWijden) drop non-updated peers after the merge
- return nil
- // return errors.New("unexpected block announces")
+ return errors.New("disallowed block announcement")
}
// Schedule all the unknown hashes for retrieval
var (
@@ -119,9 +123,7 @@ func (h *ethHandler) handleBlockBroadcast(peer *eth.Peer, block *types.Block, td
// the chain already entered the pos stage and disconnect the
// remote peer.
if h.merger.PoSFinalized() {
- // TODO (MariusVanDerWijden) drop non-updated peers after the merge
- return nil
- // return errors.New("unexpected block announces")
+ return errors.New("disallowed block broadcast")
}
// Schedule the block for import
h.blockFetcher.Enqueue(peer.ID(), block)
diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go
index 932de1a3f3..d7470f5a0f 100644
--- a/eth/handler_eth_test.go
+++ b/eth/handler_eth_test.go
@@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
@@ -62,7 +61,7 @@ func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
h.blockBroadcasts.Send(packet.Block)
return nil
- case *eth.NewPooledTransactionHashesPacket66:
+ case *eth.NewPooledTransactionHashesPacket67:
h.txAnnounces.Send(([]common.Hash)(*packet))
return nil
@@ -74,7 +73,7 @@ func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
h.txBroadcasts.Send(([]*types.Transaction)(*packet))
return nil
- case *eth.PooledTransactionsPacket:
+ case *eth.PooledTransactionsResponse:
h.txBroadcasts.Send(([]*types.Transaction)(*packet))
return nil
@@ -85,7 +84,6 @@ 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 TestForkIDSplit66(t *testing.T) { testForkIDSplit(t, eth.ETH66) }
func TestForkIDSplit67(t *testing.T) { testForkIDSplit(t, eth.ETH67) }
func TestForkIDSplit68(t *testing.T) { testForkIDSplit(t, eth.ETH68) }
@@ -258,7 +256,6 @@ func testForkIDSplit(t *testing.T, protocol uint) {
}
// Tests that received transactions are added to the local pool.
-func TestRecvTransactions66(t *testing.T) { testRecvTransactions(t, eth.ETH66) }
func TestRecvTransactions67(t *testing.T) { testRecvTransactions(t, eth.ETH67) }
func TestRecvTransactions68(t *testing.T) { testRecvTransactions(t, eth.ETH68) }
@@ -269,10 +266,10 @@ func testRecvTransactions(t *testing.T, protocol uint) {
handler := newTestHandler()
defer handler.close()
- handler.handler.acceptTxs.Store(true) // mark synced to accept transactions
+ handler.handler.synced.Store(true) // mark synced to accept transactions
txs := make(chan core.NewTxsEvent)
- sub := handler.txpool.SubscribeNewTxsEvent(txs)
+ sub := handler.txpool.SubscribeTransactions(txs, false)
defer sub.Unsubscribe()
// Create a source peer to send messages through and a sink handler to receive them
@@ -391,7 +388,6 @@ func testWaitBscExtensionTimout(t *testing.T, protocol uint) {
}
// This test checks that pending transactions are sent.
-func TestSendTransactions66(t *testing.T) { testSendTransactions(t, eth.ETH66) }
func TestSendTransactions67(t *testing.T) { testSendTransactions(t, eth.ETH67) }
func TestSendTransactions68(t *testing.T) { testSendTransactions(t, eth.ETH68) }
@@ -402,12 +398,11 @@ func testSendTransactions(t *testing.T, protocol uint) {
handler := newTestHandler()
defer handler.close()
- insert := make([]*txpool.Transaction, 100)
+ insert := make([]*types.Transaction, 100)
for nonce := range insert {
tx := types.NewTransaction(uint64(nonce), common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, 10240))
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
-
- insert[nonce] = &txpool.Transaction{Tx: tx}
+ insert[nonce] = tx
}
go handler.txpool.Add(insert, false, false) // Need goroutine to not block on feed
time.Sleep(250 * time.Millisecond) // Wait until tx events get out of the system (can't use events, tx broadcaster races with peer join)
@@ -452,7 +447,7 @@ func testSendTransactions(t *testing.T, protocol uint) {
seen := make(map[common.Hash]struct{})
for len(seen) < len(insert) {
switch protocol {
- case 66, 67, 68:
+ case 67, 68:
select {
case hashes := <-anns:
for _, hash := range hashes {
@@ -470,15 +465,14 @@ func testSendTransactions(t *testing.T, protocol uint) {
}
}
for _, tx := range insert {
- if _, ok := seen[tx.Tx.Hash()]; !ok {
- t.Errorf("missing transaction: %x", tx.Tx.Hash())
+ if _, ok := seen[tx.Hash()]; !ok {
+ t.Errorf("missing transaction: %x", tx.Hash())
}
}
}
// Tests that transactions get propagated to all attached peers, either via direct
// broadcasts or via announcements/retrievals.
-func TestTransactionPropagation66(t *testing.T) { testTransactionPropagation(t, eth.ETH66) }
func TestTransactionPropagation67(t *testing.T) { testTransactionPropagation(t, eth.ETH67) }
func TestTransactionPropagation68(t *testing.T) { testTransactionPropagation(t, eth.ETH68) }
@@ -497,7 +491,7 @@ func testTransactionPropagation(t *testing.T, protocol uint) {
sinks[i] = newTestHandler()
defer sinks[i].close()
- sinks[i].handler.acceptTxs.Store(true) // mark synced to accept transactions
+ sinks[i].handler.synced.Store(true) // mark synced to accept transactions
}
// Interconnect all the sink handlers with the source handler
for i, sink := range sinks {
@@ -524,16 +518,15 @@ func testTransactionPropagation(t *testing.T, protocol uint) {
for i := 0; i < len(sinks); i++ {
txChs[i] = make(chan core.NewTxsEvent, 1024)
- sub := sinks[i].txpool.SubscribeNewTxsEvent(txChs[i])
+ sub := sinks[i].txpool.SubscribeTransactions(txChs[i], false)
defer sub.Unsubscribe()
}
// Fill the source pool with transactions and wait for them at the sinks
- txs := make([]*txpool.Transaction, 1024)
+ txs := make([]*types.Transaction, 1024)
for nonce := range txs {
tx := types.NewTransaction(uint64(nonce), common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil)
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
-
- txs[nonce] = &txpool.Transaction{Tx: tx}
+ txs[nonce] = tx
}
source.txpool.Add(txs, false, false)
@@ -562,14 +555,14 @@ func TestTransactionPendingReannounce(t *testing.T) {
sink := newTestHandler()
defer sink.close()
- sink.handler.acceptTxs.Store(true) // mark synced to accept transactions
+ sink.handler.synced.Store(true) // mark synced to accept transactions
sourcePipe, sinkPipe := p2p.MsgPipe()
defer sourcePipe.Close()
defer sinkPipe.Close()
- sourcePeer := eth.NewPeer(eth.ETH66, p2p.NewPeer(enode.ID{0}, "", nil), sourcePipe, source.txpool)
- sinkPeer := eth.NewPeer(eth.ETH66, p2p.NewPeer(enode.ID{0}, "", nil), sinkPipe, sink.txpool)
+ sourcePeer := eth.NewPeer(eth.ETH67, p2p.NewPeer(enode.ID{0}, "", nil), sourcePipe, source.txpool)
+ sinkPeer := eth.NewPeer(eth.ETH67, p2p.NewPeer(enode.ID{0}, "", nil), sinkPipe, sink.txpool)
defer sourcePeer.Close()
defer sinkPeer.Close()
@@ -582,7 +575,7 @@ func TestTransactionPendingReannounce(t *testing.T) {
// Subscribe transaction pools
txCh := make(chan core.NewTxsEvent, 1024)
- sub := sink.txpool.SubscribeNewTxsEvent(txCh)
+ sub := sink.txpool.SubscribeTransactions(txCh, false)
defer sub.Unsubscribe()
txs := make([]*types.Transaction, 64)
@@ -640,8 +633,8 @@ func testBroadcastBlock(t *testing.T, peers, bcasts int) {
defer sourcePipe.Close()
defer sinkPipe.Close()
- sourcePeer := eth.NewPeer(eth.ETH66, p2p.NewPeerPipe(enode.ID{byte(i)}, "", nil, sourcePipe), sourcePipe, nil)
- sinkPeer := eth.NewPeer(eth.ETH66, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, nil)
+ sourcePeer := eth.NewPeer(eth.ETH67, p2p.NewPeerPipe(enode.ID{byte(i)}, "", nil, sourcePipe), sourcePipe, nil)
+ sinkPeer := eth.NewPeer(eth.ETH67, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, nil)
defer sourcePeer.Close()
defer sinkPeer.Close()
@@ -693,7 +686,6 @@ func testBroadcastBlock(t *testing.T, peers, bcasts int) {
// Tests that a propagated malformed block (uncles or transactions don't match
// with the hashes in the header) gets discarded and not broadcast forward.
-func TestBroadcastMalformedBlock66(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH66) }
func TestBroadcastMalformedBlock67(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH67) }
func TestBroadcastMalformedBlock68(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH68) }
@@ -791,8 +783,8 @@ func TestOptionMaxPeersPerIP(t *testing.T) {
}
uniPort++
- src := eth.NewPeer(eth.ETH66, peer1, p2pSrc, handler.txpool)
- sink := eth.NewPeer(eth.ETH66, peer2, p2pSink, handler.txpool)
+ src := eth.NewPeer(eth.ETH67, peer1, p2pSrc, handler.txpool)
+ sink := eth.NewPeer(eth.ETH67, peer2, p2pSink, handler.txpool)
defer src.Close()
defer sink.Close()
diff --git a/eth/handler_test.go b/eth/handler_test.go
index bc22af7114..ed9bd0ef85 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -73,32 +73,23 @@ func (p *testTxPool) Has(hash common.Hash) bool {
// Get retrieves the transaction from local txpool with given
// tx hash.
-func (p *testTxPool) Get(hash common.Hash) *txpool.Transaction {
+func (p *testTxPool) Get(hash common.Hash) *types.Transaction {
p.lock.Lock()
defer p.lock.Unlock()
-
- if tx := p.pool[hash]; tx != nil {
- return &txpool.Transaction{Tx: tx}
- }
- return nil
+ return p.pool[hash]
}
// Add appends a batch of transactions to the pool, and notifies any
// listeners if the addition channel is non nil
-func (p *testTxPool) Add(txs []*txpool.Transaction, local bool, sync bool) []error {
- unwrapped := make([]*types.Transaction, len(txs))
- for i, tx := range txs {
- unwrapped[i] = tx.Tx
- }
+func (p *testTxPool) Add(txs []*types.Transaction, local bool, sync bool) []error {
p.lock.Lock()
defer p.lock.Unlock()
- for _, tx := range unwrapped {
+ for _, tx := range txs {
p.pool[tx.Hash()] = tx
}
-
- p.txFeed.Send(core.NewTxsEvent{Txs: unwrapped})
- return make([]error, len(unwrapped))
+ p.txFeed.Send(core.NewTxsEvent{Txs: txs})
+ return make([]error, len(txs))
}
// ReannouceTransactions announce the transactions to some peers.
@@ -131,19 +122,21 @@ func (p *testTxPool) Pending(enforceTips bool) map[common.Address][]*txpool.Lazy
for _, tx := range batch {
pending[addr] = append(pending[addr], &txpool.LazyTransaction{
Hash: tx.Hash(),
- Tx: &txpool.Transaction{Tx: tx},
+ Tx: tx,
Time: tx.Time(),
GasFeeCap: tx.GasFeeCap(),
GasTipCap: tx.GasTipCap(),
+ Gas: tx.Gas(),
+ BlobGas: tx.BlobGas(),
})
}
}
return pending
}
-// SubscribeNewTxsEvent should return an event subscription of NewTxsEvent and
+// SubscribeTransactions should return an event subscription of NewTxsEvent and
// send events to the given channel.
-func (p *testTxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
+func (p *testTxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription {
return p.txFeed.Subscribe(ch)
}
diff --git a/eth/peerset.go b/eth/peerset.go
index 2d9bba7d46..ff4215eda3 100644
--- a/eth/peerset.go
+++ b/eth/peerset.go
@@ -18,6 +18,7 @@ package eth
import (
"errors"
+ "fmt"
"math/big"
"sync"
"time"
@@ -84,6 +85,7 @@ type peerSet struct {
lock sync.RWMutex
closed bool
+ quitCh chan struct{} // Quit channel to signal termination
}
// newPeerSet creates a new peer set to track the active participants.
@@ -96,6 +98,7 @@ func newPeerSet() *peerSet {
trustPend: make(map[string]*trust.Peer),
bscWait: make(map[string]chan *bsc.Peer),
bscPend: make(map[string]*bsc.Peer),
+ quitCh: make(chan struct{}),
}
}
@@ -106,7 +109,7 @@ func (ps *peerSet) registerSnapExtension(peer *snap.Peer) error {
// Reject the peer if it advertises `snap` without `eth` as `snap` is only a
// satellite protocol meaningful with the chain selection of `eth`
if !peer.RunningCap(eth.ProtocolName, eth.ProtocolVersions) {
- return errSnapWithoutEth
+ return fmt.Errorf("%w: have %v", errSnapWithoutEth, peer.Caps())
}
// Ensure nobody can double connect
ps.lock.Lock()
@@ -233,6 +236,12 @@ func (ps *peerSet) waitSnapExtension(peer *eth.Peer) (*snap.Peer, error) {
delete(ps.snapWait, id)
ps.lock.Unlock()
return nil, errPeerWaitTimeout
+
+ case <-ps.quitCh:
+ ps.lock.Lock()
+ delete(ps.snapWait, id)
+ ps.lock.Unlock()
+ return nil, errPeerSetClosed
}
}
@@ -280,6 +289,12 @@ func (ps *peerSet) waitTrustExtension(peer *eth.Peer) (*trust.Peer, error) {
delete(ps.trustWait, id)
ps.lock.Unlock()
return nil, errPeerWaitTimeout
+
+ case <-ps.quitCh:
+ ps.lock.Lock()
+ delete(ps.trustWait, id)
+ ps.lock.Unlock()
+ return nil, errPeerSetClosed
}
}
@@ -339,6 +354,12 @@ func (ps *peerSet) waitBscExtension(peer *eth.Peer) (*bsc.Peer, error) {
}
}
}
+
+ case <-ps.quitCh:
+ ps.lock.Lock()
+ delete(ps.bscWait, id)
+ ps.lock.Unlock()
+ return nil, errPeerSetClosed
}
}
@@ -523,5 +544,8 @@ func (ps *peerSet) close() {
for _, p := range ps.peers {
p.Disconnect(p2p.DiscQuitting)
}
+ if !ps.closed {
+ close(ps.quitCh)
+ }
ps.closed = true
}
diff --git a/eth/protocols/eth/broadcast.go b/eth/protocols/eth/broadcast.go
index a6015c0094..c02e2fa60e 100644
--- a/eth/protocols/eth/broadcast.go
+++ b/eth/protocols/eth/broadcast.go
@@ -82,8 +82,8 @@ func (p *Peer) broadcastTransactions() {
)
for i := 0; i < len(queue) && size < maxTxPacketSize; i++ {
if tx := p.txpool.Get(queue[i]); tx != nil {
- txs = append(txs, tx.Tx)
- size += common.StorageSize(tx.Tx.Size())
+ txs = append(txs, tx)
+ size += common.StorageSize(tx.Size())
}
hashesCount++
}
@@ -155,8 +155,8 @@ func (p *Peer) announceTransactions() {
for count = 0; count < len(queue) && size < maxTxPacketSize; count++ {
if tx := p.txpool.Get(queue[count]); tx != nil {
pending = append(pending, queue[count])
- pendingTypes = append(pendingTypes, tx.Tx.Type())
- pendingSizes = append(pendingSizes, uint32(tx.Tx.Size()))
+ pendingTypes = append(pendingTypes, tx.Type())
+ pendingSizes = append(pendingSizes, uint32(tx.Size()))
size += common.HashLength
}
}
diff --git a/eth/protocols/eth/discovery.go b/eth/protocols/eth/discovery.go
index 1d3fcf9e41..91df2cf77e 100644
--- a/eth/protocols/eth/discovery.go
+++ b/eth/protocols/eth/discovery.go
@@ -67,6 +67,6 @@ func StartENRFilter(chain *core.BlockChain, p2p *p2p.Server) {
func currentENREntry(chain *core.BlockChain) *enrEntry {
head := chain.CurrentHeader()
return &enrEntry{
- ForkID: forkid.NewID(chain.Config(), chain.Genesis().Hash(), head.Number.Uint64(), head.Time),
+ ForkID: forkid.NewID(chain.Config(), chain.Genesis(), head.Number.Uint64(), head.Time),
}
}
diff --git a/eth/protocols/eth/dispatcher.go b/eth/protocols/eth/dispatcher.go
index 3f81e045ba..ae98820cd6 100644
--- a/eth/protocols/eth/dispatcher.go
+++ b/eth/protocols/eth/dispatcher.go
@@ -41,7 +41,7 @@ var (
// Request is a pending request to allow tracking it and delivering a response
// back to the requester on their chosen channel.
type Request struct {
- peer *Peer // Peer to which this request belogs for untracking
+ peer *Peer // Peer to which this request belongs for untracking
id uint64 // Request ID to match up replies to
sink chan *Response // Channel to deliver the response on
@@ -224,7 +224,7 @@ func (p *Peer) dispatcher() {
switch {
case res.Req == nil:
// Response arrived with an untracked ID. Since even cancelled
- // requests are tracked until fulfilment, a dangling response
+ // requests are tracked until fulfillment, a dangling response
// means the remote peer implements the protocol badly.
resOp.fail <- errDanglingResponse
diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go
index 87ed1874e9..42d0412a12 100644
--- a/eth/protocols/eth/handler.go
+++ b/eth/protocols/eth/handler.go
@@ -23,8 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/txpool"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
@@ -45,10 +44,6 @@ const (
// nowadays, the practical limit will always be softResponseLimit.
maxBodiesServe = 1024
- // maxNodeDataServe is the maximum number of state trie nodes to serve. This
- // number is there to limit the number of disk lookups.
- maxNodeDataServe = 1024
-
// maxReceiptsServe is the maximum number of block receipts to serve. This
// number is mostly there to limit the number of disk lookups. With block
// containing 200+ transactions nowadays, the practical limit will always
@@ -91,19 +86,19 @@ type Backend interface {
// TxPool defines the methods needed by the protocol handler to serve transactions.
type TxPool interface {
// Get retrieves the transaction from the local txpool with the given hash.
- Get(hash common.Hash) *txpool.Transaction
+ Get(hash common.Hash) *types.Transaction
}
// MakeProtocols constructs the P2P protocol definitions for `eth`.
func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2p.Protocol {
protocols := make([]p2p.Protocol, 0, len(ProtocolVersions))
for _, version := range ProtocolVersions {
- version := version // Closure
-
- // Path scheme does not support GetNodeData, don't advertise eth66 on it
- if version <= ETH66 && backend.Chain().TrieDB().Scheme() == rawdb.PathScheme {
+ // Blob transactions require eth/68 announcements, disable everything else
+ if version <= ETH67 && backend.Chain().Config().CancunTime != nil {
continue
}
+ version := version // Closure
+
protocols = append(protocols, p2p.Protocol{
Name: ProtocolName,
Version: version,
@@ -171,36 +166,19 @@ type Decoder interface {
Time() time.Time
}
-var eth66 = map[uint64]msgHandler{
- NewBlockHashesMsg: handleNewBlockhashes,
- NewBlockMsg: handleNewBlock,
- TransactionsMsg: handleTransactions,
- NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes66,
- GetBlockHeadersMsg: handleGetBlockHeaders66,
- BlockHeadersMsg: handleBlockHeaders66,
- GetBlockBodiesMsg: handleGetBlockBodies66,
- BlockBodiesMsg: handleBlockBodies66,
- GetNodeDataMsg: handleGetNodeData66,
- NodeDataMsg: handleNodeData66,
- GetReceiptsMsg: handleGetReceipts66,
- ReceiptsMsg: handleReceipts66,
- GetPooledTransactionsMsg: handleGetPooledTransactions66,
- PooledTransactionsMsg: handlePooledTransactions66,
-}
-
var eth67 = map[uint64]msgHandler{
NewBlockHashesMsg: handleNewBlockhashes,
NewBlockMsg: handleNewBlock,
TransactionsMsg: handleTransactions,
- NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes66,
- GetBlockHeadersMsg: handleGetBlockHeaders66,
- BlockHeadersMsg: handleBlockHeaders66,
- GetBlockBodiesMsg: handleGetBlockBodies66,
- BlockBodiesMsg: handleBlockBodies66,
- GetReceiptsMsg: handleGetReceipts66,
- ReceiptsMsg: handleReceipts66,
- GetPooledTransactionsMsg: handleGetPooledTransactions66,
- PooledTransactionsMsg: handlePooledTransactions66,
+ NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes67,
+ GetBlockHeadersMsg: handleGetBlockHeaders,
+ BlockHeadersMsg: handleBlockHeaders,
+ GetBlockBodiesMsg: handleGetBlockBodies,
+ BlockBodiesMsg: handleBlockBodies,
+ GetReceiptsMsg: handleGetReceipts,
+ ReceiptsMsg: handleReceipts,
+ GetPooledTransactionsMsg: handleGetPooledTransactions,
+ PooledTransactionsMsg: handlePooledTransactions,
}
var eth68 = map[uint64]msgHandler{
@@ -208,14 +186,14 @@ var eth68 = map[uint64]msgHandler{
NewBlockMsg: handleNewBlock,
TransactionsMsg: handleTransactions,
NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes68,
- GetBlockHeadersMsg: handleGetBlockHeaders66,
- BlockHeadersMsg: handleBlockHeaders66,
- GetBlockBodiesMsg: handleGetBlockBodies66,
- BlockBodiesMsg: handleBlockBodies66,
- GetReceiptsMsg: handleGetReceipts66,
- ReceiptsMsg: handleReceipts66,
- GetPooledTransactionsMsg: handleGetPooledTransactions66,
- PooledTransactionsMsg: handlePooledTransactions66,
+ GetBlockHeadersMsg: handleGetBlockHeaders,
+ BlockHeadersMsg: handleBlockHeaders,
+ GetBlockBodiesMsg: handleGetBlockBodies,
+ BlockBodiesMsg: handleBlockBodies,
+ GetReceiptsMsg: handleGetReceipts,
+ ReceiptsMsg: handleReceipts,
+ GetPooledTransactionsMsg: handleGetPooledTransactions,
+ PooledTransactionsMsg: handlePooledTransactions,
}
// handleMessage is invoked whenever an inbound message is received from a remote
@@ -231,14 +209,10 @@ func handleMessage(backend Backend, peer *Peer) error {
}
defer msg.Discard()
- var handlers = eth66
- if peer.Version() == ETH67 {
- handlers = eth67
- }
+ var handlers = eth67
if peer.Version() >= ETH68 {
handlers = eth68
}
-
// Track the amount of time it takes to serve the request and run the handler
if metrics.Enabled {
h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code)
diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go
index f2f8ee2d2b..310e75400b 100644
--- a/eth/protocols/eth/handler_test.go
+++ b/eth/protocols/eth/handler_test.go
@@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
"github.com/ethereum/go-ethereum/core/types"
@@ -151,7 +150,6 @@ func (b *testBackend) Handle(*Peer, Packet) error {
}
// Tests that block headers can be retrieved from a remote chain based on user queries.
-func TestGetBlockHeaders66(t *testing.T) { testGetBlockHeaders(t, ETH66) }
func TestGetBlockHeaders67(t *testing.T) { testGetBlockHeaders(t, ETH67) }
func TestGetBlockHeaders68(t *testing.T) { testGetBlockHeaders(t, ETH68) }
@@ -178,29 +176,29 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
// Create a batch of tests for various scenarios
limit := uint64(maxHeadersServe)
tests := []struct {
- query *GetBlockHeadersPacket // The query to execute for header retrieval
- expect []common.Hash // The hashes of the block whose headers are expected
+ query *GetBlockHeadersRequest // The query to execute for header retrieval
+ expect []common.Hash // The hashes of the block whose headers are expected
}{
// A single random block should be retrievable by hash
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1},
[]common.Hash{backend.chain.GetBlockByNumber(limit / 2).Hash()},
},
// A single random block should be retrievable by number
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Amount: 1},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 1},
[]common.Hash{backend.chain.GetBlockByNumber(limit / 2).Hash()},
},
// Multiple headers should be retrievable in both directions
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Amount: 3},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 3},
[]common.Hash{
backend.chain.GetBlockByNumber(limit / 2).Hash(),
backend.chain.GetBlockByNumber(limit/2 + 1).Hash(),
backend.chain.GetBlockByNumber(limit/2 + 2).Hash(),
},
}, {
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true},
[]common.Hash{
backend.chain.GetBlockByNumber(limit / 2).Hash(),
backend.chain.GetBlockByNumber(limit/2 - 1).Hash(),
@@ -209,14 +207,14 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
},
// Multiple headers with skip lists should be retrievable
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3},
[]common.Hash{
backend.chain.GetBlockByNumber(limit / 2).Hash(),
backend.chain.GetBlockByNumber(limit/2 + 4).Hash(),
backend.chain.GetBlockByNumber(limit/2 + 8).Hash(),
},
}, {
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true},
[]common.Hash{
backend.chain.GetBlockByNumber(limit / 2).Hash(),
backend.chain.GetBlockByNumber(limit/2 - 4).Hash(),
@@ -225,31 +223,31 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
},
// The chain endpoints should be retrievable
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 0}, Amount: 1},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 0}, Amount: 1},
[]common.Hash{backend.chain.GetBlockByNumber(0).Hash()},
},
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 1},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 1},
[]common.Hash{backend.chain.CurrentBlock().Hash()},
},
{ // If the peer requests a bit into the future, we deliver what we have
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 10},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 10},
[]common.Hash{backend.chain.CurrentBlock().Hash()},
},
// Ensure protocol limits are honored
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 1}, Amount: limit + 10, Reverse: true},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 1}, Amount: limit + 10, Reverse: true},
getHashes(backend.chain.CurrentBlock().Number.Uint64(), limit),
},
// Check that requesting more than available is handled gracefully
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 3, Amount: 3},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 3, Amount: 3},
[]common.Hash{
backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 4).Hash(),
backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64()).Hash(),
},
}, {
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true},
[]common.Hash{
backend.chain.GetBlockByNumber(4).Hash(),
backend.chain.GetBlockByNumber(0).Hash(),
@@ -257,13 +255,13 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
},
// Check that requesting more than available is handled gracefully, even if mid skip
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 2, Amount: 3},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 2, Amount: 3},
[]common.Hash{
backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 4).Hash(),
backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 1).Hash(),
},
}, {
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true},
[]common.Hash{
backend.chain.GetBlockByNumber(4).Hash(),
backend.chain.GetBlockByNumber(1).Hash(),
@@ -271,7 +269,7 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
},
// Check a corner case where requesting more can iterate past the endpoints
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 2}, Amount: 5, Reverse: true},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 2}, Amount: 5, Reverse: true},
[]common.Hash{
backend.chain.GetBlockByNumber(2).Hash(),
backend.chain.GetBlockByNumber(1).Hash(),
@@ -280,24 +278,24 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
},
// Check a corner case where skipping overflow loops back into the chain start
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1},
[]common.Hash{
backend.chain.GetBlockByNumber(3).Hash(),
},
},
// Check a corner case where skipping overflow loops back to the same header
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64},
[]common.Hash{
backend.chain.GetBlockByNumber(1).Hash(),
},
},
// Check that non-existing headers aren't returned
{
- &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: unknown}, Amount: 1},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: unknown}, Amount: 1},
[]common.Hash{},
}, {
- &GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() + 1}, Amount: 1},
+ &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() + 1}, Amount: 1},
[]common.Hash{},
},
}
@@ -309,13 +307,13 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
headers = append(headers, backend.chain.GetBlockByHash(hash).Header())
}
// Send the hash request and verify the response
- p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket66{
- RequestId: 123,
- GetBlockHeadersPacket: tt.query,
+ p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket{
+ RequestId: 123,
+ GetBlockHeadersRequest: tt.query,
})
- if err := p2p.ExpectMsg(peer.app, BlockHeadersMsg, &BlockHeadersPacket66{
- RequestId: 123,
- BlockHeadersPacket: headers,
+ if err := p2p.ExpectMsg(peer.app, BlockHeadersMsg, &BlockHeadersPacket{
+ RequestId: 123,
+ BlockHeadersRequest: headers,
}); err != nil {
t.Errorf("test %d: headers mismatch: %v", i, err)
}
@@ -324,11 +322,11 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
if origin := backend.chain.GetBlockByNumber(tt.query.Origin.Number); origin != nil {
tt.query.Origin.Hash, tt.query.Origin.Number = origin.Hash(), 0
- p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket66{
- RequestId: 456,
- GetBlockHeadersPacket: tt.query,
+ p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket{
+ RequestId: 456,
+ GetBlockHeadersRequest: tt.query,
})
- expected := &BlockHeadersPacket66{RequestId: 456, BlockHeadersPacket: headers}
+ expected := &BlockHeadersPacket{RequestId: 456, BlockHeadersRequest: headers}
if err := p2p.ExpectMsg(peer.app, BlockHeadersMsg, expected); err != nil {
t.Errorf("test %d by hash: headers mismatch: %v", i, err)
}
@@ -338,7 +336,6 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
}
// Tests that block contents can be retrieved from a remote chain based on their hashes.
-func TestGetBlockBodies66(t *testing.T) { testGetBlockBodies(t, ETH66) }
func TestGetBlockBodies67(t *testing.T) { testGetBlockBodies(t, ETH67) }
func TestGetBlockBodies68(t *testing.T) { testGetBlockBodies(t, ETH68) }
@@ -420,139 +417,20 @@ func testGetBlockBodies(t *testing.T, protocol uint) {
}
// Send the hash request and verify the response
- p2p.Send(peer.app, GetBlockBodiesMsg, &GetBlockBodiesPacket66{
- RequestId: 123,
- GetBlockBodiesPacket: hashes,
+ p2p.Send(peer.app, GetBlockBodiesMsg, &GetBlockBodiesPacket{
+ RequestId: 123,
+ GetBlockBodiesRequest: hashes,
})
- if err := p2p.ExpectMsg(peer.app, BlockBodiesMsg, &BlockBodiesPacket66{
- RequestId: 123,
- BlockBodiesPacket: bodies,
+ if err := p2p.ExpectMsg(peer.app, BlockBodiesMsg, &BlockBodiesPacket{
+ RequestId: 123,
+ BlockBodiesResponse: bodies,
}); err != nil {
t.Fatalf("test %d: bodies mismatch: %v", i, err)
}
}
}
-// Tests that the state trie nodes can be retrieved based on hashes.
-func TestGetNodeData66(t *testing.T) { testGetNodeData(t, ETH66, false) }
-func TestGetNodeData67(t *testing.T) { testGetNodeData(t, ETH67, true) }
-func TestGetNodeData68(t *testing.T) { testGetNodeData(t, ETH68, true) }
-
-func testGetNodeData(t *testing.T, protocol uint, drop bool) {
- t.Parallel()
-
- // Define three accounts to simulate transactions with
- acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
- acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
- acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
- acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
-
- signer := types.HomesteadSigner{}
- // Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_makers_test)
- generator := func(i int, block *core.BlockGen) {
- switch i {
- case 0:
- // In block 1, the test bank sends account #1 some ether.
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(10_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
- block.AddTx(tx)
- case 1:
- // In block 2, the test bank sends some more ether to account #1.
- // acc1Addr passes it on to account #2.
- tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
- tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, acc1Key)
- block.AddTx(tx1)
- block.AddTx(tx2)
- case 2:
- // Block 3 is empty but was mined by account #2.
- block.SetCoinbase(acc2Addr)
- block.SetExtra([]byte("yeehaw"))
- case 3:
- // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
- b2 := block.PrevBlock(1).Header()
- b2.Extra = []byte("foo")
- block.AddUncle(b2)
- b3 := block.PrevBlock(2).Header()
- b3.Extra = []byte("foo")
- block.AddUncle(b3)
- }
- }
- // Assemble the test environment
- backend := newTestBackendWithGenerator(4, false, generator)
- defer backend.close()
-
- peer, _ := newTestPeer("peer", protocol, backend)
- defer peer.close()
-
- // Collect all state tree hashes.
- var hashes []common.Hash
- it := backend.db.NewIterator(nil, nil)
- for it.Next() {
- if key := it.Key(); len(key) == common.HashLength {
- hashes = append(hashes, common.BytesToHash(key))
- }
- }
- it.Release()
-
- // Request all hashes.
- p2p.Send(peer.app, GetNodeDataMsg, &GetNodeDataPacket66{
- RequestId: 123,
- GetNodeDataPacket: hashes,
- })
- msg, err := peer.app.ReadMsg()
- if !drop {
- if err != nil {
- t.Fatalf("failed to read node data response: %v", err)
- }
- } else {
- if err != nil {
- return
- }
- t.Fatalf("succeeded to read node data response on non-supporting protocol: %v", msg)
- }
- if msg.Code != NodeDataMsg {
- t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, NodeDataMsg)
- }
- var res NodeDataPacket66
- if err := msg.Decode(&res); err != nil {
- t.Fatalf("failed to decode response node data: %v", err)
- }
-
- // Verify that all hashes correspond to the requested data.
- data := res.NodeDataPacket
- for i, want := range hashes {
- if hash := crypto.Keccak256Hash(data[i]); hash != want {
- t.Errorf("data hash mismatch: have %x, want %x", hash, want)
- }
- }
-
- // Reconstruct state tree from the received data.
- reconstructDB := rawdb.NewMemoryDatabase()
- for i := 0; i < len(data); i++ {
- rawdb.WriteLegacyTrieNode(reconstructDB, hashes[i], data[i])
- }
-
- // Sanity check whether all state matches.
- accounts := []common.Address{testAddr, acc1Addr, acc2Addr}
- for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
- root := backend.chain.GetBlockByNumber(i).Root()
- reconstructed, _ := state.New(root, state.NewDatabase(reconstructDB), nil)
- for j, acc := range accounts {
- state, _ := backend.chain.StateAt(root)
- bw := state.GetBalance(acc)
- bh := reconstructed.GetBalance(acc)
-
- if (bw == nil) != (bh == nil) {
- t.Errorf("block %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw)
- }
- if bw != nil && bh != nil && bw.Cmp(bh) != 0 {
- t.Errorf("block %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw)
- }
- }
- }
-}
-
// Tests that the transaction receipts can be retrieved based on hashes.
-func TestGetBlockReceipts66(t *testing.T) { testGetBlockReceipts(t, ETH66) }
func TestGetBlockReceipts67(t *testing.T) { testGetBlockReceipts(t, ETH67) }
func TestGetBlockReceipts68(t *testing.T) { testGetBlockReceipts(t, ETH68) }
@@ -613,13 +491,13 @@ func testGetBlockReceipts(t *testing.T, protocol uint) {
receipts = append(receipts, backend.chain.GetReceiptsByHash(block.Hash()))
}
// Send the hash request and verify the response
- p2p.Send(peer.app, GetReceiptsMsg, &GetReceiptsPacket66{
- RequestId: 123,
- GetReceiptsPacket: hashes,
+ p2p.Send(peer.app, GetReceiptsMsg, &GetReceiptsPacket{
+ RequestId: 123,
+ GetReceiptsRequest: hashes,
})
- if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket66{
- RequestId: 123,
- ReceiptsPacket: receipts,
+ if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket{
+ RequestId: 123,
+ ReceiptsResponse: receipts,
}); err != nil {
t.Errorf("receipts mismatch: %v", err)
}
diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go
index cdac0da21a..069e92dadf 100644
--- a/eth/protocols/eth/handlers.go
+++ b/eth/protocols/eth/handlers.go
@@ -22,27 +22,25 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
-// handleGetBlockHeaders66 is the eth/66 version of handleGetBlockHeaders
-func handleGetBlockHeaders66(backend Backend, msg Decoder, peer *Peer) error {
+func handleGetBlockHeaders(backend Backend, msg Decoder, peer *Peer) error {
// Decode the complex header query
- var query GetBlockHeadersPacket66
+ var query GetBlockHeadersPacket
if err := msg.Decode(&query); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
- response := ServiceGetBlockHeadersQuery(backend.Chain(), query.GetBlockHeadersPacket, peer)
+ response := ServiceGetBlockHeadersQuery(backend.Chain(), query.GetBlockHeadersRequest, peer)
return peer.ReplyBlockHeadersRLP(query.RequestId, response)
}
// ServiceGetBlockHeadersQuery assembles the response to a header query. It is
// exposed to allow external packages to test protocol behavior.
-func ServiceGetBlockHeadersQuery(chain *core.BlockChain, query *GetBlockHeadersPacket, peer *Peer) []rlp.RawValue {
+func ServiceGetBlockHeadersQuery(chain *core.BlockChain, query *GetBlockHeadersRequest, peer *Peer) []rlp.RawValue {
if query.Skip == 0 {
// The fast path: when the request is for a contiguous segment of headers.
return serviceContiguousBlockHeaderQuery(chain, query)
@@ -51,7 +49,7 @@ func ServiceGetBlockHeadersQuery(chain *core.BlockChain, query *GetBlockHeadersP
}
}
-func serviceNonContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersPacket, peer *Peer) []rlp.RawValue {
+func serviceNonContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersRequest, peer *Peer) []rlp.RawValue {
hashMode := query.Origin.Hash != (common.Hash{})
first := true
maxNonCanonical := uint64(100)
@@ -140,7 +138,7 @@ func serviceNonContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBloc
return headers
}
-func serviceContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersPacket) []rlp.RawValue {
+func serviceContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersRequest) []rlp.RawValue {
count := query.Amount
if count > maxHeadersServe {
count = maxHeadersServe
@@ -203,19 +201,19 @@ func serviceContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHe
}
}
-func handleGetBlockBodies66(backend Backend, msg Decoder, peer *Peer) error {
+func handleGetBlockBodies(backend Backend, msg Decoder, peer *Peer) error {
// Decode the block body retrieval message
- var query GetBlockBodiesPacket66
+ var query GetBlockBodiesPacket
if err := msg.Decode(&query); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
- response := ServiceGetBlockBodiesQuery(backend.Chain(), query.GetBlockBodiesPacket)
+ response := ServiceGetBlockBodiesQuery(backend.Chain(), query.GetBlockBodiesRequest)
return peer.ReplyBlockBodiesRLP(query.RequestId, response)
}
// ServiceGetBlockBodiesQuery assembles the response to a body query. It is
// exposed to allow external packages to test protocol behavior.
-func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesPacket) []rlp.RawValue {
+func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesRequest) []rlp.RawValue {
// Gather blocks until the fetch or network limits is reached
var (
bytes int
@@ -234,60 +232,19 @@ func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesPack
return bodies
}
-func handleGetNodeData66(backend Backend, msg Decoder, peer *Peer) error {
- // Decode the trie node data retrieval message
- var query GetNodeDataPacket66
- if err := msg.Decode(&query); err != nil {
- return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
- }
- response := ServiceGetNodeDataQuery(backend.Chain(), query.GetNodeDataPacket)
- return peer.ReplyNodeData(query.RequestId, response)
-}
-
-// ServiceGetNodeDataQuery assembles the response to a node data query. It is
-// exposed to allow external packages to test protocol behavior.
-func ServiceGetNodeDataQuery(chain *core.BlockChain, query GetNodeDataPacket) [][]byte {
- // Request nodes by hash is not supported in path-based scheme.
- if chain.TrieDB().Scheme() == rawdb.PathScheme {
- return nil
- }
- // Gather state data until the fetch or network limits is reached
- var (
- bytes int
- nodes [][]byte
- )
- for lookups, hash := range query {
- if bytes >= softResponseLimit || len(nodes) >= maxNodeDataServe ||
- lookups >= 2*maxNodeDataServe {
- break
- }
- // Retrieve the requested state entry
- entry, err := chain.TrieDB().Node(hash)
- if len(entry) == 0 || err != nil {
- // Read the contract code with prefix only to save unnecessary lookups.
- entry, err = chain.ContractCodeWithPrefix(hash)
- }
- if err == nil && len(entry) > 0 {
- nodes = append(nodes, entry)
- bytes += len(entry)
- }
- }
- return nodes
-}
-
-func handleGetReceipts66(backend Backend, msg Decoder, peer *Peer) error {
+func handleGetReceipts(backend Backend, msg Decoder, peer *Peer) error {
// Decode the block receipts retrieval message
- var query GetReceiptsPacket66
+ var query GetReceiptsPacket
if err := msg.Decode(&query); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
- response := ServiceGetReceiptsQuery(backend.Chain(), query.GetReceiptsPacket)
+ response := ServiceGetReceiptsQuery(backend.Chain(), query.GetReceiptsRequest)
return peer.ReplyReceiptsRLP(query.RequestId, response)
}
// ServiceGetReceiptsQuery assembles the response to a receipt query. It is
// exposed to allow external packages to test protocol behavior.
-func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsPacket) []rlp.RawValue {
+func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsRequest) []rlp.RawValue {
// Gather state data until the fetch or network limits is reached
var (
bytes int
@@ -356,15 +313,15 @@ func handleNewBlock(backend Backend, msg Decoder, peer *Peer) error {
return backend.Handle(peer, ann)
}
-func handleBlockHeaders66(backend Backend, msg Decoder, peer *Peer) error {
+func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error {
// A batch of headers arrived to one of our previous requests
- res := new(BlockHeadersPacket66)
+ res := new(BlockHeadersPacket)
if err := msg.Decode(res); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
metadata := func() interface{} {
- hashes := make([]common.Hash, len(res.BlockHeadersPacket))
- for i, header := range res.BlockHeadersPacket {
+ hashes := make([]common.Hash, len(res.BlockHeadersRequest))
+ for i, header := range res.BlockHeadersRequest {
hashes[i] = header.Hash()
}
return hashes
@@ -372,24 +329,24 @@ func handleBlockHeaders66(backend Backend, msg Decoder, peer *Peer) error {
return peer.dispatchResponse(&Response{
id: res.RequestId,
code: BlockHeadersMsg,
- Res: &res.BlockHeadersPacket,
+ Res: &res.BlockHeadersRequest,
}, metadata)
}
-func handleBlockBodies66(backend Backend, msg Decoder, peer *Peer) error {
+func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error {
// A batch of block bodies arrived to one of our previous requests
- res := new(BlockBodiesPacket66)
+ res := new(BlockBodiesPacket)
if err := msg.Decode(res); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
metadata := func() interface{} {
var (
- txsHashes = make([]common.Hash, len(res.BlockBodiesPacket))
- uncleHashes = make([]common.Hash, len(res.BlockBodiesPacket))
- withdrawalHashes = make([]common.Hash, len(res.BlockBodiesPacket))
+ txsHashes = make([]common.Hash, len(res.BlockBodiesResponse))
+ uncleHashes = make([]common.Hash, len(res.BlockBodiesResponse))
+ withdrawalHashes = make([]common.Hash, len(res.BlockBodiesResponse))
)
hasher := trie.NewStackTrie(nil)
- for i, body := range res.BlockBodiesPacket {
+ for i, body := range res.BlockBodiesResponse {
txsHashes[i] = types.DeriveSha(types.Transactions(body.Transactions), hasher)
uncleHashes[i] = types.CalcUncleHash(body.Uncles)
if body.Withdrawals != nil {
@@ -401,33 +358,20 @@ func handleBlockBodies66(backend Backend, msg Decoder, peer *Peer) error {
return peer.dispatchResponse(&Response{
id: res.RequestId,
code: BlockBodiesMsg,
- Res: &res.BlockBodiesPacket,
+ Res: &res.BlockBodiesResponse,
}, metadata)
}
-func handleNodeData66(backend Backend, msg Decoder, peer *Peer) error {
- // A batch of node state data arrived to one of our previous requests
- res := new(NodeDataPacket66)
- if err := msg.Decode(res); err != nil {
- return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
- }
- return peer.dispatchResponse(&Response{
- id: res.RequestId,
- code: NodeDataMsg,
- Res: &res.NodeDataPacket,
- }, nil) // No post-processing, we're not using this packet anymore
-}
-
-func handleReceipts66(backend Backend, msg Decoder, peer *Peer) error {
+func handleReceipts(backend Backend, msg Decoder, peer *Peer) error {
// A batch of receipts arrived to one of our previous requests
- res := new(ReceiptsPacket66)
+ res := new(ReceiptsPacket)
if err := msg.Decode(res); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
metadata := func() interface{} {
hasher := trie.NewStackTrie(nil)
- hashes := make([]common.Hash, len(res.ReceiptsPacket))
- for i, receipt := range res.ReceiptsPacket {
+ hashes := make([]common.Hash, len(res.ReceiptsResponse))
+ for i, receipt := range res.ReceiptsResponse {
hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher)
}
return hashes
@@ -435,17 +379,17 @@ func handleReceipts66(backend Backend, msg Decoder, peer *Peer) error {
return peer.dispatchResponse(&Response{
id: res.RequestId,
code: ReceiptsMsg,
- Res: &res.ReceiptsPacket,
+ Res: &res.ReceiptsResponse,
}, metadata)
}
-func handleNewPooledTransactionHashes66(backend Backend, msg Decoder, peer *Peer) error {
+func handleNewPooledTransactionHashes67(backend Backend, msg Decoder, peer *Peer) error {
// New transaction announcement arrived, make sure we have
// a valid and fresh chain to handle them
if !backend.AcceptTxs() {
return nil
}
- ann := new(NewPooledTransactionHashesPacket66)
+ ann := new(NewPooledTransactionHashesPacket67)
if err := msg.Decode(ann); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
@@ -476,17 +420,17 @@ func handleNewPooledTransactionHashes68(backend Backend, msg Decoder, peer *Peer
return backend.Handle(peer, ann)
}
-func handleGetPooledTransactions66(backend Backend, msg Decoder, peer *Peer) error {
+func handleGetPooledTransactions(backend Backend, msg Decoder, peer *Peer) error {
// Decode the pooled transactions retrieval message
- var query GetPooledTransactionsPacket66
+ var query GetPooledTransactionsPacket
if err := msg.Decode(&query); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
- hashes, txs := answerGetPooledTransactions(backend, query.GetPooledTransactionsPacket, peer)
+ hashes, txs := answerGetPooledTransactions(backend, query.GetPooledTransactionsRequest)
return peer.ReplyPooledTransactionsRLP(query.RequestId, hashes, txs)
}
-func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsPacket, peer *Peer) ([]common.Hash, []rlp.RawValue) {
+func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsRequest) ([]common.Hash, []rlp.RawValue) {
// Gather transactions until the fetch or network limits is reached
var (
bytes int
@@ -503,7 +447,7 @@ func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsPac
continue
}
// If known, encode and queue for response packet
- if encoded, err := rlp.EncodeToBytes(tx.Tx); err != nil {
+ if encoded, err := rlp.EncodeToBytes(tx); err != nil {
log.Error("Failed to encode transaction", "err", err)
} else {
hashes = append(hashes, hash)
@@ -534,17 +478,17 @@ func handleTransactions(backend Backend, msg Decoder, peer *Peer) error {
return backend.Handle(peer, &txs)
}
-func handlePooledTransactions66(backend Backend, msg Decoder, peer *Peer) error {
+func handlePooledTransactions(backend Backend, msg Decoder, peer *Peer) error {
// Transactions arrived, make sure we have a valid and fresh chain to handle them
if !backend.AcceptTxs() {
return nil
}
// Transactions can be processed, parse all of them and deliver to the pool
- var txs PooledTransactionsPacket66
+ var txs PooledTransactionsPacket
if err := msg.Decode(&txs); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
- for i, tx := range txs.PooledTransactionsPacket {
+ for i, tx := range txs.PooledTransactionsResponse {
// Validate and mark the remote transaction
if tx == nil {
return fmt.Errorf("%w: transaction %d is nil", errDecode, i)
@@ -553,5 +497,5 @@ func handlePooledTransactions66(backend Backend, msg Decoder, peer *Peer) error
}
requestTracker.Fulfil(peer.id, peer.version, PooledTransactionsMsg, txs.RequestId)
- return backend.Handle(peer, &txs.PooledTransactionsPacket)
+ return backend.Handle(peer, &txs.PooledTransactionsResponse)
}
diff --git a/eth/protocols/eth/handshake_test.go b/eth/protocols/eth/handshake_test.go
index e9c8bc5104..bdabfb165f 100644
--- a/eth/protocols/eth/handshake_test.go
+++ b/eth/protocols/eth/handshake_test.go
@@ -27,7 +27,8 @@ import (
)
// Tests that handshake failures are detected and reported correctly.
-func TestHandshake66(t *testing.T) { testHandshake(t, ETH66) }
+func TestHandshake67(t *testing.T) { testHandshake(t, ETH67) }
+func TestHandshake68(t *testing.T) { testHandshake(t, ETH68) }
func testHandshake(t *testing.T, protocol uint) {
t.Parallel()
@@ -40,7 +41,7 @@ func testHandshake(t *testing.T, protocol uint) {
genesis = backend.chain.Genesis()
head = backend.chain.CurrentBlock()
td = backend.chain.GetTd(head.Hash(), head.Number.Uint64())
- forkID = forkid.NewID(backend.chain.Config(), backend.chain.Genesis().Hash(), backend.chain.CurrentHeader().Number.Uint64(), backend.chain.CurrentHeader().Time)
+ forkID = forkid.NewID(backend.chain.Config(), backend.chain.Genesis(), backend.chain.CurrentHeader().Number.Uint64(), backend.chain.CurrentHeader().Time)
)
tests := []struct {
code uint64
diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go
index 8440ff95b1..c58d133d1a 100644
--- a/eth/protocols/eth/peer.go
+++ b/eth/protocols/eth/peer.go
@@ -86,7 +86,7 @@ type Peer struct {
txBroadcast chan []common.Hash // Channel used to queue transaction propagation requests
txAnnounce chan []common.Hash // Channel used to queue transaction announcement requests
- reqDispatch chan *request // Dispatch channel to send requests and track then until fulfilment
+ reqDispatch chan *request // Dispatch channel to send requests and track then until fulfillment
reqCancel chan *cancel // Dispatch channel to cancel pending requests and untrack them
resDispatch chan *response // Dispatch channel to fulfil pending requests and untrack them
@@ -243,7 +243,7 @@ func (p *Peer) AsyncSendTransactions(hashes []common.Hash) {
func (p *Peer) sendPooledTransactionHashes66(hashes []common.Hash) error {
// Mark all the transactions as known, but ensure we don't overflow our limits
p.knownTxs.Add(hashes...)
- return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket66(hashes))
+ return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket67(hashes))
}
// sendPooledTransactionHashes68 sends transaction hashes (tagged with their type
@@ -274,15 +274,15 @@ func (p *Peer) AsyncSendPooledTransactionHashes(hashes []common.Hash) {
}
}
-// ReplyPooledTransactionsRLP is the eth/66 version of SendPooledTransactionsRLP.
+// ReplyPooledTransactionsRLP is the response to RequestTxs.
func (p *Peer) ReplyPooledTransactionsRLP(id uint64, hashes []common.Hash, txs []rlp.RawValue) error {
// Mark all the transactions as known, but ensure we don't overflow our limits
p.knownTxs.Add(hashes...)
- // Not packed into PooledTransactionsPacket to avoid RLP decoding
- return p2p.Send(p.rw, PooledTransactionsMsg, &PooledTransactionsRLPPacket66{
- RequestId: id,
- PooledTransactionsRLPPacket: txs,
+ // Not packed into PooledTransactionsResponse to avoid RLP decoding
+ return p2p.Send(p.rw, PooledTransactionsMsg, &PooledTransactionsRLPPacket{
+ RequestId: id,
+ PooledTransactionsRLPResponse: txs,
})
}
@@ -335,41 +335,28 @@ func (p *Peer) AsyncSendNewBlock(block *types.Block, td *big.Int) {
}
}
-// SendBlockHeaders sends a batch of block headers to the remote peer.
-func (p *Peer) SendBlockHeaders(headers []*types.Header) error {
- return p2p.Send(p.rw, BlockHeadersMsg, BlockHeadersPacket(headers))
-}
-
-// ReplyBlockHeadersRLP is the eth/66 response to GetBlockHeaders.
+// ReplyBlockHeadersRLP is the response to GetBlockHeaders.
func (p *Peer) ReplyBlockHeadersRLP(id uint64, headers []rlp.RawValue) error {
- return p2p.Send(p.rw, BlockHeadersMsg, &BlockHeadersRLPPacket66{
- RequestId: id,
- BlockHeadersRLPPacket: headers,
+ return p2p.Send(p.rw, BlockHeadersMsg, &BlockHeadersRLPPacket{
+ RequestId: id,
+ BlockHeadersRLPResponse: headers,
})
}
-// ReplyBlockBodiesRLP is the eth/66 response to GetBlockBodies.
+// ReplyBlockBodiesRLP is the response to GetBlockBodies.
func (p *Peer) ReplyBlockBodiesRLP(id uint64, bodies []rlp.RawValue) error {
- // Not packed into BlockBodiesPacket to avoid RLP decoding
- return p2p.Send(p.rw, BlockBodiesMsg, &BlockBodiesRLPPacket66{
- RequestId: id,
- BlockBodiesRLPPacket: bodies,
- })
-}
-
-// ReplyNodeData is the eth/66 response to GetNodeData.
-func (p *Peer) ReplyNodeData(id uint64, data [][]byte) error {
- return p2p.Send(p.rw, NodeDataMsg, &NodeDataPacket66{
- RequestId: id,
- NodeDataPacket: data,
+ // Not packed into BlockBodiesResponse to avoid RLP decoding
+ return p2p.Send(p.rw, BlockBodiesMsg, &BlockBodiesRLPPacket{
+ RequestId: id,
+ BlockBodiesRLPResponse: bodies,
})
}
-// ReplyReceiptsRLP is the eth/66 response to GetReceipts.
+// ReplyReceiptsRLP is the response to GetReceipts.
func (p *Peer) ReplyReceiptsRLP(id uint64, receipts []rlp.RawValue) error {
- return p2p.Send(p.rw, ReceiptsMsg, &ReceiptsRLPPacket66{
- RequestId: id,
- ReceiptsRLPPacket: receipts,
+ return p2p.Send(p.rw, ReceiptsMsg, &ReceiptsRLPPacket{
+ RequestId: id,
+ ReceiptsRLPResponse: receipts,
})
}
@@ -384,9 +371,9 @@ func (p *Peer) RequestOneHeader(hash common.Hash, sink chan *Response) (*Request
sink: sink,
code: GetBlockHeadersMsg,
want: BlockHeadersMsg,
- data: &GetBlockHeadersPacket66{
+ data: &GetBlockHeadersPacket{
RequestId: id,
- GetBlockHeadersPacket: &GetBlockHeadersPacket{
+ GetBlockHeadersRequest: &GetBlockHeadersRequest{
Origin: HashOrNumber{Hash: hash},
Amount: uint64(1),
Skip: uint64(0),
@@ -411,9 +398,9 @@ func (p *Peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, re
sink: sink,
code: GetBlockHeadersMsg,
want: BlockHeadersMsg,
- data: &GetBlockHeadersPacket66{
+ data: &GetBlockHeadersPacket{
RequestId: id,
- GetBlockHeadersPacket: &GetBlockHeadersPacket{
+ GetBlockHeadersRequest: &GetBlockHeadersRequest{
Origin: HashOrNumber{Hash: origin},
Amount: uint64(amount),
Skip: uint64(skip),
@@ -438,9 +425,9 @@ func (p *Peer) RequestHeadersByNumber(origin uint64, amount int, skip int, rever
sink: sink,
code: GetBlockHeadersMsg,
want: BlockHeadersMsg,
- data: &GetBlockHeadersPacket66{
+ data: &GetBlockHeadersPacket{
RequestId: id,
- GetBlockHeadersPacket: &GetBlockHeadersPacket{
+ GetBlockHeadersRequest: &GetBlockHeadersRequest{
Origin: HashOrNumber{Number: origin},
Amount: uint64(amount),
Skip: uint64(skip),
@@ -465,31 +452,9 @@ func (p *Peer) RequestBodies(hashes []common.Hash, sink chan *Response) (*Reques
sink: sink,
code: GetBlockBodiesMsg,
want: BlockBodiesMsg,
- data: &GetBlockBodiesPacket66{
- RequestId: id,
- GetBlockBodiesPacket: hashes,
- },
- }
- if err := p.dispatchRequest(req); err != nil {
- return nil, err
- }
- return req, nil
-}
-
-// RequestNodeData fetches a batch of arbitrary data from a node's known state
-// data, corresponding to the specified hashes.
-func (p *Peer) RequestNodeData(hashes []common.Hash, sink chan *Response) (*Request, error) {
- p.Log().Debug("Fetching batch of state data", "count", len(hashes))
- id := rand.Uint64()
-
- req := &Request{
- id: id,
- sink: sink,
- code: GetNodeDataMsg,
- want: NodeDataMsg,
- data: &GetNodeDataPacket66{
- RequestId: id,
- GetNodeDataPacket: hashes,
+ data: &GetBlockBodiesPacket{
+ RequestId: id,
+ GetBlockBodiesRequest: hashes,
},
}
if err := p.dispatchRequest(req); err != nil {
@@ -508,9 +473,9 @@ func (p *Peer) RequestReceipts(hashes []common.Hash, sink chan *Response) (*Requ
sink: sink,
code: GetReceiptsMsg,
want: ReceiptsMsg,
- data: &GetReceiptsPacket66{
- RequestId: id,
- GetReceiptsPacket: hashes,
+ data: &GetReceiptsPacket{
+ RequestId: id,
+ GetReceiptsRequest: hashes,
},
}
if err := p.dispatchRequest(req); err != nil {
@@ -525,9 +490,9 @@ func (p *Peer) RequestTxs(hashes []common.Hash) error {
id := rand.Uint64()
requestTracker.Track(p.id, p.version, GetPooledTransactionsMsg, PooledTransactionsMsg, id)
- return p2p.Send(p.rw, GetPooledTransactionsMsg, &GetPooledTransactionsPacket66{
- RequestId: id,
- GetPooledTransactionsPacket: hashes,
+ return p2p.Send(p.rw, GetPooledTransactionsMsg, &GetPooledTransactionsPacket{
+ RequestId: id,
+ GetPooledTransactionsRequest: hashes,
})
}
diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go
index 59c1c59d85..18d33cdb72 100644
--- a/eth/protocols/eth/protocol.go
+++ b/eth/protocols/eth/protocol.go
@@ -30,7 +30,6 @@ import (
// Constants to match up protocol versions and messages
const (
- ETH66 = 66
ETH67 = 67
ETH68 = 68
)
@@ -41,11 +40,11 @@ const ProtocolName = "eth"
// ProtocolVersions are the supported versions of the `eth` protocol (first
// is primary).
-var ProtocolVersions = []uint{ETH68, ETH67, ETH66}
+var ProtocolVersions = []uint{ETH68, ETH67}
// protocolLengths are the number of implemented message corresponding to
// different protocol versions.
-var protocolLengths = map[uint]uint64{ETH68: 17, ETH67: 18, ETH66: 17}
+var protocolLengths = map[uint]uint64{ETH68: 17, ETH67: 18}
// maxMessageSize is the maximum cap on the size of a protocol message.
const maxMessageSize = 10 * 1024 * 1024
@@ -63,8 +62,6 @@ const (
GetPooledTransactionsMsg = 0x09
PooledTransactionsMsg = 0x0a
UpgradeStatusMsg = 0x0b // Protocol messages overloaded in eth/66
- GetNodeDataMsg = 0x0d
- NodeDataMsg = 0x0e
GetReceiptsMsg = 0x0f
ReceiptsMsg = 0x10
)
@@ -86,7 +83,7 @@ type Packet interface {
Kind() byte // Kind returns the message type.
}
-// StatusPacket is the network packet for the status message for eth/64 and later.
+// StatusPacket is the network packet for the status message.
type StatusPacket struct {
ProtocolVersion uint32
NetworkID uint64
@@ -148,18 +145,18 @@ func (p *NewBlockHashesPacket) Unpack() ([]common.Hash, []uint64) {
// TransactionsPacket is the network packet for broadcasting new transactions.
type TransactionsPacket []*types.Transaction
-// GetBlockHeadersPacket represents a block header query.
-type GetBlockHeadersPacket struct {
+// GetBlockHeadersRequest represents a block header query.
+type GetBlockHeadersRequest struct {
Origin HashOrNumber // Block from which to retrieve headers
Amount uint64 // Maximum number of headers to retrieve
Skip uint64 // Blocks to skip between consecutive headers
Reverse bool // Query direction (false = rising towards latest, true = falling towards genesis)
}
-// GetBlockHeadersPacket66 represents a block header query over eth/66
-type GetBlockHeadersPacket66 struct {
+// GetBlockHeadersPacket represents a block header query with request ID wrapping.
+type GetBlockHeadersPacket struct {
RequestId uint64
- *GetBlockHeadersPacket
+ *GetBlockHeadersRequest
}
// HashOrNumber is a combined field for specifying an origin block.
@@ -198,23 +195,23 @@ func (hn *HashOrNumber) DecodeRLP(s *rlp.Stream) error {
}
}
-// BlockHeadersPacket represents a block header response.
-type BlockHeadersPacket []*types.Header
+// BlockHeadersRequest represents a block header response.
+type BlockHeadersRequest []*types.Header
-// BlockHeadersPacket66 represents a block header response over eth/66.
-type BlockHeadersPacket66 struct {
+// BlockHeadersPacket represents a block header response over with request ID wrapping.
+type BlockHeadersPacket struct {
RequestId uint64
- BlockHeadersPacket
+ BlockHeadersRequest
}
-// BlockHeadersRLPPacket represents a block header response, to use when we already
+// BlockHeadersRLPResponse represents a block header response, to use when we already
// have the headers rlp encoded.
-type BlockHeadersRLPPacket []rlp.RawValue
+type BlockHeadersRLPResponse []rlp.RawValue
-// BlockHeadersRLPPacket66 represents a block header response over eth/66.
-type BlockHeadersRLPPacket66 struct {
+// BlockHeadersRLPPacket represents a block header response with request ID wrapping.
+type BlockHeadersRLPPacket struct {
RequestId uint64
- BlockHeadersRLPPacket
+ BlockHeadersRLPResponse
}
// NewBlockPacket is the network packet for the block propagation message.
@@ -236,33 +233,34 @@ func (request *NewBlockPacket) sanityCheck() error {
return nil
}
-// GetBlockBodiesPacket represents a block body query.
-type GetBlockBodiesPacket []common.Hash
+// GetBlockBodiesRequest represents a block body query.
+type GetBlockBodiesRequest []common.Hash
-// GetBlockBodiesPacket66 represents a block body query over eth/66.
-type GetBlockBodiesPacket66 struct {
+// GetBlockBodiesPacket represents a block body query with request ID wrapping.
+type GetBlockBodiesPacket struct {
RequestId uint64
- GetBlockBodiesPacket
+ GetBlockBodiesRequest
}
-// BlockBodiesPacket is the network packet for block content distribution.
-type BlockBodiesPacket []*BlockBody
+// BlockBodiesResponse is the network packet for block content distribution.
+type BlockBodiesResponse []*BlockBody
-// BlockBodiesPacket66 is the network packet for block content distribution over eth/66.
-type BlockBodiesPacket66 struct {
+// BlockBodiesPacket is the network packet for block content distribution with
+// request ID wrapping.
+type BlockBodiesPacket struct {
RequestId uint64
- BlockBodiesPacket
+ BlockBodiesResponse
}
-// BlockBodiesRLPPacket is used for replying to block body requests, in cases
+// BlockBodiesRLPResponse is used for replying to block body requests, in cases
// where we already have them RLP-encoded, and thus can avoid the decode-encode
// roundtrip.
-type BlockBodiesRLPPacket []rlp.RawValue
+type BlockBodiesRLPResponse []rlp.RawValue
-// BlockBodiesRLPPacket66 is the BlockBodiesRLPPacket over eth/66
-type BlockBodiesRLPPacket66 struct {
+// BlockBodiesRLPPacket is the BlockBodiesRLPResponse with request ID wrapping.
+type BlockBodiesRLPPacket struct {
RequestId uint64
- BlockBodiesRLPPacket
+ BlockBodiesRLPResponse
}
// BlockBody represents the data content of a single block.
@@ -274,7 +272,7 @@ type BlockBody struct {
// Unpack retrieves the transactions and uncles from the range packet and returns
// them in a split flat format that's more consistent with the internal data structures.
-func (p *BlockBodiesPacket) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal) {
+func (p *BlockBodiesResponse) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal) {
// TODO(matt): add support for withdrawals to fetchers
var (
txset = make([][]*types.Transaction, len(*p))
@@ -287,53 +285,36 @@ func (p *BlockBodiesPacket) Unpack() ([][]*types.Transaction, [][]*types.Header,
return txset, uncleset, withdrawalset
}
-// GetNodeDataPacket represents a trie node data query.
-type GetNodeDataPacket []common.Hash
-
-// GetNodeDataPacket66 represents a trie node data query over eth/66.
-type GetNodeDataPacket66 struct {
- RequestId uint64
- GetNodeDataPacket
-}
-
-// NodeDataPacket is the network packet for trie node data distribution.
-type NodeDataPacket [][]byte
+// GetReceiptsRequest represents a block receipts query.
+type GetReceiptsRequest []common.Hash
-// NodeDataPacket66 is the network packet for trie node data distribution over eth/66.
-type NodeDataPacket66 struct {
+// GetReceiptsPacket represents a block receipts query with request ID wrapping.
+type GetReceiptsPacket struct {
RequestId uint64
- NodeDataPacket
+ GetReceiptsRequest
}
-// GetReceiptsPacket represents a block receipts query.
-type GetReceiptsPacket []common.Hash
+// ReceiptsResponse is the network packet for block receipts distribution.
+type ReceiptsResponse [][]*types.Receipt
-// GetReceiptsPacket66 represents a block receipts query over eth/66.
-type GetReceiptsPacket66 struct {
+// ReceiptsPacket is the network packet for block receipts distribution with
+// request ID wrapping.
+type ReceiptsPacket struct {
RequestId uint64
- GetReceiptsPacket
+ ReceiptsResponse
}
-// ReceiptsPacket is the network packet for block receipts distribution.
-type ReceiptsPacket [][]*types.Receipt
+// ReceiptsRLPResponse is used for receipts, when we already have it encoded
+type ReceiptsRLPResponse []rlp.RawValue
-// ReceiptsPacket66 is the network packet for block receipts distribution over eth/66.
-type ReceiptsPacket66 struct {
+// ReceiptsRLPPacket is ReceiptsRLPResponse with request ID wrapping.
+type ReceiptsRLPPacket struct {
RequestId uint64
- ReceiptsPacket
+ ReceiptsRLPResponse
}
-// ReceiptsRLPPacket is used for receipts, when we already have it encoded
-type ReceiptsRLPPacket []rlp.RawValue
-
-// ReceiptsRLPPacket66 is the eth-66 version of ReceiptsRLPPacket
-type ReceiptsRLPPacket66 struct {
- RequestId uint64
- ReceiptsRLPPacket
-}
-
-// NewPooledTransactionHashesPacket66 represents a transaction announcement packet on eth/66 and eth/67.
-type NewPooledTransactionHashesPacket66 []common.Hash
+// NewPooledTransactionHashesPacket67 represents a transaction announcement packet on eth/67.
+type NewPooledTransactionHashesPacket67 []common.Hash
// NewPooledTransactionHashesPacket68 represents a transaction announcement packet on eth/68 and newer.
type NewPooledTransactionHashesPacket68 struct {
@@ -342,31 +323,33 @@ type NewPooledTransactionHashesPacket68 struct {
Hashes []common.Hash
}
-// GetPooledTransactionsPacket represents a transaction query.
-type GetPooledTransactionsPacket []common.Hash
+// GetPooledTransactionsRequest represents a transaction query.
+type GetPooledTransactionsRequest []common.Hash
-type GetPooledTransactionsPacket66 struct {
+// GetPooledTransactionsPacket represents a transaction query with request ID wrapping.
+type GetPooledTransactionsPacket struct {
RequestId uint64
- GetPooledTransactionsPacket
+ GetPooledTransactionsRequest
}
-// PooledTransactionsPacket is the network packet for transaction distribution.
-type PooledTransactionsPacket []*types.Transaction
+// PooledTransactionsResponse is the network packet for transaction distribution.
+type PooledTransactionsResponse []*types.Transaction
-// PooledTransactionsPacket66 is the network packet for transaction distribution over eth/66.
-type PooledTransactionsPacket66 struct {
+// PooledTransactionsPacket is the network packet for transaction distribution
+// with request ID wrapping.
+type PooledTransactionsPacket struct {
RequestId uint64
- PooledTransactionsPacket
+ PooledTransactionsResponse
}
-// PooledTransactionsRLPPacket is the network packet for transaction distribution, used
+// PooledTransactionsRLPResponse is the network packet for transaction distribution, used
// in the cases we already have them in rlp-encoded form
-type PooledTransactionsRLPPacket []rlp.RawValue
+type PooledTransactionsRLPResponse []rlp.RawValue
-// PooledTransactionsRLPPacket66 is the eth/66 form of PooledTransactionsRLPPacket
-type PooledTransactionsRLPPacket66 struct {
+// PooledTransactionsRLPPacket is PooledTransactionsRLPResponse with request ID wrapping.
+type PooledTransactionsRLPPacket struct {
RequestId uint64
- PooledTransactionsRLPPacket
+ PooledTransactionsRLPResponse
}
func (*StatusPacket) Name() string { return "Status" }
@@ -381,40 +364,34 @@ func (*NewBlockHashesPacket) Kind() byte { return NewBlockHashesMsg }
func (*TransactionsPacket) Name() string { return "Transactions" }
func (*TransactionsPacket) Kind() byte { return TransactionsMsg }
-func (*GetBlockHeadersPacket) Name() string { return "GetBlockHeaders" }
-func (*GetBlockHeadersPacket) Kind() byte { return GetBlockHeadersMsg }
+func (*GetBlockHeadersRequest) Name() string { return "GetBlockHeaders" }
+func (*GetBlockHeadersRequest) Kind() byte { return GetBlockHeadersMsg }
-func (*BlockHeadersPacket) Name() string { return "BlockHeaders" }
-func (*BlockHeadersPacket) Kind() byte { return BlockHeadersMsg }
+func (*BlockHeadersRequest) Name() string { return "BlockHeaders" }
+func (*BlockHeadersRequest) Kind() byte { return BlockHeadersMsg }
-func (*GetBlockBodiesPacket) Name() string { return "GetBlockBodies" }
-func (*GetBlockBodiesPacket) Kind() byte { return GetBlockBodiesMsg }
+func (*GetBlockBodiesRequest) Name() string { return "GetBlockBodies" }
+func (*GetBlockBodiesRequest) Kind() byte { return GetBlockBodiesMsg }
-func (*BlockBodiesPacket) Name() string { return "BlockBodies" }
-func (*BlockBodiesPacket) Kind() byte { return BlockBodiesMsg }
+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 (*NewPooledTransactionHashesPacket66) Name() string { return "NewPooledTransactionHashes" }
-func (*NewPooledTransactionHashesPacket66) Kind() byte { return NewPooledTransactionHashesMsg }
+func (*NewPooledTransactionHashesPacket67) Name() string { return "NewPooledTransactionHashes" }
+func (*NewPooledTransactionHashesPacket67) Kind() byte { return NewPooledTransactionHashesMsg }
func (*NewPooledTransactionHashesPacket68) Name() string { return "NewPooledTransactionHashes" }
func (*NewPooledTransactionHashesPacket68) Kind() byte { return NewPooledTransactionHashesMsg }
-func (*GetPooledTransactionsPacket) Name() string { return "GetPooledTransactions" }
-func (*GetPooledTransactionsPacket) Kind() byte { return GetPooledTransactionsMsg }
-
-func (*PooledTransactionsPacket) Name() string { return "PooledTransactions" }
-func (*PooledTransactionsPacket) Kind() byte { return PooledTransactionsMsg }
-
-func (*GetNodeDataPacket) Name() string { return "GetNodeData" }
-func (*GetNodeDataPacket) Kind() byte { return GetNodeDataMsg }
+func (*GetPooledTransactionsRequest) Name() string { return "GetPooledTransactions" }
+func (*GetPooledTransactionsRequest) Kind() byte { return GetPooledTransactionsMsg }
-func (*NodeDataPacket) Name() string { return "NodeData" }
-func (*NodeDataPacket) Kind() byte { return NodeDataMsg }
+func (*PooledTransactionsResponse) Name() string { return "PooledTransactions" }
+func (*PooledTransactionsResponse) Kind() byte { return PooledTransactionsMsg }
-func (*GetReceiptsPacket) Name() string { return "GetReceipts" }
-func (*GetReceiptsPacket) Kind() byte { return GetReceiptsMsg }
+func (*GetReceiptsRequest) Name() string { return "GetReceipts" }
+func (*GetReceiptsRequest) Kind() byte { return GetReceiptsMsg }
-func (*ReceiptsPacket) Name() string { return "Receipts" }
-func (*ReceiptsPacket) Kind() byte { return ReceiptsMsg }
+func (*ReceiptsResponse) Name() string { return "Receipts" }
+func (*ReceiptsResponse) Kind() byte { return ReceiptsMsg }
diff --git a/eth/protocols/eth/protocol_test.go b/eth/protocols/eth/protocol_test.go
index a86fbb0a69..bc2545dea2 100644
--- a/eth/protocols/eth/protocol_test.go
+++ b/eth/protocols/eth/protocol_test.go
@@ -35,19 +35,19 @@ func TestGetBlockHeadersDataEncodeDecode(t *testing.T) {
}
// Assemble some table driven tests
tests := []struct {
- packet *GetBlockHeadersPacket
+ packet *GetBlockHeadersRequest
fail bool
}{
// Providing the origin as either a hash or a number should both work
- {fail: false, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 314}}},
- {fail: false, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: hash}}},
+ {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 314}}},
+ {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash}}},
// Providing arbitrary query field should also work
- {fail: false, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Number: 314}, Amount: 314, Skip: 1, Reverse: true}},
- {fail: false, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: hash}, Amount: 314, Skip: 1, Reverse: true}},
+ {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 314}, Amount: 314, Skip: 1, Reverse: true}},
+ {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash}, Amount: 314, Skip: 1, Reverse: true}},
// Providing both the origin hash and origin number must fail
- {fail: true, packet: &GetBlockHeadersPacket{Origin: HashOrNumber{Hash: hash, Number: 314}}},
+ {fail: true, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash, Number: 314}}},
}
// Iterate over each of the tests and try to encode and then decode
for i, tt := range tests {
@@ -58,7 +58,7 @@ func TestGetBlockHeadersDataEncodeDecode(t *testing.T) {
t.Fatalf("test %d: encode should have failed", i)
}
if !tt.fail {
- packet := new(GetBlockHeadersPacket)
+ packet := new(GetBlockHeadersRequest)
if err := rlp.DecodeBytes(bytes, packet); err != nil {
t.Fatalf("test %d: failed to decode packet: %v", i, err)
}
@@ -70,46 +70,40 @@ func TestGetBlockHeadersDataEncodeDecode(t *testing.T) {
}
}
-// TestEth66EmptyMessages tests encoding of empty eth66 messages
-func TestEth66EmptyMessages(t *testing.T) {
+// TestEmptyMessages tests encoding of empty messages.
+func TestEmptyMessages(t *testing.T) {
// All empty messages encodes to the same format
want := common.FromHex("c4820457c0")
for i, msg := range []interface{}{
// Headers
- GetBlockHeadersPacket66{1111, nil},
- BlockHeadersPacket66{1111, nil},
+ GetBlockHeadersPacket{1111, nil},
+ BlockHeadersPacket{1111, nil},
// Bodies
- GetBlockBodiesPacket66{1111, nil},
- BlockBodiesPacket66{1111, nil},
- BlockBodiesRLPPacket66{1111, nil},
- // Node data
- GetNodeDataPacket66{1111, nil},
- NodeDataPacket66{1111, nil},
+ GetBlockBodiesPacket{1111, nil},
+ BlockBodiesPacket{1111, nil},
+ BlockBodiesRLPPacket{1111, nil},
// Receipts
- GetReceiptsPacket66{1111, nil},
- ReceiptsPacket66{1111, nil},
+ GetReceiptsPacket{1111, nil},
+ ReceiptsPacket{1111, nil},
// Transactions
- GetPooledTransactionsPacket66{1111, nil},
- PooledTransactionsPacket66{1111, nil},
- PooledTransactionsRLPPacket66{1111, nil},
+ GetPooledTransactionsPacket{1111, nil},
+ PooledTransactionsPacket{1111, nil},
+ PooledTransactionsRLPPacket{1111, nil},
// Headers
- BlockHeadersPacket66{1111, BlockHeadersPacket([]*types.Header{})},
+ BlockHeadersPacket{1111, BlockHeadersRequest([]*types.Header{})},
// Bodies
- GetBlockBodiesPacket66{1111, GetBlockBodiesPacket([]common.Hash{})},
- BlockBodiesPacket66{1111, BlockBodiesPacket([]*BlockBody{})},
- BlockBodiesRLPPacket66{1111, BlockBodiesRLPPacket([]rlp.RawValue{})},
- // Node data
- GetNodeDataPacket66{1111, GetNodeDataPacket([]common.Hash{})},
- NodeDataPacket66{1111, NodeDataPacket([][]byte{})},
+ GetBlockBodiesPacket{1111, GetBlockBodiesRequest([]common.Hash{})},
+ BlockBodiesPacket{1111, BlockBodiesResponse([]*BlockBody{})},
+ BlockBodiesRLPPacket{1111, BlockBodiesRLPResponse([]rlp.RawValue{})},
// Receipts
- GetReceiptsPacket66{1111, GetReceiptsPacket([]common.Hash{})},
- ReceiptsPacket66{1111, ReceiptsPacket([][]*types.Receipt{})},
+ GetReceiptsPacket{1111, GetReceiptsRequest([]common.Hash{})},
+ ReceiptsPacket{1111, ReceiptsResponse([][]*types.Receipt{})},
// Transactions
- GetPooledTransactionsPacket66{1111, GetPooledTransactionsPacket([]common.Hash{})},
- PooledTransactionsPacket66{1111, PooledTransactionsPacket([]*types.Transaction{})},
- PooledTransactionsRLPPacket66{1111, PooledTransactionsRLPPacket([]rlp.RawValue{})},
+ GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest([]common.Hash{})},
+ PooledTransactionsPacket{1111, PooledTransactionsResponse([]*types.Transaction{})},
+ PooledTransactionsRLPPacket{1111, PooledTransactionsRLPResponse([]rlp.RawValue{})},
} {
if have, _ := rlp.EncodeToBytes(msg); !bytes.Equal(have, want) {
t.Errorf("test %d, type %T, have\n\t%x\nwant\n\t%x", i, msg, have, want)
@@ -117,8 +111,8 @@ func TestEth66EmptyMessages(t *testing.T) {
}
}
-// TestEth66Messages tests the encoding of all redefined eth66 messages
-func TestEth66Messages(t *testing.T) {
+// TestMessages tests the encoding of all messages.
+func TestMessages(t *testing.T) {
// Some basic structs used during testing
var (
header *types.Header
@@ -169,10 +163,6 @@ func TestEth66Messages(t *testing.T) {
common.HexToHash("deadc0de"),
common.HexToHash("feedbeef"),
}
- byteSlices := [][]byte{
- common.FromHex("deadc0de"),
- common.FromHex("feedbeef"),
- }
// init the receipts
{
receipts = []*types.Receipt{
@@ -203,59 +193,51 @@ func TestEth66Messages(t *testing.T) {
want []byte
}{
{
- GetBlockHeadersPacket66{1111, &GetBlockHeadersPacket{HashOrNumber{hashes[0], 0}, 5, 5, false}},
+ GetBlockHeadersPacket{1111, &GetBlockHeadersRequest{HashOrNumber{hashes[0], 0}, 5, 5, false}},
common.FromHex("e8820457e4a000000000000000000000000000000000000000000000000000000000deadc0de050580"),
},
{
- GetBlockHeadersPacket66{1111, &GetBlockHeadersPacket{HashOrNumber{common.Hash{}, 9999}, 5, 5, false}},
+ GetBlockHeadersPacket{1111, &GetBlockHeadersRequest{HashOrNumber{common.Hash{}, 9999}, 5, 5, false}},
common.FromHex("ca820457c682270f050580"),
},
{
- BlockHeadersPacket66{1111, BlockHeadersPacket{header}},
+ BlockHeadersPacket{1111, BlockHeadersRequest{header}},
common.FromHex("f90202820457f901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"),
},
{
- GetBlockBodiesPacket66{1111, GetBlockBodiesPacket(hashes)},
+ GetBlockBodiesPacket{1111, GetBlockBodiesRequest(hashes)},
common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"),
},
{
- BlockBodiesPacket66{1111, BlockBodiesPacket([]*BlockBody{blockBody})},
+ BlockBodiesPacket{1111, BlockBodiesResponse([]*BlockBody{blockBody})},
common.FromHex("f902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"),
},
{ // Identical to non-rlp-shortcut version
- BlockBodiesRLPPacket66{1111, BlockBodiesRLPPacket([]rlp.RawValue{blockBodyRlp})},
+ BlockBodiesRLPPacket{1111, BlockBodiesRLPResponse([]rlp.RawValue{blockBodyRlp})},
common.FromHex("f902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"),
},
{
- GetNodeDataPacket66{1111, GetNodeDataPacket(hashes)},
- common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"),
- },
- {
- NodeDataPacket66{1111, NodeDataPacket(byteSlices)},
- common.FromHex("ce820457ca84deadc0de84feedbeef"),
- },
- {
- GetReceiptsPacket66{1111, GetReceiptsPacket(hashes)},
+ GetReceiptsPacket{1111, GetReceiptsRequest(hashes)},
common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"),
},
{
- ReceiptsPacket66{1111, ReceiptsPacket([][]*types.Receipt{receipts})},
+ ReceiptsPacket{1111, ReceiptsResponse([][]*types.Receipt{receipts})},
common.FromHex("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"),
},
{
- ReceiptsRLPPacket66{1111, ReceiptsRLPPacket([]rlp.RawValue{receiptsRlp})},
+ ReceiptsRLPPacket{1111, ReceiptsRLPResponse([]rlp.RawValue{receiptsRlp})},
common.FromHex("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"),
},
{
- GetPooledTransactionsPacket66{1111, GetPooledTransactionsPacket(hashes)},
+ GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest(hashes)},
common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"),
},
{
- PooledTransactionsPacket66{1111, PooledTransactionsPacket(txs)},
+ PooledTransactionsPacket{1111, PooledTransactionsResponse(txs)},
common.FromHex("f8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb"),
},
{
- PooledTransactionsRLPPacket66{1111, PooledTransactionsRLPPacket(txRlps)},
+ PooledTransactionsRLPPacket{1111, PooledTransactionsRLPResponse(txRlps)},
common.FromHex("f8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb"),
},
} {
diff --git a/tests/fuzzers/snap/fuzz_handler.go b/eth/protocols/snap/handler_fuzzing_test.go
similarity index 75%
rename from tests/fuzzers/snap/fuzz_handler.go
rename to eth/protocols/snap/handler_fuzzing_test.go
index 784b526dc0..daed7ed44a 100644
--- a/tests/fuzzers/snap/fuzz_handler.go
+++ b/eth/protocols/snap/handler_fuzzing_test.go
@@ -21,6 +21,7 @@ import (
"encoding/binary"
"fmt"
"math/big"
+ "testing"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -28,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/eth/protocols/snap"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params"
@@ -36,6 +36,56 @@ import (
fuzz "github.com/google/gofuzz"
)
+func FuzzARange(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ doFuzz(data, &GetAccountRangePacket{}, GetAccountRangeMsg)
+ })
+}
+
+func FuzzSRange(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ doFuzz(data, &GetStorageRangesPacket{}, GetStorageRangesMsg)
+ })
+}
+
+func FuzzByteCodes(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ doFuzz(data, &GetByteCodesPacket{}, GetByteCodesMsg)
+ })
+}
+
+func FuzzTrieNodes(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ doFuzz(data, &GetTrieNodesPacket{}, GetTrieNodesMsg)
+ })
+}
+
+func doFuzz(input []byte, obj interface{}, code int) {
+ bc := getChain()
+ defer bc.Stop()
+ fuzz.NewFromGoFuzz(input).Fuzz(obj)
+ var data []byte
+ switch p := obj.(type) {
+ case *GetTrieNodesPacket:
+ p.Root = trieRoot
+ data, _ = rlp.EncodeToBytes(obj)
+ default:
+ data, _ = rlp.EncodeToBytes(obj)
+ }
+ cli := &dummyRW{
+ code: uint64(code),
+ data: data,
+ }
+ peer := NewFakePeer(65, "gazonk01", cli)
+ err := HandleMessage(&dummyBackend{bc}, peer)
+ switch {
+ case err == nil && cli.writeCount != 1:
+ panic(fmt.Sprintf("Expected 1 response, got %d", cli.writeCount))
+ case err != nil && cli.writeCount != 0:
+ panic(fmt.Sprintf("Expected 0 response, got %d", cli.writeCount))
+ }
+}
+
var trieRoot common.Hash
func getChain() *core.BlockChain {
@@ -86,10 +136,10 @@ type dummyBackend struct {
chain *core.BlockChain
}
-func (d *dummyBackend) Chain() *core.BlockChain { return d.chain }
-func (d *dummyBackend) RunPeer(*snap.Peer, snap.Handler) error { return nil }
-func (d *dummyBackend) PeerInfo(enode.ID) interface{} { return "Foo" }
-func (d *dummyBackend) Handle(*snap.Peer, snap.Packet) error { return nil }
+func (d *dummyBackend) Chain() *core.BlockChain { return d.chain }
+func (d *dummyBackend) RunPeer(*Peer, Handler) error { return nil }
+func (d *dummyBackend) PeerInfo(enode.ID) interface{} { return "Foo" }
+func (d *dummyBackend) Handle(*Peer, Packet) error { return nil }
type dummyRW struct {
code uint64
@@ -110,51 +160,3 @@ func (d *dummyRW) WriteMsg(msg p2p.Msg) error {
d.writeCount++
return nil
}
-
-func doFuzz(input []byte, obj interface{}, code int) int {
- if len(input) > 1024*4 {
- return -1
- }
- bc := getChain()
- defer bc.Stop()
- backend := &dummyBackend{bc}
- fuzz.NewFromGoFuzz(input).Fuzz(obj)
- var data []byte
- switch p := obj.(type) {
- case *snap.GetTrieNodesPacket:
- p.Root = trieRoot
- data, _ = rlp.EncodeToBytes(obj)
- default:
- data, _ = rlp.EncodeToBytes(obj)
- }
- cli := &dummyRW{
- code: uint64(code),
- data: data,
- }
- peer := snap.NewFakePeer(65, "gazonk01", cli)
- err := snap.HandleMessage(backend, peer)
- switch {
- case err == nil && cli.writeCount != 1:
- panic(fmt.Sprintf("Expected 1 response, got %d", cli.writeCount))
- case err != nil && cli.writeCount != 0:
- panic(fmt.Sprintf("Expected 0 response, got %d", cli.writeCount))
- }
- return 1
-}
-
-// To run a fuzzer, do
-// $ CGO_ENABLED=0 go-fuzz-build -func FuzzTrieNodes
-// $ go-fuzz
-
-func FuzzARange(input []byte) int {
- return doFuzz(input, &snap.GetAccountRangePacket{}, snap.GetAccountRangeMsg)
-}
-func FuzzSRange(input []byte) int {
- return doFuzz(input, &snap.GetStorageRangesPacket{}, snap.GetStorageRangesMsg)
-}
-func FuzzByteCodes(input []byte) int {
- return doFuzz(input, &snap.GetByteCodesPacket{}, snap.GetByteCodesMsg)
-}
-func FuzzTrieNodes(input []byte) int {
- return doFuzz(input, &snap.GetTrieNodesPacket{}, snap.GetTrieNodesMsg)
-}
diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go
index d91368b171..988a632e5a 100644
--- a/eth/protocols/snap/sync.go
+++ b/eth/protocols/snap/sync.go
@@ -2503,13 +2503,7 @@ func (s *Syncer) OnAccounts(peer SyncPeer, id uint64, hashes []common.Hash, acco
for i, node := range proof {
nodes[i] = node
}
- proofdb := nodes.Set()
-
- var end []byte
- if len(keys) > 0 {
- end = keys[len(keys)-1]
- }
- cont, err := trie.VerifyRangeProof(root, req.origin[:], end, keys, accounts, proofdb)
+ cont, err := trie.VerifyRangeProof(root, req.origin[:], keys, accounts, nodes.Set())
if err != nil {
logger.Warn("Account range failed proof", "err", err)
// Signal this request as failed, and ready for rescheduling
@@ -2761,7 +2755,7 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
if len(nodes) == 0 {
// No proof has been attached, the response must cover the entire key
// space and hash to the origin root.
- _, err = trie.VerifyRangeProof(req.roots[i], nil, nil, keys, slots[i], nil)
+ _, err = trie.VerifyRangeProof(req.roots[i], nil, keys, slots[i], nil)
if err != nil {
s.scheduleRevertStorageRequest(req) // reschedule request
logger.Warn("Storage slots failed proof", "err", err)
@@ -2772,11 +2766,7 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
// returned data is indeed part of the storage trie
proofdb := nodes.Set()
- var end []byte
- if len(keys) > 0 {
- end = keys[len(keys)-1]
- }
- cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], end, keys, slots[i], proofdb)
+ cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], keys, slots[i], proofdb)
if err != nil {
s.scheduleRevertStorageRequest(req) // reschedule request
logger.Warn("Storage range failed proof", "err", err)
diff --git a/eth/protocols/snap/sync_test.go b/eth/protocols/snap/sync_test.go
index 5d4099a814..73d61c2ffd 100644
--- a/eth/protocols/snap/sync_test.go
+++ b/eth/protocols/snap/sync_test.go
@@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/trie/testutil"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
"golang.org/x/exp/slices"
)
@@ -1510,7 +1511,7 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv)
for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(i),
})
@@ -1561,7 +1562,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
for i := 0; i < len(boundaries); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: uint64(0),
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(uint64(i)),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(uint64(i)),
})
@@ -1573,7 +1574,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(i),
})
@@ -1617,7 +1618,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: stRoot,
CodeHash: codehash,
})
@@ -1683,7 +1684,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: stRoot,
CodeHash: codehash,
})
diff --git a/eth/state_accessor.go b/eth/state_accessor.go
index 0971ef246a..26acdcd1d5 100644
--- a/eth/state_accessor.go
+++ b/eth/state_accessor.go
@@ -20,7 +20,6 @@ import (
"context"
"errors"
"fmt"
- "math/big"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -28,11 +27,13 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/systemcontracts"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
// noopReleaser is returned in case there is no operation expected
@@ -239,12 +240,37 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
if err != nil {
return nil, vm.BlockContext{}, nil, nil, err
}
+ // upgrade build-in system contract before normal txs if Feynman is not enabled
+ if !eth.blockchain.Config().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(eth.blockchain.Config(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
if txIndex == 0 && len(block.Transactions()) == 0 {
return nil, vm.BlockContext{}, statedb, release, nil
}
// Recompute transactions up to the target index.
- signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time())
+ var (
+ signer = types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time())
+ beforeSystemTx = true
+ )
for idx, tx := range block.Transactions() {
+ // upgrade build-in system contract before system txs if Feynman is enabled
+ if beforeSystemTx {
+ if posa, ok := eth.Engine().(consensus.PoSA); ok {
+ if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
+ balance := statedb.GetBalance(consensus.SystemAddress)
+ if balance.Cmp(common.U2560) > 0 {
+ statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0))
+ statedb.AddBalance(block.Header().Coinbase, balance)
+ }
+
+ if eth.blockchain.Config().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(eth.blockchain.Config(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
+ beforeSystemTx = false
+ }
+ }
+ }
+
// Assemble the transaction call message and return if the requested offset
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
txContext := core.NewEVMTxContext(msg)
@@ -254,14 +280,6 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
}
// Not yet the searched for transaction, execute on top of the current state
vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{})
- if posa, ok := eth.Engine().(consensus.PoSA); ok && msg.From == context.Coinbase &&
- posa.IsSystemContract(msg.To) && msg.GasPrice.Cmp(big.NewInt(0)) == 0 {
- balance := statedb.GetBalance(consensus.SystemAddress)
- if balance.Cmp(common.Big0) > 0 {
- statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
- statedb.AddBalance(context.Coinbase, balance)
- }
- }
statedb.SetTxContext(tx.Hash(), idx)
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
diff --git a/eth/sync.go b/eth/sync.go
index 5fb8c2be2a..d13e9c28b9 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -197,9 +197,10 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
return downloader.SnapSync, td
}
// We are probably in full sync, but we might have rewound to before the
- // snap sync pivot, check if we should reenable
+ // snap sync pivot, check if we should re-enable snap sync.
+ head := cs.handler.chain.CurrentBlock()
if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil {
- if head := cs.handler.chain.CurrentBlock(); head.Number.Uint64() < *pivot {
+ if head.Number.Uint64() < *pivot {
if rawdb.ReadAncientType(cs.handler.database) == rawdb.PruneFreezerType {
log.Crit("Current rewound to before the fast sync pivot, can't enable pruneancient mode", "current block number", head.Number.Uint64(), "pivot", *pivot)
}
@@ -208,9 +209,16 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
return downloader.SnapSync, td
}
}
-
+ // We are in a full sync, but the associated head state is missing. To complete
+ // the head state, forcefully rerun the snap sync. Note it doesn't mean the
+ // persistent state is corrupted, just mismatch with the head block.
+ if !cs.handler.chain.HasState(head.Root) {
+ block := cs.handler.chain.CurrentSnapBlock()
+ td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64())
+ log.Info("Reenabled snap sync as chain is stateless")
+ return downloader.SnapSync, td
+ }
// Nope, we're really full syncing
- head := cs.handler.chain.CurrentBlock()
td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64())
return downloader.FullSync, td
}
@@ -223,36 +231,12 @@ func (cs *chainSyncer) startSync(op *chainSyncOp) {
// doSync synchronizes the local blockchain with a remote peer.
func (h *handler) doSync(op *chainSyncOp) error {
- if op.mode == downloader.SnapSync {
- // Before launch the snap sync, we have to ensure user uses the same
- // txlookup limit.
- // The main concern here is: during the snap sync Geth won't index the
- // block(generate tx indices) before the HEAD-limit. But if user changes
- // the limit in the next snap sync(e.g. user kill Geth manually and
- // restart) then it will be hard for Geth to figure out the oldest block
- // has been indexed. So here for the user-experience wise, it's non-optimal
- // that user can't change limit during the snap sync. If changed, Geth
- // will just blindly use the original one.
- limit := h.chain.TxLookupLimit()
- if stored := rawdb.ReadFastTxLookupLimit(h.database); stored == nil {
- rawdb.WriteFastTxLookupLimit(h.database, limit)
- } else if *stored != limit {
- h.chain.SetTxLookupLimit(*stored)
- log.Warn("Update txLookup limit", "provided", limit, "updated", *stored)
- }
- }
// Run the sync cycle, and disable snap sync if we're past the pivot block
err := h.downloader.LegacySync(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode)
if err != nil {
return err
}
- if h.snapSync.Load() {
- log.Info("Snap sync complete, auto disabling")
- h.snapSync.Store(false)
- }
- // If we've successfully finished a sync cycle, enable accepting transactions
- // from the network.
- h.acceptTxs.Store(true)
+ h.enableSyncedFeatures()
head := h.chain.CurrentBlock()
if head.Number.Uint64() > 0 {
diff --git a/eth/sync_test.go b/eth/sync_test.go
index b5e00298b9..d26cbb66ea 100644
--- a/eth/sync_test.go
+++ b/eth/sync_test.go
@@ -28,8 +28,8 @@ import (
)
// Tests that snap sync is disabled after a successful sync cycle.
-func TestSnapSyncDisabling66(t *testing.T) { testSnapSyncDisabling(t, eth.ETH66, snap.SNAP1) }
func TestSnapSyncDisabling67(t *testing.T) { testSnapSyncDisabling(t, eth.ETH67, 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.
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index b4f80a6b08..7308116b68 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -18,12 +18,10 @@ package tracers
import (
"bufio"
- "bytes"
"context"
"encoding/json"
"errors"
"fmt"
- "math/big"
"os"
"runtime"
"sync"
@@ -36,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/systemcontracts"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
@@ -45,6 +44,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/holiman/uint256"
)
const (
@@ -83,7 +83,7 @@ type Backend interface {
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
- GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
+ GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
RPCGasCap() uint64
ChainConfig() *params.ChainConfig
Engine() consensus.Engine
@@ -167,6 +167,7 @@ type TraceCallConfig struct {
TraceConfig
StateOverrides *ethapi.StateOverride
BlockOverrides *ethapi.BlockOverrides
+ TxIndex *hexutil.Uint
}
// StdTraceConfig holds extra parameters to standard-json trace functions.
@@ -187,6 +188,7 @@ type txTraceResult struct {
// being traced.
type blockTraceTask struct {
statedb *state.StateDB // Intermediate state prepped for tracing
+ parent *types.Block // Parent block of the trace block
block *types.Block // Block to trace the transactions from
release StateReleaseFunc // The function to release the held resource for this task
results []*txTraceResult // Trace results produced by the task
@@ -203,8 +205,9 @@ type blockTraceResult struct {
// txTraceTask represents a single transaction trace task when an entire block
// is being traced.
type txTraceTask struct {
- statedb *state.StateDB // Intermediate state prepped for tracing
- index int // Transaction offset in the block
+ statedb *state.StateDB // Intermediate state prepped for tracing
+ index int // Transaction offset in the block
+ isSystemTx bool // Whether the transaction is a system transaction
}
// TraceChain returns the structured logs created during the execution of EVM
@@ -267,11 +270,30 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
// Fetch and execute the block trace taskCh
for task := range taskCh {
var (
- signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time())
- blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
+ signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time())
+ blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
+ beforeSystemTx = true
)
// Trace all the transactions contained within
for i, tx := range task.block.Transactions() {
+ // upgrade build-in system contract before system txs if Feynman is enabled
+ if beforeSystemTx {
+ if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
+ if isSystem, _ := posa.IsSystemTransaction(tx, task.block.Header()); isSystem {
+ balance := task.statedb.GetBalance(consensus.SystemAddress)
+ if balance.Cmp(common.U2560) > 0 {
+ task.statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0))
+ task.statedb.AddBalance(blockCtx.Coinbase, balance)
+ }
+
+ if api.backend.ChainConfig().IsFeynman(task.block.Number(), task.block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), task.block.Number(), task.parent.Time(), task.block.Time(), task.statedb)
+ }
+ beforeSystemTx = false
+ }
+ }
+ }
+
msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee())
txctx := &Context{
BlockHash: task.block.Hash(),
@@ -279,7 +301,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
TxIndex: i,
TxHash: tx.Hash(),
}
- res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
+ res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config, !beforeSystemTx)
if err != nil {
task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()}
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
@@ -386,10 +408,15 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
// may fail if we release too early.
tracker.callReleases()
+ // upgrade build-in system contract before normal txs if Feynman is not enabled
+ if !api.backend.ChainConfig().IsFeynman(next.Number(), next.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), next.Number(), block.Time(), next.Time(), statedb)
+ }
+
// Send the block over to the concurrent tracers (if not in the fast-forward phase)
txs := next.Transactions()
select {
- case taskCh <- &blockTraceTask{statedb: statedb.Copy(), block: next, release: release, results: make([]*txTraceResult, len(txs))}:
+ case taskCh <- &blockTraceTask{statedb: statedb.Copy(), parent: block, block: next, release: release, results: make([]*txTraceResult, len(txs))}:
case <-closed:
tracker.releaseState(number, release)
return
@@ -456,7 +483,7 @@ func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *
// and returns them as a JSON object.
func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *TraceConfig) ([]*txTraceResult, error) {
block := new(types.Block)
- if err := rlp.Decode(bytes.NewReader(blob), block); err != nil {
+ if err := rlp.DecodeBytes(blob, block); err != nil {
return nil, fmt.Errorf("could not decode block: %v", err)
}
return api.traceBlock(ctx, block, config)
@@ -522,12 +549,18 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
}
defer release()
+ // upgrade build-in system contract before normal txs if Feynman is not enabled
+ if !api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
+
var (
roots []common.Hash
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
chainConfig = api.backend.ChainConfig()
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
+ beforeSystemTx = true
)
for i, tx := range block.Transactions() {
if err := ctx.Err(); err != nil {
@@ -542,10 +575,15 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
balance := statedb.GetBalance(consensus.SystemAddress)
- if balance.Cmp(common.Big0) > 0 {
- statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
+ if balance.Cmp(common.U2560) > 0 {
+ statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0))
statedb.AddBalance(vmctx.Coinbase, balance)
}
+
+ if beforeSystemTx && api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
+ beforeSystemTx = false
+ }
}
}
@@ -602,6 +640,11 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
}
defer release()
+ // upgrade build-in system contract before normal txs if Feynman is not enabled
+ if !api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
+
// JS tracers have high overhead. In this case run a parallel
// process that generates states in one thread and traces txes
// in separate worker threads.
@@ -610,16 +653,36 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
return api.traceBlockParallel(ctx, block, statedb, config)
}
}
+
// Native tracers have low overhead
var (
- txs = block.Transactions()
- blockHash = block.Hash()
- is158 = api.backend.ChainConfig().IsEIP158(block.Number())
- blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
- signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
- results = make([]*txTraceResult, len(txs))
+ txs = block.Transactions()
+ blockHash = block.Hash()
+ is158 = api.backend.ChainConfig().IsEIP158(block.Number())
+ blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
+ signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
+ results = make([]*txTraceResult, len(txs))
+ beforeSystemTx = true
)
for i, tx := range txs {
+ // upgrade build-in system contract before system txs if Feynman is enabled
+ if beforeSystemTx {
+ if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
+ if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
+ balance := statedb.GetBalance(consensus.SystemAddress)
+ if balance.Cmp(common.U2560) > 0 {
+ statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0))
+ statedb.AddBalance(blockCtx.Coinbase, balance)
+ }
+
+ if api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
+ beforeSystemTx = false
+ }
+ }
+ }
+
// Generate the next state snapshot fast without tracing
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
txctx := &Context{
@@ -628,7 +691,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
TxIndex: i,
TxHash: tx.Hash(),
}
- res, err := api.traceTx(ctx, msg, txctx, blockCtx, statedb, config)
+ res, err := api.traceTx(ctx, msg, txctx, blockCtx, statedb, config, !beforeSystemTx)
if err != nil {
return nil, err
}
@@ -672,7 +735,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
TxIndex: task.index,
TxHash: txs[task.index].Hash(),
}
- res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
+ res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config, task.isSystemTx)
if err != nil {
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
continue
@@ -682,12 +745,38 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
})
}
+ parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
+ if err != nil {
+ return nil, err
+ }
+
// Feed the transactions into the tracers and return
- var failed error
+ var (
+ failed error
+ beforeSystemTx = true
+ )
txloop:
for i, tx := range txs {
+ // upgrade build-in system contract before system txs if Feynman is enabled
+ if beforeSystemTx {
+ if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
+ if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
+ balance := statedb.GetBalance(consensus.SystemAddress)
+ if balance.Cmp(common.U2560) > 0 {
+ statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0))
+ statedb.AddBalance(block.Header().Coinbase, balance)
+ }
+
+ if api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
+ beforeSystemTx = false
+ }
+ }
+ }
+
// Send the trace task over for execution
- task := &txTraceTask{statedb: statedb.Copy(), index: i}
+ task := &txTraceTask{statedb: statedb.Copy(), index: i, isSystemTx: !beforeSystemTx}
select {
case <-ctx.Done():
failed = ctx.Err()
@@ -697,15 +786,6 @@ txloop:
// Generate the next state snapshot fast without tracing
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
- if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
- if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
- balance := statedb.GetBalance(consensus.SystemAddress)
- if balance.Cmp(common.Big0) > 0 {
- statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
- statedb.AddBalance(block.Header().Coinbase, balance)
- }
- }
- }
statedb.SetTxContext(tx.Hash(), i)
vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{})
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
@@ -754,6 +834,11 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
}
defer release()
+ // upgrade build-in system contract before normal txs if Feynman is not enabled
+ if !api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
+
// Retrieve the tracing configurations, or use default values
var (
logConfig logger.Config
@@ -767,11 +852,12 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
// Execute transaction, either tracing all or just the requested one
var (
- dumps []string
- signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
- chainConfig = api.backend.ChainConfig()
- vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
- canon = true
+ dumps []string
+ signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
+ chainConfig = api.backend.ChainConfig()
+ vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
+ canon = true
+ beforeSystemTx = true
)
// Check if there are any overrides: the caller may wish to enable a future
// fork when executing this block. Note, such overrides are only applicable to the
@@ -782,7 +868,26 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
// Note: This copies the config, to not screw up the main config
chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
}
+
for i, tx := range block.Transactions() {
+ // upgrade build-in system contract before system txs if Feynman is enabled
+ if beforeSystemTx {
+ if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
+ if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
+ balance := statedb.GetBalance(consensus.SystemAddress)
+ if balance.Cmp(common.U2560) > 0 {
+ statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0))
+ statedb.AddBalance(vmctx.Coinbase, balance)
+ }
+
+ if api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
+ beforeSystemTx = false
+ }
+ }
+ }
+
// Prepare the transaction for un-traced execution
var (
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
@@ -814,15 +919,6 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
}
// Execute the transaction and flush any traces to disk
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
- if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
- if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
- balance := statedb.GetBalance(consensus.SystemAddress)
- if balance.Cmp(common.Big0) > 0 {
- statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
- statedb.AddBalance(vmctx.Coinbase, balance)
- }
- }
- }
statedb.SetTxContext(tx.Hash(), i)
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
if writer != nil {
@@ -861,12 +957,12 @@ func containsTx(block *types.Block, hash common.Hash) bool {
// TraceTransaction returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
- tx, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
+ found, tx, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
if err != nil {
- return nil, err
+ return nil, ethapi.NewTxIndexingError()
}
// Only mined txes are supported
- if tx == nil {
+ if !found {
return nil, errTxNotFound
}
// It shouldn't happen in practice.
@@ -887,23 +983,36 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
}
defer release()
+ var isSystemTx bool
+ if posa, ok := api.backend.Engine().(consensus.PoSA); ok {
+ if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
+ isSystemTx = true
+ }
+ }
+
txctx := &Context{
BlockHash: blockHash,
BlockNumber: block.Number(),
TxIndex: int(index),
TxHash: hash,
}
- return api.traceTx(ctx, msg, txctx, vmctx, statedb, config)
+ return api.traceTx(ctx, msg, txctx, vmctx, statedb, config, isSystemTx)
}
// TraceCall lets you trace a given eth_call. It collects the structured logs
// created during the execution of EVM if the given transaction was added on
// top of the provided block and returns them as a JSON object.
+// If no transaction index is specified, the trace will be conducted on the state
+// after executing the specified block. However, if a transaction index is provided,
+// the trace will be conducted on the state after executing the specified transaction
+// within the specified block.
func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
// Try to retrieve the specified block
var (
- err error
- block *types.Block
+ err error
+ block *types.Block
+ statedb *state.StateDB
+ release StateReleaseFunc
)
if hash, ok := blockNrOrHash.Hash(); ok {
block, err = api.blockByHash(ctx, hash)
@@ -928,12 +1037,28 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
- statedb, release, err := api.backend.StateAtBlock(ctx, block, reexec, nil, true, false)
+
+ if config != nil && config.TxIndex != nil {
+ _, _, statedb, release, err = api.backend.StateAtTransaction(ctx, block, int(*config.TxIndex), reexec)
+ } else {
+ statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, nil, true, false)
+ }
if err != nil {
return nil, err
}
defer release()
+ // upgrade build-in system contract before tracing if Feynman is not enabled
+ if block.NumberU64() > 0 {
+ parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
+ if err != nil {
+ return nil, err
+ }
+ if !api.backend.ChainConfig().IsFeynman(block.Number(), block.Time()) {
+ systemcontracts.UpgradeBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb)
+ }
+ }
+
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
// Apply the customization rules if required.
if config != nil {
@@ -952,13 +1077,13 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
if config != nil {
traceConfig = &config.TraceConfig
}
- return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig)
+ return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig, false)
}
// traceTx configures a new tracer according to the provided configuration, and
// executes the given message in the provided environment. The return value will
// be tracer dependent.
-func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
+func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig, isSystemTx bool) (interface{}, error) {
var (
tracer Tracer
err error
@@ -997,13 +1122,7 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
var intrinsicGas uint64 = 0
// Run the transaction with tracing enabled.
- if posa, ok := api.backend.Engine().(consensus.PoSA); ok && message.From == vmctx.Coinbase &&
- posa.IsSystemContract(message.To) && message.GasPrice.Cmp(big.NewInt(0)) == 0 {
- balance := statedb.GetBalance(consensus.SystemAddress)
- if balance.Cmp(common.Big0) > 0 {
- statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
- statedb.AddBalance(vmctx.Coinbase, balance)
- }
+ if isSystemTx {
intrinsicGas, _ = core.IntrinsicGas(message.Data, message.AccessList, false, true, true, false)
}
diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go
index c665f8c32b..8799639366 100644
--- a/eth/tracers/api_test.go
+++ b/eth/tracers/api_test.go
@@ -114,9 +114,9 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
return b.chain.GetBlockByNumber(uint64(number)), nil
}
-func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
+func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash)
- return tx, hash, blockNumber, index, nil
+ return tx != nil, tx, hash, blockNumber, index, nil
}
func (b *testBackend) RPCGasCap() uint64 {
@@ -201,13 +201,51 @@ func TestTraceCall(t *testing.T) {
}
genBlocks := 10
signer := types.HomesteadSigner{}
+ nonce := uint64(0)
backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
- tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
+ tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
+ Nonce: nonce,
+ To: &accounts[1].addr,
+ Value: big.NewInt(1000),
+ Gas: params.TxGas,
+ GasPrice: b.BaseFee(),
+ Data: nil}),
+ signer, accounts[0].key)
b.AddTx(tx)
+ nonce++
+
+ if i == genBlocks-2 {
+ // Transfer from account[0] to account[2]
+ tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{
+ Nonce: nonce,
+ To: &accounts[2].addr,
+ Value: big.NewInt(1000),
+ Gas: params.TxGas,
+ GasPrice: b.BaseFee(),
+ Data: nil}),
+ signer, accounts[0].key)
+ b.AddTx(tx)
+ nonce++
+
+ // Transfer from account[0] to account[1] again
+ tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{
+ Nonce: nonce,
+ To: &accounts[1].addr,
+ Value: big.NewInt(1000),
+ Gas: params.TxGas,
+ GasPrice: b.BaseFee(),
+ Data: nil}),
+ signer, accounts[0].key)
+ b.AddTx(tx)
+ nonce++
+ }
})
+
+ uintPtr := func(i int) *hexutil.Uint { x := hexutil.Uint(i); return &x }
+
defer backend.teardown()
api := NewAPI(backend)
var testSuite = []struct {
@@ -241,6 +279,51 @@ func TestTraceCall(t *testing.T) {
expectErr: nil,
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
},
+ // Upon the last state, default to the post block's state
+ {
+ blockNumber: rpc.BlockNumber(genBlocks - 1),
+ call: ethapi.TransactionArgs{
+ From: &accounts[2].addr,
+ To: &accounts[0].addr,
+ Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
+ },
+ config: nil,
+ expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
+ },
+ // Before the first transaction, should be failed
+ {
+ blockNumber: rpc.BlockNumber(genBlocks - 1),
+ call: ethapi.TransactionArgs{
+ From: &accounts[2].addr,
+ To: &accounts[0].addr,
+ Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
+ },
+ config: &TraceCallConfig{TxIndex: uintPtr(0)},
+ expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr),
+ },
+ // Before the target transaction, should be failed
+ {
+ blockNumber: rpc.BlockNumber(genBlocks - 1),
+ call: ethapi.TransactionArgs{
+ From: &accounts[2].addr,
+ To: &accounts[0].addr,
+ Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
+ },
+ config: &TraceCallConfig{TxIndex: uintPtr(1)},
+ expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr),
+ },
+ // After the target transaction, should be succeed
+ {
+ blockNumber: rpc.BlockNumber(genBlocks - 1),
+ call: ethapi.TransactionArgs{
+ From: &accounts[2].addr,
+ To: &accounts[0].addr,
+ Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
+ },
+ config: &TraceCallConfig{TxIndex: uintPtr(2)},
+ expectErr: nil,
+ expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
+ },
// Standard JSON trace upon the non-existent block, error expects
{
blockNumber: rpc.BlockNumber(genBlocks + 1),
@@ -251,7 +334,7 @@ func TestTraceCall(t *testing.T) {
},
config: nil,
expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
- //expect: nil,
+ // expect: nil,
},
// Standard JSON trace upon the latest block
{
@@ -298,8 +381,8 @@ func TestTraceCall(t *testing.T) {
t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
continue
}
- if !reflect.DeepEqual(err, testspec.expectErr) {
- t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err)
+ if !reflect.DeepEqual(err.Error(), testspec.expectErr.Error()) {
+ t.Errorf("test %d: error mismatch, want '%v', got '%v'", i, testspec.expectErr, err)
}
} else {
if err != nil {
@@ -339,7 +422,14 @@ func TestTraceTransaction(t *testing.T) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
- tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
+ tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
+ Nonce: uint64(i),
+ To: &accounts[1].addr,
+ Value: big.NewInt(1000),
+ Gas: params.TxGas,
+ GasPrice: b.BaseFee(),
+ Data: nil}),
+ signer, accounts[0].key)
b.AddTx(tx)
target = tx.Hash()
})
@@ -389,7 +479,14 @@ func TestTraceBlock(t *testing.T) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
- tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
+ tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
+ Nonce: uint64(i),
+ To: &accounts[1].addr,
+ Value: big.NewInt(1000),
+ Gas: params.TxGas,
+ GasPrice: b.BaseFee(),
+ Data: nil}),
+ signer, accounts[0].key)
b.AddTx(tx)
txHash = tx.Hash()
})
@@ -479,7 +576,14 @@ func TestTracingWithOverrides(t *testing.T) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
- tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
+ tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
+ Nonce: uint64(i),
+ To: &accounts[1].addr,
+ Value: big.NewInt(1000),
+ Gas: params.TxGas,
+ GasPrice: b.BaseFee(),
+ Data: nil}),
+ signer, accounts[0].key)
b.AddTx(tx)
})
defer backend.chain.Stop()
@@ -547,7 +651,7 @@ func TestTracingWithOverrides(t *testing.T) {
Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number()
},
config: &TraceCallConfig{
- //Tracer: &tracer,
+ // Tracer: &tracer,
StateOverrides: ðapi.StateOverride{
randomAccounts[2].addr: ethapi.OverrideAccount{
Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")),
@@ -563,7 +667,7 @@ func TestTracingWithOverrides(t *testing.T) {
From: &accounts[0].addr,
// BLOCKNUMBER PUSH1 MSTORE
Input: newRPCBytes(common.Hex2Bytes("4360005260206000f3")),
- //&hexutil.Bytes{0x43}, // blocknumber
+ // &hexutil.Bytes{0x43}, // blocknumber
},
config: &TraceCallConfig{
BlockOverrides: ðapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
@@ -639,7 +743,7 @@ func TestTracingWithOverrides(t *testing.T) {
},
},
},
- //want: `{"gas":46900,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000539"}`,
+ // want: `{"gas":46900,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000539"}`,
want: `{"gas":44100,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000001"}`,
},
{ // No state override
diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go
index 6df49a90c1..0b43a021ea 100644
--- a/eth/tracers/internal/tracetest/calltrace_test.go
+++ b/eth/tracers/internal/tracetest/calltrace_test.go
@@ -47,9 +47,10 @@ type callContext struct {
// callLog is the result of LOG opCode
type callLog struct {
- Address common.Address `json:"address"`
- Topics []common.Hash `json:"topics"`
- Data hexutil.Bytes `json:"data"`
+ Address common.Address `json:"address"`
+ Topics []common.Hash `json:"topics"`
+ Data hexutil.Bytes `json:"data"`
+ Position hexutil.Uint `json:"position"`
}
// callTrace is the result of a callTracer run.
@@ -121,12 +122,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
}
// Configure a blockchain with the given prestate
var (
- signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ = signer.Sender(tx)
- txContext = vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
+ signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
context = vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
@@ -145,11 +141,11 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
+ evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil {
t.Fatalf("failed to execute transaction: %v", err)
@@ -221,10 +217,6 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.Fatalf("failed to parse testcase input: %v", err)
}
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- msg, err := core.TransactionToMessage(tx, signer, nil)
- if err != nil {
- b.Fatalf("failed to prepare transaction for tracing: %v", err)
- }
origin, _ := signer.Sender(tx)
txContext := vm.TxContext{
Origin: origin,
@@ -239,6 +231,10 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
}
+ msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
+ if err != nil {
+ b.Fatalf("failed to prepare transaction for tracing: %v", err)
+ }
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
defer triedb.Close()
@@ -324,7 +320,7 @@ func TestInternals(t *testing.T) {
byte(vm.LOG0),
},
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
- want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}],"value":"0x0","type":"CALL"}`,
+ want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","position":"0x0"}],"value":"0x0","type":"CALL"}`,
},
{
// Leads to OOM on the prestate tracer
diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go
index 423167b13c..b318548bc1 100644
--- a/eth/tracers/internal/tracetest/flat_calltrace_test.go
+++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go
@@ -86,11 +86,6 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
return fmt.Errorf("failed to parse testcase input: %v", err)
}
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ := signer.Sender(tx)
- txContext := vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
context := vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
@@ -108,12 +103,11 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
if err != nil {
return fmt.Errorf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
}
+ evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, err = st.TransitionDb(); err != nil {
diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go
index b4fa5b6272..666a5fda78 100644
--- a/eth/tracers/internal/tracetest/prestate_test.go
+++ b/eth/tracers/internal/tracetest/prestate_test.go
@@ -92,12 +92,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
}
// Configure a blockchain with the given prestate
var (
- signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ = signer.Sender(tx)
- txContext = vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
+ signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
context = vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
@@ -116,11 +111,11 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
+ evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, err = st.TransitionDb(); err != nil {
t.Fatalf("failed to execute transaction: %v", err)
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json
index 9264f1e2fd..dbece7229d 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json
@@ -95,14 +95,16 @@
"topics": [
"0xe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda"
],
- "data": "0x0000000000000000000000004f5777744b500616697cb655dcb02ee6cd51deb5be96016bb57376da7a6d296e0a405ee1501778227dfa604df0a81cb1ae018598"
+ "data": "0x0000000000000000000000004f5777744b500616697cb655dcb02ee6cd51deb5be96016bb57376da7a6d296e0a405ee1501778227dfa604df0a81cb1ae018598",
+ "position": "0x0"
},
{
"address": "0x200edd17f30485a8735878661960cd7a9a95733f",
"topics": [
"0xacbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x0"
}
],
"value": "0x8ac7230489e80000",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json
index f63dbd47dc..2b03dbb8dd 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json
@@ -257,7 +257,8 @@
"0x0000000000000000000000003de712784baf97260455ae25fb74f574ec9c1add",
"0x0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5"
],
- "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac"
+ "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -278,7 +279,8 @@
"0x0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5",
"0x0000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd"
],
- "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac"
+ "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -307,7 +309,8 @@
"0x0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5",
"0x0000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd"
],
- "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac"
+ "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -328,7 +331,8 @@
"0x0000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd",
"0x000000000000000000000000950ca4a06c78934a148b7a3ff3ea8fc366f77a06"
],
- "data": "0x0000000000000000000000000000000000000000000000000041f50e27d56848"
+ "data": "0x0000000000000000000000000000000000000000000000000041f50e27d56848",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -391,7 +395,8 @@
"0x0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5",
"0x0000000000000000000000003de712784baf97260455ae25fb74f574ec9c1add"
],
- "data": "0x000000000000000000000000000000000000000000000000de0b6b3a76400000"
+ "data": "0x000000000000000000000000000000000000000000000000de0b6b3a76400000",
+ "position": "0x0"
}
],
"type": "DELEGATECALL",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json
index 5e5d953867..263e88d6e1 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json
@@ -357,7 +357,8 @@
"0x000000000000000000000000c0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89",
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd"
],
- "data": "0x00000000000000000000000000000000000000000001819451f999d617dafa93"
+ "data": "0x00000000000000000000000000000000000000000001819451f999d617dafa93",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -370,7 +371,8 @@
"topics": [
"0x69ca02dd4edd7bf0a4abb9ed3b7af3f14778db5d61921c7dc7cd545266326de2"
],
- "data": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa93"
+ "data": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa93",
+ "position": "0x1"
}
],
"value": "0x0",
@@ -491,7 +493,8 @@
"0x000000000000000000000000f835a0247b0063c04ef22006ebe57c5f11977cc4",
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd"
],
- "data": "0x00000000000000000000000000000000000000000001819451f999d617dafa76"
+ "data": "0x00000000000000000000000000000000000000000001819451f999d617dafa76",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -504,7 +507,8 @@
"topics": [
"0x69ca02dd4edd7bf0a4abb9ed3b7af3f14778db5d61921c7dc7cd545266326de2"
],
- "data": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa76"
+ "data": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa76",
+ "position": "0x1"
}
],
"value": "0x0",
@@ -692,7 +696,8 @@
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd",
"0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc"
],
- "data": "0x0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccd"
+ "data": "0x0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccd",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -874,7 +879,8 @@
"0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc",
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd"
],
- "data": "0x0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccc"
+ "data": "0x0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccc",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -892,7 +898,8 @@
"0x9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc",
"0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc"
],
- "data": "0x0000000000000000000000000000000000000000000000022b1c8c12279fffff"
+ "data": "0x0000000000000000000000000000000000000000000000022b1c8c12279fffff",
+ "position": "0x1"
}
],
"value": "0x0",
@@ -914,7 +921,8 @@
"0x9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc",
"0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc"
],
- "data": "0x0000000000000000000000000000000000000000000000022b1c8c12279fffff"
+ "data": "0x0000000000000000000000000000000000000000000000022b1c8c12279fffff",
+ "position": "0x1"
}
],
"value": "0x0",
@@ -939,7 +947,8 @@
"0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc",
"0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000001"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -952,14 +961,16 @@
"topics": [
"0x07cf7e805770612a8b2ee8e0bcbba8aa908df5f85fbc4f9e2ef384cf75315038"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x6"
},
{
"address": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc",
"topics": [
"0x7027eecbd2a688fc1fa281702b311ed7168571514adfd17014a55d828cb43382"
],
- "data": "0x000000000000000000000000000000000000000000000004563918244f400000"
+ "data": "0x000000000000000000000000000000000000000000000004563918244f400000",
+ "position": "0x8"
}
],
"value": "0x0",
@@ -1035,7 +1046,8 @@
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd",
"0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000063"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000063",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -1162,7 +1174,8 @@
"0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f",
"0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000064"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000064",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -1175,14 +1188,16 @@
"topics": [
"0x4b0bc4f25f8d0b92d2e12b686ba96cd75e4e69325e6cf7b1f3119d14eaf2cbdf"
],
- "data": "0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526"
+ "data": "0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526",
+ "position": "0x6"
},
{
"address": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f",
"topics": [
"0xf340c079d598119636d42046c6a2d2faf7a68c04aecee516f0e0b8a9e79b8666"
],
- "data": "0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e9652600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e9652600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x9"
}
],
"value": "0x0",
@@ -1231,7 +1246,8 @@
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd",
"0x0000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000001"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -1324,7 +1340,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000001"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -1417,7 +1434,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000002"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -1510,7 +1528,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000003"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -1603,7 +1622,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000004"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -1696,7 +1716,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000005"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -1789,7 +1810,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000006"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -1882,7 +1904,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000007"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -1975,7 +1998,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000008"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -2068,7 +2092,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x0000000000000000000000000000000000000000000000000000000000000009"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -2161,7 +2186,8 @@
"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f",
"0x000000000000000000000000000000000000000000000000000000000000000a"
],
- "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000"
+ "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
+ "position": "0x2"
}
],
"value": "0x0",
@@ -2213,7 +2239,8 @@
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd",
"0x0000000000000000000000007ccbc69292c7a6d7b538c91f3b283de97906cf30"
],
- "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c"
+ "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -2234,7 +2261,8 @@
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd",
"0x0000000000000000000000001b9ec8ba24630b75a7a958153ffff56dd6d4b6a2"
],
- "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c"
+ "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -2255,7 +2283,8 @@
"0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd",
"0x000000000000000000000000c3a2c744ad1f5253c736875b93bacce5b01b060b"
],
- "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c"
+ "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c",
+ "position": "0x0"
}
],
"value": "0x0",
@@ -2268,21 +2297,24 @@
"topics": [
"0xc6d8c0af6d21f291e7c359603aa97e0ed500f04db6e983b9fce75a91c6b8da6b"
],
- "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c"
+ "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c",
+ "position": "0x2"
},
{
"address": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd",
"topics": [
"0xc6d8c0af6d21f291e7c359603aa97e0ed500f04db6e983b9fce75a91c6b8da6b"
],
- "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c"
+ "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c",
+ "position": "0x3"
},
{
"address": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd",
"topics": [
"0xc6d8c0af6d21f291e7c359603aa97e0ed500f04db6e983b9fce75a91c6b8da6b"
],
- "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c"
+ "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c",
+ "position": "0x4"
}
],
"value": "0x0",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json
index 1ffffd240e..66d4582008 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json
@@ -178,350 +178,400 @@
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebebeb0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebebeb0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8888880000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8888880000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3b3b30000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3b3b30000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfc0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfc0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e30000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e30000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e3e3e0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e3e3e0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdb0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdb0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f4f40000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f4f40000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfb0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfb0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0b0b00000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0b0b00000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0a0a00000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0a0a00000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5b5b0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5b5b0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababa0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababa0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaea0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaea0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa9a9a90000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa9a9a90000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9b9b90000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9b9b90000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfb0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfb0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababa0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababa0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6363630000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6363630000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f9f90000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f9f90000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaea0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaea0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c9c9c0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c9c9c0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f80000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f80000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfc0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfc0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d4e530000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d4e530000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
- "data": "0x00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f494b0000000000000000000000000000000000000000000000000011c37937e08000"
+ "data": "0x00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f494b0000000000000000000000000000000000000000000000000011c37937e08000",
+ "position": "0x0"
}
],
"value": "0x3782dace9d90000",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json
index 116606b3c7..762ccbe58f 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json
@@ -266,7 +266,8 @@
"topics": [
"0xaf30e4d66b2f1f23e63ef4591058a897f67e6867233e33ca3508b982dcc4129b"
],
- "data": "0x00000000000000000000000050739060a2c32dc076e507ae1a893aab28ecfe68d1b13c1538a940417bf0e73b2498634436753c854c7fb971224d971bd2ae3e8800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000249f011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000355524c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000436a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174612e300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012c4244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d0000000000000000000000000000000000000000"
+ "data": "0x00000000000000000000000050739060a2c32dc076e507ae1a893aab28ecfe68d1b13c1538a940417bf0e73b2498634436753c854c7fb971224d971bd2ae3e8800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000249f011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000355524c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000436a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174612e300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012c4244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d0000000000000000000000000000000000000000",
+ "position": "0x4"
}
],
"value": "0x179d63013c5654",
@@ -277,7 +278,8 @@
{
"address": "0x50739060a2c32dc076e507ae1a893aab28ecfe68",
"topics": [],
- "data": "0x62616e6b726f6c6c5f6d69736d61746368"
+ "data": "0x62616e6b726f6c6c5f6d69736d61746368",
+ "position": "0x2"
}
],
"value": "0x429d069189e0000",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json
index 30f1777067..64941dd4db 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json
@@ -75,7 +75,8 @@
"0x000000000000000000000000d1220a0cf47c7b9be7a2e6ba89f429762e7b9adb",
"0x000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb"
],
- "data": "0x0000000000000000000000000000000000000000000000000000000000989680"
+ "data": "0x0000000000000000000000000000000000000000000000000000000000989680",
+ "position": "0x0"
}
],
"value": "0x0",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json
index eb2514427c..6faf898a0f 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json
@@ -98,7 +98,8 @@
"topics": [
"0x92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004"
],
- "data": "0x00000000000000000000000001115b41bd2731353dd3e6abf44818fdc035aaf10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c1894130000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008861393035396362623030303030303030303030303030303030303030303030303930643363313831326465323636396266383037626437373538636562316533343937616337653430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031633662663532363334303030"
+ "data": "0x00000000000000000000000001115b41bd2731353dd3e6abf44818fdc035aaf10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c1894130000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008861393035396362623030303030303030303030303030303030303030303030303930643363313831326465323636396266383037626437373538636562316533343937616337653430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031633662663532363334303030",
+ "position": "0x0"
}
],
"value": "0x0",
diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
index e80dad5667..561ead05b6 100644
--- a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
+++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
@@ -83,7 +83,7 @@
},
"post": {
"0x808b4da0be6c9512e948521452227efc619bea52": {
- "balance": "0x2cd72a36dd031f089",
+ "balance": "0x2cd987071ba2346b6",
"nonce": 1223933
},
"0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7": {
diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go
index 3f3b29ede8..feeb45c649 100644
--- a/eth/tracers/js/goja.go
+++ b/eth/tracers/js/goja.go
@@ -142,19 +142,29 @@ func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracer
vm: vm,
ctx: make(map[string]goja.Value),
}
+
+ t.setTypeConverters()
+ t.setBuiltinFunctions()
+
if ctx == nil {
ctx = new(tracers.Context)
}
if ctx.BlockHash != (common.Hash{}) {
- t.ctx["blockHash"] = vm.ToValue(ctx.BlockHash.Bytes())
+ blockHash, err := t.toBuf(vm, ctx.BlockHash.Bytes())
+ if err != nil {
+ return nil, err
+ }
+ t.ctx["blockHash"] = blockHash
if ctx.TxHash != (common.Hash{}) {
t.ctx["txIndex"] = vm.ToValue(ctx.TxIndex)
- t.ctx["txHash"] = vm.ToValue(ctx.TxHash.Bytes())
+ txHash, err := t.toBuf(vm, ctx.TxHash.Bytes())
+ if err != nil {
+ return nil, err
+ }
+ t.ctx["txHash"] = txHash
}
}
- t.setTypeConverters()
- t.setBuiltinFunctions()
ret, err := vm.RunString("(" + code + ")")
if err != nil {
return nil, err
@@ -226,6 +236,10 @@ func (t *jsTracer) CaptureSystemTxEnd(intrinsicGas uint64) {}
// CaptureStart implements the Tracer interface to initialize the tracing operation.
func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ cancel := func(err error) {
+ t.err = err
+ t.env.Cancel()
+ }
t.env = env
db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
t.dbValue = db.setupObject()
@@ -234,14 +248,34 @@ func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr
} else {
t.ctx["type"] = t.vm.ToValue("CALL")
}
- t.ctx["from"] = t.vm.ToValue(from.Bytes())
- t.ctx["to"] = t.vm.ToValue(to.Bytes())
- t.ctx["input"] = t.vm.ToValue(input)
+ fromVal, err := t.toBuf(t.vm, from.Bytes())
+ if err != nil {
+ cancel(err)
+ return
+ }
+ t.ctx["from"] = fromVal
+ toVal, err := t.toBuf(t.vm, to.Bytes())
+ if err != nil {
+ cancel(err)
+ return
+ }
+ t.ctx["to"] = toVal
+ inputVal, err := t.toBuf(t.vm, input)
+ if err != nil {
+ cancel(err)
+ return
+ }
+ t.ctx["input"] = inputVal
t.ctx["gas"] = t.vm.ToValue(t.gasLimit)
- t.ctx["gasPrice"] = t.vm.ToValue(env.TxContext.GasPrice)
+ gasPriceBig, err := t.toBig(t.vm, env.TxContext.GasPrice.String())
+ if err != nil {
+ cancel(err)
+ return
+ }
+ t.ctx["gasPrice"] = gasPriceBig
valueBig, err := t.toBig(t.vm, value.String())
if err != nil {
- t.err = err
+ cancel(err)
return
}
t.ctx["value"] = valueBig
@@ -290,10 +324,15 @@ func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope
// CaptureEnd is called after the call finishes to finalize the tracing.
func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
- t.ctx["output"] = t.vm.ToValue(output)
if err != nil {
t.ctx["error"] = t.vm.ToValue(err.Error())
}
+ outputVal, err := t.toBuf(t.vm, output)
+ if err != nil {
+ t.err = err
+ return
+ }
+ t.ctx["output"] = outputVal
}
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
@@ -462,13 +501,13 @@ func (t *jsTracer) setBuiltinFunctions() {
}
return false
})
- vm.Set("slice", func(slice goja.Value, start, end int) goja.Value {
+ vm.Set("slice", func(slice goja.Value, start, end int64) goja.Value {
b, err := t.fromBuf(vm, slice, false)
if err != nil {
vm.Interrupt(err)
return nil
}
- if start < 0 || start > end || end > len(b) {
+ if start < 0 || start > end || end > int64(len(b)) {
vm.Interrupt(fmt.Sprintf("Tracer accessed out of bound memory: available %d, offset %d, size %d", len(b), start, end-start))
return nil
}
diff --git a/eth/tracers/js/internal/tracers/4byte_tracer.js b/eth/tracers/js/internal/tracers/4byte_tracer.js
deleted file mode 100644
index 9ec3209f8b..0000000000
--- a/eth/tracers/js/internal/tracers/4byte_tracer.js
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2017 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 .
-
-// 4byteTracer searches for 4byte-identifiers, and collects them for post-processing.
-// It collects the methods identifiers along with the size of the supplied data, so
-// a reversed signature can be matched against the size of the data.
-//
-// Example:
-// > debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"})
-// {
-// 0x27dc297e-128: 1,
-// 0x38cc4831-0: 2,
-// 0x524f3889-96: 1,
-// 0xadf59f99-288: 1,
-// 0xc281d19e-0: 1
-// }
-{
- // ids aggregates the 4byte ids found.
- ids : {},
-
- // store save the given indentifier and datasize.
- store: function(id, size){
- var key = "" + toHex(id) + "-" + size;
- this.ids[key] = this.ids[key] + 1 || 1;
- },
-
- enter: function(frame) {
- // Skip any pre-compile invocations, those are just fancy opcodes
- if (isPrecompiled(frame.getTo())) {
- return;
- }
- var input = frame.getInput()
- if (input.length >= 4) {
- this.store(slice(input, 0, 4), input.length - 4);
- }
- },
-
- exit: function(frameResult) {},
-
- // fault is invoked when the actual execution of an opcode fails.
- fault: function(log, db) {},
-
- // result is invoked when all the opcodes have been iterated over and returns
- // the final result of the tracing.
- result: function(ctx) {
- // Save the outer calldata also
- if (ctx.input.length >= 4) {
- this.store(slice(ctx.input, 0, 4), ctx.input.length-4)
- }
- return this.ids;
- },
-}
diff --git a/eth/tracers/js/internal/tracers/call_tracer_js.js b/eth/tracers/js/internal/tracers/call_tracer_js.js
deleted file mode 100644
index 7da7bf216a..0000000000
--- a/eth/tracers/js/internal/tracers/call_tracer_js.js
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2021 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 .
-
-
-// callFrameTracer uses the new call frame tracing methods to report useful information
-// about internal messages of a transaction.
-{
- callstack: [{}],
- fault: function(log, db) {},
- result: function(ctx, db) {
- // Prepare outer message info
- var result = {
- type: ctx.type,
- from: toHex(ctx.from),
- to: toHex(ctx.to),
- value: '0x' + ctx.value.toString(16),
- gas: '0x' + bigInt(ctx.gas).toString(16),
- gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16),
- input: toHex(ctx.input),
- output: toHex(ctx.output),
- }
- if (this.callstack[0].calls !== undefined) {
- result.calls = this.callstack[0].calls
- }
- if (this.callstack[0].error !== undefined) {
- result.error = this.callstack[0].error
- } else if (ctx.error !== undefined) {
- result.error = ctx.error
- }
- if (result.error !== undefined && (result.error !== "execution reverted" || result.output ==="0x")) {
- delete result.output
- }
-
- return this.finalize(result)
- },
- enter: function(frame) {
- var call = {
- type: frame.getType(),
- from: toHex(frame.getFrom()),
- to: toHex(frame.getTo()),
- input: toHex(frame.getInput()),
- gas: '0x' + bigInt(frame.getGas()).toString('16'),
- }
- if (frame.getValue() !== undefined){
- call.value='0x' + bigInt(frame.getValue()).toString(16)
- }
- this.callstack.push(call)
- },
- exit: function(frameResult) {
- var len = this.callstack.length
- if (len > 1) {
- var call = this.callstack.pop()
- call.gasUsed = '0x' + bigInt(frameResult.getGasUsed()).toString('16')
- var error = frameResult.getError()
- if (error === undefined) {
- call.output = toHex(frameResult.getOutput())
- } else {
- call.error = error
- if (call.type === 'CREATE' || call.type === 'CREATE2') {
- delete call.to
- }
- }
- len -= 1
- if (this.callstack[len-1].calls === undefined) {
- this.callstack[len-1].calls = []
- }
- this.callstack[len-1].calls.push(call)
- }
- },
- // finalize recreates a call object using the final desired field oder for json
- // serialization. This is a nicety feature to pass meaningfully ordered results
- // to users who don't interpret it, just display it.
- finalize: function(call) {
- var sorted = {
- type: call.type,
- from: call.from,
- to: call.to,
- value: call.value,
- gas: call.gas,
- gasUsed: call.gasUsed,
- input: call.input,
- output: call.output,
- error: call.error,
- time: call.time,
- calls: call.calls,
- }
- for (var key in sorted) {
- if (sorted[key] === undefined) {
- delete sorted[key]
- }
- }
- if (sorted.calls !== undefined) {
- for (var i=0; i.
-
-// noopTracer is just the barebone boilerplate code required from a JavaScript
-// object to be usable as a transaction tracer.
-{
- // step is invoked for every opcode that the VM executes.
- step: function(log, db) { },
-
- // fault is invoked when the actual execution of an opcode fails.
- fault: function(log, db) { },
-
- // result is invoked when all the opcodes have been iterated over and returns
- // the final result of the tracing.
- result: function(ctx, db) { return {}; }
-}
diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go
index 81c8cf53aa..2e3d84661b 100644
--- a/eth/tracers/js/tracer_test.go
+++ b/eth/tracers/js/tracer_test.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
type account struct{}
@@ -37,9 +38,9 @@ func (account) SubBalance(amount *big.Int) {}
func (account) AddBalance(amount *big.Int) {}
func (account) SetAddress(common.Address) {}
func (account) Value() *big.Int { return nil }
-func (account) SetBalance(*big.Int) {}
+func (account) SetBalance(*uint256.Int) {}
func (account) SetNonce(uint64) {}
-func (account) Balance() *big.Int { return nil }
+func (account) Balance() *uint256.Int { return nil }
func (account) Address() common.Address { return common.Address{} }
func (account) SetCode(common.Hash, []byte) {}
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
@@ -48,8 +49,8 @@ type dummyStatedb struct {
state.StateDB
}
-func (*dummyStatedb) GetRefund() uint64 { return 1337 }
-func (*dummyStatedb) GetBalance(addr common.Address) *big.Int { return new(big.Int) }
+func (*dummyStatedb) GetRefund() uint64 { return 1337 }
+func (*dummyStatedb) GetBalance(addr common.Address) *uint256.Int { return new(uint256.Int) }
type vmContext struct {
blockCtx vm.BlockContext
@@ -65,7 +66,7 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer})
gasLimit uint64 = 31000
startGas uint64 = 10000
- value = big.NewInt(0)
+ value = uint256.NewInt(0)
contract = vm.NewContract(account{}, account{}, value, startGas)
)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
@@ -74,7 +75,7 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
}
tracer.CaptureTxStart(gasLimit)
- tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
+ tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value.ToBig())
ret, err := env.Interpreter().Run(contract, []byte{}, false)
tracer.CaptureEnd(ret, startGas-contract.Gas, err)
// Rest gas assumes no refund
@@ -182,7 +183,7 @@ func TestHaltBetweenSteps(t *testing.T) {
}
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer})
scope := &vm.ScopeContext{
- Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
}
tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 0, big.NewInt(0))
tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil)
@@ -273,7 +274,7 @@ func TestEnterExit(t *testing.T) {
t.Fatal(err)
}
scope := &vm.ScopeContext{
- Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
}
tracer.CaptureEnter(vm.CALL, scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
tracer.CaptureExit([]byte{}, 400, nil)
diff --git a/eth/tracers/logger/gen_structlog.go b/eth/tracers/logger/gen_structlog.go
index df06a9ee6b..b406cb3445 100644
--- a/eth/tracers/logger/gen_structlog.go
+++ b/eth/tracers/logger/gen_structlog.go
@@ -23,7 +23,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
GasCost math.HexOrDecimal64 `json:"gasCost"`
Memory hexutil.Bytes `json:"memory,omitempty"`
MemorySize int `json:"memSize"`
- Stack []uint256.Int `json:"stack"`
+ Stack []hexutil.U256 `json:"stack"`
ReturnData hexutil.Bytes `json:"returnData,omitempty"`
Storage map[common.Hash]common.Hash `json:"-"`
Depth int `json:"depth"`
@@ -39,7 +39,12 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
enc.GasCost = math.HexOrDecimal64(s.GasCost)
enc.Memory = s.Memory
enc.MemorySize = s.MemorySize
- enc.Stack = s.Stack
+ if s.Stack != nil {
+ enc.Stack = make([]hexutil.U256, len(s.Stack))
+ for k, v := range s.Stack {
+ enc.Stack[k] = hexutil.U256(v)
+ }
+ }
enc.ReturnData = s.ReturnData
enc.Storage = s.Storage
enc.Depth = s.Depth
@@ -59,7 +64,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
GasCost *math.HexOrDecimal64 `json:"gasCost"`
Memory *hexutil.Bytes `json:"memory,omitempty"`
MemorySize *int `json:"memSize"`
- Stack []uint256.Int `json:"stack"`
+ Stack []hexutil.U256 `json:"stack"`
ReturnData *hexutil.Bytes `json:"returnData,omitempty"`
Storage map[common.Hash]common.Hash `json:"-"`
Depth *int `json:"depth"`
@@ -89,7 +94,10 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
s.MemorySize = *dec.MemorySize
}
if dec.Stack != nil {
- s.Stack = dec.Stack
+ s.Stack = make([]uint256.Int, len(dec.Stack))
+ for k, v := range dec.Stack {
+ s.Stack[k] = uint256.Int(v)
+ }
}
if dec.ReturnData != nil {
s.ReturnData = *dec.ReturnData
diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go
index abcd2e655f..6f3a20f9c0 100644
--- a/eth/tracers/logger/logger.go
+++ b/eth/tracers/logger/logger.go
@@ -83,6 +83,7 @@ type structLogMarshaling struct {
GasCost math.HexOrDecimal64
Memory hexutil.Bytes
ReturnData hexutil.Bytes
+ Stack []hexutil.U256
OpName string `json:"opName"` // adds call to OpName() in MarshalJSON
ErrorString string `json:"error,omitempty"` // adds call to ErrorString() in MarshalJSON
}
diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go
index 3192a15cba..1d8eb320f6 100644
--- a/eth/tracers/logger/logger_test.go
+++ b/eth/tracers/logger/logger_test.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
type dummyContractRef struct {
@@ -56,7 +57,7 @@ func TestStoreCapture(t *testing.T) {
var (
logger = NewStructLogger(nil)
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger})
- contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 100000)
+ contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 100000)
)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
var index common.Hash
diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go
index 4fcc1420ca..555c41a451 100644
--- a/eth/tracers/native/call.go
+++ b/eth/tracers/native/call.go
@@ -40,6 +40,9 @@ type callLog struct {
Address common.Address `json:"address"`
Topics []common.Hash `json:"topics"`
Data hexutil.Bytes `json:"data"`
+ // Position of the log relative to subcalls within the same trace
+ // See https://github.com/ethereum/go-ethereum/pull/28389 for details
+ Position hexutil.Uint `json:"position"`
}
type callFrame struct {
@@ -188,7 +191,12 @@ func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
return
}
- log := callLog{Address: scope.Contract.Address(), Topics: topics, Data: hexutil.Bytes(data)}
+ log := callLog{
+ Address: scope.Contract.Address(),
+ Topics: topics,
+ Data: hexutil.Bytes(data),
+ Position: hexutil.Uint(len(t.callstack[len(t.callstack)-1].Calls)),
+ }
t.callstack[len(t.callstack)-1].Logs = append(t.callstack[len(t.callstack)-1].Logs, log)
}
}
diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go
index dad085fd46..a1d511fb3c 100644
--- a/eth/tracers/native/prestate.go
+++ b/eth/tracers/native/prestate.go
@@ -195,7 +195,7 @@ func (t *prestateTracer) CaptureTxEnd(restGas uint64) {
}
modified := false
postAccount := &account{Storage: make(map[common.Hash]common.Hash)}
- newBalance := t.env.StateDB.GetBalance(addr)
+ newBalance := t.env.StateDB.GetBalance(addr).ToBig()
newNonce := t.env.StateDB.GetNonce(addr)
newCode := t.env.StateDB.GetCode(addr)
@@ -281,7 +281,7 @@ func (t *prestateTracer) lookupAccount(addr common.Address) {
}
t.pre[addr] = &account{
- Balance: t.env.StateDB.GetBalance(addr),
+ Balance: t.env.StateDB.GetBalance(addr).ToBig(),
Nonce: t.env.StateDB.GetNonce(addr),
Code: t.env.StateDB.GetCode(addr),
Storage: make(map[common.Hash]common.Hash),
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index b4989ec984..54d34ec5d1 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -90,7 +90,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
//EnableReturnData: false,
})
evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer})
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
index 0765fd5d49..c5c6a391c7 100644
--- a/ethclient/ethclient.go
+++ b/ethclient/ethclient.go
@@ -52,6 +52,16 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) {
return NewClient(c), nil
}
+// DialOptions creates a new RPC client for the given URL. You can supply any of the
+// pre-defined client options to configure the underlying transport.
+func DialOptions(ctx context.Context, rawurl string, opts ...rpc.ClientOption) (*Client, error) {
+ c, err := rpc.DialOptions(ctx, rawurl, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return NewClient(c), nil
+}
+
// NewClient creates a client that uses the given RPC client.
func NewClient(c *rpc.Client) *Client {
return &Client{c}
@@ -374,10 +384,8 @@ func (ec *Client) TransactionDataAndReceipt(ctx context.Context, txHash common.H
func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
var r *types.Receipt
err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash)
- if err == nil {
- if r == nil {
- return nil, ethereum.NotFound
- }
+ if err == nil && r == nil {
+ return nil, ethereum.NotFound
}
return r, err
}
@@ -448,6 +456,13 @@ func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNu
return (*big.Int)(&result), err
}
+// BalanceAtHash returns the wei balance of the given account.
+func (ec *Client) BalanceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (*big.Int, error) {
+ var result hexutil.Big
+ err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
+ return (*big.Int)(&result), err
+}
+
// StorageAt returns the value of key in the contract storage of the given account.
// The block number can be nil, in which case the value is taken from the latest known block.
func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
@@ -456,6 +471,13 @@ func (ec *Client) StorageAt(ctx context.Context, account common.Address, key com
return result, err
}
+// StorageAtHash returns the value of key in the contract storage of the given account.
+func (ec *Client) StorageAtHash(ctx context.Context, account common.Address, key common.Hash, blockHash common.Hash) ([]byte, error) {
+ var result hexutil.Bytes
+ err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, rpc.BlockNumberOrHashWithHash(blockHash, false))
+ return result, err
+}
+
// CodeAt returns the contract code of the given account.
// The block number can be nil, in which case the code is taken from the latest known block.
func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) {
@@ -464,6 +486,13 @@ func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumbe
return result, err
}
+// CodeAtHash returns the contract code of the given account.
+func (ec *Client) CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) {
+ var result hexutil.Bytes
+ err := ec.c.CallContext(ctx, &result, "eth_getCode", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
+ return result, err
+}
+
// NonceAt returns the account nonce of the given account.
// The block number can be nil, in which case the nonce is taken from the latest known block.
func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) {
@@ -472,6 +501,13 @@ func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumb
return uint64(result), err
}
+// NonceAtHash returns the account nonce of the given account.
+func (ec *Client) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) {
+ var result hexutil.Uint64
+ err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
+ return uint64(result), err
+}
+
// Filters
// FilterLogs executes a filter query.
@@ -689,6 +725,43 @@ func (ec *Client) SendTransactionConditional(ctx context.Context, tx *types.Tran
return ec.c.CallContext(ctx, nil, "eth_sendRawTransactionConditional", hexutil.Encode(data), opts)
}
+// MevRunning returns whether MEV is running
+func (ec *Client) MevRunning(ctx context.Context) (bool, error) {
+ var result bool
+ err := ec.c.CallContext(ctx, &result, "mev_running")
+ return result, err
+}
+
+// SendBid sends a bid
+func (ec *Client) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, error) {
+ var hash common.Hash
+ err := ec.c.CallContext(ctx, &hash, "mev_sendBid", args)
+ if err != nil {
+ return common.Hash{}, err
+ }
+ return hash, nil
+}
+
+// BestBidGasFee returns the gas fee of the best bid for the given parent hash.
+func (ec *Client) BestBidGasFee(ctx context.Context, parentHash common.Hash) (*big.Int, error) {
+ var fee *big.Int
+ err := ec.c.CallContext(ctx, &fee, "mev_bestBidGasFee", parentHash)
+ if err != nil {
+ return nil, err
+ }
+ return fee, nil
+}
+
+// MevParams returns the static params of mev
+func (ec *Client) MevParams(ctx context.Context) (*types.MevParams, error) {
+ var params types.MevParams
+ err := ec.c.CallContext(ctx, ¶ms, "mev_params")
+ if err != nil {
+ return nil, err
+ }
+ return ¶ms, err
+}
+
func toBlockNumArg(number *big.Int) string {
if number == nil {
return "latest"
@@ -710,7 +783,7 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
"to": msg.To,
}
if len(msg.Data) > 0 {
- arg["data"] = hexutil.Bytes(msg.Data)
+ arg["input"] = hexutil.Bytes(msg.Data)
}
if msg.Value != nil {
arg["value"] = (*hexutil.Big)(msg.Value)
@@ -721,6 +794,15 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
if msg.GasPrice != nil {
arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
}
+ if msg.GasFeeCap != nil {
+ arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap)
+ }
+ if msg.GasTipCap != nil {
+ arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
+ }
+ if msg.AccessList != nil {
+ arg["accessList"] = msg.AccessList
+ }
return arg
}
@@ -733,18 +815,20 @@ type rpcProgress struct {
PulledStates hexutil.Uint64
KnownStates hexutil.Uint64
- SyncedAccounts hexutil.Uint64
- SyncedAccountBytes hexutil.Uint64
- SyncedBytecodes hexutil.Uint64
- SyncedBytecodeBytes hexutil.Uint64
- SyncedStorage hexutil.Uint64
- SyncedStorageBytes hexutil.Uint64
- HealedTrienodes hexutil.Uint64
- HealedTrienodeBytes hexutil.Uint64
- HealedBytecodes hexutil.Uint64
- HealedBytecodeBytes hexutil.Uint64
- HealingTrienodes hexutil.Uint64
- HealingBytecode hexutil.Uint64
+ SyncedAccounts hexutil.Uint64
+ SyncedAccountBytes hexutil.Uint64
+ SyncedBytecodes hexutil.Uint64
+ SyncedBytecodeBytes hexutil.Uint64
+ SyncedStorage hexutil.Uint64
+ SyncedStorageBytes hexutil.Uint64
+ HealedTrienodes hexutil.Uint64
+ HealedTrienodeBytes hexutil.Uint64
+ HealedBytecodes hexutil.Uint64
+ HealedBytecodeBytes hexutil.Uint64
+ HealingTrienodes hexutil.Uint64
+ HealingBytecode hexutil.Uint64
+ TxIndexFinishedBlocks hexutil.Uint64
+ TxIndexRemainingBlocks hexutil.Uint64
}
func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
@@ -752,22 +836,24 @@ func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
return nil
}
return ðereum.SyncProgress{
- StartingBlock: uint64(p.StartingBlock),
- CurrentBlock: uint64(p.CurrentBlock),
- HighestBlock: uint64(p.HighestBlock),
- PulledStates: uint64(p.PulledStates),
- KnownStates: uint64(p.KnownStates),
- SyncedAccounts: uint64(p.SyncedAccounts),
- SyncedAccountBytes: uint64(p.SyncedAccountBytes),
- SyncedBytecodes: uint64(p.SyncedBytecodes),
- SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes),
- SyncedStorage: uint64(p.SyncedStorage),
- SyncedStorageBytes: uint64(p.SyncedStorageBytes),
- HealedTrienodes: uint64(p.HealedTrienodes),
- HealedTrienodeBytes: uint64(p.HealedTrienodeBytes),
- HealedBytecodes: uint64(p.HealedBytecodes),
- HealedBytecodeBytes: uint64(p.HealedBytecodeBytes),
- HealingTrienodes: uint64(p.HealingTrienodes),
- HealingBytecode: uint64(p.HealingBytecode),
+ StartingBlock: uint64(p.StartingBlock),
+ CurrentBlock: uint64(p.CurrentBlock),
+ HighestBlock: uint64(p.HighestBlock),
+ PulledStates: uint64(p.PulledStates),
+ KnownStates: uint64(p.KnownStates),
+ SyncedAccounts: uint64(p.SyncedAccounts),
+ SyncedAccountBytes: uint64(p.SyncedAccountBytes),
+ SyncedBytecodes: uint64(p.SyncedBytecodes),
+ SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes),
+ SyncedStorage: uint64(p.SyncedStorage),
+ SyncedStorageBytes: uint64(p.SyncedStorageBytes),
+ HealedTrienodes: uint64(p.HealedTrienodes),
+ HealedTrienodeBytes: uint64(p.HealedTrienodeBytes),
+ HealedBytecodes: uint64(p.HealedBytecodes),
+ HealedBytecodeBytes: uint64(p.HealedBytecodeBytes),
+ HealingTrienodes: uint64(p.HealingTrienodes),
+ HealingBytecode: uint64(p.HealingBytecode),
+ TxIndexFinishedBlocks: uint64(p.TxIndexFinishedBlocks),
+ TxIndexRemainingBlocks: uint64(p.TxIndexRemainingBlocks),
}
}
diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go
index 45e0e9f413..5f2a437185 100644
--- a/ethclient/ethclient_test.go
+++ b/ethclient/ethclient_test.go
@@ -271,9 +271,25 @@ var genesis = &core.Genesis{
Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}},
ExtraData: []byte("test genesis"),
Timestamp: 9000,
- BaseFee: big.NewInt(params.InitialBaseFee),
+ BaseFee: big.NewInt(params.InitialBaseFeeForBSC),
}
+var testTx1 = types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{
+ Nonce: 254,
+ Value: big.NewInt(12),
+ GasPrice: testGasPrice,
+ Gas: params.TxGas,
+ To: &common.Address{2},
+})
+
+var testTx2 = types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{
+ Nonce: 255,
+ Value: big.NewInt(8),
+ GasPrice: testGasPrice,
+ Gas: params.TxGas,
+ To: &common.Address{2},
+})
+
type testTransactionParam struct {
to common.Address
value *big.Int
@@ -310,6 +326,13 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
t.Fatalf("can't import test blocks: %v", err)
}
+ // Ensure the tx indexing is fully generated
+ for ; ; time.Sleep(time.Millisecond * 100) {
+ progress, err := ethservice.BlockChain().TxIndexProgress()
+ if err == nil && progress.Done() {
+ break
+ }
+ }
return n, blocks
}
@@ -352,6 +375,11 @@ func generateTestChain() []*types.Block {
}
}
}
+ // for testTransactionInBlock
+ if i+1 == testBlockNum {
+ block.AddTxWithChain(chain, testTx1)
+ block.AddTxWithChain(chain, testTx2)
+ }
}
gblock := genesis.MustCommit(db, trie.NewDatabase(db, nil))
engine := ethash.NewFaker()
@@ -376,7 +404,7 @@ func TestEthClient(t *testing.T) {
func(t *testing.T) { testBalanceAt(t, client) },
},
"TxInBlockInterrupted": {
- func(t *testing.T) { testTransactionInBlockInterrupted(t, client) },
+ func(t *testing.T) { testTransactionInBlock(t, client) },
},
"ChainID": {
func(t *testing.T) { testChainID(t, client) },
@@ -393,13 +421,13 @@ func TestEthClient(t *testing.T) {
"CallContractAtHash": {
func(t *testing.T) { testCallContractAtHash(t, client) },
},
+ // DO not have TestAtFunctions now, because we do not have pending block now
// "AtFunctions": {
// func(t *testing.T) { testAtFunctions(t, client) },
// },
"TestSendTransactionConditional": {
func(t *testing.T) { testSendTransactionConditional(t, client) },
},
- // DO not have TestAtFunctions now, because we do not have pending block now
}
t.Parallel()
@@ -452,7 +480,7 @@ func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) {
// because reflect.DeepEqual(*types.Header, *types.Header) sometimes
// returns false even though the underlying field values are exactly the same.
if !reflect.DeepEqual(gotBytes, wantBytes) {
- t.Fatalf("HeaderByNumber(%v)\n = %v\nwant %v", tt.block, got, tt.want)
+ t.Fatalf("HeaderByNumber(%v) got = %v, want %v", tt.block, got, tt.want)
}
})
}
@@ -504,7 +532,7 @@ func testBalanceAt(t *testing.T, client *rpc.Client) {
}
}
-func testTransactionInBlockInterrupted(t *testing.T, client *rpc.Client) {
+func testTransactionInBlock(t *testing.T, client *rpc.Client) {
ec := NewClient(client)
// Get current block by number.
@@ -513,21 +541,27 @@ func testTransactionInBlockInterrupted(t *testing.T, client *rpc.Client) {
t.Fatalf("unexpected error: %v", err)
}
- // Test tx in block interrupted.
- ctx, cancel := context.WithCancel(context.Background())
- cancel()
- tx, err := ec.TransactionInBlock(ctx, block.Hash(), 0)
- if tx != nil {
- t.Fatal("transaction should be nil")
- }
- if err == nil || err == ethereum.NotFound {
- t.Fatal("error should not be nil/notfound")
- }
-
// Test tx in block not found.
if _, err := ec.TransactionInBlock(context.Background(), block.Hash(), 20); err != ethereum.NotFound {
t.Fatal("error should be ethereum.NotFound")
}
+
+ // Test tx in block found.
+ tx, err := ec.TransactionInBlock(context.Background(), block.Hash(), 2)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if tx.Hash() != testTx1.Hash() {
+ t.Fatalf("unexpected transaction: %v", tx)
+ }
+
+ tx, err = ec.TransactionInBlock(context.Background(), block.Hash(), 3)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if tx.Hash() != testTx2.Hash() {
+ t.Fatalf("unexpected transaction: %v", tx)
+ }
}
func testChainID(t *testing.T, client *rpc.Client) {
@@ -603,7 +637,7 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
- if networkID.Cmp(big.NewInt(0)) != 0 {
+ if networkID.Cmp(big.NewInt(1337)) != 0 {
t.Fatalf("unexpected networkID: %v", networkID)
}
@@ -639,8 +673,8 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) {
},
},
BaseFee: []*big.Int{
- big.NewInt(params.InitialBaseFee),
- big.NewInt(params.InitialBaseFee),
+ big.NewInt(params.InitialBaseFeeForBSC),
+ big.NewInt(params.InitialBaseFeeForBSC),
},
GasUsedRatio: []float64{0.008912678667376286},
}
diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go
index c029611678..73d05d499e 100644
--- a/ethclient/gethclient/gethclient.go
+++ b/ethclient/gethclient/gethclient.go
@@ -225,7 +225,7 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
"to": msg.To,
}
if len(msg.Data) > 0 {
- arg["data"] = hexutil.Bytes(msg.Data)
+ arg["input"] = hexutil.Bytes(msg.Data)
}
if msg.Value != nil {
arg["value"] = (*hexutil.Big)(msg.Value)
@@ -236,6 +236,15 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
if msg.GasPrice != nil {
arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
}
+ if msg.GasFeeCap != nil {
+ arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap)
+ }
+ if msg.GasTipCap != nil {
+ arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
+ }
+ if msg.AccessList != nil {
+ arg["accessList"] = msg.AccessList
+ }
return arg
}
diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go
index 19003d2e13..dbe2310a62 100644
--- a/ethclient/gethclient/gethclient_test.go
+++ b/ethclient/gethclient/gethclient_test.go
@@ -39,11 +39,13 @@ import (
)
var (
- testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
- testSlot = common.HexToHash("0xdeadbeef")
- testValue = crypto.Keccak256Hash(testSlot[:])
- testBalance = big.NewInt(2e15)
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
+ testContract = common.HexToAddress("0xbeef")
+ testEmpty = common.HexToAddress("0xeeee")
+ testSlot = common.HexToHash("0xdeadbeef")
+ testValue = crypto.Keccak256Hash(testSlot[:])
+ testBalance = big.NewInt(2e15)
)
func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
@@ -78,8 +80,12 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
func generateTestChain() (*core.Genesis, []*types.Block) {
genesis := &core.Genesis{
- Config: params.AllEthashProtocolChanges,
- Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}}},
+ Config: params.AllEthashProtocolChanges,
+ Alloc: core.GenesisAlloc{
+ testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}},
+ testContract: {Nonce: 1, Code: []byte{0x13, 0x37}},
+ testEmpty: {Balance: big.NewInt(1)},
+ },
ExtraData: []byte("test genesis"),
Timestamp: 9000,
}
@@ -103,8 +109,17 @@ func TestGethClient(t *testing.T) {
test func(t *testing.T)
}{
{
- "TestGetProof",
- func(t *testing.T) { testGetProof(t, client) },
+ "TestGetProof1",
+ func(t *testing.T) { testGetProof(t, client, testAddr) },
+ }, {
+ "TestGetProof2",
+ func(t *testing.T) { testGetProof(t, client, testContract) },
+ }, {
+ "TestGetProofEmpty",
+ func(t *testing.T) { testGetProof(t, client, testEmpty) },
+ }, {
+ "TestGetProofNonExistent",
+ func(t *testing.T) { testGetProofNonExistent(t, client) },
}, {
"TestGetProofCanonicalizeKeys",
func(t *testing.T) { testGetProofCanonicalizeKeys(t, client) },
@@ -154,7 +169,7 @@ func testAccessList(t *testing.T, client *rpc.Client) {
From: testAddr,
To: &common.Address{},
Gas: 21000,
- GasPrice: big.NewInt(params.InitialBaseFee),
+ GasPrice: big.NewInt(875000000),
Value: big.NewInt(1),
}
al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
@@ -201,38 +216,41 @@ func testAccessList(t *testing.T, client *rpc.Client) {
}
}
-func testGetProof(t *testing.T, client *rpc.Client) {
+func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) {
ec := New(client)
ethcl := ethclient.NewClient(client)
- result, err := ec.GetProof(context.Background(), testAddr, []string{testSlot.String()}, nil)
+ result, err := ec.GetProof(context.Background(), addr, []string{testSlot.String()}, nil)
if err != nil {
t.Fatal(err)
}
- if !bytes.Equal(result.Address[:], testAddr[:]) {
- t.Fatalf("unexpected address, want: %v got: %v", testAddr, result.Address)
+ if result.Address != addr {
+ t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr)
}
// test nonce
- nonce, _ := ethcl.NonceAt(context.Background(), result.Address, nil)
- if result.Nonce != nonce {
+ if nonce, _ := ethcl.NonceAt(context.Background(), addr, nil); result.Nonce != nonce {
t.Fatalf("invalid nonce, want: %v got: %v", nonce, result.Nonce)
}
// test balance
- balance, _ := ethcl.BalanceAt(context.Background(), result.Address, nil)
- if result.Balance.Cmp(balance) != 0 {
+ if balance, _ := ethcl.BalanceAt(context.Background(), addr, nil); result.Balance.Cmp(balance) != 0 {
t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance)
}
-
// test storage
if len(result.StorageProof) != 1 {
t.Fatalf("invalid storage proof, want 1 proof, got %v proof(s)", len(result.StorageProof))
}
- proof := result.StorageProof[0]
- slotValue, _ := ethcl.StorageAt(context.Background(), testAddr, testSlot, nil)
- if !bytes.Equal(slotValue, proof.Value.Bytes()) {
- t.Fatalf("invalid storage proof value, want: %v, got: %v", slotValue, proof.Value.Bytes())
+ for _, proof := range result.StorageProof {
+ if proof.Key != testSlot.String() {
+ t.Fatalf("invalid storage proof key, want: %q, got: %q", testSlot.String(), proof.Key)
+ }
+ slotValue, _ := ethcl.StorageAt(context.Background(), addr, common.HexToHash(proof.Key), nil)
+ if have, want := common.BigToHash(proof.Value), common.BytesToHash(slotValue); have != want {
+ t.Fatalf("addr %x, invalid storage proof value: have: %v, want: %v", addr, have, want)
+ }
}
- if proof.Key != testSlot.String() {
- t.Fatalf("invalid storage proof key, want: %q, got: %q", testSlot.String(), proof.Key)
+ // test code
+ code, _ := ethcl.CodeAt(context.Background(), addr, nil)
+ if have, want := result.CodeHash, crypto.Keccak256Hash(code); have != want {
+ t.Fatalf("codehash wrong, have %v want %v ", have, want)
}
}
@@ -266,6 +284,38 @@ func testGetProofCanonicalizeKeys(t *testing.T, client *rpc.Client) {
}
}
+func testGetProofNonExistent(t *testing.T, client *rpc.Client) {
+ addr := common.HexToAddress("0x0001")
+ ec := New(client)
+ result, err := ec.GetProof(context.Background(), addr, nil, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if result.Address != addr {
+ t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr)
+ }
+ // test nonce
+ if result.Nonce != 0 {
+ t.Fatalf("invalid nonce, want: %v got: %v", 0, result.Nonce)
+ }
+ // test balance
+ if result.Balance.Cmp(big.NewInt(0)) != 0 {
+ t.Fatalf("invalid balance, want: %v got: %v", 0, result.Balance)
+ }
+ // test storage
+ if have := len(result.StorageProof); have != 0 {
+ t.Fatalf("invalid storage proof, want 0 proof, got %v proof(s)", have)
+ }
+ // test codeHash
+ if have, want := result.CodeHash, (common.Hash{}); have != want {
+ t.Fatalf("codehash wrong, have %v want %v ", have, want)
+ }
+ // test codeHash
+ if have, want := result.StorageHash, (common.Hash{}); have != want {
+ t.Fatalf("storagehash wrong, have %v want %v ", have, want)
+ }
+}
+
func testGCStats(t *testing.T, client *rpc.Client) {
ec := New(client)
_, err := ec.GCStats(context.Background())
@@ -400,7 +450,7 @@ func testCallContract(t *testing.T, client *rpc.Client) {
func TestOverrideAccountMarshal(t *testing.T) {
om := map[common.Address]OverrideAccount{
{0x11}: {
- // Zero-valued nonce is not overriddden, but simply dropped by the encoder.
+ // Zero-valued nonce is not overridden, but simply dropped by the encoder.
Nonce: 0,
},
{0xaa}: {
diff --git a/ethclient/simulated/backend.go b/ethclient/simulated/backend.go
new file mode 100644
index 0000000000..3327297c32
--- /dev/null
+++ b/ethclient/simulated/backend.go
@@ -0,0 +1,196 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package simulated
+
+import (
+ "context"
+ "time"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/eth/catalyst"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/eth/filters"
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// TransactionConditionalSender injects the conditional transaction into the pending pool for execution after verification.
+type TransactionConditionalSender interface {
+ SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts ethapi.TransactionOpts) error
+}
+
+// Client exposes the methods provided by the Ethereum RPC client.
+type Client interface {
+ ethereum.BlockNumberReader
+ ethereum.ChainReader
+ ethereum.ChainStateReader
+ ethereum.ContractCaller
+ ethereum.GasEstimator
+ ethereum.GasPricer
+ ethereum.GasPricer1559
+ ethereum.FeeHistoryReader
+ ethereum.LogFilterer
+ ethereum.PendingStateReader
+ ethereum.PendingContractCaller
+ ethereum.TransactionReader
+ ethereum.TransactionSender
+ ethereum.ChainIDReader
+ TransactionConditionalSender
+}
+
+// simClient wraps ethclient. This exists to prevent extracting ethclient.Client
+// from the Client interface returned by Backend.
+type simClient struct {
+ *ethclient.Client
+}
+
+// Backend is a simulated blockchain. You can use it to test your contracts or
+// other code that interacts with the Ethereum chain.
+type Backend struct {
+ eth *eth.Ethereum
+ beacon *catalyst.SimulatedBeacon
+ client simClient
+}
+
+// NewBackend creates a new simulated blockchain that can be used as a backend for
+// contract bindings in unit tests.
+//
+// A simulated backend always uses chainID 1337.
+func NewBackend(alloc core.GenesisAlloc, options ...func(nodeConf *node.Config, ethConf *ethconfig.Config)) *Backend {
+ // Create the default configurations for the outer node shell and the Ethereum
+ // service to mutate with the options afterwards
+ nodeConf := node.DefaultConfig
+ nodeConf.DataDir = ""
+ nodeConf.P2P = p2p.Config{NoDiscovery: true}
+
+ ethConf := ethconfig.Defaults
+ ethConf.Genesis = &core.Genesis{
+ Config: params.AllDevChainProtocolChanges,
+ GasLimit: ethconfig.Defaults.Miner.GasCeil,
+ Alloc: alloc,
+ }
+ ethConf.SyncMode = downloader.FullSync
+ ethConf.TxPool.NoLocals = true
+
+ for _, option := range options {
+ option(&nodeConf, ðConf)
+ }
+ // Assemble the Ethereum stack to run the chain with
+ stack, err := node.New(&nodeConf)
+ if err != nil {
+ panic(err) // this should never happen
+ }
+ sim, err := newWithNode(stack, ðConf, 0)
+ if err != nil {
+ panic(err) // this should never happen
+ }
+ return sim
+}
+
+// newWithNode sets up a simulated backend on an existing node. The provided node
+// must not be started and will be started by this method.
+func newWithNode(stack *node.Node, conf *eth.Config, blockPeriod uint64) (*Backend, error) {
+ backend, err := eth.New(stack, conf)
+ if err != nil {
+ return nil, err
+ }
+ // Register the filter system
+ filterSystem := filters.NewFilterSystem(backend.APIBackend, filters.Config{})
+ stack.RegisterAPIs([]rpc.API{{
+ Namespace: "eth",
+ Service: filters.NewFilterAPI(filterSystem, false),
+ }})
+ // Start the node
+ if err := stack.Start(); err != nil {
+ return nil, err
+ }
+ // Set up the simulated beacon
+ beacon, err := catalyst.NewSimulatedBeacon(blockPeriod, backend)
+ if err != nil {
+ return nil, err
+ }
+ // Reorg our chain back to genesis
+ if err := beacon.Fork(backend.BlockChain().GetCanonicalHash(0)); err != nil {
+ return nil, err
+ }
+ return &Backend{
+ eth: backend,
+ beacon: beacon,
+ client: simClient{ethclient.NewClient(stack.Attach())},
+ }, nil
+}
+
+// Close shuts down the simBackend.
+// The simulated backend can't be used afterwards.
+func (n *Backend) Close() error {
+ if n.client.Client != nil {
+ n.client.Close()
+ n.client = simClient{}
+ }
+ if n.beacon != nil {
+ err := n.beacon.Stop()
+ n.beacon = nil
+ return err
+ }
+ return nil
+}
+
+// Commit seals a block and moves the chain forward to a new empty block.
+func (n *Backend) Commit() common.Hash {
+ return n.beacon.Commit()
+}
+
+// Rollback removes all pending transactions, reverting to the last committed state.
+func (n *Backend) Rollback() {
+ n.beacon.Rollback()
+}
+
+// Fork creates a side-chain that can be used to simulate reorgs.
+//
+// This function should be called with the ancestor block where the new side
+// chain should be started. Transactions (old and new) can then be applied on
+// top and Commit-ed.
+//
+// Note, the side-chain will only become canonical (and trigger the events) when
+// it becomes longer. Until then CallContract will still operate on the current
+// canonical chain.
+//
+// There is a % chance that the side chain becomes canonical at the same length
+// to simulate live network behavior.
+func (n *Backend) Fork(parentHash common.Hash) error {
+ return n.beacon.Fork(parentHash)
+}
+
+// AdjustTime changes the block timestamp and creates a new block.
+// It can only be called on empty blocks.
+func (n *Backend) AdjustTime(adjustment time.Duration) error {
+ return n.beacon.AdjustTime(adjustment)
+}
+
+// Client returns a client that accesses the simulated chain.
+func (n *Backend) Client() Client {
+ return n.client
+}
diff --git a/ethclient/simulated/backend_test.go b/ethclient/simulated/backend_test.go
new file mode 100644
index 0000000000..a9a8accfea
--- /dev/null
+++ b/ethclient/simulated/backend_test.go
@@ -0,0 +1,309 @@
+// Copyright 2019 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package simulated
+
+import (
+ "context"
+ "crypto/ecdsa"
+ "math/big"
+ "math/rand"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+var _ bind.ContractBackend = (Client)(nil)
+
+var (
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
+)
+
+func simTestBackend(testAddr common.Address) *Backend {
+ return NewBackend(
+ core.GenesisAlloc{
+ testAddr: {Balance: big.NewInt(10000000000000000)},
+ },
+ )
+}
+
+func newTx(sim *Backend, key *ecdsa.PrivateKey) (*types.Transaction, error) {
+ client := sim.Client()
+
+ // create a signed transaction to send
+ head, _ := client.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
+ gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
+ addr := crypto.PubkeyToAddress(key.PublicKey)
+ chainid, _ := client.ChainID(context.Background())
+ nonce, err := client.PendingNonceAt(context.Background(), addr)
+ if err != nil {
+ return nil, err
+ }
+ tx := types.NewTx(&types.DynamicFeeTx{
+ ChainID: chainid,
+ Nonce: nonce,
+ GasTipCap: big.NewInt(1),
+ GasFeeCap: gasPrice,
+ Gas: 21000,
+ To: &addr,
+ })
+ return types.SignTx(tx, types.LatestSignerForChainID(chainid), key)
+}
+
+func TestNewBackend(t *testing.T) {
+ sim := NewBackend(core.GenesisAlloc{})
+ defer sim.Close()
+
+ client := sim.Client()
+ num, err := client.BlockNumber(context.Background())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if num != 0 {
+ t.Fatalf("expected 0 got %v", num)
+ }
+ // Create a block
+ sim.Commit()
+ num, err = client.BlockNumber(context.Background())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if num != 1 {
+ t.Fatalf("expected 1 got %v", num)
+ }
+}
+
+func TestAdjustTime(t *testing.T) {
+ sim := NewBackend(core.GenesisAlloc{})
+ defer sim.Close()
+
+ client := sim.Client()
+ block1, _ := client.BlockByNumber(context.Background(), nil)
+
+ // Create a block
+ if err := sim.AdjustTime(time.Minute); err != nil {
+ t.Fatal(err)
+ }
+ block2, _ := client.BlockByNumber(context.Background(), nil)
+ prevTime := block1.Time()
+ newTime := block2.Time()
+ if newTime-prevTime != uint64(time.Minute) {
+ t.Errorf("adjusted time not equal to 60 seconds. prev: %v, new: %v", prevTime, newTime)
+ }
+}
+
+func TestSendTransaction(t *testing.T) {
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ signedTx, err := newTx(sim, testKey)
+ if err != nil {
+ t.Errorf("could not create transaction: %v", err)
+ }
+ // send tx to simulated backend
+ err = client.SendTransaction(ctx, signedTx)
+ if err != nil {
+ t.Errorf("could not add tx to pending block: %v", err)
+ }
+ sim.Commit()
+ block, err := client.BlockByNumber(ctx, big.NewInt(1))
+ if err != nil {
+ t.Errorf("could not get block at height 1: %v", err)
+ }
+
+ if signedTx.Hash() != block.Transactions()[0].Hash() {
+ t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash())
+ }
+}
+
+// TestFork check that the chain length after a reorg is correct.
+// Steps:
+// 1. Save the current block which will serve as parent for the fork.
+// 2. Mine n blocks with n ∈ [0, 20].
+// 3. Assert that the chain length is n.
+// 4. Fork by using the parent block as ancestor.
+// 5. Mine n+1 blocks which should trigger a reorg.
+// 6. Assert that the chain length is n+1.
+// Since Commit() was called 2n+1 times in total,
+// having a chain length of just n+1 means that a reorg occurred.
+func TestFork(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // 1.
+ parent, _ := client.HeaderByNumber(ctx, nil)
+
+ // 2.
+ n := int(rand.Int31n(21))
+ for i := 0; i < n; i++ {
+ sim.Commit()
+ }
+
+ // 3.
+ b, _ := client.BlockNumber(ctx)
+ if b != uint64(n) {
+ t.Error("wrong chain length")
+ }
+
+ // 4.
+ sim.Fork(parent.Hash())
+
+ // 5.
+ for i := 0; i < n+1; i++ {
+ sim.Commit()
+ }
+
+ // 6.
+ b, _ = client.BlockNumber(ctx)
+ if b != uint64(n+1) {
+ t.Error("wrong chain length")
+ }
+}
+
+// TestForkResendTx checks that re-sending a TX after a fork
+// is possible and does not cause a "nonce mismatch" panic.
+// Steps:
+// 1. Save the current block which will serve as parent for the fork.
+// 2. Send a transaction.
+// 3. Check that the TX is included in block 1.
+// 4. Fork by using the parent block as ancestor.
+// 5. Mine a block, Re-send the transaction and mine another one.
+// 6. Check that the TX is now included in block 2.
+func TestForkResendTx(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // 1.
+ parent, _ := client.HeaderByNumber(ctx, nil)
+
+ // 2.
+ tx, err := newTx(sim, testKey)
+ if err != nil {
+ t.Fatalf("could not create transaction: %v", err)
+ }
+ client.SendTransaction(ctx, tx)
+ sim.Commit()
+
+ // 3.
+ receipt, _ := client.TransactionReceipt(ctx, tx.Hash())
+ if h := receipt.BlockNumber.Uint64(); h != 1 {
+ t.Errorf("TX included in wrong block: %d", h)
+ }
+
+ // 4.
+ if err := sim.Fork(parent.Hash()); err != nil {
+ t.Errorf("forking: %v", err)
+ }
+
+ // 5.
+ sim.Commit()
+ if err := client.SendTransaction(ctx, tx); err != nil {
+ t.Fatalf("sending transaction: %v", err)
+ }
+ sim.Commit()
+ receipt, _ = client.TransactionReceipt(ctx, tx.Hash())
+ if h := receipt.BlockNumber.Uint64(); h != 2 {
+ t.Errorf("TX included in wrong block: %d", h)
+ }
+}
+
+func TestCommitReturnValue(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // Test if Commit returns the correct block hash
+ h1 := sim.Commit()
+ cur, _ := client.HeaderByNumber(ctx, nil)
+ if h1 != cur.Hash() {
+ t.Error("Commit did not return the hash of the last block.")
+ }
+
+ // Create a block in the original chain (containing a transaction to force different block hashes)
+ head, _ := client.HeaderByNumber(ctx, nil) // Should be child's, good enough
+ gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
+ _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
+ tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
+ client.SendTransaction(ctx, tx)
+
+ h2 := sim.Commit()
+
+ // Create another block in the original chain
+ sim.Commit()
+
+ // Fork at the first bock
+ if err := sim.Fork(h1); err != nil {
+ t.Errorf("forking: %v", err)
+ }
+
+ // Test if Commit returns the correct block hash after the reorg
+ h2fork := sim.Commit()
+ if h2 == h2fork {
+ t.Error("The block in the fork and the original block are the same block!")
+ }
+ if header, err := client.HeaderByHash(ctx, h2fork); err != nil || header == nil {
+ t.Error("Could not retrieve the just created block (side-chain)")
+ }
+}
+
+// TestAdjustTimeAfterFork ensures that after a fork, AdjustTime uses the pending fork
+// block's parent rather than the canonical head's parent.
+func TestAdjustTimeAfterFork(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ sim.Commit() // h1
+ h1, _ := client.HeaderByNumber(ctx, nil)
+
+ sim.Commit() // h2
+ sim.Fork(h1.Hash())
+ sim.AdjustTime(1 * time.Second)
+ sim.Commit()
+
+ head, _ := client.HeaderByNumber(ctx, nil)
+ if head.Number.Uint64() == 2 && head.ParentHash != h1.Hash() {
+ t.Errorf("failed to build block on fork")
+ }
+}
diff --git a/ethclient/simulated/options.go b/ethclient/simulated/options.go
new file mode 100644
index 0000000000..1b2f4c090d
--- /dev/null
+++ b/ethclient/simulated/options.go
@@ -0,0 +1,39 @@
+// Copyright 2024 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package simulated
+
+import (
+ "github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/node"
+)
+
+// WithBlockGasLimit configures the simulated backend to target a specific gas limit
+// when producing blocks.
+func WithBlockGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ ethConf.Genesis.GasLimit = gaslimit
+ ethConf.Miner.GasCeil = gaslimit
+ }
+}
+
+// WithCallGasLimit configures the simulated backend to cap eth_calls to a specific
+// gas limit when running client operations.
+func WithCallGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ ethConf.RPCGasCap = gaslimit
+ }
+}
diff --git a/ethclient/simulated/options_test.go b/ethclient/simulated/options_test.go
new file mode 100644
index 0000000000..d9ff3b428a
--- /dev/null
+++ b/ethclient/simulated/options_test.go
@@ -0,0 +1,73 @@
+// Copyright 2024 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package simulated
+
+import (
+ "context"
+ "math/big"
+ "strings"
+ "testing"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// Tests that the simulator starts with the initial gas limit in the genesis block,
+// and that it keeps the same target value.
+func TestWithBlockGasLimitOption(t *testing.T) {
+ // Construct a simulator, targeting a different gas limit
+ sim := NewBackend(core.GenesisAlloc{}, WithBlockGasLimit(12_345_678))
+ defer sim.Close()
+
+ client := sim.Client()
+ genesis, err := client.BlockByNumber(context.Background(), big.NewInt(0))
+ if err != nil {
+ t.Fatalf("failed to retrieve genesis block: %v", err)
+ }
+ if genesis.GasLimit() != 12_345_678 {
+ t.Errorf("genesis gas limit mismatch: have %v, want %v", genesis.GasLimit(), 12_345_678)
+ }
+ // Produce a number of blocks and verify the locked in gas target
+ sim.Commit()
+ head, err := client.BlockByNumber(context.Background(), big.NewInt(1))
+ if err != nil {
+ t.Fatalf("failed to retrieve head block: %v", err)
+ }
+ if head.GasLimit() != 12_345_678 {
+ t.Errorf("head gas limit mismatch: have %v, want %v", head.GasLimit(), 12_345_678)
+ }
+}
+
+// Tests that the simulator honors the RPC call caps set by the options.
+func TestWithCallGasLimitOption(t *testing.T) {
+ // Construct a simulator, targeting a different gas limit
+ sim := NewBackend(core.GenesisAlloc{
+ testAddr: {Balance: big.NewInt(10000000000000000)},
+ }, WithCallGasLimit(params.TxGas-1))
+ defer sim.Close()
+
+ client := sim.Client()
+ _, err := client.CallContract(context.Background(), ethereum.CallMsg{
+ From: testAddr,
+ To: &testAddr,
+ Gas: 21000,
+ }, nil)
+ if !strings.Contains(err.Error(), core.ErrIntrinsicGas.Error()) {
+ t.Fatalf("error mismatch: have %v, want %v", err, core.ErrIntrinsicGas)
+ }
+}
diff --git a/ethdb/dbtest/testsuite.go b/ethdb/dbtest/testsuite.go
index 0d3d5f5aa6..29bd24364e 100644
--- a/ethdb/dbtest/testsuite.go
+++ b/ethdb/dbtest/testsuite.go
@@ -273,9 +273,13 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
b.Put([]byte("5"), nil)
b.Delete([]byte("1"))
b.Put([]byte("6"), nil)
- b.Delete([]byte("3"))
+
+ b.Delete([]byte("3")) // delete then put
b.Put([]byte("3"), nil)
+ b.Put([]byte("7"), nil) // put then delete
+ b.Delete([]byte("7"))
+
if err := b.Write(); err != nil {
t.Fatal(err)
}
diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go
index c0e0eb250a..e58efbddbe 100644
--- a/ethdb/leveldb/leveldb.go
+++ b/ethdb/leveldb/leveldb.go
@@ -22,6 +22,7 @@ package leveldb
import (
"fmt"
+ "strings"
"sync"
"time"
@@ -245,6 +246,11 @@ func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
// Stat returns a particular internal stat of the database.
func (db *Database) Stat(property string) (string, error) {
+ if property == "" {
+ property = "leveldb.stats"
+ } else if !strings.HasPrefix(property, "leveldb.") {
+ property = "leveldb." + property
+ }
return db.db.GetProperty(property)
}
diff --git a/ethdb/memorydb/memorydb.go b/ethdb/memorydb/memorydb.go
index f9f74322b5..2a939f9a18 100644
--- a/ethdb/memorydb/memorydb.go
+++ b/ethdb/memorydb/memorydb.go
@@ -207,7 +207,7 @@ func (db *Database) Len() int {
// keyvalue is a key-value tuple tagged with a deletion field to allow creating
// memory-database write batches.
type keyvalue struct {
- key []byte
+ key string
value []byte
delete bool
}
@@ -222,14 +222,14 @@ type batch struct {
// Put inserts the given value into the batch for later committing.
func (b *batch) Put(key, value []byte) error {
- b.writes = append(b.writes, keyvalue{common.CopyBytes(key), common.CopyBytes(value), false})
+ b.writes = append(b.writes, keyvalue{string(key), common.CopyBytes(value), false})
b.size += len(key) + len(value)
return nil
}
// Delete inserts the a key removal into the batch for later committing.
func (b *batch) Delete(key []byte) error {
- b.writes = append(b.writes, keyvalue{common.CopyBytes(key), nil, true})
+ b.writes = append(b.writes, keyvalue{string(key), nil, true})
b.size += len(key)
return nil
}
@@ -249,10 +249,10 @@ func (b *batch) Write() error {
}
for _, keyvalue := range b.writes {
if keyvalue.delete {
- delete(b.db.db, string(keyvalue.key))
+ delete(b.db.db, keyvalue.key)
continue
}
- b.db.db[string(keyvalue.key)] = keyvalue.value
+ b.db.db[keyvalue.key] = keyvalue.value
}
return nil
}
@@ -267,12 +267,12 @@ func (b *batch) Reset() {
func (b *batch) Replay(w ethdb.KeyValueWriter) error {
for _, keyvalue := range b.writes {
if keyvalue.delete {
- if err := w.Delete(keyvalue.key); err != nil {
+ if err := w.Delete([]byte(keyvalue.key)); err != nil {
return err
}
continue
}
- if err := w.Put(keyvalue.key, keyvalue.value); err != nil {
+ if err := w.Put([]byte(keyvalue.key), keyvalue.value); err != nil {
return err
}
}
diff --git a/ethdb/memorydb/memorydb_test.go b/ethdb/memorydb/memorydb_test.go
index dba18ad306..51499c3b1f 100644
--- a/ethdb/memorydb/memorydb_test.go
+++ b/ethdb/memorydb/memorydb_test.go
@@ -17,6 +17,7 @@
package memorydb
import (
+ "encoding/binary"
"testing"
"github.com/ethereum/go-ethereum/ethdb"
@@ -30,3 +31,20 @@ func TestMemoryDB(t *testing.T) {
})
})
}
+
+// BenchmarkBatchAllocs measures the time/allocs for storing 120 kB of data
+func BenchmarkBatchAllocs(b *testing.B) {
+ b.ReportAllocs()
+ var key = make([]byte, 20)
+ var val = make([]byte, 100)
+ // 120 * 1_000 -> 120_000 == 120kB
+ for i := 0; i < b.N; i++ {
+ batch := New().NewBatch()
+ for j := uint64(0); j < 1000; j++ {
+ binary.BigEndian.PutUint64(key, j)
+ binary.BigEndian.PutUint64(val, j)
+ batch.Put(key, val)
+ }
+ batch.Write()
+ }
+}
diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go
index 429e92004e..37ead29f86 100644
--- a/ethdb/pebble/pebble.go
+++ b/ethdb/pebble/pebble.go
@@ -25,7 +25,6 @@ import (
"sync/atomic"
"time"
- "github.com/cockroachdb/errors"
"github.com/cockroachdb/pebble"
"github.com/cockroachdb/pebble/bloom"
"github.com/ethereum/go-ethereum/common"
@@ -72,6 +71,8 @@ type Database struct {
seekCompGauge metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt
manualMemAllocGauge metrics.Gauge // Gauge for tracking amount of non-managed memory currently allocated
+ levelsGauge []metrics.Gauge // Gauge for tracking the number of tables in levels
+
quitLock sync.RWMutex // Mutex protecting the quit channel and the closed flag
quitChan chan chan error // Quit channel to stop the metrics collection before closing the database
closed bool // keep track of whether we're Closed
@@ -86,6 +87,8 @@ type Database struct {
writeDelayStartTime time.Time // The start time of the latest write stall
writeDelayCount atomic.Int64 // Total number of write stall counts
writeDelayTime atomic.Int64 // Total time spent in write stalls
+
+ writeOptions *pebble.WriteOptions
}
func (d *Database) onCompactionBegin(info pebble.CompactionInfo) {
@@ -119,18 +122,23 @@ func (d *Database) onWriteStallEnd() {
}
// panicLogger is just a noop logger to disable Pebble's internal logger.
+//
+// TODO(karalabe): Remove when Pebble sets this as the default.
type panicLogger struct{}
func (l panicLogger) Infof(format string, args ...interface{}) {
}
+func (l panicLogger) Errorf(format string, args ...interface{}) {
+}
+
func (l panicLogger) Fatalf(format string, args ...interface{}) {
- panic(errors.Errorf("fatal: "+format, args...))
+ panic(fmt.Errorf("fatal: "+format, args...))
}
// New returns a wrapped pebble DB object. The namespace is the prefix that the
// metrics reporting should use for surfacing internal stats.
-func New(file string, cache int, handles int, namespace string, readonly bool) (*Database, error) {
+func New(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (*Database, error) {
// Ensure we have some minimal caching and file guarantees
if cache < minCache {
cache = minCache
@@ -171,9 +179,10 @@ func New(file string, cache int, handles int, namespace string, readonly bool) (
"handles", handles, "memory table", common.StorageSize(memTableSize))
db := &Database{
- fn: file,
- log: logger,
- quitChan: make(chan chan error),
+ fn: file,
+ log: logger,
+ quitChan: make(chan chan error),
+ writeOptions: &pebble.WriteOptions{Sync: !ephemeral},
}
opt := &pebble.Options{
// Pebble has a single combined cache area and the write
@@ -248,7 +257,7 @@ func New(file string, cache int, handles int, namespace string, readonly bool) (
db.manualMemAllocGauge = metrics.NewRegisteredGauge(namespace+"memory/manualalloc", nil)
// Start up the metrics gathering and return
- go db.meter(metricsGatheringInterval)
+ go db.meter(metricsGatheringInterval, namespace)
return db, nil
}
@@ -314,7 +323,7 @@ func (d *Database) Put(key []byte, value []byte) error {
if d.closed {
return pebble.ErrClosed
}
- return d.db.Set(key, value, pebble.Sync)
+ return d.db.Set(key, value, d.writeOptions)
}
// Delete removes the key from the key-value store.
@@ -337,9 +346,6 @@ func (d *Database) NewBatch() ethdb.Batch {
}
// NewBatchWithSize creates a write-only database batch with pre-allocated buffer.
-// It's not supported by pebble, but pebble has better memory allocation strategy
-// which turns out a lot faster than leveldb. It's performant enough to construct
-// batch object without any pre-allocated space.
func (d *Database) NewBatchWithSize(size int) ethdb.Batch {
return &batch{
b: d.db.NewBatchWithSize(size),
@@ -411,9 +417,12 @@ func upperBound(prefix []byte) (limit []byte) {
return limit
}
-// Stat returns a particular internal stat of the database.
+// Stat returns the internal metrics of Pebble in a text format. It's a developer
+// method to read everything there is to read independent of Pebble version.
+//
+// The property is unused in Pebble as there's only one thing to retrieve.
func (d *Database) Stat(property string) (string, error) {
- return "", nil
+ return d.db.Metrics().String(), nil
}
// Compact flattens the underlying data store for the given key range. In essence,
@@ -445,7 +454,7 @@ func (d *Database) Path() string {
// meter periodically retrieves internal pebble counters and reports them to
// the metrics subsystem.
-func (d *Database) meter(refresh time.Duration) {
+func (d *Database) meter(refresh time.Duration, namespace string) {
var errc chan error
timer := time.NewTimer(refresh)
defer timer.Stop()
@@ -468,7 +477,7 @@ func (d *Database) meter(refresh time.Duration) {
compRead int64
nWrite int64
- metrics = d.db.Metrics()
+ stats = d.db.Metrics()
compTime = d.compTime.Load()
writeDelayCount = d.writeDelayCount.Load()
writeDelayTime = d.writeDelayTime.Load()
@@ -479,14 +488,14 @@ func (d *Database) meter(refresh time.Duration) {
writeDelayCounts[i%2] = writeDelayCount
compTimes[i%2] = compTime
- for _, levelMetrics := range metrics.Levels {
+ for _, levelMetrics := range stats.Levels {
nWrite += int64(levelMetrics.BytesCompacted)
nWrite += int64(levelMetrics.BytesFlushed)
compWrite += int64(levelMetrics.BytesCompacted)
compRead += int64(levelMetrics.BytesRead)
}
- nWrite += int64(metrics.WAL.BytesWritten)
+ nWrite += int64(stats.WAL.BytesWritten)
compWrites[i%2] = compWrite
compReads[i%2] = compRead
@@ -508,7 +517,7 @@ func (d *Database) meter(refresh time.Duration) {
d.compWriteMeter.Mark(compWrites[i%2] - compWrites[(i-1)%2])
}
if d.diskSizeGauge != nil {
- d.diskSizeGauge.Update(int64(metrics.DiskSpaceUsage()))
+ d.diskSizeGauge.Update(int64(stats.DiskSpaceUsage()))
}
if d.diskReadMeter != nil {
d.diskReadMeter.Mark(0) // pebble doesn't track non-compaction reads
@@ -517,12 +526,20 @@ func (d *Database) meter(refresh time.Duration) {
d.diskWriteMeter.Mark(nWrites[i%2] - nWrites[(i-1)%2])
}
// See https://github.com/cockroachdb/pebble/pull/1628#pullrequestreview-1026664054
- manuallyAllocated := metrics.BlockCache.Size + int64(metrics.MemTable.Size) + int64(metrics.MemTable.ZombieSize)
+ manuallyAllocated := stats.BlockCache.Size + int64(stats.MemTable.Size) + int64(stats.MemTable.ZombieSize)
d.manualMemAllocGauge.Update(manuallyAllocated)
- d.memCompGauge.Update(metrics.Flush.Count)
+ d.memCompGauge.Update(stats.Flush.Count)
d.nonlevel0CompGauge.Update(nonLevel0CompCount)
d.level0CompGauge.Update(level0CompCount)
- d.seekCompGauge.Update(metrics.Compact.ReadCount)
+ d.seekCompGauge.Update(stats.Compact.ReadCount)
+
+ for i, level := range stats.Levels {
+ // Append metrics for additional layers
+ if i >= len(d.levelsGauge) {
+ d.levelsGauge = append(d.levelsGauge, metrics.NewRegisteredGauge(namespace+fmt.Sprintf("tables/level%v", i), nil))
+ }
+ d.levelsGauge[i].Update(level.NumFiles)
+ }
// Sleep a bit, then repeat the stats collection
select {
@@ -570,7 +587,7 @@ func (b *batch) Write() error {
if b.db.closed {
return pebble.ErrClosed
}
- return b.b.Commit(pebble.Sync)
+ return b.b.Commit(b.db.writeOptions)
}
// Reset resets the batch for reuse.
@@ -602,9 +619,12 @@ func (b *batch) Replay(w ethdb.KeyValueWriter) error {
// pebbleIterator is a wrapper of underlying iterator in storage engine.
// The purpose of this structure is to implement the missing APIs.
+//
+// The pebble iterator is not thread-safe.
type pebbleIterator struct {
- iter *pebble.Iterator
- moved bool
+ iter *pebble.Iterator
+ moved bool
+ released bool
}
// NewIterator creates a binary-alphabetical iterator over a subset
@@ -616,7 +636,7 @@ func (d *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
UpperBound: upperBound(prefix),
})
iter.First()
- return &pebbleIterator{iter: iter, moved: true}
+ return &pebbleIterator{iter: iter, moved: true, released: false}
}
// Next moves the iterator to the next key/value pair. It returns whether the
@@ -651,4 +671,9 @@ func (iter *pebbleIterator) Value() []byte {
// Release releases associated resources. Release should always succeed and can
// be called multiple times without causing error.
-func (iter *pebbleIterator) Release() { iter.iter.Close() }
+func (iter *pebbleIterator) Release() {
+ if !iter.released {
+ iter.iter.Close()
+ iter.released = true
+ }
+}
diff --git a/ethstats/ethstats.go b/ethstats/ethstats.go
index ebfcb98ebb..29559991be 100644
--- a/ethstats/ethstats.go
+++ b/ethstats/ethstats.go
@@ -75,12 +75,18 @@ type backend interface {
// reporting to ethstats
type fullNodeBackend interface {
backend
- Miner() *miner.Miner
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
- CurrentBlock() *types.Block
+ CurrentBlock() *types.Header
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
}
+// miningNodeBackend encompasses the functionality necessary for a mining node
+// reporting to ethstats
+type miningNodeBackend interface {
+ fullNodeBackend
+ Miner() *miner.Miner
+}
+
// Service implements an Ethereum netstats reporting daemon that pushes local
// chain statistics up to a monitoring server.
type Service struct {
@@ -633,7 +639,8 @@ func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
fullBackend, ok := s.backend.(fullNodeBackend)
if ok {
if block == nil {
- block = fullBackend.CurrentBlock()
+ head := fullBackend.CurrentBlock()
+ block, _ = fullBackend.BlockByNumber(context.Background(), rpc.BlockNumber(head.Number.Uint64()))
}
header = block.Header()
td = fullBackend.GetTd(context.Background(), header.Hash())
@@ -778,13 +785,14 @@ func (s *Service) reportStats(conn *connWrapper) error {
gasprice int
)
// check if backend is a full node
- fullBackend, ok := s.backend.(fullNodeBackend)
- if ok {
- mining = fullBackend.Miner().Mining()
- hashrate = int(fullBackend.Miner().Hashrate())
+ if fullBackend, ok := s.backend.(fullNodeBackend); ok {
+ if miningBackend, ok := s.backend.(miningNodeBackend); ok {
+ mining = miningBackend.Miner().Mining()
+ hashrate = int(miningBackend.Miner().Hashrate())
+ }
sync := fullBackend.SyncProgress()
- syncing = fullBackend.CurrentHeader().Number.Uint64() >= sync.HighestBlock
+ syncing = !sync.Done()
price, _ := fullBackend.SuggestGasTipCap(context.Background())
gasprice = int(price.Uint64())
@@ -793,7 +801,7 @@ func (s *Service) reportStats(conn *connWrapper) error {
}
} else {
sync := s.backend.SyncProgress()
- syncing = s.backend.CurrentHeader().Number.Uint64() >= sync.HighestBlock
+ syncing = !sync.Done()
}
// Assemble the node stats and send it to the server
log.Trace("Sending node details to ethstats")
diff --git a/event/subscription.go b/event/subscription.go
index 080985d1d4..19a5509dbc 100644
--- a/event/subscription.go
+++ b/event/subscription.go
@@ -121,7 +121,7 @@ func ResubscribeErr(backoffMax time.Duration, fn ResubscribeErrFunc) Subscriptio
backoffMax: backoffMax,
fn: fn,
err: make(chan error),
- unsub: make(chan struct{}),
+ unsub: make(chan struct{}, 1),
}
go s.loop()
return s
diff --git a/event/subscription_test.go b/event/subscription_test.go
index ba081705c4..743d0bf67d 100644
--- a/event/subscription_test.go
+++ b/event/subscription_test.go
@@ -154,3 +154,27 @@ func TestResubscribeWithErrorHandler(t *testing.T) {
t.Fatalf("unexpected subscription errors %v, want %v", subErrs, expectedSubErrs)
}
}
+
+func TestResubscribeWithCompletedSubscription(t *testing.T) {
+ t.Parallel()
+
+ quitProducerAck := make(chan struct{})
+ quitProducer := make(chan struct{})
+
+ sub := ResubscribeErr(100*time.Millisecond, func(ctx context.Context, lastErr error) (Subscription, error) {
+ return NewSubscription(func(unsubscribed <-chan struct{}) error {
+ select {
+ case <-quitProducer:
+ quitProducerAck <- struct{}{}
+ return nil
+ case <-unsubscribed:
+ return nil
+ }
+ }), nil
+ })
+
+ // Ensure producer has started and exited before Unsubscribe
+ close(quitProducer)
+ <-quitProducerAck
+ sub.Unsubscribe()
+}
diff --git a/go.mod b/go.mod
index ed760753e6..ad14a8a76e 100644
--- a/go.mod
+++ b/go.mod
@@ -5,24 +5,24 @@ go 1.21
toolchain go1.21.5
require (
- github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0
+ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0
+ github.com/Microsoft/go-winio v0.6.1
github.com/VictoriaMetrics/fastcache v1.12.1
- github.com/aws/aws-sdk-go-v2 v1.17.8
- github.com/aws/aws-sdk-go-v2/config v1.1.1
- github.com/aws/aws-sdk-go-v2/credentials v1.1.1
- github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1
+ github.com/aws/aws-sdk-go-v2 v1.21.2
+ github.com/aws/aws-sdk-go-v2/config v1.18.45
+ github.com/aws/aws-sdk-go-v2/credentials v1.13.43
+ github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2
github.com/bnb-chain/ics23 v0.1.0
github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/cespare/cp v1.1.1
- github.com/cloudflare/cloudflare-go v0.14.0
- github.com/cockroachdb/errors v1.9.1
+ github.com/cloudflare/cloudflare-go v0.79.0
github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593
github.com/cometbft/cometbft v0.37.0
github.com/consensys/gnark-crypto v0.12.1
+ github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233
github.com/crate-crypto/go-kzg-4844 v0.7.0
github.com/davecgh/go-spew v1.1.1
github.com/deckarep/golang-set/v2 v2.1.0
- github.com/docker/docker v24.0.7+incompatible
github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127
github.com/ethereum/c-kzg-4844 v0.4.0
github.com/fatih/color v1.13.0
@@ -31,11 +31,10 @@ require (
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
github.com/fsnotify/fsnotify v1.6.0
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08
- github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b
- github.com/go-stack/stack v1.8.1
+ github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46
github.com/gofrs/flock v0.8.1
github.com/golang-jwt/jwt/v4 v4.5.0
- github.com/golang/protobuf v1.5.3
+ github.com/golang/protobuf v1.5.4
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb
github.com/google/gofuzz v1.2.0
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b
@@ -46,12 +45,12 @@ require (
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7
github.com/holiman/bloomfilter/v2 v2.0.3
- github.com/holiman/uint256 v1.2.3
+ github.com/holiman/uint256 v1.2.4
github.com/huin/goupnp v1.3.0
github.com/influxdata/influxdb-client-go/v2 v2.4.0
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
github.com/jackpal/go-nat-pmp v1.0.2
- github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
+ github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267
github.com/julienschmidt/httprouter v1.3.0
github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c
github.com/kylelemons/godebug v1.1.0
@@ -84,34 +83,37 @@ require (
golang.org/x/crypto v0.17.0
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611
golang.org/x/sync v0.5.0
- golang.org/x/sys v0.15.0
+ golang.org/x/sys v0.16.0
golang.org/x/text v0.14.0
golang.org/x/time v0.3.0
golang.org/x/tools v0.16.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
- gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
gopkg.in/yaml.v3 v3.0.1
)
require (
contrib.go.opencensus.io/exporter/jaeger v0.2.1 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/aristanetworks/goarista v0.0.0-20200805130819-fd197cf57d96 // indirect
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 // indirect
- github.com/aws/aws-sdk-go-v2/internal/ini v1.3.33 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
- github.com/aws/smithy-go v1.13.5 // indirect
+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 // indirect
+ github.com/aws/smithy-go v1.15.0 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
- github.com/bits-and-blooms/bitset v1.7.0 // indirect
+ github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
+ github.com/cockroachdb/errors v1.9.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/redact v1.1.3 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
@@ -120,7 +122,6 @@ require (
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cosmos/gogoproto v1.4.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
- github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect
@@ -139,28 +140,33 @@ require (
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect
- github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.13.0 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
+ github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/go-cmp v0.5.9 // indirect
+ github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 // indirect
github.com/gtank/merlin v0.1.1 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
+ github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
@@ -275,7 +281,7 @@ require (
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.56.3 // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apimachinery v0.20.0 // indirect
@@ -293,5 +299,5 @@ replace (
github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-tendermint v0.0.0-20230417032003-4cda1f296fb2
github.com/grpc-ecosystem/grpc-gateway/v2 => github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1
github.com/syndtr/goleveldb v1.0.1 => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
- github.com/tendermint/tendermint => github.com/bnb-chain/tendermint v0.31.15
+ github.com/tendermint/tendermint => github.com/bnb-chain/tendermint v0.31.16
)
diff --git a/go.sum b/go.sum
index f7987ab3ec..87e3ff9ae4 100644
--- a/go.sum
+++ b/go.sum
@@ -58,12 +58,16 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOv
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 h1:qoVeMsc9/fh/yhxVaA0obYjVH/oI/ihrOoMwsLS9KSA=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM=
-github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 h1:E+m3SkZCN0Bf5q7YdTs5lSm2CYY3CK4spn5OmUIiQtk=
-github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJNuUB6n7rs5Wsel4dXLe90Um2n4=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+3LoSsYf9YMjkupeAnHMX8O9mmY=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4=
github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
@@ -84,6 +88,8 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@@ -97,6 +103,8 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@@ -149,27 +157,40 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo=
-github.com/aws/aws-sdk-go-v2 v1.17.8 h1:GMupCNNI7FARX27L7GjCJM8NgivWbRgpjNI/hOQjFS8=
-github.com/aws/aws-sdk-go-v2 v1.17.8/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
-github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo=
+github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA=
+github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM=
github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y=
-github.com/aws/aws-sdk-go-v2/credentials v1.1.1 h1:NbvWIM1Mx6sNPTxowHgS2ewXCRp+NGTzUYb/96FZJbY=
+github.com/aws/aws-sdk-go-v2/config v1.18.45 h1:Aka9bI7n8ysuwPeFdm77nfbyHCAKQ3z9ghB3S/38zes=
+github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE=
github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 h1:EtEU7WRaWliitZh2nmuxEXrN0Cb8EgPUFGIoTMeqbzI=
+github.com/aws/aws-sdk-go-v2/credentials v1.13.43 h1:LU8vo40zBlo3R7bAvBVy/ku4nxGEyZe9N8MqAeFTzF8=
+github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.3.33 h1:HbH1VjUgrCdLJ+4lnnuLI4iVNRvBbBELGaJ5f69ClA8=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.3.33/go.mod h1:zG2FcwjQarWaqXSCGpgcr3RSjZ6dHGguZSppUL0XR7Q=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 h1:4AH9fFjUlVktQMznF+YN33aWNXaR4VgDXyP28qokJC0=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 h1:PIktER+hwIG286DqXyvVENjgLTAwGgoeriLDD5C+YlQ=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 h1:nFBQlGtkbPzp/NjZLuFxRqmT91rLJkgvsEQs68h962Y=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 h1:JRVhO25+r3ar2mKGP7E0LDl8K9/G36gjlqca5iQbaqc=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 h1:hze8YsjSh8Wl1rYa1CJpRmXP21BvOBuc76YhW0HsuQ4=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8=
-github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 h1:cKr6St+CtC3/dl/rEBJvlk7A/IN5D5F02GNkGzfbtVU=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 h1:WWZA/I2K4ptBS1kg0kV1JbBtG/umed0vwHRrmcr9z7k=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck=
github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4=
-github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 h1:37QubsarExl5ZuCBlnRP+7l1tNwZPBSTqpTBrPH98RU=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2 h1:/RPQNjh1sDIezpXaFIkZb7MlXnSyAqjVdAwcJuGYTqg=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2/go.mod h1:TQZBt/WaQy+zTHoW++rnl8JBrmZ0VO6EUbVua1+foCA=
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0=
-github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 h1:TJoIfnIFubCX0ACVeJ0w46HEH5MwjwYN4iFhuYIhfIY=
+github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 h1:JuPGc7IkOP4AaqcZSIcyqLpFSqBWK32rM9+a1g6u73k=
+github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 h1:HFiiRkf1SdaAmV3/BHOFZ9DjFynPHj8G/UIO1lQS+fk=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3/go.mod h1:a7bHA82fyUXOm+ZSWKU6PIoBxrjSprdLoM8xPYvzYVg=
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM=
+github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 h1:0BkLfgeDjfZnZ+MhB3ONb01u9pwFYTCZVhlsSSBvlbU=
+github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ=
github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
-github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
-github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
+github.com/aws/smithy-go v1.15.0 h1:PS/durmlzvAFpQHDs4wi4sNNP9ExsqZh6IlfdHXgKK8=
+github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/bazelbuild/rules_go v0.23.2 h1:Wxu7JjqnF78cKZbsBsARLSXx/jlGaSLCnUV3mTlyHvM=
github.com/bazelbuild/rules_go v0.23.2/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M=
@@ -185,16 +206,16 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo=
-github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
+github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
+github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
github.com/bnb-chain/greenfield-tendermint v0.0.0-20230417032003-4cda1f296fb2 h1:jubavYCs/mCFj/g6Utl+l4SfpykdBdWJFPsvb9FcEXU=
github.com/bnb-chain/greenfield-tendermint v0.0.0-20230417032003-4cda1f296fb2/go.mod h1:9q11eHNRY9FDwFH+4pompzPNGv//Z3VcfvkELaHJPMs=
github.com/bnb-chain/ics23 v0.1.0 h1:DvjGOts2FBfbxB48384CYD1LbcrfjThFz8kowY/7KxU=
github.com/bnb-chain/ics23 v0.1.0/go.mod h1:cU6lTGolbbLFsGCgceNB2AzplH1xecLp6+KXvxM32nI=
-github.com/bnb-chain/tendermint v0.31.15 h1:Xyn/Hifb/7X4E1zSuMdnZdMSoM2Fx6cZuKCNnqIxbNU=
-github.com/bnb-chain/tendermint v0.31.15/go.mod h1:cmt8HHmQUSVaWQ/hoTefRxsh5X3ERaM1zCUIR0DPbFU=
+github.com/bnb-chain/tendermint v0.31.16 h1:rOO6WG61JDAuRCCL8TKnGhorJftQDVygq0mqR7A0ck4=
+github.com/bnb-chain/tendermint v0.31.16/go.mod h1:cmt8HHmQUSVaWQ/hoTefRxsh5X3ERaM1zCUIR0DPbFU=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
@@ -244,8 +265,9 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA=
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
+github.com/cloudflare/cloudflare-go v0.79.0 h1:ErwCYDjFCYppDJlDJ/5WhsSmzegAUe2+K9qgFyQDg3M=
+github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -302,8 +324,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 h1:DuBDHVjgGMPki7bAyh91+3cF1Vh34sAEdH8JQgbc2R0=
-github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI=
+github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ=
+github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs=
github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA=
github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
@@ -351,12 +373,9 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
-github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
-github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
@@ -439,8 +458,8 @@ github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
-github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b h1:vMT47RYsrftsHSTQhqXwC3BYflo38OLC3Y4LtXtLyU0=
-github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b/go.mod h1:CDncRYVRSDqwakm282WEkjfaAj1hxU/v5RXxk5nXOiI=
+github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE=
+github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc=
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c=
@@ -483,8 +502,9 @@ github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@@ -511,8 +531,6 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
-github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
@@ -521,6 +539,8 @@ github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaL
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
@@ -586,8 +606,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -619,6 +639,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
+github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -707,9 +729,16 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
+github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
+github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
+github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
+github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA=
+github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
@@ -739,8 +768,8 @@ github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
-github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o=
-github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw=
+github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=
+github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
@@ -821,13 +850,16 @@ github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsj
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
-github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U=
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
+github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY=
+github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jhump/protoreflect v1.8.1/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
@@ -1179,7 +1211,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
-github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
@@ -1340,6 +1371,8 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi
github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -1872,7 +1905,6 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
@@ -1886,7 +1918,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -1928,7 +1959,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -2035,7 +2065,6 @@ golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2044,12 +2073,13 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -2315,8 +2345,8 @@ google.golang.org/protobuf v1.25.1-0.20201208041424-160c7477e0e8/go.mod h1:hFxJC
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=
@@ -2345,7 +2375,6 @@ gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLv
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
-gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
@@ -2372,10 +2401,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
-gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I=
-gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/graphql/graphql.go b/graphql/graphql.go
index ddf6541ba8..fd782206fb 100644
--- a/graphql/graphql.go
+++ b/graphql/graphql.go
@@ -41,7 +41,8 @@ import (
)
var (
- errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash")
+ errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash")
+ errInvalidBlockRange = errors.New("invalid from and to block combination: from > to")
)
type Long int64
@@ -99,7 +100,7 @@ func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) {
if err != nil {
return hexutil.Big{}, err
}
- balance := state.GetBalance(a.address)
+ balance := state.GetBalance(a.address).ToBig()
if balance == nil {
return hexutil.Big{}, fmt.Errorf("failed to load balance %x", a.address)
}
@@ -229,8 +230,8 @@ func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, *Block)
return t.tx, t.block
}
// Try to return an already finalized transaction
- tx, blockHash, _, index, err := t.r.backend.GetTransaction(ctx, t.hash)
- if err == nil && tx != nil {
+ found, tx, blockHash, _, index, _ := t.r.backend.GetTransaction(ctx, t.hash)
+ if found {
t.tx = tx
blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
t.block = &Block{
@@ -272,8 +273,6 @@ func (t *Transaction) GasPrice(ctx context.Context) hexutil.Big {
return hexutil.Big{}
}
switch tx.Type() {
- case types.AccessListTxType:
- return hexutil.Big(*tx.GasPrice())
case types.DynamicFeeTxType:
if block != nil {
if baseFee, _ := block.BaseFeePerGas(ctx); baseFee != nil {
@@ -312,9 +311,7 @@ func (t *Transaction) MaxFeePerGas(ctx context.Context) *hexutil.Big {
return nil
}
switch tx.Type() {
- case types.AccessListTxType:
- return nil
- case types.DynamicFeeTxType:
+ case types.DynamicFeeTxType, types.BlobTxType:
return (*hexutil.Big)(tx.GasFeeCap())
default:
return nil
@@ -327,15 +324,33 @@ func (t *Transaction) MaxPriorityFeePerGas(ctx context.Context) *hexutil.Big {
return nil
}
switch tx.Type() {
- case types.AccessListTxType:
- return nil
- case types.DynamicFeeTxType:
+ case types.DynamicFeeTxType, types.BlobTxType:
return (*hexutil.Big)(tx.GasTipCap())
default:
return nil
}
}
+func (t *Transaction) MaxFeePerBlobGas(ctx context.Context) *hexutil.Big {
+ tx, _ := t.resolve(ctx)
+ if tx == nil {
+ return nil
+ }
+ return (*hexutil.Big)(tx.BlobGasFeeCap())
+}
+
+func (t *Transaction) BlobVersionedHashes(ctx context.Context) *[]common.Hash {
+ tx, _ := t.resolve(ctx)
+ if tx == nil {
+ return nil
+ }
+ if tx.Type() != types.BlobTxType {
+ return nil
+ }
+ blobHashes := tx.BlobHashes()
+ return &blobHashes
+}
+
func (t *Transaction) EffectiveTip(ctx context.Context) (*hexutil.Big, error) {
tx, block := t.resolve(ctx)
if tx == nil {
@@ -468,6 +483,40 @@ func (t *Transaction) CumulativeGasUsed(ctx context.Context) (*hexutil.Uint64, e
return &ret, nil
}
+func (t *Transaction) BlobGasUsed(ctx context.Context) (*hexutil.Uint64, error) {
+ tx, _ := t.resolve(ctx)
+ if tx == nil {
+ return nil, nil
+ }
+ if tx.Type() != types.BlobTxType {
+ return nil, nil
+ }
+
+ receipt, err := t.getReceipt(ctx)
+ if err != nil || receipt == nil {
+ return nil, err
+ }
+ ret := hexutil.Uint64(receipt.BlobGasUsed)
+ return &ret, nil
+}
+
+func (t *Transaction) BlobGasPrice(ctx context.Context) (*hexutil.Big, error) {
+ tx, _ := t.resolve(ctx)
+ if tx == nil {
+ return nil, nil
+ }
+ if tx.Type() != types.BlobTxType {
+ return nil, nil
+ }
+
+ receipt, err := t.getReceipt(ctx)
+ if err != nil || receipt == nil {
+ return nil, err
+ }
+ ret := (*hexutil.Big)(receipt.BlobGasPrice)
+ return ret, nil
+}
+
func (t *Transaction) CreatedContract(ctx context.Context, args BlockNumberArgs) (*Account, error) {
receipt, err := t.getReceipt(ctx)
if err != nil || receipt == nil || receipt.ContractAddress == (common.Address{}) {
@@ -566,13 +615,13 @@ func (t *Transaction) V(ctx context.Context) hexutil.Big {
return hexutil.Big(*v)
}
-func (t *Transaction) YParity(ctx context.Context) (*hexutil.Uint64, error) {
+func (t *Transaction) YParity(ctx context.Context) (*hexutil.Big, error) {
tx, _ := t.resolve(ctx)
if tx == nil || tx.Type() == types.LegacyTxType {
return nil, nil
}
v, _, _ := tx.RawSignatureValues()
- ret := hexutil.Uint64(v.Int64())
+ ret := hexutil.Big(*v)
return &ret, nil
}
@@ -1019,6 +1068,30 @@ func (b *Block) Withdrawals(ctx context.Context) (*[]*Withdrawal, error) {
return &ret, nil
}
+func (b *Block) BlobGasUsed(ctx context.Context) (*hexutil.Uint64, error) {
+ header, err := b.resolveHeader(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if header.BlobGasUsed == nil {
+ return nil, nil
+ }
+ ret := hexutil.Uint64(*header.BlobGasUsed)
+ return &ret, nil
+}
+
+func (b *Block) ExcessBlobGas(ctx context.Context) (*hexutil.Uint64, error) {
+ header, err := b.resolveHeader(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if header.ExcessBlobGas == nil {
+ return nil, nil
+ }
+ ret := hexutil.Uint64(*header.ExcessBlobGas)
+ return &ret, nil
+}
+
// BlockFilterCriteria encapsulates criteria passed to a `logs` accessor inside
// a block.
type BlockFilterCriteria struct {
@@ -1217,6 +1290,9 @@ func (r *Resolver) Block(ctx context.Context, args struct {
Number *Long
Hash *common.Hash
}) (*Block, error) {
+ if args.Number != nil && args.Hash != nil {
+ return nil, errors.New("only one of number or hash must be specified")
+ }
var numberOrHash rpc.BlockNumberOrHash
if args.Number != nil {
if *args.Number < 0 {
@@ -1249,6 +1325,9 @@ func (r *Resolver) Blocks(ctx context.Context, args struct {
From *Long
To *Long
}) ([]*Block, error) {
+ if args.From == nil {
+ return nil, errors.New("from block number must be specified")
+ }
from := rpc.BlockNumber(*args.From)
var to rpc.BlockNumber
@@ -1258,7 +1337,7 @@ func (r *Resolver) Blocks(ctx context.Context, args struct {
to = rpc.BlockNumber(r.backend.CurrentBlock().Number.Int64())
}
if to < from {
- return []*Block{}, nil
+ return nil, errInvalidBlockRange
}
var ret []*Block
for i := from; i <= to; i++ {
@@ -1341,6 +1420,9 @@ func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria
if args.Filter.ToBlock != nil {
end = int64(*args.Filter.ToBlock)
}
+ if begin > 0 && end > 0 && begin > end {
+ return nil, errInvalidBlockRange
+ }
var addresses []common.Address
if args.Filter.Addresses != nil {
addresses = *args.Filter.Addresses
@@ -1427,6 +1509,12 @@ func (s *SyncState) HealingTrienodes() hexutil.Uint64 {
func (s *SyncState) HealingBytecode() hexutil.Uint64 {
return hexutil.Uint64(s.progress.HealingBytecode)
}
+func (s *SyncState) TxIndexFinishedBlocks() hexutil.Uint64 {
+ return hexutil.Uint64(s.progress.TxIndexFinishedBlocks)
+}
+func (s *SyncState) TxIndexRemainingBlocks() hexutil.Uint64 {
+ return hexutil.Uint64(s.progress.TxIndexRemainingBlocks)
+}
// Syncing returns false in case the node is currently not syncing with the network. It can be up-to-date or has not
// yet received the latest block headers from its pears. In case it is synchronizing:
@@ -1445,11 +1533,13 @@ func (s *SyncState) HealingBytecode() hexutil.Uint64 {
// - healedBytecodeBytes: number of bytecodes persisted to disk
// - healingTrienodes: number of state trie nodes pending
// - healingBytecode: number of bytecodes pending
+// - txIndexFinishedBlocks: number of blocks whose transactions are indexed
+// - txIndexRemainingBlocks: number of blocks whose transactions are not indexed yet
func (r *Resolver) Syncing() (*SyncState, error) {
progress := r.backend.SyncProgress()
// Return not syncing if the synchronisation already completed
- if progress.CurrentBlock >= progress.HighestBlock {
+ if progress.Done() {
return nil, nil
}
// Otherwise gather the block sync stats
diff --git a/graphql/graphql_test.go b/graphql/graphql_test.go
index 65b85a0922..f91229d015 100644
--- a/graphql/graphql_test.go
+++ b/graphql/graphql_test.go
@@ -139,7 +139,7 @@ func TestGraphQLBlockSerialization(t *testing.T) {
// should return `estimateGas` as decimal
{
body: `{"query": "{block{ estimateGas(data:{}) }}"}`,
- want: `{"data":{"block":{"estimateGas":"0xcf08"}}}`,
+ want: `{"data":{"block":{"estimateGas":"0xd221"}}}`,
code: 200,
},
// should return `status` as decimal
@@ -148,6 +148,11 @@ func TestGraphQLBlockSerialization(t *testing.T) {
want: `{"data":{"block":{"number":"0xa","call":{"data":"0x","status":"0x1"}}}}`,
code: 200,
},
+ {
+ body: `{"query": "{blocks {number}}"}`,
+ want: `{"errors":[{"message":"from block number must be specified","path":["blocks"]}],"data":null}`,
+ code: 400,
+ },
} {
resp, err := http.Post(fmt.Sprintf("%s/graphql", stack.HTTPEndpoint()), "application/json", strings.NewReader(tt.body))
if err != nil {
@@ -164,6 +169,9 @@ func TestGraphQLBlockSerialization(t *testing.T) {
if tt.code != resp.StatusCode {
t.Errorf("testcase %d %s,\nwrong statuscode, have: %v, want: %v", i, tt.body, resp.StatusCode, tt.code)
}
+ if ctype := resp.Header.Get("Content-Type"); ctype != "application/json" {
+ t.Errorf("testcase %d \nwrong Content-Type, have: %v, want: %v", i, ctype, "application/json")
+ }
}
}
@@ -200,7 +208,7 @@ func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
To: &dad,
Value: big.NewInt(100),
Gas: 50000,
- GasPrice: big.NewInt(params.InitialBaseFeeForEthMainnet),
+ GasPrice: big.NewInt(params.InitialBaseFee),
})
gen.AddTx(tx)
tx, _ = types.SignNewTx(key, signer, &types.AccessListTx{
@@ -208,7 +216,7 @@ func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
Nonce: uint64(1),
To: &dad,
Gas: 30000,
- GasPrice: big.NewInt(params.InitialBaseFeeForEthMainnet),
+ GasPrice: big.NewInt(params.InitialBaseFee),
Value: big.NewInt(50),
AccessList: types.AccessList{{
Address: dad,
@@ -295,11 +303,11 @@ func TestGraphQLConcurrentResolvers(t *testing.T) {
var tx *types.Transaction
handler, chain := newGQLService(t, stack, false, genesis, 1, func(i int, gen *core.BlockGen) {
- tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFeeForEthMainnet)})
+ tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)})
gen.AddTx(tx)
- tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Nonce: 1, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFeeForEthMainnet)})
+ tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Nonce: 1, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)})
gen.AddTx(tx)
- tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Nonce: 2, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFeeForEthMainnet)})
+ tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Nonce: 2, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)})
gen.AddTx(tx)
})
// start node
@@ -381,7 +389,7 @@ func TestWithdrawals(t *testing.T) {
defer stack.Close()
handler, _ := newGQLService(t, stack, true, genesis, 1, func(i int, gen *core.BlockGen) {
- tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{To: &common.Address{}, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFeeForEthMainnet)})
+ tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{To: &common.Address{}, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)})
gen.AddTx(tx)
gen.AddWithdrawal(&types.Withdrawal{
Validator: 5,
diff --git a/graphql/schema.go b/graphql/schema.go
index 5de5bad305..8264f1c286 100644
--- a/graphql/schema.go
+++ b/graphql/schema.go
@@ -71,8 +71,8 @@ const schema string = `
transaction: Transaction!
}
- #EIP-2718
- type AccessTuple{
+ # EIP-2718
+ type AccessTuple {
address: Address!
storageKeys : [Bytes32!]!
}
@@ -112,6 +112,8 @@ const schema string = `
maxFeePerGas: BigInt
# MaxPriorityFeePerGas is the maximum miner tip per gas offered to include a transaction, in wei.
maxPriorityFeePerGas: BigInt
+ # MaxFeePerBlobGas is the maximum blob gas fee cap per blob the sender is willing to pay for blob transaction, in wei.
+ maxFeePerBlobGas: BigInt
# EffectiveTip is the actual amount of reward going to miner after considering the max fee cap.
effectiveTip: BigInt
# Gas is the maximum amount of gas this transaction can consume.
@@ -141,6 +143,10 @@ const schema string = `
# coerced into the EIP-1559 format by setting both maxFeePerGas and
# maxPriorityFeePerGas as the transaction's gas price.
effectiveGasPrice: BigInt
+ # BlobGasUsed is the amount of blob gas used by this transaction.
+ blobGasUsed: Long
+ # blobGasPrice is the actual value per blob gas deducted from the senders account.
+ blobGasPrice: BigInt
# CreatedContract is the account that was created by a contract creation
# transaction. If the transaction was not a contract creation transaction,
# or it has not yet been mined, this field will be null.
@@ -151,7 +157,7 @@ const schema string = `
r: BigInt!
s: BigInt!
v: BigInt!
- yParity: Long
+ yParity: BigInt
# Envelope transaction support
type: Long
accessList: [AccessTuple!]
@@ -162,6 +168,8 @@ const schema string = `
# RawReceipt is the canonical encoding of the receipt. For post EIP-2718 typed transactions
# this is equivalent to TxType || ReceiptEncoding.
rawReceipt: Bytes!
+ # BlobVersionedHashes is a set of hash outputs from the blobs in the transaction.
+ blobVersionedHashes: [Bytes32!]
}
# BlockFilterCriteria encapsulates log filter criteria for a filter applied
@@ -171,16 +179,16 @@ const schema string = `
# empty, results will not be filtered by address.
addresses: [Address!]
# Topics list restricts matches to particular event topics. Each event has a list
- # of topics. Topics matches a prefix of that list. An empty element array matches any
- # topic. Non-empty elements represent an alternative that matches any of the
- # contained topics.
- #
- # Examples:
- # - [] or nil matches any topic list
- # - [[A]] matches topic A in first position
- # - [[], [B]] matches any topic in first position, B in second position
- # - [[A], [B]] matches topic A in first position, B in second position
- # - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position
+ # of topics. Topics matches a prefix of that list. An empty element array matches any
+ # topic. Non-empty elements represent an alternative that matches any of the
+ # contained topics.
+ #
+ # Examples:
+ # - [] or nil matches any topic list
+ # - [[A]] matches topic A in first position
+ # - [[], [B]] matches any topic in first position, B in second position
+ # - [[A], [B]] matches topic A in first position, B in second position
+ # - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position
topics: [[Bytes32!]!]
}
@@ -267,6 +275,10 @@ const schema string = `
# Withdrawals is a list of withdrawals associated with this block. If
# withdrawals are unavailable for this block, this field will be null.
withdrawals: [Withdrawal!]
+ # BlobGasUsed is the total amount of gas used by the transactions.
+ blobGasUsed: Long
+ # ExcessBlobGas is a running total of blob gas consumed in excess of the target, prior to the block.
+ excessBlobGas: Long
}
# CallData represents the data associated with a local contract call.
@@ -312,21 +324,21 @@ const schema string = `
# empty, results will not be filtered by address.
addresses: [Address!]
# Topics list restricts matches to particular event topics. Each event has a list
- # of topics. Topics matches a prefix of that list. An empty element array matches any
- # topic. Non-empty elements represent an alternative that matches any of the
- # contained topics.
- #
- # Examples:
- # - [] or nil matches any topic list
- # - [[A]] matches topic A in first position
- # - [[], [B]] matches any topic in first position, B in second position
- # - [[A], [B]] matches topic A in first position, B in second position
- # - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position
+ # of topics. Topics matches a prefix of that list. An empty element array matches any
+ # topic. Non-empty elements represent an alternative that matches any of the
+ # contained topics.
+ #
+ # Examples:
+ # - [] or nil matches any topic list
+ # - [[A]] matches topic A in first position
+ # - [[], [B]] matches any topic in first position, B in second position
+ # - [[A], [B]] matches topic A in first position, B in second position
+ # - [[A, B]], [C, D]] matches topic (A OR B) in first position, (C OR D) in second position
topics: [[Bytes32!]!]
}
# SyncState contains the current synchronisation state of the client.
- type SyncState{
+ type SyncState {
# StartingBlock is the block number at which synchronisation started.
startingBlock: Long!
# CurrentBlock is the point at which synchronisation has presently reached.
@@ -337,17 +349,17 @@ const schema string = `
# Pending represents the current pending state.
type Pending {
- # TransactionCount is the number of transactions in the pending state.
- transactionCount: Long!
- # Transactions is a list of transactions in the current pending state.
- transactions: [Transaction!]
- # Account fetches an Ethereum account for the pending state.
- account(address: Address!): Account!
- # Call executes a local call operation for the pending state.
- call(data: CallData!): CallResult
- # EstimateGas estimates the amount of gas that will be required for
- # successful execution of a transaction for the pending state.
- estimateGas(data: CallData!): Long!
+ # TransactionCount is the number of transactions in the pending state.
+ transactionCount: Long!
+ # Transactions is a list of transactions in the current pending state.
+ transactions: [Transaction!]
+ # Account fetches an Ethereum account for the pending state.
+ account(address: Address!): Account!
+ # Call executes a local call operation for the pending state.
+ call(data: CallData!): CallResult
+ # EstimateGas estimates the amount of gas that will be required for
+ # successful execution of a transaction for the pending state.
+ estimateGas(data: CallData!): Long!
}
type Query {
diff --git a/graphql/service.go b/graphql/service.go
index 4ca427658a..584165bdb8 100644
--- a/graphql/service.go
+++ b/graphql/service.go
@@ -73,12 +73,12 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
// Setting this disables gzip compression in package node.
- w.Header().Set("transfer-encoding", "identity")
+ w.Header().Set("Transfer-Encoding", "identity")
// Flush the response. Since we are writing close to the response timeout,
// chunked transfer encoding must be disabled by setting content-length.
- w.Header().Set("content-type", "application/json")
- w.Header().Set("content-length", strconv.Itoa(len(responseJSON)))
+ w.Header().Set("Content-Type", "application/json")
+ w.Header().Set("Content-Length", strconv.Itoa(len(responseJSON)))
w.Write(responseJSON)
if flush, ok := w.(http.Flusher); ok {
flush.Flush()
@@ -88,17 +88,19 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
response := h.Schema.Exec(ctx, params.Query, params.OperationName, params.Variables)
- timer.Stop()
+ if timer != nil {
+ timer.Stop()
+ }
responded.Do(func() {
responseJSON, err := json.Marshal(response)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
+ w.Header().Set("Content-Type", "application/json")
if len(response.Errors) > 0 {
w.WriteHeader(http.StatusBadRequest)
}
- w.Header().Set("Content-Type", "application/json")
w.Write(responseJSON)
})
}
diff --git a/interfaces.go b/interfaces.go
index eb9af60076..c6aee295ee 100644
--- a/interfaces.go
+++ b/interfaces.go
@@ -29,8 +29,6 @@ import (
// NotFound is returned by API methods if the requested item does not exist.
var NotFound = errors.New("not found")
-// TODO: move subscription to package event
-
// Subscription represents an event subscription where events are
// delivered on a data channel.
type Subscription interface {
@@ -122,6 +120,18 @@ type SyncProgress struct {
HealingTrienodes uint64 // Number of state trie nodes pending
HealingBytecode uint64 // Number of bytecodes pending
+
+ // "transaction indexing" fields
+ TxIndexFinishedBlocks uint64 // Number of blocks whose transactions are already indexed
+ TxIndexRemainingBlocks uint64 // Number of blocks whose transactions are not indexed yet
+}
+
+// Done returns the indicator if the initial sync is finished or not.
+func (prog SyncProgress) Done() bool {
+ if prog.CurrentBlock < prog.HighestBlock {
+ return false
+ }
+ return prog.TxIndexRemainingBlocks == 0
}
// ChainSyncReader wraps access to the node's current sync status. If there's no
@@ -201,6 +211,16 @@ type GasPricer interface {
SuggestGasPrice(ctx context.Context) (*big.Int, error)
}
+// GasPricer1559 provides access to the EIP-1559 gas price oracle.
+type GasPricer1559 interface {
+ SuggestGasTipCap(ctx context.Context) (*big.Int, error)
+}
+
+// FeeHistoryReader provides access to the fee history oracle.
+type FeeHistoryReader interface {
+ FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*FeeHistory, error)
+}
+
// FeeHistory provides recent fee market data that consumers can use to determine
// a reasonable maxPriorityFeePerGas value.
type FeeHistory struct {
@@ -241,3 +261,13 @@ type GasEstimator interface {
type PendingStateEventer interface {
SubscribePendingTransactions(ctx context.Context, ch chan<- *types.Transaction) (Subscription, error)
}
+
+// BlockNumberReader provides access to the current block number.
+type BlockNumberReader interface {
+ BlockNumber(ctx context.Context) (uint64, error)
+}
+
+// ChainIDReader provides access to the chain ID.
+type ChainIDReader interface {
+ ChainID(ctx context.Context) (*big.Int, error)
+}
diff --git a/internal/build/azure.go b/internal/build/azure.go
index 9d1c4f300a..4085228d14 100644
--- a/internal/build/azure.go
+++ b/internal/build/azure.go
@@ -22,6 +22,7 @@ import (
"os"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
)
// AzureBlobstoreConfig is an authentication and configuration struct containing
@@ -48,8 +49,8 @@ func AzureBlobstoreUpload(path string, name string, config AzureBlobstoreConfig)
if err != nil {
return err
}
- u := fmt.Sprintf("https://%s.blob.core.windows.net/%s", config.Account, config.Container)
- container, err := azblob.NewContainerClientWithSharedKey(u, credential, nil)
+ a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account)
+ client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil)
if err != nil {
return err
}
@@ -60,38 +61,38 @@ func AzureBlobstoreUpload(path string, name string, config AzureBlobstoreConfig)
}
defer in.Close()
- blockblob := container.NewBlockBlobClient(name)
- _, err = blockblob.Upload(context.Background(), in, nil)
+ _, err = client.UploadFile(context.Background(), config.Container, name, in, nil)
return err
}
// AzureBlobstoreList lists all the files contained within an azure blobstore.
-func AzureBlobstoreList(config AzureBlobstoreConfig) ([]*azblob.BlobItemInternal, error) {
+func AzureBlobstoreList(config AzureBlobstoreConfig) ([]*container.BlobItem, error) {
// Create an authenticated client against the Azure cloud
credential, err := azblob.NewSharedKeyCredential(config.Account, config.Token)
if err != nil {
return nil, err
}
- u := fmt.Sprintf("https://%s.blob.core.windows.net/%s", config.Account, config.Container)
- container, err := azblob.NewContainerClientWithSharedKey(u, credential, nil)
+ a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account)
+ client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil)
if err != nil {
return nil, err
}
- var maxResults int32 = 5000
- pager := container.ListBlobsFlat(&azblob.ContainerListBlobFlatSegmentOptions{
- Maxresults: &maxResults,
- })
- var allBlobs []*azblob.BlobItemInternal
- for pager.NextPage(context.Background()) {
- res := pager.PageResponse()
- allBlobs = append(allBlobs, res.ContainerListBlobFlatSegmentResult.Segment.BlobItems...)
+ pager := client.NewListBlobsFlatPager(config.Container, nil)
+
+ var blobs []*container.BlobItem
+ for pager.More() {
+ page, err := pager.NextPage(context.TODO())
+ if err != nil {
+ return nil, err
+ }
+ blobs = append(blobs, page.Segment.BlobItems...)
}
- return allBlobs, pager.Err()
+ return blobs, nil
}
// AzureBlobstoreDelete iterates over a list of files to delete and removes them
// from the blobstore.
-func AzureBlobstoreDelete(config AzureBlobstoreConfig, blobs []*azblob.BlobItemInternal) error {
+func AzureBlobstoreDelete(config AzureBlobstoreConfig, blobs []*container.BlobItem) error {
if *DryRunFlag {
for _, blob := range blobs {
fmt.Printf("would delete %s (%s) from %s/%s\n", *blob.Name, blob.Properties.LastModified, config.Account, config.Container)
@@ -103,15 +104,14 @@ func AzureBlobstoreDelete(config AzureBlobstoreConfig, blobs []*azblob.BlobItemI
if err != nil {
return err
}
- u := fmt.Sprintf("https://%s.blob.core.windows.net/%s", config.Account, config.Container)
- container, err := azblob.NewContainerClientWithSharedKey(u, credential, nil)
+ a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account)
+ client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil)
if err != nil {
return err
}
// Iterate over the blobs and delete them
for _, blob := range blobs {
- blockblob := container.NewBlockBlobClient(*blob.Name)
- if _, err := blockblob.Delete(context.Background(), &azblob.DeleteBlobOptions{}); err != nil {
+ if _, err := client.DeleteBlob(context.Background(), config.Container, *blob.Name, nil); err != nil {
return err
}
fmt.Printf("deleted %s (%s)\n", *blob.Name, blob.Properties.LastModified)
diff --git a/internal/build/gotool.go b/internal/build/gotool.go
index 296ba8c36e..2a47460418 100644
--- a/internal/build/gotool.go
+++ b/internal/build/gotool.go
@@ -84,7 +84,11 @@ func (g *GoToolchain) goTool(command string, args ...string) *exec.Cmd {
// DownloadGo downloads the Go binary distribution and unpacks it into a temporary
// directory. It returns the GOROOT of the unpacked toolchain.
-func DownloadGo(csdb *ChecksumDB, version string) string {
+func DownloadGo(csdb *ChecksumDB) string {
+ version, err := Version(csdb, "golang")
+ if err != nil {
+ log.Fatal(err)
+ }
// Shortcut: if the Go version that runs this script matches the
// requested version exactly, there is no need to download anything.
activeGo := strings.TrimPrefix(runtime.Version(), "go")
@@ -126,3 +130,51 @@ func DownloadGo(csdb *ChecksumDB, version string) string {
}
return goroot
}
+
+// Version returns the versions defined in the checksumdb.
+func Version(csdb *ChecksumDB, version string) (string, error) {
+ for _, l := range csdb.allChecksums {
+ if !strings.HasPrefix(l, "# version:") {
+ continue
+ }
+ v := strings.Split(l, ":")[1]
+ parts := strings.Split(v, " ")
+ if len(parts) != 2 {
+ log.Print("Erroneous version-string", "v", l)
+ continue
+ }
+ if parts[0] == version {
+ return parts[1], nil
+ }
+ }
+ return "", fmt.Errorf("no version found for '%v'", version)
+}
+
+// DownloadAndVerifyChecksums downloads all files and checks that they match
+// the checksum given in checksums.txt.
+// This task can be used to sanity-check new checksums.
+func DownloadAndVerifyChecksums(csdb *ChecksumDB) {
+ var (
+ base = ""
+ ucache = os.TempDir()
+ )
+ for _, l := range csdb.allChecksums {
+ if strings.HasPrefix(l, "# https://") {
+ base = l[2:]
+ continue
+ }
+ if strings.HasPrefix(l, "#") {
+ continue
+ }
+ hashFile := strings.Split(l, " ")
+ if len(hashFile) != 2 {
+ continue
+ }
+ file := hashFile[1]
+ url := base + file
+ dst := filepath.Join(ucache, file)
+ if err := csdb.DownloadFile(url, dst); err != nil {
+ log.Print(err)
+ }
+ }
+}
diff --git a/internal/build/util.go b/internal/build/util.go
index 5c77b236dc..b41014a16f 100644
--- a/internal/build/util.go
+++ b/internal/build/util.go
@@ -68,6 +68,27 @@ func MustRunCommand(cmd string, args ...string) {
MustRun(exec.Command(cmd, args...))
}
+// MustRunCommandWithOutput runs the given command, and ensures that some output will be
+// printed while it runs. This is useful for CI builds where the process will be stopped
+// when there is no output.
+func MustRunCommandWithOutput(cmd string, args ...string) {
+ interval := time.NewTicker(time.Minute)
+ done := make(chan struct{})
+ defer interval.Stop()
+ defer close(done)
+ go func() {
+ for {
+ select {
+ case <-interval.C:
+ fmt.Printf("Waiting for command %q\n", cmd)
+ case <-done:
+ return
+ }
+ }
+ }()
+ MustRun(exec.Command(cmd, args...))
+}
+
var warnedAboutGit bool
// RunGit runs a git subcommand and returns its output.
diff --git a/internal/cmdtest/test_cmd.go b/internal/cmdtest/test_cmd.go
index 43137053c1..4890d0b7c6 100644
--- a/internal/cmdtest/test_cmd.go
+++ b/internal/cmdtest/test_cmd.go
@@ -32,7 +32,7 @@ import (
"text/template"
"time"
- "github.com/docker/docker/pkg/reexec"
+ "github.com/ethereum/go-ethereum/internal/reexec"
)
func NewTestCmd(t *testing.T, data interface{}) *TestCmd {
diff --git a/internal/debug/api.go b/internal/debug/api.go
index 42d0fa15ed..482989e0d0 100644
--- a/internal/debug/api.go
+++ b/internal/debug/api.go
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/hashicorp/go-bexpr"
+ "golang.org/x/exp/slog"
)
// Handler is the global debugging handler.
@@ -56,7 +57,7 @@ type HandlerT struct {
// Verbosity sets the log verbosity ceiling. The verbosity of individual packages
// and source files can be raised using Vmodule.
func (*HandlerT) Verbosity(level int) {
- glogger.Verbosity(log.Lvl(level))
+ glogger.Verbosity(slog.Level(level))
}
// Vmodule sets the log verbosity pattern. See package log for details on the
@@ -65,12 +66,6 @@ func (*HandlerT) Vmodule(pattern string) error {
return glogger.Vmodule(pattern)
}
-// BacktraceAt sets the log backtrace location. See package log for details on
-// the pattern syntax.
-func (*HandlerT) BacktraceAt(location string) error {
- return glogger.BacktraceAt(location)
-}
-
// MemStats returns detailed runtime memory statistics.
func (*HandlerT) MemStats() *runtime.MemStats {
s := new(runtime.MemStats)
diff --git a/internal/debug/flags.go b/internal/debug/flags.go
index 736fede943..dac878a7b1 100644
--- a/internal/debug/flags.go
+++ b/internal/debug/flags.go
@@ -34,6 +34,7 @@ import (
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
+ "golang.org/x/exp/slog"
"gopkg.in/natefinch/lumberjack.v2"
)
@@ -75,17 +76,6 @@ var (
Usage: "Write logs to a file",
Category: flags.LoggingCategory,
}
- backtraceAtFlag = &cli.StringFlag{
- Name: "log.backtrace",
- Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")",
- Value: "",
- Category: flags.LoggingCategory,
- }
- debugFlag = &cli.BoolFlag{
- Name: "log.debug",
- Usage: "Prepends log messages with call-site location (file and line number)",
- Category: flags.LoggingCategory,
- }
logRotateFlag = &cli.BoolFlag{
Name: "log.rotate",
Usage: "Enables log file rotation",
@@ -160,8 +150,6 @@ var Flags = []cli.Flag{
verbosityFlag,
logVmoduleFlag,
vmoduleFlag,
- backtraceAtFlag,
- debugFlag,
logjsonFlag,
logFormatFlag,
logFileFlag,
@@ -180,48 +168,26 @@ var Flags = []cli.Flag{
}
var (
- glogger *log.GlogHandler
- logOutputStream log.Handler
+ glogger *log.GlogHandler
+ logOutputFile io.WriteCloser
)
func init() {
- glogger = log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
- glogger.Verbosity(log.LvlInfo)
- log.Root().SetHandler(glogger)
+ glogger = log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
}
// Setup initializes profiling and logging based on the CLI flags.
// It should be called as early as possible in the program.
func Setup(ctx *cli.Context) error {
var (
- logfmt log.Format
- output = io.Writer(os.Stderr)
- logFmtFlag = ctx.String(logFormatFlag.Name)
+ handler slog.Handler
+ terminalOutput = io.Writer(os.Stderr)
+ output io.Writer
+ logFmtFlag = ctx.String(logFormatFlag.Name)
)
- switch {
- case ctx.Bool(logjsonFlag.Name):
- // Retain backwards compatibility with `--log.json` flag if `--log.format` not set
- defer log.Warn("The flag '--log.json' is deprecated, please use '--log.format=json' instead")
- logfmt = log.JSONFormat()
- case logFmtFlag == "json":
- logfmt = log.JSONFormat()
- case logFmtFlag == "logfmt":
- logfmt = log.LogfmtFormat()
- case logFmtFlag == "", logFmtFlag == "terminal":
- useColor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
- if useColor {
- output = colorable.NewColorableStderr()
- }
- logfmt = log.TerminalFormat(useColor)
- default:
- // Unknown log format specified
- return fmt.Errorf("unknown log format: %v", ctx.String(logFormatFlag.Name))
- }
var (
- stdHandler = log.StreamHandler(output, logfmt)
- ostream = stdHandler
- logFile = ctx.String(logFileFlag.Name)
- rotation = ctx.Bool(logRotateFlag.Name)
+ logFile = ctx.String(logFileFlag.Name)
+ rotation = ctx.Bool(logRotateFlag.Name)
)
if len(logFile) > 0 {
if err := validateLogLocation(filepath.Dir(logFile)); err != nil {
@@ -242,26 +208,55 @@ func Setup(ctx *cli.Context) error {
} else {
context = append(context, "location", filepath.Join(os.TempDir(), "geth-lumberjack.log"))
}
- ostream = log.MultiHandler(log.StreamHandler(&lumberjack.Logger{
+ logOutputFile = &lumberjack.Logger{
Filename: logFile,
MaxSize: ctx.Int(logMaxSizeMBsFlag.Name),
MaxBackups: ctx.Int(logMaxBackupsFlag.Name),
MaxAge: ctx.Int(logMaxAgeFlag.Name),
Compress: ctx.Bool(logCompressFlag.Name),
- }, logfmt), stdHandler)
+ }
+ output = io.MultiWriter(terminalOutput, logOutputFile)
} else if logFile != "" {
- if logOutputStream, err := log.FileHandler(logFile, logfmt); err != nil {
+ var err error
+ if logOutputFile, err = os.OpenFile(logFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644); err != nil {
return err
- } else {
- ostream = log.MultiHandler(logOutputStream, stdHandler)
- context = append(context, "location", logFile)
}
+ output = io.MultiWriter(logOutputFile, terminalOutput)
+ context = append(context, "location", logFile)
+ } else {
+ output = terminalOutput
}
- glogger.SetHandler(ostream)
+
+ switch {
+ case ctx.Bool(logjsonFlag.Name):
+ // Retain backwards compatibility with `--log.json` flag if `--log.format` not set
+ defer log.Warn("The flag '--log.json' is deprecated, please use '--log.format=json' instead")
+ handler = log.JSONHandler(output)
+ case logFmtFlag == "json":
+ handler = log.JSONHandler(output)
+ case logFmtFlag == "logfmt":
+ handler = log.LogfmtHandler(output)
+ case logFmtFlag == "", logFmtFlag == "terminal":
+ useColor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
+ if useColor {
+ terminalOutput = colorable.NewColorableStderr()
+ if logOutputFile != nil {
+ output = io.MultiWriter(logOutputFile, terminalOutput)
+ } else {
+ output = terminalOutput
+ }
+ }
+ handler = log.NewTerminalHandler(output, useColor)
+ default:
+ // Unknown log format specified
+ return fmt.Errorf("unknown log format: %v", ctx.String(logFormatFlag.Name))
+ }
+
+ glogger = log.NewGlogHandler(handler)
// logging
- verbosity := ctx.Int(verbosityFlag.Name)
- glogger.Verbosity(log.Lvl(verbosity))
+ verbosity := log.FromLegacyLevel(ctx.Int(verbosityFlag.Name))
+ glogger.Verbosity(verbosity)
vmodule := ctx.String(logVmoduleFlag.Name)
if vmodule == "" {
// Retain backwards compatibility with `--vmodule` flag if `--log.vmodule` not set
@@ -272,16 +267,7 @@ func Setup(ctx *cli.Context) error {
}
glogger.Vmodule(vmodule)
- debug := ctx.Bool(debugFlag.Name)
- if ctx.IsSet(debugFlag.Name) {
- debug = ctx.Bool(debugFlag.Name)
- }
- log.PrintOrigins(debug)
-
- backtrace := ctx.String(backtraceAtFlag.Name)
- glogger.BacktraceAt(backtrace)
-
- log.Root().SetHandler(glogger)
+ log.SetDefault(log.NewLogger(glogger))
// profiling, tracing
runtime.MemProfileRate = memprofilerateFlag.Value
@@ -341,8 +327,8 @@ func StartPProf(address string, withMetrics bool) {
func Exit() {
Handler.StopCPUProfile()
Handler.StopGoTrace()
- if closer, ok := logOutputStream.(io.Closer); ok {
- closer.Close()
+ if logOutputFile != nil {
+ logOutputFile.Close()
}
}
diff --git a/internal/debug/loudpanic.go b/internal/debug/loudpanic.go
index 86e6bc88f8..a7296e7b3f 100644
--- a/internal/debug/loudpanic.go
+++ b/internal/debug/loudpanic.go
@@ -14,9 +14,6 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build go1.6
-// +build go1.6
-
package debug
import "runtime/debug"
diff --git a/internal/debug/trace.go b/internal/debug/trace.go
index eea8798234..e291030b82 100644
--- a/internal/debug/trace.go
+++ b/internal/debug/trace.go
@@ -14,9 +14,6 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build go1.5
-// +build go1.5
-
package debug
import (
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 503594e212..4f9bfa2c40 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -28,7 +28,6 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/common"
@@ -43,17 +42,18 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/gasestimator"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
"github.com/tyler-smith/go-bip39"
)
-const UnHealthyTimeout = 5 * time.Second
-
// max is a helper function which returns the larger of the two given integers.
func max(a, b int64) int64 {
if a > b {
@@ -62,8 +62,15 @@ func max(a, b int64) int64 {
return b
}
-// PublicEthereumAPI provides an API to access Ethereum related information.
-// It offers only methods that operate on public data that is freely available to anyone.
+const UnHealthyTimeout = 5 * time.Second
+
+// estimateGasErrorRatio is the amount of overestimation eth_estimateGas is
+// allowed to produce in order to speed up calculations.
+const estimateGasErrorRatio = 0.015
+
+var errBlobTxNotSupported = errors.New("signing blob transactions not supported")
+
+// EthereumAPI provides an API to access Ethereum related information.
type EthereumAPI struct {
b Backend
}
@@ -140,26 +147,28 @@ func (s *EthereumAPI) Syncing() (interface{}, error) {
progress := s.b.SyncProgress()
// Return not syncing if the synchronisation already completed
- if progress.CurrentBlock >= progress.HighestBlock {
+ if progress.Done() {
return false, nil
}
// Otherwise gather the block sync stats
return map[string]interface{}{
- "startingBlock": hexutil.Uint64(progress.StartingBlock),
- "currentBlock": hexutil.Uint64(progress.CurrentBlock),
- "highestBlock": hexutil.Uint64(progress.HighestBlock),
- "syncedAccounts": hexutil.Uint64(progress.SyncedAccounts),
- "syncedAccountBytes": hexutil.Uint64(progress.SyncedAccountBytes),
- "syncedBytecodes": hexutil.Uint64(progress.SyncedBytecodes),
- "syncedBytecodeBytes": hexutil.Uint64(progress.SyncedBytecodeBytes),
- "syncedStorage": hexutil.Uint64(progress.SyncedStorage),
- "syncedStorageBytes": hexutil.Uint64(progress.SyncedStorageBytes),
- "healedTrienodes": hexutil.Uint64(progress.HealedTrienodes),
- "healedTrienodeBytes": hexutil.Uint64(progress.HealedTrienodeBytes),
- "healedBytecodes": hexutil.Uint64(progress.HealedBytecodes),
- "healedBytecodeBytes": hexutil.Uint64(progress.HealedBytecodeBytes),
- "healingTrienodes": hexutil.Uint64(progress.HealingTrienodes),
- "healingBytecode": hexutil.Uint64(progress.HealingBytecode),
+ "startingBlock": hexutil.Uint64(progress.StartingBlock),
+ "currentBlock": hexutil.Uint64(progress.CurrentBlock),
+ "highestBlock": hexutil.Uint64(progress.HighestBlock),
+ "syncedAccounts": hexutil.Uint64(progress.SyncedAccounts),
+ "syncedAccountBytes": hexutil.Uint64(progress.SyncedAccountBytes),
+ "syncedBytecodes": hexutil.Uint64(progress.SyncedBytecodes),
+ "syncedBytecodeBytes": hexutil.Uint64(progress.SyncedBytecodeBytes),
+ "syncedStorage": hexutil.Uint64(progress.SyncedStorage),
+ "syncedStorageBytes": hexutil.Uint64(progress.SyncedStorageBytes),
+ "healedTrienodes": hexutil.Uint64(progress.HealedTrienodes),
+ "healedTrienodeBytes": hexutil.Uint64(progress.HealedTrienodeBytes),
+ "healedBytecodes": hexutil.Uint64(progress.HealedBytecodes),
+ "healedBytecodeBytes": hexutil.Uint64(progress.HealedBytecodeBytes),
+ "healingTrienodes": hexutil.Uint64(progress.HealingTrienodes),
+ "healingBytecode": hexutil.Uint64(progress.HealingBytecode),
+ "txIndexFinishedBlocks": hexutil.Uint64(progress.TxIndexFinishedBlocks),
+ "txIndexRemainingBlocks": hexutil.Uint64(progress.TxIndexRemainingBlocks),
}, nil
}
@@ -476,6 +485,9 @@ func (s *PersonalAccountAPI) SendTransaction(ctx context.Context, args Transacti
s.nonceLock.LockAddr(args.from())
defer s.nonceLock.UnlockAddr(args.from())
}
+ if args.IsEIP4844() {
+ return common.Hash{}, errBlobTxNotSupported
+ }
signed, err := s.signTransaction(ctx, &args, passwd)
if err != nil {
log.Warn("Failed transaction send attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err)
@@ -500,6 +512,9 @@ func (s *PersonalAccountAPI) SignTransaction(ctx context.Context, args Transacti
if args.GasPrice == nil && (args.MaxFeePerGas == nil || args.MaxPriorityFeePerGas == nil) {
return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
}
+ if args.IsEIP4844() {
+ return nil, errBlobTxNotSupported
+ }
if args.Nonce == nil {
return nil, errors.New("nonce not specified")
}
@@ -649,7 +664,8 @@ func (s *BlockChainAPI) GetBalance(ctx context.Context, address common.Address,
if state == nil || err != nil {
return nil, err
}
- return (*hexutil.Big)(state.GetBalance(address)), state.Error()
+ b := state.GetBalance(address).ToBig()
+ return (*hexutil.Big)(b), state.Error()
}
// Result structs for GetProof
@@ -688,9 +704,6 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
keys = make([]common.Hash, len(storageKeys))
keyLengths = make([]int, len(storageKeys))
storageProof = make([]StorageResult, len(storageKeys))
- storageTrie state.Trie
- storageHash = types.EmptyRootHash
- codeHash = types.EmptyCodeHash
)
// Deserialize all keys. This prevents state access on invalid input.
for i, hexKey := range storageKeys {
@@ -700,61 +713,66 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
return nil, err
}
}
-
- state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
- if state == nil || err != nil {
- return nil, err
- }
- if storageTrie, err = state.StorageTrie(address); err != nil {
+ statedb, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
+ if statedb == nil || err != nil {
return nil, err
}
+ codeHash := statedb.GetCodeHash(address)
+ storageRoot := statedb.GetStorageRoot(address)
- // If we have a storageTrie, the account exists and we must update
- // the storage root hash and the code hash.
- if storageTrie != nil {
- storageHash = storageTrie.Hash()
- codeHash = state.GetCodeHash(address)
- }
- // Create the proofs for the storageKeys.
- for i, key := range keys {
- // Output key encoding is a bit special: if the input was a 32-byte hash, it is
- // returned as such. Otherwise, we apply the QUANTITY encoding mandated by the
- // JSON-RPC spec for getProof. This behavior exists to preserve backwards
- // compatibility with older client versions.
- var outputKey string
- if keyLengths[i] != 32 {
- outputKey = hexutil.EncodeBig(key.Big())
- } else {
- outputKey = hexutil.Encode(key[:])
- }
-
- if storageTrie == nil {
- storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}}
- continue
- }
- var proof proofList
- if err := storageTrie.Prove(crypto.Keccak256(key.Bytes()), &proof); err != nil {
- return nil, err
+ if len(keys) > 0 {
+ var storageTrie state.Trie
+ if storageRoot != types.EmptyRootHash && storageRoot != (common.Hash{}) {
+ id := trie.StorageTrieID(header.Root, crypto.Keccak256Hash(address.Bytes()), storageRoot)
+ st, err := trie.NewStateTrie(id, statedb.Database().TrieDB())
+ if err != nil {
+ return nil, err
+ }
+ storageTrie = st
+ }
+ // Create the proofs for the storageKeys.
+ for i, key := range keys {
+ // Output key encoding is a bit special: if the input was a 32-byte hash, it is
+ // returned as such. Otherwise, we apply the QUANTITY encoding mandated by the
+ // JSON-RPC spec for getProof. This behavior exists to preserve backwards
+ // compatibility with older client versions.
+ var outputKey string
+ if keyLengths[i] != 32 {
+ outputKey = hexutil.EncodeBig(key.Big())
+ } else {
+ outputKey = hexutil.Encode(key[:])
+ }
+ if storageTrie == nil {
+ storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}}
+ continue
+ }
+ var proof proofList
+ if err := storageTrie.Prove(crypto.Keccak256(key.Bytes()), &proof); err != nil {
+ return nil, err
+ }
+ value := (*hexutil.Big)(statedb.GetState(address, key).Big())
+ storageProof[i] = StorageResult{outputKey, value, proof}
}
- value := (*hexutil.Big)(state.GetState(address, key).Big())
- storageProof[i] = StorageResult{outputKey, value, proof}
}
-
// Create the accountProof.
- accountProof, proofErr := state.GetProof(address)
- if proofErr != nil {
- return nil, proofErr
+ tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), statedb.Database().TrieDB())
+ if err != nil {
+ return nil, err
}
-
+ var accountProof proofList
+ if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil {
+ return nil, err
+ }
+ balance := statedb.GetBalance(address).ToBig()
return &AccountResult{
Address: address,
- AccountProof: toHexSlice(accountProof),
- Balance: (*hexutil.Big)(state.GetBalance(address)),
+ AccountProof: accountProof,
+ Balance: (*hexutil.Big)(balance),
CodeHash: codeHash,
- Nonce: hexutil.Uint64(state.GetNonce(address)),
- StorageHash: storageHash,
+ Nonce: hexutil.Uint64(statedb.GetNonce(address)),
+ StorageHash: storageRoot,
StorageProof: storageProof,
- }, state.Error()
+ }, statedb.Error()
}
// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
@@ -839,7 +857,7 @@ func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fu
func (s *BlockChainAPI) Health() bool {
if rpc.RpcServingTimer != nil {
- return rpc.RpcServingTimer.Percentile(0.75) < float64(UnHealthyTimeout)
+ return rpc.RpcServingTimer.Snapshot().Percentile(0.75) < float64(UnHealthyTimeout)
}
return true
}
@@ -1025,7 +1043,8 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
}
// Override account balance.
if account.Balance != nil {
- state.SetBalance(addr, (*big.Int)(*account.Balance))
+ u256Balance, _ := uint256.FromBig((*big.Int)(*account.Balance))
+ state.SetBalance(addr, u256Balance)
}
if account.State != nil && account.StateDiff != nil {
return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
@@ -1050,13 +1069,14 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
// BlockOverrides is a set of header fields to override.
type BlockOverrides struct {
- Number *hexutil.Big
- Difficulty *hexutil.Big
- Time *hexutil.Uint64
- GasLimit *hexutil.Uint64
- Coinbase *common.Address
- Random *common.Hash
- BaseFee *hexutil.Big
+ Number *hexutil.Big
+ Difficulty *hexutil.Big
+ Time *hexutil.Uint64
+ GasLimit *hexutil.Uint64
+ Coinbase *common.Address
+ Random *common.Hash
+ BaseFee *hexutil.Big
+ BlobBaseFee *hexutil.Big
}
// Apply overrides the given header fields into the given block context.
@@ -1085,6 +1105,9 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
if diff.BaseFee != nil {
blockCtx.BaseFee = diff.BaseFee.ToInt()
}
+ if diff.BlobBaseFee != nil {
+ blockCtx.BlobBaseFee = diff.BlobBaseFee.ToInt()
+ }
}
// ChainContextBackend provides methods required to implement ChainContext.
@@ -1144,7 +1167,7 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S
if blockOverrides != nil {
blockOverrides.Apply(&blockCtx)
}
- evm, vmError := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx)
+ evm := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx)
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
@@ -1156,7 +1179,7 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S
// Execute the message.
gp := new(core.GasPool).AddGas(math.MaxUint64)
result, err := core.ApplyMessage(evm, msg, gp)
- if err := vmError(); err != nil {
+ if err := state.Error(); err != nil {
return nil, err
}
@@ -1181,189 +1204,70 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap)
}
-func newRevertError(result *core.ExecutionResult) *revertError {
- reason, errUnpack := abi.UnpackRevert(result.Revert())
- err := errors.New("execution reverted")
- if errUnpack == nil {
- err = fmt.Errorf("execution reverted: %v", reason)
- }
- return &revertError{
- error: err,
- reason: hexutil.Encode(result.Revert()),
- }
-}
-
-// revertError is an API error that encompasses an EVM revertal with JSON error
-// code and a binary data blob.
-type revertError struct {
- error
- reason string // revert reason hex encoded
-}
-
-// ErrorCode returns the JSON error code for a revertal.
-// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
-func (e *revertError) ErrorCode() int {
- return 3
-}
-
-// ErrorData returns the hex encoded revert reason.
-func (e *revertError) ErrorData() interface{} {
- return e.reason
-}
-
// Call executes the given transaction on the state for the given block number.
//
// Additionally, the caller can specify a batch of contract for fields overriding.
//
// Note, this function doesn't make and changes in the state/blockchain and is
// useful to execute and retrieve values.
-func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
- result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
+func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
+ if blockNrOrHash == nil {
+ latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
+ blockNrOrHash = &latest
+ }
+ result, err := DoCall(ctx, s.b, args, *blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
if err != nil {
return nil, err
}
// If the result contains a revert reason, try to unpack and return it.
if len(result.Revert()) > 0 {
- return nil, newRevertError(result)
+ return nil, newRevertError(result.Revert())
}
return result.Return(), result.Err
}
+// DoEstimateGas returns the lowest possible gas limit that allows the transaction to run
+// successfully at block `blockNrOrHash`. It returns error if the transaction would revert, or if
+// there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil &
+// non-zero) and `gasCap` (if non-zero).
func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, gasCap uint64) (hexutil.Uint64, error) {
- // Binary search the gas requirement, as it may be higher than the amount used
- var (
- lo uint64 = params.TxGas - 1
- hi uint64
- cap uint64
- )
- // Use zero address if sender unspecified.
- if args.From == nil {
- args.From = new(common.Address)
- }
- // Determine the highest gas limit can be used during the estimation.
- if args.Gas != nil && uint64(*args.Gas) >= params.TxGas {
- hi = uint64(*args.Gas)
- } else {
- // Retrieve the block to act as the gas ceiling
- block, err := b.BlockByNumberOrHash(ctx, blockNrOrHash)
- if err != nil {
- return 0, err
- }
- if block == nil {
- return 0, errors.New("block not found")
- }
- hi = block.GasLimit()
- }
- // Normalize the max fee per gas the call is willing to spend.
- var feeCap *big.Int
- if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
- return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
- } else if args.GasPrice != nil {
- feeCap = args.GasPrice.ToInt()
- } else if args.MaxFeePerGas != nil {
- feeCap = args.MaxFeePerGas.ToInt()
- } else {
- feeCap = common.Big0
- }
- // Recap the highest gas limit with account's available balance.
- if feeCap.BitLen() != 0 {
- state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
- if err != nil {
- return 0, err
- }
- err = overrides.Apply(state)
- if err != nil {
- return 0, err
- }
- balance := state.GetBalance(*args.From) // from can't be nil
- available := new(big.Int).Set(balance)
- if args.Value != nil {
- if args.Value.ToInt().Cmp(available) >= 0 {
- return 0, core.ErrInsufficientFundsForTransfer
- }
- available.Sub(available, args.Value.ToInt())
- }
- allowance := new(big.Int).Div(available, feeCap)
-
- // If the allowance is larger than maximum uint64, skip checking
- if allowance.IsUint64() && hi > allowance.Uint64() {
- transfer := args.Value
- if transfer == nil {
- transfer = new(hexutil.Big)
- }
- log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
- "sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance)
- hi = allowance.Uint64()
- }
- }
- // Recap the highest gas allowance with specified gascap.
- if gasCap != 0 && hi > gasCap {
- log.Debug("Caller gas above allowance, capping", "requested", hi, "cap", gasCap)
- hi = gasCap
- }
- cap = hi
-
- // Create a helper to check if a gas allowance results in an executable transaction
- executable := func(gas uint64, state *state.StateDB, header *types.Header) (bool, *core.ExecutionResult, error) {
- args.Gas = (*hexutil.Uint64)(&gas)
-
- result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap)
- if err != nil {
- if errors.Is(err, core.ErrIntrinsicGas) {
- return true, nil, nil // Special case, raise gas limit
- }
- return true, nil, err // Bail out
- }
- return result.Failed(), result, nil
- }
+ // Retrieve the base state and mutate it with any overrides
state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return 0, err
}
- err = overrides.Apply(state)
- if err != nil {
+ if err = overrides.Apply(state); err != nil {
return 0, err
}
- // Execute the binary search and hone in on an executable gas limit
- for lo+1 < hi {
- s := state.Copy()
- mid := (hi + lo) / 2
- failed, _, err := executable(mid, s, header)
-
- // If the error is not nil(consensus error), it means the provided message
- // call or transaction will never be accepted no matter how much gas it is
- // assigned. Return the error directly, don't struggle any more.
- if err != nil {
- return 0, err
- }
- if failed {
- lo = mid
- } else {
- hi = mid
- }
+ // Construct the gas estimator option from the user input
+ opts := &gasestimator.Options{
+ Config: b.ChainConfig(),
+ Chain: NewChainContext(ctx, b),
+ Header: header,
+ State: state,
+ ErrorRatio: estimateGasErrorRatio,
}
- // Reject the transaction as invalid if it still fails at the highest allowance
- if hi == cap {
- failed, result, err := executable(hi, state, header)
- if err != nil {
- return 0, err
- }
- if failed {
- if result != nil && result.Err != vm.ErrOutOfGas {
- if len(result.Revert()) > 0 {
- return 0, newRevertError(result)
- }
- return 0, result.Err
- }
- // Otherwise, the specified gas cap is too low
- return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap)
+ // Run the gas estimation andwrap any revertals into a custom return
+ call, err := args.ToMessage(gasCap, header.BaseFee)
+ if err != nil {
+ return 0, err
+ }
+ estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
+ if err != nil {
+ if len(revert) > 0 {
+ return 0, newRevertError(revert)
}
+ return 0, err
}
- return hexutil.Uint64(hi), nil
+ return hexutil.Uint64(estimate), nil
}
-// EstimateGas returns an estimate of the amount of gas needed to execute the
-// given transaction against the current pending block.
+// EstimateGas returns the lowest possible gas limit that allows the transaction to run
+// successfully at block `blockNrOrHash`, or the latest block if `blockNrOrHash` is unspecified. It
+// returns error if the transaction would revert or if there are unexpected failures. The returned
+// value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap
+// configuration (if non-zero).
+// Note: Required blob gas is not computed in this method.
func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) {
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
@@ -1382,8 +1286,8 @@ func (s *BlockChainAPI) needToReplay(ctx context.Context, block *types.Block, ac
for _, account := range accounts {
accountSet[account] = struct{}{}
}
- spendValueMap := make(map[common.Address]int64, len(accounts))
- receiveValueMap := make(map[common.Address]int64, len(accounts))
+ spendValueMap := make(map[common.Address]uint64, len(accounts))
+ receiveValueMap := make(map[common.Address]uint64, len(accounts))
signer := types.MakeSigner(s.b.ChainConfig(), block.Number(), block.Time())
for index, tx := range block.Transactions() {
@@ -1394,9 +1298,9 @@ func (s *BlockChainAPI) needToReplay(ctx context.Context, block *types.Block, ac
}
if _, exists := accountSet[from]; exists {
- spendValueMap[from] += int64(receipt.GasUsed) * tx.GasPrice().Int64()
+ spendValueMap[from] += receipt.GasUsed * tx.GasPrice().Uint64()
if receipt.Status == types.ReceiptStatusSuccessful {
- spendValueMap[from] += tx.Value().Int64()
+ spendValueMap[from] += tx.Value().Uint64()
}
}
@@ -1405,7 +1309,7 @@ func (s *BlockChainAPI) needToReplay(ctx context.Context, block *types.Block, ac
}
if _, exists := accountSet[*tx.To()]; exists && receipt.Status == types.ReceiptStatusSuccessful {
- receiveValueMap[*tx.To()] += tx.Value().Int64()
+ receiveValueMap[*tx.To()] += tx.Value().Uint64()
}
}
@@ -1422,8 +1326,8 @@ func (s *BlockChainAPI) needToReplay(ctx context.Context, block *types.Block, ac
return false, fmt.Errorf("statedb not found for block number (%d): %v", block.NumberU64(), err)
}
for _, account := range accounts {
- parentBalance := parentState.GetBalance(account).Int64()
- currentBalance := currentState.GetBalance(account).Int64()
+ parentBalance := parentState.GetBalance(account).Uint64()
+ currentBalance := currentState.GetBalance(account).Uint64()
if receiveValueMap[account]-spendValueMap[account] != currentBalance-parentBalance {
return true, nil
}
@@ -1474,7 +1378,7 @@ func (s *BlockChainAPI) replay(ctx context.Context, block *types.Block, accounts
if !skip {
// Record account balance
for _, account := range accounts {
- diffTx.Accounts[account] = statedb.GetBalance(account)
+ diffTx.Accounts[account] = statedb.GetBalance(account).ToBig()
}
}
@@ -1487,8 +1391,8 @@ func (s *BlockChainAPI) replay(ctx context.Context, block *types.Block, accounts
if posa, ok := s.b.Engine().(consensus.PoSA); ok {
if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem {
balance := statedb.GetBalance(consensus.SystemAddress)
- if balance.Cmp(common.Big0) > 0 {
- statedb.SetBalance(consensus.SystemAddress, big.NewInt(0))
+ if balance.Cmp(common.U2560) > 0 {
+ statedb.SetBalance(consensus.SystemAddress, uint256.NewInt(0))
statedb.AddBalance(block.Header().Coinbase, balance)
}
}
@@ -1502,7 +1406,7 @@ func (s *BlockChainAPI) replay(ctx context.Context, block *types.Block, accounts
if !skip {
// Compute account balance diff.
for _, account := range accounts {
- diffTx.Accounts[account] = new(big.Int).Sub(statedb.GetBalance(account), diffTx.Accounts[account])
+ diffTx.Accounts[account] = new(big.Int).Sub(statedb.GetBalance(account).ToBig(), diffTx.Accounts[account])
if diffTx.Accounts[account].Cmp(big.NewInt(0)) == 0 {
delete(diffTx.Accounts, account)
}
@@ -1568,15 +1472,21 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
"transactionsRoot": head.TxHash,
"receiptsRoot": head.ReceiptHash,
}
-
if head.BaseFee != nil {
result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
}
-
if head.WithdrawalsHash != nil {
result["withdrawalsRoot"] = head.WithdrawalsHash
}
-
+ if head.BlobGasUsed != nil {
+ result["blobGasUsed"] = hexutil.Uint64(*head.BlobGasUsed)
+ }
+ if head.ExcessBlobGas != nil {
+ result["excessBlobGas"] = hexutil.Uint64(*head.ExcessBlobGas)
+ }
+ if head.ParentBeaconRoot != nil {
+ result["parentBeaconBlockRoot"] = head.ParentBeaconRoot
+ }
return result
}
@@ -1635,26 +1545,28 @@ func (s *BlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inc
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
type RPCTransaction struct {
- BlockHash *common.Hash `json:"blockHash"`
- BlockNumber *hexutil.Big `json:"blockNumber"`
- From common.Address `json:"from"`
- Gas hexutil.Uint64 `json:"gas"`
- GasPrice *hexutil.Big `json:"gasPrice"`
- GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
- GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
- Hash common.Hash `json:"hash"`
- Input hexutil.Bytes `json:"input"`
- Nonce hexutil.Uint64 `json:"nonce"`
- To *common.Address `json:"to"`
- TransactionIndex *hexutil.Uint64 `json:"transactionIndex"`
- Value *hexutil.Big `json:"value"`
- Type hexutil.Uint64 `json:"type"`
- Accesses *types.AccessList `json:"accessList,omitempty"`
- ChainID *hexutil.Big `json:"chainId,omitempty"`
- V *hexutil.Big `json:"v"`
- R *hexutil.Big `json:"r"`
- S *hexutil.Big `json:"s"`
- YParity *hexutil.Uint64 `json:"yParity,omitempty"`
+ BlockHash *common.Hash `json:"blockHash"`
+ BlockNumber *hexutil.Big `json:"blockNumber"`
+ From common.Address `json:"from"`
+ Gas hexutil.Uint64 `json:"gas"`
+ GasPrice *hexutil.Big `json:"gasPrice"`
+ GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
+ GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
+ MaxFeePerBlobGas *hexutil.Big `json:"maxFeePerBlobGas,omitempty"`
+ Hash common.Hash `json:"hash"`
+ Input hexutil.Bytes `json:"input"`
+ Nonce hexutil.Uint64 `json:"nonce"`
+ To *common.Address `json:"to"`
+ TransactionIndex *hexutil.Uint64 `json:"transactionIndex"`
+ Value *hexutil.Big `json:"value"`
+ Type hexutil.Uint64 `json:"type"`
+ Accesses *types.AccessList `json:"accessList,omitempty"`
+ ChainID *hexutil.Big `json:"chainId,omitempty"`
+ BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
+ V *hexutil.Big `json:"v"`
+ R *hexutil.Big `json:"r"`
+ S *hexutil.Big `json:"s"`
+ YParity *hexutil.Uint64 `json:"yParity,omitempty"`
}
// newRPCTransaction returns a transaction that will serialize to the RPC
@@ -1708,15 +1620,43 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
// if the transaction has been mined, compute the effective gas price
if baseFee != nil && blockHash != (common.Hash{}) {
// price = min(gasTipCap + baseFee, gasFeeCap)
- price := math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap())
- result.GasPrice = (*hexutil.Big)(price)
+ result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
+ } else {
+ result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
+ }
+
+ case types.BlobTxType:
+ al := tx.AccessList()
+ yparity := hexutil.Uint64(v.Sign())
+ result.Accesses = &al
+ result.ChainID = (*hexutil.Big)(tx.ChainId())
+ result.YParity = &yparity
+ result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
+ result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
+ // if the transaction has been mined, compute the effective gas price
+ if baseFee != nil && blockHash != (common.Hash{}) {
+ result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
} else {
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
}
+ result.MaxFeePerBlobGas = (*hexutil.Big)(tx.BlobGasFeeCap())
+ result.BlobVersionedHashes = tx.BlobHashes()
}
return result
}
+// effectiveGasPrice computes the transaction gas fee, based on the given basefee value.
+//
+// price = min(gasTipCap + baseFee, gasFeeCap)
+func effectiveGasPrice(tx *types.Transaction, baseFee *big.Int) *big.Int {
+ fee := tx.GasTipCap()
+ fee = fee.Add(fee, baseFee)
+ if tx.GasFeeCapIntCmp(fee) < 0 {
+ return tx.GasFeeCap()
+ }
+ return fee
+}
+
// NewRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig) *RPCTransaction {
var (
@@ -1774,7 +1714,7 @@ type accessListResult struct {
// CreateAccessList creates an EIP-2930 type AccessList for the given transaction.
// Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state.
func (s *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) {
- bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
+ bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
bNrOrHash = *blockNrOrHash
}
@@ -1840,7 +1780,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
// Apply the transaction with the access list tracer
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
config := vm.Config{Tracer: tracer, NoBaseFee: true}
- vmenv, _ := b.GetEVM(ctx, msg, statedb, header, &config, nil)
+ vmenv := b.GetEVM(ctx, msg, statedb, header, &config, nil)
res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
if err != nil {
return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.toTransaction().Hash(), err)
@@ -1947,40 +1887,37 @@ func (s *TransactionAPI) GetTransactionCount(ctx context.Context, address common
// GetTransactionByHash returns the transaction for the given hash
func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
// Try to return an already finalized transaction
- tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
- if err != nil {
- return nil, err
- }
- if tx != nil {
- header, err := s.b.HeaderByHash(ctx, blockHash)
- if err != nil {
- return nil, err
+ found, tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
+ if !found {
+ // No finalized transaction, try to retrieve it from the pool
+ if tx := s.b.GetPoolTransaction(hash); tx != nil {
+ return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil
}
- return newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, s.b.ChainConfig()), nil
+ if err == nil {
+ return nil, nil
+ }
+ return nil, NewTxIndexingError()
}
- // No finalized transaction, try to retrieve it from the pool
- if tx := s.b.GetPoolTransaction(hash); tx != nil {
- return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil
+ header, err := s.b.HeaderByHash(ctx, blockHash)
+ if err != nil {
+ return nil, err
}
-
- // Transaction unknown, return as such
- return nil, nil
+ return newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, s.b.ChainConfig()), nil
}
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
func (s *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
- tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
- if err != nil {
- return nil, err
- }
- if tx == nil {
- if tx = s.b.GetPoolTransaction(hash); tx == nil {
- // Transaction not found anywhere, abort
+ found, tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
+ if !found {
+ if tx = s.b.GetPoolTransaction(hash); tx != nil {
+ return tx.MarshalBinary()
+ }
+ if err == nil {
return nil, nil
}
+ return nil, NewTxIndexingError()
}
- // Serialize to RLP and return
return tx.MarshalBinary()
}
@@ -2037,7 +1974,7 @@ func (s *TransactionAPI) GetTransactionReceiptsByBlockNumber(ctx context.Context
fields["status"] = hexutil.Uint(receipt.Status)
}
if receipt.Logs == nil {
- fields["logs"] = [][]*types.Log{}
+ fields["logs"] = []*types.Log{}
}
// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if receipt.ContractAddress != (common.Address{}) {
@@ -2071,10 +2008,10 @@ func (s *TransactionAPI) GetTransactionDataAndReceipt(ctx context.Context, hash
return nil, err
}
signer := types.MakeSigner(s.b.ChainConfig(), header.Number, header.Time)
- from, _ := types.Sender(signer, tx)
+ fields := marshalReceipt(receipt, blockHash, blockNumber, signer, tx, int(index))
+
// TODO use nil basefee before landon fork is enabled
rpcTransaction := newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, nil, s.b.ChainConfig())
-
txData := map[string]interface{}{
"blockHash": rpcTransaction.BlockHash.String(),
"blockNumber": rpcTransaction.BlockNumber.String(),
@@ -2092,35 +2029,6 @@ func (s *TransactionAPI) GetTransactionDataAndReceipt(ctx context.Context, hash
"s": rpcTransaction.S.String(),
}
- fields := map[string]interface{}{
- "blockHash": blockHash,
- "blockNumber": hexutil.Uint64(blockNumber),
- "transactionHash": hash,
- "transactionIndex": hexutil.Uint64(index),
- "from": from,
- "to": tx.To(),
- "gasUsed": hexutil.Uint64(receipt.GasUsed),
- "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
- "contractAddress": nil,
- "logs": receipt.Logs,
- "logsBloom": receipt.Bloom,
- "type": hexutil.Uint(tx.Type()),
- "effectiveGasPrice": (*hexutil.Big)(receipt.EffectiveGasPrice),
- }
-
- // Assign receipt status or post state.
- if len(receipt.PostState) > 0 {
- fields["root"] = hexutil.Bytes(receipt.PostState)
- } else {
- fields["status"] = hexutil.Uint(receipt.Status)
- }
- if receipt.Logs == nil {
- fields["logs"] = []*types.Log{}
- }
- // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
- if receipt.ContractAddress != (common.Address{}) {
- fields["contractAddress"] = receipt.ContractAddress
- }
result := map[string]interface{}{
"txData": txData,
"receipt": fields,
@@ -2130,11 +2038,12 @@ func (s *TransactionAPI) GetTransactionDataAndReceipt(ctx context.Context, hash
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
- tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
- if tx == nil || err != nil {
- // When the transaction doesn't exist, the RPC method should return JSON null
- // as per specification.
- return nil, nil
+ found, tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
+ if err != nil {
+ return nil, NewTxIndexingError() // transaction is not fully indexed
+ }
+ if !found {
+ return nil, nil // transaction is not existent or reachable
}
header, err := s.b.HeaderByHash(ctx, blockHash)
if err != nil {
@@ -2184,6 +2093,11 @@ func marshalReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber u
fields["logs"] = []*types.Log{}
}
+ if tx.Type() == types.BlobTxType {
+ fields["blobGasUsed"] = hexutil.Uint64(receipt.BlobGasUsed)
+ fields["blobGasPrice"] = (*hexutil.Big)(receipt.BlobGasPrice)
+ }
+
// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if receipt.ContractAddress != (common.Address{}) {
fields["contractAddress"] = receipt.ContractAddress
@@ -2253,6 +2167,9 @@ func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionAr
s.nonceLock.LockAddr(args.from())
defer s.nonceLock.UnlockAddr(args.from())
}
+ if args.IsEIP4844() {
+ return common.Hash{}, errBlobTxNotSupported
+ }
// Set some sanity defaults and terminate on failure
if err := args.setDefaults(ctx, s.b); err != nil {
@@ -2278,6 +2195,7 @@ func (s *TransactionAPI) FillTransaction(ctx context.Context, args TransactionAr
}
// Assemble the transaction and obtain rlp
tx := args.toTransaction()
+ // TODO(s1na): fill in blob proofs, commitments
data, err := tx.MarshalBinary()
if err != nil {
return nil, err
@@ -2354,6 +2272,9 @@ func (s *TransactionAPI) SignTransaction(ctx context.Context, args TransactionAr
if args.GasPrice == nil && (args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil) {
return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
}
+ if args.IsEIP4844() {
+ return nil, errBlobTxNotSupported
+ }
if args.Nonce == nil {
return nil, errors.New("nonce not specified")
}
@@ -2531,15 +2452,15 @@ func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.Block
// GetRawTransaction returns the bytes of the transaction for the given hash.
func (s *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
- tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
- if err != nil {
- return nil, err
- }
- if tx == nil {
- if tx = s.b.GetPoolTransaction(hash); tx == nil {
- // Transaction not found anywhere, abort
+ found, tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
+ if !found {
+ if tx = s.b.GetPoolTransaction(hash); tx != nil {
+ return tx.MarshalBinary()
+ }
+ if err == nil {
return nil, nil
}
+ return nil, NewTxIndexingError()
}
return tx.MarshalBinary()
}
@@ -2555,20 +2476,23 @@ func (api *DebugAPI) PrintBlock(ctx context.Context, number uint64) (string, err
// ChaindbProperty returns leveldb properties of the key-value database.
func (api *DebugAPI) ChaindbProperty(property string) (string, error) {
- if property == "" {
- property = "leveldb.stats"
- } else if !strings.HasPrefix(property, "leveldb.") {
- property = "leveldb." + property
- }
return api.b.ChainDb().Stat(property)
}
// ChaindbCompact flattens the entire key-value database into a single level,
// removing all unused slots and merging all keys.
func (api *DebugAPI) ChaindbCompact() error {
- for b := byte(0); b < 255; b++ {
- log.Info("Compacting chain database", "range", fmt.Sprintf("0x%0.2X-0x%0.2X", b, b+1))
- if err := api.b.ChainDb().Compact([]byte{b}, []byte{b + 1}); err != nil {
+ cstart := time.Now()
+ for b := 0; b <= 255; b++ {
+ var (
+ start = []byte{byte(b)}
+ end = []byte{byte(b + 1)}
+ )
+ if b == 255 {
+ end = nil
+ }
+ log.Info("Compacting database", "range", fmt.Sprintf("%#X-%#X", start, end), "elapsed", common.PrettyDuration(time.Since(cstart)))
+ if err := api.b.ChainDb().Compact(start, end); err != nil {
log.Error("Database compaction failed", "err", err)
return err
}
@@ -2621,12 +2545,3 @@ func checkTxFee(gasPrice *big.Int, gas uint64, cap float64) error {
}
return nil
}
-
-// toHexSlice creates a slice of hex-strings based on []byte.
-func toHexSlice(b [][]byte) []string {
- r := make([]string, len(b))
- for i := range b {
- r[i] = hexutil.Encode(b[i])
- }
- return r
-}
diff --git a/internal/ethapi/api_mev.go b/internal/ethapi/api_mev.go
new file mode 100644
index 0000000000..0fa92af1af
--- /dev/null
+++ b/internal/ethapi/api_mev.go
@@ -0,0 +1,111 @@
+package ethapi
+
+import (
+ "context"
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+)
+
+const (
+ TransferTxGasLimit = 25000
+)
+
+// MevAPI implements the interfaces that defined in the BEP-322.
+// It offers methods for the interaction between builders and validators.
+type MevAPI struct {
+ b Backend
+}
+
+// NewMevAPI creates a new MevAPI.
+func NewMevAPI(b Backend) *MevAPI {
+ return &MevAPI{b}
+}
+
+// SendBid receives bid from the builders.
+// If mev is not running or bid is invalid, return error.
+// Otherwise, creates a builder bid for the given argument, submit it to the miner.
+func (m *MevAPI) SendBid(ctx context.Context, args *types.BidArgs) (common.Hash, error) {
+ if !m.b.MevRunning() {
+ return common.Hash{}, types.ErrMevNotRunning
+ }
+
+ if !m.b.MinerInTurn() {
+ return common.Hash{}, types.ErrMevNotInTurn
+ }
+
+ var (
+ rawBid = args.RawBid
+ currentHeader = m.b.CurrentHeader()
+ )
+
+ if rawBid == nil {
+ return common.Hash{}, types.NewInvalidBidError("rawBid should not be nil")
+ }
+
+ // only support bidding for the next block not for the future block
+ if rawBid.BlockNumber != currentHeader.Number.Uint64()+1 {
+ return common.Hash{}, types.NewInvalidBidError("stale block number or block in future")
+ }
+
+ if rawBid.ParentHash != currentHeader.Hash() {
+ return common.Hash{}, types.NewInvalidBidError(
+ fmt.Sprintf("non-aligned parent hash: %v", currentHeader.Hash()))
+ }
+
+ if rawBid.GasFee == nil || rawBid.GasFee.Cmp(common.Big0) == 0 || rawBid.GasUsed == 0 {
+ return common.Hash{}, types.NewInvalidBidError("empty gasFee or empty gasUsed")
+ }
+
+ if rawBid.BuilderFee != nil {
+ builderFee := rawBid.BuilderFee
+ if builderFee.Cmp(common.Big0) < 0 {
+ return common.Hash{}, types.NewInvalidBidError("builder fee should not be less than 0")
+ }
+
+ if builderFee.Cmp(common.Big0) == 0 {
+ if len(args.PayBidTx) != 0 || args.PayBidTxGasUsed != 0 {
+ return common.Hash{}, types.NewInvalidPayBidTxError("payBidTx should be nil when builder fee is 0")
+ }
+ }
+
+ if builderFee.Cmp(rawBid.GasFee) >= 0 {
+ return common.Hash{}, types.NewInvalidBidError("builder fee must be less than gas fee")
+ }
+
+ if builderFee.Cmp(common.Big0) > 0 {
+ // payBidTx can be nil when validator and builder take some other settlement
+
+ if args.PayBidTxGasUsed > TransferTxGasLimit {
+ return common.Hash{}, types.NewInvalidBidError(
+ fmt.Sprintf("transfer tx gas used must be no more than %v", TransferTxGasLimit))
+ }
+
+ if (len(args.PayBidTx) == 0 && args.PayBidTxGasUsed != 0) ||
+ (len(args.PayBidTx) != 0 && args.PayBidTxGasUsed == 0) {
+ return common.Hash{}, types.NewInvalidPayBidTxError("non-aligned payBidTx and payBidTxGasUsed")
+ }
+ }
+ } else {
+ if len(args.PayBidTx) != 0 || args.PayBidTxGasUsed != 0 {
+ return common.Hash{}, types.NewInvalidPayBidTxError("payBidTx should be nil when builder fee is nil")
+ }
+ }
+
+ return m.b.SendBid(ctx, args)
+}
+
+func (m *MevAPI) BestBidGasFee(_ context.Context, parentHash common.Hash) *big.Int {
+ return m.b.BestBidGasFee(parentHash)
+}
+
+func (m *MevAPI) Params() *types.MevParams {
+ return m.b.MevParams()
+}
+
+// Running returns true if mev is running
+func (m *MevAPI) Running() bool {
+ return m.b.MevRunning()
+}
diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go
index 7435616c9c..654442f7ca 100644
--- a/internal/ethapi/api_test.go
+++ b/internal/ethapi/api_test.go
@@ -17,21 +17,30 @@
package ethapi
import (
+ "bytes"
"context"
"crypto/ecdsa"
"encoding/json"
"errors"
"fmt"
"math/big"
+ "os"
+ "path/filepath"
"reflect"
"testing"
"time"
+ "github.com/holiman/uint256"
+ "github.com/stretchr/testify/require"
+ "golang.org/x/exp/slices"
+
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
@@ -45,19 +54,15 @@ import (
"github.com/ethereum/go-ethereum/internal/blocktest"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "golang.org/x/exp/slices"
)
-func TestTransaction_RoundTripRpcJSON(t *testing.T) {
+func testTransactionMarshal(t *testing.T, tests []txData, config *params.ChainConfig) {
+ t.Parallel()
var (
- config = params.AllEthashProtocolChanges
signer = types.LatestSigner(config)
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- tests = allTransactionTypes(common.Address{0xde, 0xad}, config)
)
- t.Parallel()
+
for i, tt := range tests {
var tx2 types.Transaction
tx, err := types.SignNewTx(key, signer, tt.Tx)
@@ -88,6 +93,23 @@ func TestTransaction_RoundTripRpcJSON(t *testing.T) {
}
}
+func TestTransaction_RoundTripRpcJSON(t *testing.T) {
+ var (
+ config = params.AllEthashProtocolChanges
+ tests = allTransactionTypes(common.Address{0xde, 0xad}, config)
+ )
+ testTransactionMarshal(t, tests, config)
+}
+
+func TestTransactionBlobTx(t *testing.T) {
+ config := *params.TestChainConfig
+ config.ShanghaiTime = new(uint64)
+ config.CancunTime = new(uint64)
+ tests := allBlobTxs(common.Address{0xde, 0xad}, &config)
+
+ testTransactionMarshal(t, tests, &config)
+}
+
type txData struct {
Tx types.TxData
Want string
@@ -338,15 +360,80 @@ func allTransactionTypes(addr common.Address, config *params.ChainConfig) []txDa
}
}
+func allBlobTxs(addr common.Address, config *params.ChainConfig) []txData {
+ return []txData{
+ {
+ Tx: &types.BlobTx{
+ Nonce: 6,
+ GasTipCap: uint256.NewInt(1),
+ GasFeeCap: uint256.NewInt(5),
+ Gas: 6,
+ To: addr,
+ BlobFeeCap: uint256.NewInt(1),
+ BlobHashes: []common.Hash{{1}},
+ Value: new(uint256.Int),
+ V: uint256.NewInt(32),
+ R: uint256.NewInt(10),
+ S: uint256.NewInt(11),
+ },
+ Want: `{
+ "blockHash": null,
+ "blockNumber": null,
+ "from": "0x71562b71999873db5b286df957af199ec94617f7",
+ "gas": "0x6",
+ "gasPrice": "0x5",
+ "maxFeePerGas": "0x5",
+ "maxPriorityFeePerGas": "0x1",
+ "maxFeePerBlobGas": "0x1",
+ "hash": "0x1f2b59a20e61efc615ad0cbe936379d6bbea6f938aafaf35eb1da05d8e7f46a3",
+ "input": "0x",
+ "nonce": "0x6",
+ "to": "0xdead000000000000000000000000000000000000",
+ "transactionIndex": null,
+ "value": "0x0",
+ "type": "0x3",
+ "accessList": [],
+ "chainId": "0x1",
+ "blobVersionedHashes": [
+ "0x0100000000000000000000000000000000000000000000000000000000000000"
+ ],
+ "v": "0x0",
+ "r": "0x618be8908e0e5320f8f3b48042a079fe5a335ebd4ed1422a7d2207cd45d872bc",
+ "s": "0x27b2bc6c80e849a8e8b764d4549d8c2efac3441e73cf37054eb0a9b9f8e89b27",
+ "yParity": "0x0"
+ }`,
+ },
+ }
+}
+
+func newTestAccountManager(t *testing.T) (*accounts.Manager, accounts.Account) {
+ var (
+ dir = t.TempDir()
+ am = accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true})
+ b = keystore.NewKeyStore(dir, 2, 1)
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ )
+ acc, err := b.ImportECDSA(testKey, "")
+ if err != nil {
+ t.Fatalf("failed to create test account: %v", err)
+ }
+ if err := b.Unlock(acc, ""); err != nil {
+ t.Fatalf("failed to unlock account: %v\n", err)
+ }
+ am.AddBackend(b)
+ return am, acc
+}
+
type testBackend struct {
db ethdb.Database
chain *core.BlockChain
pending *types.Block
+ accman *accounts.Manager
+ acc accounts.Account
}
-func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend {
+func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend {
var (
- engine = ethash.NewFaker()
cacheConfig = &core.CacheConfig{
TrieCleanLimit: 256,
TrieDirtyLimit: 256,
@@ -355,6 +442,8 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i i
TrieDirtyDisabled: true, // Archive mode
}
)
+ accman, acc := newTestAccountManager(t)
+ gspec.Alloc[acc.Address] = core.GenesisAccount{Balance: big.NewInt(params.Ether)}
// Generate blocks for testing
db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
txlookupLimit := uint64(0)
@@ -366,7 +455,7 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i i
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
}
- backend := &testBackend{db: db, chain: chain}
+ backend := &testBackend{db: db, chain: chain, accman: accman, acc: acc}
return backend
}
@@ -388,7 +477,7 @@ func (b testBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBloc
return nil, nil, nil, nil, nil
}
func (b testBackend) ChainDb() ethdb.Database { return b.db }
-func (b testBackend) AccountManager() *accounts.Manager { return nil }
+func (b testBackend) AccountManager() *accounts.Manager { return b.accman }
func (b testBackend) ExtRPCEnabled() bool { return false }
func (b testBackend) RPCGasCap() uint64 { return 10000000 }
func (b testBackend) RPCEVMTimeout() time.Duration { return time.Second }
@@ -478,8 +567,7 @@ func (b testBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
}
return big.NewInt(1)
}
-func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) (*vm.EVM, func() error) {
- vmError := func() error { return nil }
+func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM {
if vmConfig == nil {
vmConfig = b.chain.GetVMConfig()
}
@@ -488,7 +576,7 @@ func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state *state
if blockContext != nil {
context = *blockContext
}
- return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig), vmError
+ return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig)
}
func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
panic("implement me")
@@ -508,14 +596,14 @@ func (b testBackend) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Su
func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
panic("implement me")
}
-func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
+func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
- return tx, blockHash, blockNumber, index, nil
+ return true, tx, blockHash, blockNumber, index, nil
}
func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") }
func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") }
func (b testBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
- panic("implement me")
+ return 0, nil
}
func (b testBackend) Stats() (pending int, queued int) { panic("implement me") }
func (b testBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
@@ -546,13 +634,30 @@ func (b testBackend) ServiceFilter(ctx context.Context, session *bloombits.Match
panic("implement me")
}
+func (b *testBackend) MevRunning() bool { return false }
+func (b *testBackend) MevParams() *types.MevParams {
+ return &types.MevParams{}
+}
+func (b *testBackend) StartMev() {}
+func (b *testBackend) StopMev() {}
+func (b *testBackend) AddBuilder(builder common.Address, builderUrl string) error { return nil }
+func (b *testBackend) RemoveBuilder(builder common.Address) error { return nil }
+func (b *testBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) {
+ panic("implement me")
+}
+func (b *testBackend) MinerInTurn() bool { return false }
+func (b *testBackend) BestBidGasFee(parentHash common.Hash) *big.Int {
+ //TODO implement me
+ panic("implement me")
+}
+
func TestEstimateGas(t *testing.T) {
t.Parallel()
// Initialize test accounts
var (
accounts = newAccounts(2)
genesis = &core.Genesis{
- Config: params.TestChainConfig,
+ Config: params.MergedTestChainConfig,
Alloc: core.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
@@ -562,12 +667,13 @@ func TestEstimateGas(t *testing.T) {
signer = types.HomesteadSigner{}
randomAccounts = newAccounts(2)
)
- api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
+ api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key)
b.AddTx(tx)
+ b.SetPoS()
}))
var testSuite = []struct {
blockNumber rpc.BlockNumber
@@ -626,6 +732,59 @@ func TestEstimateGas(t *testing.T) {
},
expectErr: core.ErrInsufficientFunds,
},
+ // Test for a bug where the gas price was set to zero but the basefee non-zero
+ //
+ // contract BasefeeChecker {
+ // constructor() {
+ // require(tx.gasprice >= block.basefee);
+ // if (tx.gasprice > 0) {
+ // require(block.basefee > 0);
+ // }
+ // }
+ //}
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[0].addr,
+ Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"),
+ GasPrice: (*hexutil.Big)(big.NewInt(1_000_000_000)), // Legacy as pricing
+ },
+ expectErr: nil,
+ want: 67617,
+ },
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[0].addr,
+ Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"),
+ MaxFeePerGas: (*hexutil.Big)(big.NewInt(1_000_000_000)), // 1559 gas pricing
+ },
+ expectErr: nil,
+ want: 67617,
+ },
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[0].addr,
+ Input: hex2Bytes("6080604052348015600f57600080fd5b50483a1015601c57600080fd5b60003a111560315760004811603057600080fd5b5b603f80603e6000396000f3fe6080604052600080fdfea264697066735822122060729c2cee02b10748fae5200f1c9da4661963354973d9154c13a8e9ce9dee1564736f6c63430008130033"),
+ GasPrice: nil, // No legacy gas pricing
+ MaxFeePerGas: nil, // No 1559 gas pricing
+ },
+ expectErr: nil,
+ want: 67595,
+ },
+ // Blobs should have no effect on gas estimate
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[0].addr,
+ To: &accounts[1].addr,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
+ BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
+ },
+ want: 21000,
+ },
}
for i, tc := range testSuite {
result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides)
@@ -643,7 +802,7 @@ func TestEstimateGas(t *testing.T) {
t.Errorf("test %d: want no error, have %v", i, err)
continue
}
- if uint64(result) != tc.want {
+ if float64(result) > float64(tc.want)*(1+estimateGasErrorRatio) {
t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, uint64(result), tc.want)
}
}
@@ -655,7 +814,7 @@ func TestCall(t *testing.T) {
var (
accounts = newAccounts(3)
genesis = &core.Genesis{
- Config: params.TestChainConfig,
+ Config: params.MergedTestChainConfig,
Alloc: core.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
@@ -665,12 +824,13 @@ func TestCall(t *testing.T) {
genBlocks = 10
signer = types.HomesteadSigner{}
)
- api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
+ api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key)
b.AddTx(tx)
+ b.SetPoS()
}))
randomAccounts := newAccounts(3)
var testSuite = []struct {
@@ -792,9 +952,35 @@ func TestCall(t *testing.T) {
blockOverrides: BlockOverrides{Number: (*hexutil.Big)(big.NewInt(11))},
want: "0x000000000000000000000000000000000000000000000000000000000000000b",
},
+ // Invalid blob tx
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[1].addr,
+ Input: &hexutil.Bytes{0x00},
+ BlobHashes: []common.Hash{},
+ },
+ expectErr: core.ErrBlobTxCreate,
+ },
+ // BLOBHASH opcode
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[1].addr,
+ To: &randomAccounts[2].addr,
+ BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
+ BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
+ },
+ overrides: StateOverride{
+ randomAccounts[2].addr: {
+ Code: hex2Bytes("60004960005260206000f3"),
+ },
+ },
+ want: "0x0122000000000000000000000000000000000000000000000000000000000000",
+ },
}
for i, tc := range testSuite {
- result, err := api.Call(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)
+ result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)
if tc.expectErr != nil {
if err == nil {
t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr)
@@ -818,18 +1004,146 @@ func TestCall(t *testing.T) {
}
}
-type Account struct {
+func TestSignTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ var (
+ key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ to = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.MergedTestChainConfig,
+ Alloc: core.GenesisAlloc{},
+ }
+ )
+ b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+ b.SetPoS()
+ })
+ api := NewTransactionAPI(b, nil)
+ res, err := api.FillTransaction(context.Background(), TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ })
+ if err != nil {
+ t.Fatalf("failed to fill tx defaults: %v\n", err)
+ }
+
+ res, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v\n", err)
+ }
+ tx, err := json.Marshal(res.Tx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expect := `{"type":"0x2","chainId":"0x1","nonce":"0x0","to":"0x703c4b2bd70c169f5717101caee543299fc946c7","gas":"0x5208","gasPrice":null,"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x684ee180","value":"0x1","input":"0x","accessList":[],"v":"0x0","r":"0x8fabeb142d585dd9247f459f7e6fe77e2520c88d50ba5d220da1533cea8b34e1","s":"0x582dd68b21aef36ba23f34e49607329c20d981d30404daf749077f5606785ce7","yParity":"0x0","hash":"0x93927839207cfbec395da84b8a2bc38b7b65d2cb2819e9fef1f091f5b1d4cc8f"}`
+ if !bytes.Equal(tx, []byte(expect)) {
+ t.Errorf("result mismatch. Have:\n%s\nWant:\n%s\n", tx, expect)
+ }
+}
+
+func TestSignBlobTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ var (
+ key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ to = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.MergedTestChainConfig,
+ Alloc: core.GenesisAlloc{},
+ }
+ )
+ b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+ b.SetPoS()
+ })
+ api := NewTransactionAPI(b, nil)
+ res, err := api.FillTransaction(context.Background(), TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{{0x01, 0x22}},
+ })
+ if err != nil {
+ t.Fatalf("failed to fill tx defaults: %v\n", err)
+ }
+
+ _, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+ if err == nil {
+ t.Fatalf("should fail on blob transaction")
+ }
+ if !errors.Is(err, errBlobTxNotSupported) {
+ t.Errorf("error mismatch. Have: %v, want: %v", err, errBlobTxNotSupported)
+ }
+}
+
+func TestSendBlobTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ var (
+ key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ to = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.MergedTestChainConfig,
+ Alloc: core.GenesisAlloc{},
+ }
+ )
+ b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+ b.SetPoS()
+ })
+ api := NewTransactionAPI(b, nil)
+ res, err := api.FillTransaction(context.Background(), TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
+ })
+ if err != nil {
+ t.Fatalf("failed to fill tx defaults: %v\n", err)
+ }
+
+ _, err = api.SendTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+ if err == nil {
+ t.Errorf("sending tx should have failed")
+ } else if !errors.Is(err, errBlobTxNotSupported) {
+ t.Errorf("unexpected error. Have %v, want %v\n", err, errBlobTxNotSupported)
+ }
+}
+
+func argsFromTransaction(tx *types.Transaction, from common.Address) TransactionArgs {
+ var (
+ gas = tx.Gas()
+ nonce = tx.Nonce()
+ input = tx.Data()
+ )
+ return TransactionArgs{
+ From: &from,
+ To: tx.To(),
+ Gas: (*hexutil.Uint64)(&gas),
+ MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()),
+ MaxPriorityFeePerGas: (*hexutil.Big)(tx.GasTipCap()),
+ Value: (*hexutil.Big)(tx.Value()),
+ Nonce: (*hexutil.Uint64)(&nonce),
+ Input: (*hexutil.Bytes)(&input),
+ ChainID: (*hexutil.Big)(tx.ChainId()),
+ // TODO: impl accessList conversion
+ //AccessList: tx.AccessList(),
+ BlobFeeCap: (*hexutil.Big)(tx.BlobGasFeeCap()),
+ BlobHashes: tx.BlobHashes(),
+ }
+}
+
+type account struct {
key *ecdsa.PrivateKey
addr common.Address
}
-func newAccounts(n int) (accounts []Account) {
+func newAccounts(n int) (accounts []account) {
for i := 0; i < n; i++ {
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
- accounts = append(accounts, Account{key: key, addr: addr})
+ accounts = append(accounts, account{key: key, addr: addr})
}
- slices.SortFunc(accounts, func(a, b Account) int { return a.addr.Cmp(b.addr) })
+ slices.SortFunc(accounts, func(a, b account) int { return a.addr.Cmp(b.addr) })
return accounts
}
@@ -1048,12 +1362,10 @@ func TestRPCMarshalBlock(t *testing.T) {
t.Errorf("test %d: json marshal error: %v", i, err)
continue
}
- assert.JSONEqf(t, tc.want, string(out), "test %d", i)
+ require.JSONEqf(t, tc.want, string(out), "test %d", i)
}
}
-// test cases faied because of basefee logic
-/*
func TestRPCGetBlockOrHeader(t *testing.T) {
t.Parallel()
@@ -1088,7 +1400,7 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
}
pending = types.NewBlockWithWithdrawals(&types.Header{Number: big.NewInt(11), Time: 42}, []*types.Transaction{tx}, nil, nil, []*types.Withdrawal{withdrawal}, blocktest.NewHasher())
)
- backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
+ backend := newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
@@ -1113,628 +1425,156 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
blockHash *common.Hash
fullTx bool
reqHeader bool
- want string
+ file string
expectErr error
}{
// 0. latest header
{
blockNumber: rpc.LatestBlockNumber,
reqHeader: true,
- want: `{
- "baseFeePerGas": "0xfdc7303",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0xa",
- "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91",
- "timestamp": "0x64",
- "totalDifficulty": "0x1",
- "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445"
- }`,
+ file: "tag-latest",
},
// 1. genesis header
{
blockNumber: rpc.BlockNumber(0),
reqHeader: true,
- want: `{
- "baseFeePerGas": "0x3b9aca00",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x0",
- "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x0",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
- "timestamp": "0x0",
- "totalDifficulty": "0x1",
- "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
- }`,
+ file: "number-0",
},
// 2. #1 header
{
blockNumber: rpc.BlockNumber(1),
reqHeader: true,
- want: `{
- "baseFeePerGas": "0x342770c0",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x1",
- "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22",
- "timestamp": "0xa",
- "totalDifficulty": "0x1",
- "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7"
- }`,
+ file: "number-1",
},
// 3. latest-1 header
{
blockNumber: rpc.BlockNumber(9),
reqHeader: true,
- want: `{
- "baseFeePerGas": "0x121a9cca",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x9",
- "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0",
- "timestamp": "0x5a",
- "totalDifficulty": "0x1",
- "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5"
- }`,
+ file: "number-latest-1",
},
// 4. latest+1 header
{
blockNumber: rpc.BlockNumber(11),
reqHeader: true,
- want: "null",
+ file: "number-latest+1",
},
// 5. pending header
{
blockNumber: rpc.PendingBlockNumber,
reqHeader: true,
- want: `{
- "difficulty": "0x0",
- "extraData": "0x",
- "gasLimit": "0x0",
- "gasUsed": "0x0",
- "hash": null,
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": null,
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": null,
- "number": "0xb",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "timestamp": "0x2a",
- "totalDifficulty": null,
- "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
- "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84"
- }`,
+ file: "tag-pending",
},
// 6. latest block
{
blockNumber: rpc.LatestBlockNumber,
- want: `{
- "baseFeePerGas": "0xfdc7303",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0xa",
- "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x26a",
- "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91",
- "timestamp": "0x64",
- "totalDifficulty": "0x1",
- "transactions": [
- "0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644"
- ],
- "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445",
- "uncles": []
- }`,
+ file: "tag-latest",
},
// 7. genesis block
{
blockNumber: rpc.BlockNumber(0),
- want: `{
- "baseFeePerGas": "0x3b9aca00",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x0",
- "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x0",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x200",
- "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
- "timestamp": "0x0",
- "totalDifficulty": "0x1",
- "transactions": [],
- "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "uncles": []
- }`,
+ file: "number-0",
},
// 8. #1 block
{
blockNumber: rpc.BlockNumber(1),
- want: `{
- "baseFeePerGas": "0x342770c0",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x1",
- "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x26a",
- "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22",
- "timestamp": "0xa",
- "totalDifficulty": "0x1",
- "transactions": [
- "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e"
- ],
- "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7",
- "uncles": []
- }`,
+ file: "number-1",
},
// 9. latest-1 block
{
blockNumber: rpc.BlockNumber(9),
fullTx: true,
- want: `{
- "baseFeePerGas": "0x121a9cca",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x9",
- "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x26a",
- "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0",
- "timestamp": "0x5a",
- "totalDifficulty": "0x1",
- "transactions": [
- {
- "blockHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "blockNumber": "0x9",
- "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
- "gas": "0x5208",
- "gasPrice": "0x121a9cca",
- "hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725",
- "input": "0x",
- "nonce": "0x8",
- "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
- "transactionIndex": "0x0",
- "value": "0x3e8",
- "type": "0x0",
- "v": "0x1b",
- "r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd",
- "s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d"
- }
- ],
- "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5",
- "uncles": []
- }`,
+ file: "number-latest-1",
},
// 10. latest+1 block
{
blockNumber: rpc.BlockNumber(11),
fullTx: true,
- want: "null",
+ file: "number-latest+1",
},
// 11. pending block
{
blockNumber: rpc.PendingBlockNumber,
- want: `{
- "difficulty": "0x0",
- "extraData": "0x",
- "gasLimit": "0x0",
- "gasUsed": "0x0",
- "hash": null,
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": null,
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": null,
- "number": "0xb",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x256",
- "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "timestamp": "0x2a",
- "totalDifficulty": null,
- "transactions": [
- "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298"
- ],
- "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
- "withdrawals": [
- {
- "index": "0x0",
- "validatorIndex": "0x1",
- "address": "0x1234000000000000000000000000000000000000",
- "amount": "0xa"
- }
- ],
- "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84",
- "uncles": []
- }`,
+ file: "tag-pending",
},
// 12. pending block + fullTx
{
blockNumber: rpc.PendingBlockNumber,
fullTx: true,
- want: `{
- "difficulty": "0x0",
- "extraData": "0x",
- "gasLimit": "0x0",
- "gasUsed": "0x0",
- "hash": null,
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": null,
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": null,
- "number": "0xb",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x256",
- "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "timestamp": "0x2a",
- "totalDifficulty": null,
- "transactions": [
- {
- "blockHash": "0x6cebd9f966ea686f44b981685e3f0eacea28591a7a86d7fbbe521a86e9f81165",
- "blockNumber": "0xb",
- "from": "0x0000000000000000000000000000000000000000",
- "gas": "0x457",
- "gasPrice": "0x2b67",
- "hash": "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298",
- "input": "0x111111",
- "nonce": "0xb",
- "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
- "transactionIndex": "0x0",
- "value": "0x6f",
- "type": "0x0",
- "chainId": "0x7fffffffffffffee",
- "v": "0x0",
- "r": "0x0",
- "s": "0x0"
- }
- ],
- "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
- "uncles": [],
- "withdrawals": [
- {
- "index": "0x0",
- "validatorIndex": "0x1",
- "address": "0x1234000000000000000000000000000000000000",
- "amount": "0xa"
- }
- ],
- "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84"
- }`,
+ file: "tag-pending-fullTx",
},
// 13. latest header by hash
{
blockHash: &blockHashes[len(blockHashes)-1],
reqHeader: true,
- want: `{
- "baseFeePerGas": "0xfdc7303",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0xa",
- "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91",
- "timestamp": "0x64",
- "totalDifficulty": "0x1",
- "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445"
- }`,
+ file: "hash-latest",
},
// 14. genesis header by hash
{
blockHash: &blockHashes[0],
reqHeader: true,
- want: `{
- "baseFeePerGas": "0x3b9aca00",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x0",
- "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x0",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
- "timestamp": "0x0",
- "totalDifficulty": "0x1",
- "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
- }`,
+ file: "hash-0",
},
// 15. #1 header
{
blockHash: &blockHashes[1],
reqHeader: true,
- want: `{
- "baseFeePerGas": "0x342770c0",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x1",
- "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22",
- "timestamp": "0xa",
- "totalDifficulty": "0x1",
- "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7"
- }`,
+ file: "hash-1",
},
// 16. latest-1 header
{
blockHash: &blockHashes[len(blockHashes)-2],
reqHeader: true,
- want: `{
- "baseFeePerGas": "0x121a9cca",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x9",
- "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0",
- "timestamp": "0x5a",
- "totalDifficulty": "0x1",
- "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5"
- }`,
+ file: "hash-latest-1",
},
// 17. empty hash
{
blockHash: &common.Hash{},
reqHeader: true,
- want: "null",
+ file: "hash-empty",
},
// 18. pending hash
{
blockHash: &pendingHash,
reqHeader: true,
- want: `null`,
+ file: `hash-pending`,
},
// 19. latest block
{
blockHash: &blockHashes[len(blockHashes)-1],
- want: `{
- "baseFeePerGas": "0xfdc7303",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0xa",
- "parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x26a",
- "stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91",
- "timestamp": "0x64",
- "totalDifficulty": "0x1",
- "transactions": [
- "0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644"
- ],
- "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445",
- "uncles": []
- }`,
+ file: "hash-latest",
},
// 20. genesis block
{
blockHash: &blockHashes[0],
- want: `{
- "baseFeePerGas": "0x3b9aca00",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x0",
- "hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x0",
- "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x200",
- "stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
- "timestamp": "0x0",
- "totalDifficulty": "0x1",
- "transactions": [],
- "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "uncles": []
- }`,
+ file: "hash-genesis",
},
// 21. #1 block
{
blockHash: &blockHashes[1],
- want: `{
- "baseFeePerGas": "0x342770c0",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x1",
- "parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x26a",
- "stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22",
- "timestamp": "0xa",
- "totalDifficulty": "0x1",
- "transactions": [
- "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e"
- ],
- "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7",
- "uncles": []
- }`,
+ file: "hash-1",
},
// 22. latest-1 block
{
blockHash: &blockHashes[len(blockHashes)-2],
fullTx: true,
- want: `{
- "baseFeePerGas": "0x121a9cca",
- "difficulty": "0x20000",
- "extraData": "0x",
- "gasLimit": "0x47e7c4",
- "gasUsed": "0x5208",
- "hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": "0x9",
- "parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7",
- "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x26a",
- "stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0",
- "timestamp": "0x5a",
- "totalDifficulty": "0x1",
- "transactions": [
- {
- "blockHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
- "blockNumber": "0x9",
- "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
- "gas": "0x5208",
- "gasPrice": "0x121a9cca",
- "hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725",
- "input": "0x",
- "nonce": "0x8",
- "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
- "transactionIndex": "0x0",
- "value": "0x3e8",
- "type": "0x0",
- "v": "0x1b",
- "r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd",
- "s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d"
- }
- ],
- "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5",
- "uncles": []
- }`,
+ file: "hash-latest-1-fullTx",
},
// 23. empty hash + body
{
blockHash: &common.Hash{},
fullTx: true,
- want: "null",
+ file: "hash-empty-fullTx",
},
// 24. pending block
{
blockHash: &pendingHash,
- want: `null`,
+ file: `hash-pending`,
},
// 25. pending block + fullTx
{
blockHash: &pendingHash,
fullTx: true,
- want: `null`,
+ file: "hash-pending-fullTx",
},
}
@@ -1742,18 +1582,23 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
var (
result map[string]interface{}
err error
+ rpc string
)
if tt.blockHash != nil {
if tt.reqHeader {
result = api.GetHeaderByHash(context.Background(), *tt.blockHash)
+ rpc = "eth_getHeaderByHash"
} else {
result, err = api.GetBlockByHash(context.Background(), *tt.blockHash, tt.fullTx)
+ rpc = "eth_getBlockByHash"
}
} else {
if tt.reqHeader {
result, err = api.GetHeaderByNumber(context.Background(), tt.blockNumber)
+ rpc = "eth_getHeaderByNumber"
} else {
result, err = api.GetBlockByNumber(context.Background(), tt.blockNumber, tt.fullTx)
+ rpc = "eth_getBlockByNumber"
}
}
if tt.expectErr != nil {
@@ -1770,19 +1615,13 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
t.Errorf("test %d: want no error, have %v", i, err)
continue
}
- data, err := json.Marshal(result)
- if err != nil {
- t.Errorf("test %d: json marshal error", i)
- continue
- }
- want, have := tt.want, string(data)
- require.JSONEqf(t, want, have, "test %d: json not match, want: %s, have: %s", i, want, have)
+
+ testRPCResponseWithFile(t, i, result, rpc, tt.file)
}
}
-*/
func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Hash) {
- // Initialize test accounts
+ config := *params.MergedTestChainConfig
var (
acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
@@ -1790,7 +1629,9 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey)
contract = common.HexToAddress("0000000000000000000000000000000000031ec7")
genesis = &core.Genesis{
- Config: params.TestChainConfig,
+ Config: &config,
+ ExcessBlobGas: new(uint64),
+ BlobGasUsed: new(uint64),
Alloc: core.GenesisAlloc{
acc1Addr: {Balance: big.NewInt(params.Ether)},
acc2Addr: {Balance: big.NewInt(params.Ether)},
@@ -1809,9 +1650,9 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
}
signer = types.LatestSignerForChainID(params.TestChainConfig.ChainID)
txHashes = make([]common.Hash, genBlocks)
- gasPrice = big.NewInt(3e9) // 3Gwei
)
- backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
+
+ backend := newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
var (
tx *types.Transaction
err error
@@ -1819,29 +1660,43 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
switch i {
case 0:
// transfer 1000wei
- tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &acc2Addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: gasPrice, Data: nil}), types.HomesteadSigner{}, acc1Key)
+ tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &acc2Addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), types.HomesteadSigner{}, acc1Key)
case 1:
// create contract
- tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: nil, Gas: 53100, GasPrice: gasPrice, Data: common.FromHex("0x60806040")}), signer, acc1Key)
+ tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: nil, Gas: 53100, GasPrice: b.BaseFee(), Data: common.FromHex("0x60806040")}), signer, acc1Key)
case 2:
// with logs
// transfer(address to, uint256 value)
data := fmt.Sprintf("0xa9059cbb%s%s", common.HexToHash(common.BigToAddress(big.NewInt(int64(i + 1))).Hex()).String()[2:], common.BytesToHash([]byte{byte(i + 11)}).String()[2:])
- tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &contract, Gas: 60000, GasPrice: gasPrice, Data: common.FromHex(data)}), signer, acc1Key)
+ tx, err = types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &contract, Gas: 60000, GasPrice: b.BaseFee(), Data: common.FromHex(data)}), signer, acc1Key)
case 3:
// dynamic fee with logs
// transfer(address to, uint256 value)
data := fmt.Sprintf("0xa9059cbb%s%s", common.HexToHash(common.BigToAddress(big.NewInt(int64(i + 1))).Hex()).String()[2:], common.BytesToHash([]byte{byte(i + 11)}).String()[2:])
- fee := gasPrice
+ fee := big.NewInt(500)
fee.Add(fee, b.BaseFee())
- tx, err = types.SignTx(types.NewTx(&types.DynamicFeeTx{Nonce: uint64(i), To: &contract, Gas: 60000, Value: big.NewInt(1), GasTipCap: gasPrice, GasFeeCap: fee, Data: common.FromHex(data)}), signer, acc1Key)
+ tx, err = types.SignTx(types.NewTx(&types.DynamicFeeTx{Nonce: uint64(i), To: &contract, Gas: 60000, Value: big.NewInt(1), GasTipCap: big.NewInt(500), GasFeeCap: fee, Data: common.FromHex(data)}), signer, acc1Key)
case 4:
// access list with contract create
accessList := types.AccessList{{
Address: contract,
StorageKeys: []common.Hash{{0}},
}}
- tx, err = types.SignTx(types.NewTx(&types.AccessListTx{Nonce: uint64(i), To: nil, Gas: 58100, GasPrice: gasPrice, Data: common.FromHex("0x60806040"), AccessList: accessList}), signer, acc1Key)
+ tx, err = types.SignTx(types.NewTx(&types.AccessListTx{Nonce: uint64(i), To: nil, Gas: 58100, GasPrice: b.BaseFee(), Data: common.FromHex("0x60806040"), AccessList: accessList}), signer, acc1Key)
+ case 5:
+ // blob tx
+ fee := big.NewInt(500)
+ fee.Add(fee, b.BaseFee())
+ tx, err = types.SignTx(types.NewTx(&types.BlobTx{
+ Nonce: uint64(i),
+ GasTipCap: uint256.NewInt(1),
+ GasFeeCap: uint256.MustFromBig(fee),
+ Gas: params.TxGas,
+ To: acc2Addr,
+ BlobFeeCap: uint256.NewInt(1),
+ BlobHashes: []common.Hash{{1}},
+ Value: new(uint256.Int),
+ }), signer, acc1Key)
}
if err != nil {
t.Errorf("failed to sign tx: %v", err)
@@ -1850,6 +1705,7 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
b.AddTx(tx)
txHashes[i] = tx.Hash()
}
+ b.SetPoS()
})
return backend, txHashes
}
@@ -1858,139 +1714,53 @@ func TestRPCGetTransactionReceipt(t *testing.T) {
t.Parallel()
var (
- backend, txHashes = setupReceiptBackend(t, 5)
+ backend, txHashes = setupReceiptBackend(t, 6)
api = NewTransactionAPI(backend, new(AddrLocker))
)
var testSuite = []struct {
txHash common.Hash
- want string
+ file string
}{
// 0. normal success
{
txHash: txHashes[0],
- want: `{
- "blockHash": "0xcf5e82a62028debbeecba9a6a7cbeaed67b431800a4250a60943101a611d179a",
- "blockNumber": "0x1",
- "contractAddress": null,
- "cumulativeGasUsed": "0x5208",
- "effectiveGasPrice": "0xb2d05e00",
- "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
- "gasUsed": "0x5208",
- "logs": [],
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "status": "0x1",
- "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
- "transactionHash": "0xf875edfe4579e2a5e1ad45c4d802c1e5abbca19561398e9c58c41dabd86a3aa6",
- "transactionIndex": "0x0",
- "type": "0x0"
- }`,
+ file: "normal-transfer-tx",
},
// 1. create contract
{
txHash: txHashes[1],
- want: `{
- "blockHash": "0x739ed5e516e6b2b0fa16f22a335a371a1fac616bc394b7454fdf07a0fd10db30",
- "blockNumber": "0x2",
- "contractAddress": "0xae9bea628c4ce503dcfd7e305cab4e29e7476592",
- "cumulativeGasUsed": "0xcf4e",
- "effectiveGasPrice": "0xb2d05e00",
- "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
- "gasUsed": "0xcf4e",
- "logs": [],
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "status": "0x1",
- "to": null,
- "transactionHash": "0xd7a2d56946b13872c0064d0af803fa7b2a7f6be74023cf9ce6337c0dc5b06813",
- "transactionIndex": "0x0",
- "type": "0x0"
- }`,
+ file: "create-contract-tx",
},
// 2. with logs success
{
txHash: txHashes[2],
- want: `{
- "blockHash": "0x07545649b5df1cd84de57265fa5acdb473a1a033bf51c43d61c6183b13487f19",
- "blockNumber": "0x3",
- "contractAddress": null,
- "cumulativeGasUsed": "0x5e28",
- "effectiveGasPrice": "0xb2d05e00",
- "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
- "gasUsed": "0x5e28",
- "logs": [
- {
- "address": "0x0000000000000000000000000000000000031ec7",
- "topics": [
- "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
- "0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7",
- "0x0000000000000000000000000000000000000000000000000000000000000003"
- ],
- "data": "0x000000000000000000000000000000000000000000000000000000000000000d",
- "blockNumber": "0x3",
- "transactionHash": "0x2c660ba194f0e2de5bbb4e2f38a15fe9f263dd5e5c524d45be4834755b2c2a8c",
- "transactionIndex": "0x0",
- "blockHash": "0x07545649b5df1cd84de57265fa5acdb473a1a033bf51c43d61c6183b13487f19",
- "logIndex": "0x0",
- "removed": false
- }
- ],
- "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000",
- "status": "0x1",
- "to": "0x0000000000000000000000000000000000031ec7",
- "transactionHash": "0x2c660ba194f0e2de5bbb4e2f38a15fe9f263dd5e5c524d45be4834755b2c2a8c",
- "transactionIndex": "0x0",
- "type": "0x0"
- }`,
+ file: "with-logs",
},
// 3. dynamic tx with logs success
{
txHash: txHashes[3],
- want: `{
- "blockHash": "0x2a78cbbc361402d352baf99afcd8d57b34df182ed44819ca6bf0a1ceedc94a1e",
- "blockNumber": "0x4",
- "contractAddress": null,
- "cumulativeGasUsed": "0x538d",
- "effectiveGasPrice": "0xb2d05e00",
- "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
- "gasUsed": "0x538d",
- "logs": [],
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "status": "0x0",
- "to": "0x0000000000000000000000000000000000031ec7",
- "transactionHash": "0x395e5326a196a53e961b8f406b706049288d8f92e467f95677ced981fa3a40ce",
- "transactionIndex": "0x0",
- "type": "0x2"
- }`,
+ file: `dynamic-tx-with-logs`,
},
// 4. access list tx with create contract
{
txHash: txHashes[4],
- want: `{
- "blockHash": "0xde2f10e5c44cb6158aa7fbc70e98da70f51ee72f29c7a28fc30bf37e992655f7",
- "blockNumber": "0x5",
- "contractAddress": "0xfdaa97661a584d977b4d3abb5370766ff5b86a18",
- "cumulativeGasUsed": "0xe01a",
- "effectiveGasPrice": "0xb2d05e00",
- "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
- "gasUsed": "0xe01a",
- "logs": [],
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "status": "0x1",
- "to": null,
- "transactionHash": "0x1b420e5f43f9620364d175d798acbd61d6f76ed8ea8ed7e0f93e4332ab8399b2",
- "transactionIndex": "0x0",
- "type": "0x1"
- }`,
+ file: "create-contract-with-access-list",
},
// 5. txhash empty
{
txHash: common.Hash{},
- want: `null`,
+ file: "txhash-empty",
},
// 6. txhash not found
{
txHash: common.HexToHash("deadbeef"),
- want: `null`,
+ file: "txhash-notfound",
+ },
+ // 7. blob tx
+ {
+ txHash: txHashes[5],
+ file: "blob-tx",
},
}
@@ -2004,13 +1774,7 @@ func TestRPCGetTransactionReceipt(t *testing.T) {
t.Errorf("test %d: want no error, have %v", i, err)
continue
}
- data, err := json.Marshal(result)
- if err != nil {
- t.Errorf("test %d: json marshal error", i)
- continue
- }
- want, have := tt.want, string(data)
- require.JSONEqf(t, want, have, "test %d: json not match, want: %s, have: %s", i, want, have)
+ testRPCResponseWithFile(t, i, result, "eth_getTransactionReceipt", tt.file)
}
}
@@ -2018,7 +1782,7 @@ func TestRPCGetBlockReceipts(t *testing.T) {
t.Parallel()
var (
- genBlocks = 5
+ genBlocks = 6
backend, _ = setupReceiptBackend(t, genBlocks)
api = NewBlockChainAPI(backend)
)
@@ -2034,62 +1798,67 @@ func TestRPCGetBlockReceipts(t *testing.T) {
var testSuite = []struct {
test rpc.BlockNumberOrHash
- want string
+ file string
}{
// 0. block without any txs(hash)
{
test: rpc.BlockNumberOrHashWithHash(blockHashes[0], false),
- want: `[]`,
+ file: "number-0",
},
// 1. block without any txs(number)
{
test: rpc.BlockNumberOrHashWithNumber(0),
- want: `[]`,
+ file: "number-1",
},
// 2. earliest tag
{
test: rpc.BlockNumberOrHashWithNumber(rpc.EarliestBlockNumber),
- want: `[]`,
+ file: "tag-earliest",
},
// 3. latest tag
{
test: rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber),
- want: `[{"blockHash":"0xde2f10e5c44cb6158aa7fbc70e98da70f51ee72f29c7a28fc30bf37e992655f7","blockNumber":"0x5","contractAddress":"0xfdaa97661a584d977b4d3abb5370766ff5b86a18","cumulativeGasUsed":"0xe01a","effectiveGasPrice":"0xb2d05e00","from":"0x703c4b2bd70c169f5717101caee543299fc946c7","gasUsed":"0xe01a","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":null,"transactionHash":"0x1b420e5f43f9620364d175d798acbd61d6f76ed8ea8ed7e0f93e4332ab8399b2","transactionIndex":"0x0","type":"0x1"}]`,
+ file: "tag-latest",
},
// 4. block with legacy transfer tx(hash)
{
test: rpc.BlockNumberOrHashWithHash(blockHashes[1], false),
- want: `[{"blockHash":"0xcf5e82a62028debbeecba9a6a7cbeaed67b431800a4250a60943101a611d179a","blockNumber":"0x1","contractAddress":null,"cumulativeGasUsed":"0x5208","effectiveGasPrice":"0xb2d05e00","from":"0x703c4b2bd70c169f5717101caee543299fc946c7","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":"0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e","transactionHash":"0xf875edfe4579e2a5e1ad45c4d802c1e5abbca19561398e9c58c41dabd86a3aa6","transactionIndex":"0x0","type":"0x0"}]`,
+ file: "block-with-legacy-transfer-tx",
},
// 5. block with contract create tx(number)
{
test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(2)),
- want: `[{"blockHash":"0x739ed5e516e6b2b0fa16f22a335a371a1fac616bc394b7454fdf07a0fd10db30","blockNumber":"0x2","contractAddress":"0xae9bea628c4ce503dcfd7e305cab4e29e7476592","cumulativeGasUsed":"0xcf4e","effectiveGasPrice":"0xb2d05e00","from":"0x703c4b2bd70c169f5717101caee543299fc946c7","gasUsed":"0xcf4e","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":null,"transactionHash":"0xd7a2d56946b13872c0064d0af803fa7b2a7f6be74023cf9ce6337c0dc5b06813","transactionIndex":"0x0","type":"0x0"}]`,
+ file: "block-with-contract-create-tx",
},
// 6. block with legacy contract call tx(hash)
{
test: rpc.BlockNumberOrHashWithHash(blockHashes[3], false),
- want: `[{"blockHash":"0x07545649b5df1cd84de57265fa5acdb473a1a033bf51c43d61c6183b13487f19","blockNumber":"0x3","contractAddress":null,"cumulativeGasUsed":"0x5e28","effectiveGasPrice":"0xb2d05e00","from":"0x703c4b2bd70c169f5717101caee543299fc946c7","gasUsed":"0x5e28","logs":[{"address":"0x0000000000000000000000000000000000031ec7","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7","0x0000000000000000000000000000000000000000000000000000000000000003"],"data":"0x000000000000000000000000000000000000000000000000000000000000000d","blockNumber":"0x3","transactionHash":"0x2c660ba194f0e2de5bbb4e2f38a15fe9f263dd5e5c524d45be4834755b2c2a8c","transactionIndex":"0x0","blockHash":"0x07545649b5df1cd84de57265fa5acdb473a1a033bf51c43d61c6183b13487f19","logIndex":"0x0","removed":false}],"logsBloom":"0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000","status":"0x1","to":"0x0000000000000000000000000000000000031ec7","transactionHash":"0x2c660ba194f0e2de5bbb4e2f38a15fe9f263dd5e5c524d45be4834755b2c2a8c","transactionIndex":"0x0","type":"0x0"}]`,
+ file: "block-with-legacy-contract-call-tx",
},
// 7. block with dynamic fee tx(number)
{
test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(4)),
- want: `[{"blockHash":"0x2a78cbbc361402d352baf99afcd8d57b34df182ed44819ca6bf0a1ceedc94a1e","blockNumber":"0x4","contractAddress":null,"cumulativeGasUsed":"0x538d","effectiveGasPrice":"0xb2d05e00","from":"0x703c4b2bd70c169f5717101caee543299fc946c7","gasUsed":"0x538d","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x0","to":"0x0000000000000000000000000000000000031ec7","transactionHash":"0x395e5326a196a53e961b8f406b706049288d8f92e467f95677ced981fa3a40ce","transactionIndex":"0x0","type":"0x2"}]`,
+ file: "block-with-dynamic-fee-tx",
},
// 8. block is empty
{
test: rpc.BlockNumberOrHashWithHash(common.Hash{}, false),
- want: `null`,
+ file: "hash-empty",
},
// 9. block is not found
{
test: rpc.BlockNumberOrHashWithHash(common.HexToHash("deadbeef"), false),
- want: `null`,
+ file: "hash-notfound",
},
// 10. block is not found
{
test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(genBlocks + 1)),
- want: `null`,
+ file: "block-notfound",
+ },
+ // 11. block with blob tx
+ {
+ test: rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(6)),
+ file: "block-with-blob-tx",
},
}
@@ -2103,12 +1872,23 @@ func TestRPCGetBlockReceipts(t *testing.T) {
t.Errorf("test %d: want no error, have %v", i, err)
continue
}
- data, err := json.Marshal(result)
- if err != nil {
- t.Errorf("test %d: json marshal error", i)
- continue
- }
- want, have := tt.want, string(data)
- require.JSONEqf(t, want, have, "test %d: json not match, want: %s, have: %s", i, want, have)
+ testRPCResponseWithFile(t, i, result, "eth_getBlockReceipts", tt.file)
+ }
+}
+
+func testRPCResponseWithFile(t *testing.T, testid int, result interface{}, rpc string, file string) {
+ data, err := json.MarshalIndent(result, "", " ")
+ if err != nil {
+ t.Errorf("test %d: json marshal error", testid)
+ return
+ }
+ outputFile := filepath.Join("testdata", fmt.Sprintf("%s-%s.json", rpc, file))
+ if os.Getenv("WRITE_TEST_FILES") != "" {
+ os.WriteFile(outputFile, data, 0644)
+ }
+ want, err := os.ReadFile(outputFile)
+ if err != nil {
+ t.Fatalf("error reading expected test file: %s output: %v", outputFile, err)
}
+ require.JSONEqf(t, string(want), string(data), "test %d: json not match, want: %s, have: %s", testid, string(want), string(data))
}
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index d71d7e8eba..0f37e4f0f5 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -70,14 +70,14 @@ type Backend interface {
PendingBlockAndReceipts() (*types.Block, types.Receipts)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int
- GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error)
+ GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription
// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error
- GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
+ GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
@@ -101,6 +101,25 @@ type Backend interface {
ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)
SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription
SubscribeNewVoteEvent(chan<- core.NewVoteEvent) event.Subscription
+
+ // MevRunning return true if mev is running
+ MevRunning() bool
+ // MevParams returns the static params of mev
+ MevParams() *types.MevParams
+ // StartMev starts mev
+ StartMev()
+ // StopMev stops mev
+ StopMev()
+ // AddBuilder adds a builder to the bid simulator.
+ AddBuilder(builder common.Address, builderUrl string) error
+ // RemoveBuilder removes a builder from the bid simulator.
+ RemoveBuilder(builder common.Address) error
+ // SendBid receives bid from the builders.
+ SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error)
+ // BestBidGasFee returns the gas fee of the best bid for the given parent hash.
+ BestBidGasFee(parentHash common.Hash) *big.Int
+ // MinerInTurn returns true if the validator is in turn to propose the block.
+ MinerInTurn() bool
}
func GetAPIs(apiBackend Backend) []rpc.API {
@@ -127,6 +146,9 @@ func GetAPIs(apiBackend Backend) []rpc.API {
}, {
Namespace: "personal",
Service: NewPersonalAccountAPI(apiBackend, nonceLock),
+ }, {
+ Namespace: "mev",
+ Service: NewMevAPI(apiBackend),
},
}
}
diff --git a/internal/ethapi/errors.go b/internal/ethapi/errors.go
new file mode 100644
index 0000000000..b5e668a805
--- /dev/null
+++ b/internal/ethapi/errors.go
@@ -0,0 +1,78 @@
+// Copyright 2024 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package ethapi
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/vm"
+)
+
+// revertError is an API error that encompasses an EVM revert with JSON error
+// code and a binary data blob.
+type revertError struct {
+ error
+ reason string // revert reason hex encoded
+}
+
+// ErrorCode returns the JSON error code for a revert.
+// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
+func (e *revertError) ErrorCode() int {
+ return 3
+}
+
+// ErrorData returns the hex encoded revert reason.
+func (e *revertError) ErrorData() interface{} {
+ return e.reason
+}
+
+// newRevertError creates a revertError instance with the provided revert data.
+func newRevertError(revert []byte) *revertError {
+ err := vm.ErrExecutionReverted
+
+ reason, errUnpack := abi.UnpackRevert(revert)
+ if errUnpack == nil {
+ err = fmt.Errorf("%w: %v", vm.ErrExecutionReverted, reason)
+ }
+ return &revertError{
+ error: err,
+ reason: hexutil.Encode(revert),
+ }
+}
+
+// TxIndexingError is an API error that indicates the transaction indexing is not
+// fully finished yet with JSON error code and a binary data blob.
+type TxIndexingError struct{}
+
+// NewTxIndexingError creates a TxIndexingError instance.
+func NewTxIndexingError() *TxIndexingError { return &TxIndexingError{} }
+
+// Error implement error interface, returning the error message.
+func (e *TxIndexingError) Error() string {
+ return "transaction indexing is in progress"
+}
+
+// ErrorCode returns the JSON error code for a revert.
+// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
+func (e *TxIndexingError) ErrorCode() int {
+ return -32000 // to be decided
+}
+
+// ErrorData returns the hex encoded revert reason.
+func (e *TxIndexingError) ErrorData() interface{} { return "transaction indexing is in progress" }
diff --git a/internal/ethapi/testdata/eth_getBlockByHash-hash-1.json b/internal/ethapi/testdata/eth_getBlockByHash-hash-1.json
new file mode 100644
index 0000000000..73da1b1752
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByHash-hash-1.json
@@ -0,0 +1,25 @@
+{
+ "baseFeePerGas": "0x342770c0",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xeeb5c1852740ca4bbe65b0f57baf80634ed12a2b44affe30eec3fb54437c3926",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x1",
+ "parentHash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x26a",
+ "stateRoot": "0x4acfcd1a6ab9f5e62411021ecd8a749976ae50b0590e967471264b372d7ac55b",
+ "timestamp": "0xa",
+ "totalDifficulty": "0x1",
+ "transactions": [
+ "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e"
+ ],
+ "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7",
+ "uncles": []
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByHash-hash-empty-fullTx.json b/internal/ethapi/testdata/eth_getBlockByHash-hash-empty-fullTx.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByHash-hash-empty-fullTx.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json b/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json
new file mode 100644
index 0000000000..d2bdbacd73
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByHash-hash-genesis.json
@@ -0,0 +1,23 @@
+{
+ "baseFeePerGas": "0x3b9aca00",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x0",
+ "hash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x200",
+ "stateRoot": "0xd883f48b83cc9c1e8389453beb4ad4e572462eec049ca4fffbe16ecefb3fe937",
+ "timestamp": "0x0",
+ "totalDifficulty": "0x1",
+ "transactions": [],
+ "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncles": []
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByHash-hash-latest-1-fullTx.json b/internal/ethapi/testdata/eth_getBlockByHash-hash-latest-1-fullTx.json
new file mode 100644
index 0000000000..8e0748def9
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByHash-hash-latest-1-fullTx.json
@@ -0,0 +1,41 @@
+{
+ "baseFeePerGas": "0x121a9cca",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x9",
+ "parentHash": "0xcd7d78eaa8b0ddbd2956fc37e1883c30df27b43e8cc9a982020310656736637c",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x26a",
+ "stateRoot": "0x78b2b19ef1a0276dbbc23a875dbf60ae5d10dafa0017098473c4871abd3e7b5c",
+ "timestamp": "0x5a",
+ "totalDifficulty": "0x1",
+ "transactions": [
+ {
+ "blockHash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "blockNumber": "0x9",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gas": "0x5208",
+ "gasPrice": "0x121a9cca",
+ "hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725",
+ "input": "0x",
+ "nonce": "0x8",
+ "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
+ "transactionIndex": "0x0",
+ "value": "0x3e8",
+ "type": "0x0",
+ "v": "0x1b",
+ "r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd",
+ "s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d"
+ }
+ ],
+ "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5",
+ "uncles": []
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByHash-hash-latest.json b/internal/ethapi/testdata/eth_getBlockByHash-hash-latest.json
new file mode 100644
index 0000000000..6e914e37d0
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByHash-hash-latest.json
@@ -0,0 +1,25 @@
+{
+ "baseFeePerGas": "0xfdc7303",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xa063415a5020f1569fae73ecb0d37bc5649ebe86d59e764a389eb37814bd42cb",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0xa",
+ "parentHash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x26a",
+ "stateRoot": "0x118f1433ae23c4d1c12f5bd652baddb72611c55ac1cd6af6620d209db222f9e6",
+ "timestamp": "0x64",
+ "totalDifficulty": "0x1",
+ "transactions": [
+ "0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644"
+ ],
+ "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445",
+ "uncles": []
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByHash-hash-pending-fullTx.json b/internal/ethapi/testdata/eth_getBlockByHash-hash-pending-fullTx.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByHash-hash-pending-fullTx.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByHash-hash-pending.json b/internal/ethapi/testdata/eth_getBlockByHash-hash-pending.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByHash-hash-pending.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json b/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json
new file mode 100644
index 0000000000..d2bdbacd73
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-number-0.json
@@ -0,0 +1,23 @@
+{
+ "baseFeePerGas": "0x3b9aca00",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x0",
+ "hash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x200",
+ "stateRoot": "0xd883f48b83cc9c1e8389453beb4ad4e572462eec049ca4fffbe16ecefb3fe937",
+ "timestamp": "0x0",
+ "totalDifficulty": "0x1",
+ "transactions": [],
+ "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncles": []
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-number-1.json b/internal/ethapi/testdata/eth_getBlockByNumber-number-1.json
new file mode 100644
index 0000000000..73da1b1752
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-number-1.json
@@ -0,0 +1,25 @@
+{
+ "baseFeePerGas": "0x342770c0",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xeeb5c1852740ca4bbe65b0f57baf80634ed12a2b44affe30eec3fb54437c3926",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x1",
+ "parentHash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x26a",
+ "stateRoot": "0x4acfcd1a6ab9f5e62411021ecd8a749976ae50b0590e967471264b372d7ac55b",
+ "timestamp": "0xa",
+ "totalDifficulty": "0x1",
+ "transactions": [
+ "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e"
+ ],
+ "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7",
+ "uncles": []
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-number-latest+1.json b/internal/ethapi/testdata/eth_getBlockByNumber-number-latest+1.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-number-latest+1.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-number-latest-1.json b/internal/ethapi/testdata/eth_getBlockByNumber-number-latest-1.json
new file mode 100644
index 0000000000..8e0748def9
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-number-latest-1.json
@@ -0,0 +1,41 @@
+{
+ "baseFeePerGas": "0x121a9cca",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x9",
+ "parentHash": "0xcd7d78eaa8b0ddbd2956fc37e1883c30df27b43e8cc9a982020310656736637c",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x26a",
+ "stateRoot": "0x78b2b19ef1a0276dbbc23a875dbf60ae5d10dafa0017098473c4871abd3e7b5c",
+ "timestamp": "0x5a",
+ "totalDifficulty": "0x1",
+ "transactions": [
+ {
+ "blockHash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "blockNumber": "0x9",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gas": "0x5208",
+ "gasPrice": "0x121a9cca",
+ "hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725",
+ "input": "0x",
+ "nonce": "0x8",
+ "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
+ "transactionIndex": "0x0",
+ "value": "0x3e8",
+ "type": "0x0",
+ "v": "0x1b",
+ "r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd",
+ "s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d"
+ }
+ ],
+ "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5",
+ "uncles": []
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-tag-latest.json b/internal/ethapi/testdata/eth_getBlockByNumber-tag-latest.json
new file mode 100644
index 0000000000..6e914e37d0
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-tag-latest.json
@@ -0,0 +1,25 @@
+{
+ "baseFeePerGas": "0xfdc7303",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xa063415a5020f1569fae73ecb0d37bc5649ebe86d59e764a389eb37814bd42cb",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0xa",
+ "parentHash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x26a",
+ "stateRoot": "0x118f1433ae23c4d1c12f5bd652baddb72611c55ac1cd6af6620d209db222f9e6",
+ "timestamp": "0x64",
+ "totalDifficulty": "0x1",
+ "transactions": [
+ "0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644"
+ ],
+ "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445",
+ "uncles": []
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending-fullTx.json b/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending-fullTx.json
new file mode 100644
index 0000000000..1d524d6ece
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending-fullTx.json
@@ -0,0 +1,50 @@
+{
+ "difficulty": "0x0",
+ "extraData": "0x",
+ "gasLimit": "0x0",
+ "gasUsed": "0x0",
+ "hash": null,
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": null,
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": null,
+ "number": "0xb",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x256",
+ "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp": "0x2a",
+ "totalDifficulty": null,
+ "transactions": [
+ {
+ "blockHash": "0x6cebd9f966ea686f44b981685e3f0eacea28591a7a86d7fbbe521a86e9f81165",
+ "blockNumber": "0xb",
+ "from": "0x0000000000000000000000000000000000000000",
+ "gas": "0x457",
+ "gasPrice": "0x2b67",
+ "hash": "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298",
+ "input": "0x111111",
+ "nonce": "0xb",
+ "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
+ "transactionIndex": "0x0",
+ "value": "0x6f",
+ "type": "0x0",
+ "chainId": "0x7fffffffffffffee",
+ "v": "0x0",
+ "r": "0x0",
+ "s": "0x0"
+ }
+ ],
+ "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
+ "uncles": [],
+ "withdrawals": [
+ {
+ "index": "0x0",
+ "validatorIndex": "0x1",
+ "address": "0x1234000000000000000000000000000000000000",
+ "amount": "0xa"
+ }
+ ],
+ "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending.json b/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending.json
new file mode 100644
index 0000000000..c0e2b07bb8
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-tag-pending.json
@@ -0,0 +1,33 @@
+{
+ "difficulty": "0x0",
+ "extraData": "0x",
+ "gasLimit": "0x0",
+ "gasUsed": "0x0",
+ "hash": null,
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": null,
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": null,
+ "number": "0xb",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x256",
+ "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp": "0x2a",
+ "totalDifficulty": null,
+ "transactions": [
+ "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298"
+ ],
+ "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
+ "uncles": [],
+ "withdrawals": [
+ {
+ "index": "0x0",
+ "validatorIndex": "0x1",
+ "address": "0x1234000000000000000000000000000000000000",
+ "amount": "0xa"
+ }
+ ],
+ "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-block-notfound.json b/internal/ethapi/testdata/eth_getBlockReceipts-block-notfound.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-block-notfound.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json
new file mode 100644
index 0000000000..09fb734d39
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json
@@ -0,0 +1,20 @@
+[
+ {
+ "blobGasPrice": "0x1",
+ "blobGasUsed": "0x20000",
+ "blockHash": "0xd1392771155ce83f6403c6af275efd22bed567030c21168fcc9dbad5004eb245",
+ "blockNumber": "0x6",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x5208",
+ "effectiveGasPrice": "0x1b09d63b",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x5208",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x1",
+ "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
+ "transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f",
+ "transactionIndex": "0x0",
+ "type": "0x3"
+ }
+]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-block-with-contract-create-tx.json b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-contract-create-tx.json
new file mode 100644
index 0000000000..ab14d56394
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-contract-create-tx.json
@@ -0,0 +1,18 @@
+[
+ {
+ "blockHash": "0x56ea26cf955d7f2e08e194ad212ca4d5f99ee8e0b19dec3c71d8faafa33b1d22",
+ "blockNumber": "0x2",
+ "contractAddress": "0xae9bea628c4ce503dcfd7e305cab4e29e7476592",
+ "cumulativeGasUsed": "0xcf50",
+ "effectiveGasPrice": "0x2db16291",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0xcf50",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x1",
+ "to": null,
+ "transactionHash": "0x340e58cda5086495010b571fe25067fecc9954dc4ee3cedece00691fa3f5904a",
+ "transactionIndex": "0x0",
+ "type": "0x0"
+ }
+]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-block-with-dynamic-fee-tx.json b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-dynamic-fee-tx.json
new file mode 100644
index 0000000000..9e137e241f
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-dynamic-fee-tx.json
@@ -0,0 +1,18 @@
+[
+ {
+ "blockHash": "0xf41e7a7a716382f20464cf76c6ae1fa701e9d32f5cc550ebfd2391b9642ae6bc",
+ "blockNumber": "0x4",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x538d",
+ "effectiveGasPrice": "0x2325c42f",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x538d",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x0",
+ "to": "0x0000000000000000000000000000000000031ec7",
+ "transactionHash": "0xdcde2574628c9d7dff22b9afa19f235959a924ceec65a9df903a517ae91f5c84",
+ "transactionIndex": "0x0",
+ "type": "0x2"
+ }
+]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-contract-call-tx.json b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-contract-call-tx.json
new file mode 100644
index 0000000000..1db7d02b1c
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-contract-call-tx.json
@@ -0,0 +1,34 @@
+[
+ {
+ "blockHash": "0xa1410af902e98b32e0bbe464f8637ff464f1d4344b585127d2ce71f9cb39cb8a",
+ "blockNumber": "0x3",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x5e28",
+ "effectiveGasPrice": "0x281c2585",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x5e28",
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000031ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7",
+ "0x0000000000000000000000000000000000000000000000000000000000000003"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "blockNumber": "0x3",
+ "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287",
+ "transactionIndex": "0x0",
+ "blockHash": "0xa1410af902e98b32e0bbe464f8637ff464f1d4344b585127d2ce71f9cb39cb8a",
+ "logIndex": "0x0",
+ "removed": false
+ }
+ ],
+ "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000",
+ "status": "0x1",
+ "to": "0x0000000000000000000000000000000000031ec7",
+ "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287",
+ "transactionIndex": "0x0",
+ "type": "0x0"
+ }
+]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-transfer-tx.json b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-transfer-tx.json
new file mode 100644
index 0000000000..9a55927839
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-legacy-transfer-tx.json
@@ -0,0 +1,18 @@
+[
+ {
+ "blockHash": "0x797d0c5603eccb33cc8ebd1300e977746512ec49e6b89087c7aad28ff760a26f",
+ "blockNumber": "0x1",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x5208",
+ "effectiveGasPrice": "0x342770c0",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x5208",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x1",
+ "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
+ "transactionHash": "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e",
+ "transactionIndex": "0x0",
+ "type": "0x0"
+ }
+]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-hash-empty.json b/internal/ethapi/testdata/eth_getBlockReceipts-hash-empty.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-hash-empty.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-hash-notfound.json b/internal/ethapi/testdata/eth_getBlockReceipts-hash-notfound.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-hash-notfound.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-number-0.json b/internal/ethapi/testdata/eth_getBlockReceipts-number-0.json
new file mode 100644
index 0000000000..0637a088a0
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-number-0.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-number-1.json b/internal/ethapi/testdata/eth_getBlockReceipts-number-1.json
new file mode 100644
index 0000000000..0637a088a0
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-number-1.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-tag-earliest.json b/internal/ethapi/testdata/eth_getBlockReceipts-tag-earliest.json
new file mode 100644
index 0000000000..0637a088a0
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-tag-earliest.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json b/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json
new file mode 100644
index 0000000000..09fb734d39
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json
@@ -0,0 +1,20 @@
+[
+ {
+ "blobGasPrice": "0x1",
+ "blobGasUsed": "0x20000",
+ "blockHash": "0xd1392771155ce83f6403c6af275efd22bed567030c21168fcc9dbad5004eb245",
+ "blockNumber": "0x6",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x5208",
+ "effectiveGasPrice": "0x1b09d63b",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x5208",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x1",
+ "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
+ "transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f",
+ "transactionIndex": "0x0",
+ "type": "0x3"
+ }
+]
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json b/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json
new file mode 100644
index 0000000000..1bd68888b6
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByHash-hash-0.json
@@ -0,0 +1,20 @@
+{
+ "baseFeePerGas": "0x3b9aca00",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x0",
+ "hash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0xd883f48b83cc9c1e8389453beb4ad4e572462eec049ca4fffbe16ecefb3fe937",
+ "timestamp": "0x0",
+ "totalDifficulty": "0x1",
+ "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByHash-hash-1.json b/internal/ethapi/testdata/eth_getHeaderByHash-hash-1.json
new file mode 100644
index 0000000000..cf662cad75
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByHash-hash-1.json
@@ -0,0 +1,20 @@
+{
+ "baseFeePerGas": "0x342770c0",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xeeb5c1852740ca4bbe65b0f57baf80634ed12a2b44affe30eec3fb54437c3926",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x1",
+ "parentHash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0x4acfcd1a6ab9f5e62411021ecd8a749976ae50b0590e967471264b372d7ac55b",
+ "timestamp": "0xa",
+ "totalDifficulty": "0x1",
+ "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByHash-hash-empty.json b/internal/ethapi/testdata/eth_getHeaderByHash-hash-empty.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByHash-hash-empty.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest-1.json b/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest-1.json
new file mode 100644
index 0000000000..4721dd1e7a
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest-1.json
@@ -0,0 +1,20 @@
+{
+ "baseFeePerGas": "0x121a9cca",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x9",
+ "parentHash": "0xcd7d78eaa8b0ddbd2956fc37e1883c30df27b43e8cc9a982020310656736637c",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0x78b2b19ef1a0276dbbc23a875dbf60ae5d10dafa0017098473c4871abd3e7b5c",
+ "timestamp": "0x5a",
+ "totalDifficulty": "0x1",
+ "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest.json b/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest.json
new file mode 100644
index 0000000000..4dd5909159
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByHash-hash-latest.json
@@ -0,0 +1,20 @@
+{
+ "baseFeePerGas": "0xfdc7303",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xa063415a5020f1569fae73ecb0d37bc5649ebe86d59e764a389eb37814bd42cb",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0xa",
+ "parentHash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0x118f1433ae23c4d1c12f5bd652baddb72611c55ac1cd6af6620d209db222f9e6",
+ "timestamp": "0x64",
+ "totalDifficulty": "0x1",
+ "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByHash-hash-pending.json b/internal/ethapi/testdata/eth_getHeaderByHash-hash-pending.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByHash-hash-pending.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json b/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json
new file mode 100644
index 0000000000..1bd68888b6
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByNumber-number-0.json
@@ -0,0 +1,20 @@
+{
+ "baseFeePerGas": "0x3b9aca00",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x0",
+ "hash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0xd883f48b83cc9c1e8389453beb4ad4e572462eec049ca4fffbe16ecefb3fe937",
+ "timestamp": "0x0",
+ "totalDifficulty": "0x1",
+ "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByNumber-number-1.json b/internal/ethapi/testdata/eth_getHeaderByNumber-number-1.json
new file mode 100644
index 0000000000..cf662cad75
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByNumber-number-1.json
@@ -0,0 +1,20 @@
+{
+ "baseFeePerGas": "0x342770c0",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xeeb5c1852740ca4bbe65b0f57baf80634ed12a2b44affe30eec3fb54437c3926",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x1",
+ "parentHash": "0x98e056de84de969782b238b4509b32814627ba443ea622054a79c2bc7e4d92c7",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0x4acfcd1a6ab9f5e62411021ecd8a749976ae50b0590e967471264b372d7ac55b",
+ "timestamp": "0xa",
+ "totalDifficulty": "0x1",
+ "transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest+1.json b/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest+1.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest+1.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest-1.json b/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest-1.json
new file mode 100644
index 0000000000..4721dd1e7a
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByNumber-number-latest-1.json
@@ -0,0 +1,20 @@
+{
+ "baseFeePerGas": "0x121a9cca",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0x9",
+ "parentHash": "0xcd7d78eaa8b0ddbd2956fc37e1883c30df27b43e8cc9a982020310656736637c",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0x78b2b19ef1a0276dbbc23a875dbf60ae5d10dafa0017098473c4871abd3e7b5c",
+ "timestamp": "0x5a",
+ "totalDifficulty": "0x1",
+ "transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByNumber-tag-latest.json b/internal/ethapi/testdata/eth_getHeaderByNumber-tag-latest.json
new file mode 100644
index 0000000000..4dd5909159
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByNumber-tag-latest.json
@@ -0,0 +1,20 @@
+{
+ "baseFeePerGas": "0xfdc7303",
+ "difficulty": "0x20000",
+ "extraData": "0x",
+ "gasLimit": "0x47e7c4",
+ "gasUsed": "0x5208",
+ "hash": "0xa063415a5020f1569fae73ecb0d37bc5649ebe86d59e764a389eb37814bd42cb",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "0xa",
+ "parentHash": "0xedb9ccf3a85f67c095ad48abfb0fa09d47179bb0f902078d289042d12428aca5",
+ "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0x118f1433ae23c4d1c12f5bd652baddb72611c55ac1cd6af6620d209db222f9e6",
+ "timestamp": "0x64",
+ "totalDifficulty": "0x1",
+ "transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getHeaderByNumber-tag-pending.json b/internal/ethapi/testdata/eth_getHeaderByNumber-tag-pending.json
new file mode 100644
index 0000000000..da177f2189
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getHeaderByNumber-tag-pending.json
@@ -0,0 +1,20 @@
+{
+ "difficulty": "0x0",
+ "extraData": "0x",
+ "gasLimit": "0x0",
+ "gasUsed": "0x0",
+ "hash": null,
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": null,
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": null,
+ "number": "0xb",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "timestamp": "0x2a",
+ "totalDifficulty": null,
+ "transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
+ "withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getTransactionReceipt-blob-tx.json b/internal/ethapi/testdata/eth_getTransactionReceipt-blob-tx.json
new file mode 100644
index 0000000000..58f5657429
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getTransactionReceipt-blob-tx.json
@@ -0,0 +1,18 @@
+{
+ "blobGasPrice": "0x1",
+ "blobGasUsed": "0x20000",
+ "blockHash": "0xd1392771155ce83f6403c6af275efd22bed567030c21168fcc9dbad5004eb245",
+ "blockNumber": "0x6",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x5208",
+ "effectiveGasPrice": "0x1b09d63b",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x5208",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x1",
+ "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
+ "transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f",
+ "transactionIndex": "0x0",
+ "type": "0x3"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-tx.json b/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-tx.json
new file mode 100644
index 0000000000..48aa567f23
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-tx.json
@@ -0,0 +1,16 @@
+{
+ "blockHash": "0x56ea26cf955d7f2e08e194ad212ca4d5f99ee8e0b19dec3c71d8faafa33b1d22",
+ "blockNumber": "0x2",
+ "contractAddress": "0xae9bea628c4ce503dcfd7e305cab4e29e7476592",
+ "cumulativeGasUsed": "0xcf50",
+ "effectiveGasPrice": "0x2db16291",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0xcf50",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x1",
+ "to": null,
+ "transactionHash": "0x340e58cda5086495010b571fe25067fecc9954dc4ee3cedece00691fa3f5904a",
+ "transactionIndex": "0x0",
+ "type": "0x0"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-with-access-list.json b/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-with-access-list.json
new file mode 100644
index 0000000000..a679972b8e
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-with-access-list.json
@@ -0,0 +1,16 @@
+{
+ "blockHash": "0x69bf6ba924d95b6c50b0357768e5c892bd1b00cdf2f97e2e81fc06a76dfa57e3",
+ "blockNumber": "0x5",
+ "contractAddress": "0xfdaa97661a584d977b4d3abb5370766ff5b86a18",
+ "cumulativeGasUsed": "0xe01c",
+ "effectiveGasPrice": "0x1ecb3fb4",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0xe01c",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x1",
+ "to": null,
+ "transactionHash": "0xb5a1148819cfdfff9bfe70035524fec940eb735d89b76960b97751d01ae2a9f2",
+ "transactionIndex": "0x0",
+ "type": "0x1"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getTransactionReceipt-dynamic-tx-with-logs.json b/internal/ethapi/testdata/eth_getTransactionReceipt-dynamic-tx-with-logs.json
new file mode 100644
index 0000000000..1cd5656d6f
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getTransactionReceipt-dynamic-tx-with-logs.json
@@ -0,0 +1,16 @@
+{
+ "blockHash": "0xf41e7a7a716382f20464cf76c6ae1fa701e9d32f5cc550ebfd2391b9642ae6bc",
+ "blockNumber": "0x4",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x538d",
+ "effectiveGasPrice": "0x2325c42f",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x538d",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x0",
+ "to": "0x0000000000000000000000000000000000031ec7",
+ "transactionHash": "0xdcde2574628c9d7dff22b9afa19f235959a924ceec65a9df903a517ae91f5c84",
+ "transactionIndex": "0x0",
+ "type": "0x2"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getTransactionReceipt-normal-transfer-tx.json b/internal/ethapi/testdata/eth_getTransactionReceipt-normal-transfer-tx.json
new file mode 100644
index 0000000000..2400bd8252
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getTransactionReceipt-normal-transfer-tx.json
@@ -0,0 +1,16 @@
+{
+ "blockHash": "0x797d0c5603eccb33cc8ebd1300e977746512ec49e6b89087c7aad28ff760a26f",
+ "blockNumber": "0x1",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x5208",
+ "effectiveGasPrice": "0x342770c0",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x5208",
+ "logs": [],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": "0x1",
+ "to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
+ "transactionHash": "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e",
+ "transactionIndex": "0x0",
+ "type": "0x0"
+}
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-empty.json b/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-empty.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-empty.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-notfound.json b/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-notfound.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getTransactionReceipt-txhash-notfound.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/testdata/eth_getTransactionReceipt-with-logs.json b/internal/ethapi/testdata/eth_getTransactionReceipt-with-logs.json
new file mode 100644
index 0000000000..596bcdaa0d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getTransactionReceipt-with-logs.json
@@ -0,0 +1,32 @@
+{
+ "blockHash": "0xa1410af902e98b32e0bbe464f8637ff464f1d4344b585127d2ce71f9cb39cb8a",
+ "blockNumber": "0x3",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0x5e28",
+ "effectiveGasPrice": "0x281c2585",
+ "from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
+ "gasUsed": "0x5e28",
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000031ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7",
+ "0x0000000000000000000000000000000000000000000000000000000000000003"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000000000000d",
+ "blockNumber": "0x3",
+ "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287",
+ "transactionIndex": "0x0",
+ "blockHash": "0xa1410af902e98b32e0bbe464f8637ff464f1d4344b585127d2ce71f9cb39cb8a",
+ "logIndex": "0x0",
+ "removed": false
+ }
+ ],
+ "logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000",
+ "status": "0x1",
+ "to": "0x0000000000000000000000000000000000031ec7",
+ "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287",
+ "transactionIndex": "0x0",
+ "type": "0x0"
+}
\ No newline at end of file
diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go
index 1b22e8b496..333011d71f 100644
--- a/internal/ethapi/transaction_args.go
+++ b/internal/ethapi/transaction_args.go
@@ -26,10 +26,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/holiman/uint256"
)
// TransactionArgs represents the arguments to construct a new transaction
@@ -53,6 +55,10 @@ type TransactionArgs struct {
// Introduced by AccessListTxType transaction.
AccessList *types.AccessList `json:"accessList,omitempty"`
ChainID *hexutil.Big `json:"chainId,omitempty"`
+
+ // Introduced by EIP-4844.
+ BlobFeeCap *hexutil.Big `json:"maxFeePerBlobGas"`
+ BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
}
// from retrieves the transaction sender address.
@@ -92,6 +98,12 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) {
return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`)
}
+ if args.BlobHashes != nil && args.To == nil {
+ return errors.New(`blob transactions cannot have the form of a create transaction`)
+ }
+ if args.BlobHashes != nil && len(args.BlobHashes) == 0 {
+ return errors.New(`need at least 1 blob for a blob transaction`)
+ }
if args.To == nil && len(args.data()) == 0 {
return errors.New(`contract creation without any data provided`)
}
@@ -110,8 +122,8 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
Data: (*hexutil.Bytes)(&data),
AccessList: args.AccessList,
}
- pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
- estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, nil, b.RPCGasCap())
+ latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
+ estimated, err := DoEstimateGas(ctx, b, callArgs, latestBlockNr, nil, b.RPCGasCap())
if err != nil {
return err
}
@@ -137,27 +149,53 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
- // If the tx has completely specified a fee mechanism, no default is needed. This allows users
- // who are not yet synced past London to get defaults for other tx values. See
- // https://github.com/ethereum/go-ethereum/pull/23274 for more information.
+ // If the tx has completely specified a fee mechanism, no default is needed.
+ // This allows users who are not yet synced past London to get defaults for
+ // other tx values. See https://github.com/ethereum/go-ethereum/pull/23274
+ // for more information.
eip1559ParamsSet := args.MaxFeePerGas != nil && args.MaxPriorityFeePerGas != nil
- if (args.GasPrice != nil && !eip1559ParamsSet) || (args.GasPrice == nil && eip1559ParamsSet) {
- // Sanity check the EIP-1559 fee parameters if present.
- if args.GasPrice == nil && args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
+
+ // Sanity check the EIP-1559 fee parameters if present.
+ if args.GasPrice == nil && eip1559ParamsSet {
+ if args.MaxFeePerGas.ToInt().Sign() == 0 {
+ return errors.New("maxFeePerGas must be non-zero")
+ }
+ if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
}
- return nil
+ return nil // No need to set anything, user already set MaxFeePerGas and MaxPriorityFeePerGas
}
- // Now attempt to fill in default value depending on whether London is active or not.
+ // Sanity check the EIP-4844 fee parameters.
+ if args.BlobFeeCap != nil && args.BlobFeeCap.ToInt().Sign() == 0 {
+ return errors.New("maxFeePerBlobGas must be non-zero")
+ }
+ // Sanity check the non-EIP-1559 fee parameters.
head := b.CurrentHeader()
- if b.ChainConfig().IsLondon(head.Number) {
+ isLondon := b.ChainConfig().IsLondon(head.Number)
+ if args.GasPrice != nil && !eip1559ParamsSet {
+ // Zero gas-price is not allowed after London fork
+ if args.GasPrice.ToInt().Sign() == 0 && isLondon {
+ return errors.New("gasPrice must be non-zero after london fork")
+ }
+ return nil // No need to set anything, user already set GasPrice
+ }
+
+ // Now attempt to fill in default value depending on whether London is active or not.
+ if b.ChainConfig().IsCancun(head.Number, head.Time) {
+ if err := args.setCancunFeeDefaults(ctx, head, b); err != nil {
+ return err
+ }
+ } else if isLondon {
+ if args.BlobFeeCap != nil {
+ return errors.New("maxFeePerBlobGas is not valid before Cancun is active")
+ }
// London is active, set maxPriorityFeePerGas and maxFeePerGas.
if err := args.setLondonFeeDefaults(ctx, head, b); err != nil {
return err
}
} else {
- if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil {
- return errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active")
+ if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil || args.BlobFeeCap != nil {
+ return errors.New("maxFeePerGas and maxPriorityFeePerGas and maxFeePerBlobGas are not valid before London is active")
}
// London not active, set gas price.
price, err := b.SuggestGasTipCap(ctx)
@@ -169,6 +207,21 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro
return nil
}
+// setCancunFeeDefaults fills in reasonable default fee values for unspecified fields.
+func (args *TransactionArgs) setCancunFeeDefaults(ctx context.Context, head *types.Header, b Backend) error {
+ // Set maxFeePerBlobGas if it is missing.
+ if args.BlobHashes != nil && args.BlobFeeCap == nil {
+ // ExcessBlobGas must be set for a Cancun block.
+ blobBaseFee := eip4844.CalcBlobFee(*head.ExcessBlobGas)
+ // Set the max fee to be 2 times larger than the previous block's blob base fee.
+ // The additional slack allows the tx to not become invalidated if the base
+ // fee is rising.
+ val := new(big.Int).Mul(blobBaseFee, big.NewInt(2))
+ args.BlobFeeCap = (*hexutil.Big)(val)
+ }
+ return args.setLondonFeeDefaults(ctx, head, b)
+}
+
// setLondonFeeDefaults fills in reasonable default fee values for unspecified fields.
func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *types.Header, b Backend) error {
// Set maxPriorityFeePerGas if it is missing.
@@ -221,9 +274,10 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
gas = globalGasCap
}
var (
- gasPrice *big.Int
- gasFeeCap *big.Int
- gasTipCap *big.Int
+ gasPrice *big.Int
+ gasFeeCap *big.Int
+ gasTipCap *big.Int
+ blobFeeCap *big.Int
)
if baseFee == nil {
// If there's no basefee, then it must be a non-1559 execution
@@ -255,6 +309,11 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
}
}
}
+ if args.BlobFeeCap != nil {
+ blobFeeCap = args.BlobFeeCap.ToInt()
+ } else if args.BlobHashes != nil {
+ blobFeeCap = new(big.Int)
+ }
value := new(big.Int)
if args.Value != nil {
value = args.Value.ToInt()
@@ -274,6 +333,8 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
GasTipCap: gasTipCap,
Data: data,
AccessList: accessList,
+ BlobGasFeeCap: blobFeeCap,
+ BlobHashes: args.BlobHashes,
SkipAccountChecks: true,
}
return msg, nil
@@ -284,6 +345,24 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
func (args *TransactionArgs) toTransaction() *types.Transaction {
var data types.TxData
switch {
+ case args.BlobHashes != nil:
+ al := types.AccessList{}
+ if args.AccessList != nil {
+ al = *args.AccessList
+ }
+ data = &types.BlobTx{
+ To: *args.To,
+ ChainID: uint256.MustFromBig((*big.Int)(args.ChainID)),
+ Nonce: uint64(*args.Nonce),
+ Gas: uint64(*args.Gas),
+ GasFeeCap: uint256.MustFromBig((*big.Int)(args.MaxFeePerGas)),
+ GasTipCap: uint256.MustFromBig((*big.Int)(args.MaxPriorityFeePerGas)),
+ Value: uint256.MustFromBig((*big.Int)(args.Value)),
+ Data: args.data(),
+ AccessList: al,
+ BlobHashes: args.BlobHashes,
+ BlobFeeCap: uint256.MustFromBig((*big.Int)(args.BlobFeeCap)),
+ }
case args.MaxFeePerGas != nil:
al := types.AccessList{}
if args.AccessList != nil {
@@ -329,3 +408,8 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
func (args *TransactionArgs) ToTransaction() *types.Transaction {
return args.toTransaction()
}
+
+// IsEIP4844 returns an indicator if the args contains EIP4844 fields.
+func (args *TransactionArgs) IsEIP4844() bool {
+ return args.BlobHashes != nil || args.BlobFeeCap != nil
+}
diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go
index fc42df3ddb..7d1461d82e 100644
--- a/internal/ethapi/transaction_args_test.go
+++ b/internal/ethapi/transaction_args_test.go
@@ -43,15 +43,16 @@ import (
// TestSetFeeDefaults tests the logic for filling in default fee values works as expected.
func TestSetFeeDefaults(t *testing.T) {
type test struct {
- name string
- isLondon bool
- in *TransactionArgs
- want *TransactionArgs
- err error
+ name string
+ fork string // options: legacy, london, cancun
+ in *TransactionArgs
+ want *TransactionArgs
+ err error
}
var (
b = newBackendMock()
+ zero = (*hexutil.Big)(big.NewInt(0))
fortytwo = (*hexutil.Big)(big.NewInt(42))
maxFee = (*hexutil.Big)(new(big.Int).Add(new(big.Int).Mul(b.current.BaseFee, big.NewInt(2)), fortytwo.ToInt()))
al = &types.AccessList{types.AccessTuple{Address: common.Address{0xaa}, StorageKeys: []common.Hash{{0x01}}}}
@@ -61,51 +62,65 @@ func TestSetFeeDefaults(t *testing.T) {
// Legacy txs
{
"legacy tx pre-London",
- false,
+ "legacy",
&TransactionArgs{},
&TransactionArgs{GasPrice: fortytwo},
nil,
},
+ {
+ "legacy tx pre-London with zero price",
+ "legacy",
+ &TransactionArgs{GasPrice: zero},
+ &TransactionArgs{GasPrice: zero},
+ nil,
+ },
{
"legacy tx post-London, explicit gas price",
- true,
+ "london",
&TransactionArgs{GasPrice: fortytwo},
&TransactionArgs{GasPrice: fortytwo},
nil,
},
+ {
+ "legacy tx post-London with zero price",
+ "london",
+ &TransactionArgs{GasPrice: zero},
+ nil,
+ errors.New("gasPrice must be non-zero after london fork"),
+ },
// Access list txs
{
"access list tx pre-London",
- false,
+ "legacy",
&TransactionArgs{AccessList: al},
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
nil,
},
{
"access list tx post-London, explicit gas price",
- false,
+ "legacy",
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
nil,
},
{
"access list tx post-London",
- true,
+ "london",
&TransactionArgs{AccessList: al},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"access list tx post-London, only max fee",
- true,
+ "london",
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"access list tx post-London, only priority fee",
- true,
+ "london",
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
@@ -114,84 +129,118 @@ func TestSetFeeDefaults(t *testing.T) {
// Dynamic fee txs
{
"dynamic tx post-London",
- true,
+ "london",
&TransactionArgs{},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic tx post-London, only max fee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic tx post-London, only priority fee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic fee tx pre-London, maxFee set",
- false,
+ "legacy",
&TransactionArgs{MaxFeePerGas: maxFee},
nil,
- errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
+ errors.New("maxFeePerGas and maxPriorityFeePerGas and maxFeePerBlobGas are not valid before London is active"),
},
{
"dynamic fee tx pre-London, priorityFee set",
- false,
+ "legacy",
&TransactionArgs{MaxPriorityFeePerGas: fortytwo},
nil,
- errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
+ errors.New("maxFeePerGas and maxPriorityFeePerGas and maxFeePerBlobGas are not valid before London is active"),
},
{
"dynamic fee tx, maxFee < priorityFee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(1000))},
nil,
errors.New("maxFeePerGas (0x3e) < maxPriorityFeePerGas (0x3e8)"),
},
{
"dynamic fee tx, maxFee < priorityFee while setting default",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: (*hexutil.Big)(big.NewInt(7))},
nil,
errors.New("maxFeePerGas (0x7) < maxPriorityFeePerGas (0x2a)"),
},
+ {
+ "dynamic fee tx post-London, explicit gas price",
+ "london",
+ &TransactionArgs{MaxFeePerGas: zero, MaxPriorityFeePerGas: zero},
+ nil,
+ errors.New("maxFeePerGas must be non-zero"),
+ },
// Misc
{
"set all fee parameters",
- false,
+ "legacy",
&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
{
"set gas price and maxPriorityFee",
- false,
+ "legacy",
&TransactionArgs{GasPrice: fortytwo, MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
{
"set gas price and maxFee",
- true,
+ "london",
&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
+ // EIP-4844
+ {
+ "set maxFeePerBlobGas pre cancun",
+ "london",
+ &TransactionArgs{BlobFeeCap: fortytwo},
+ nil,
+ errors.New("maxFeePerBlobGas is not valid before Cancun is active"),
+ },
+ {
+ "set maxFeePerBlobGas pre london",
+ "legacy",
+ &TransactionArgs{BlobFeeCap: fortytwo},
+ nil,
+ errors.New("maxFeePerGas and maxPriorityFeePerGas and maxFeePerBlobGas are not valid before London is active"),
+ },
+ {
+ "set gas price and maxFee for blob transaction",
+ "cancun",
+ &TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, BlobHashes: []common.Hash{}},
+ nil,
+ errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
+ },
+ {
+ "fill maxFeePerBlobGas",
+ "cancun",
+ &TransactionArgs{BlobHashes: []common.Hash{}},
+ &TransactionArgs{BlobHashes: []common.Hash{}, BlobFeeCap: (*hexutil.Big)(big.NewInt(4)), MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
+ nil,
+ },
}
ctx := context.Background()
for i, test := range tests {
- if test.isLondon {
- b.activateLondon()
- } else {
- b.deactivateLondon()
+ if err := b.setFork(test.fork); err != nil {
+ t.Fatalf("failed to set fork: %v", err)
}
got := test.in
err := got.setFeeDefaults(ctx, b)
@@ -213,6 +262,7 @@ type backendMock struct {
}
func newBackendMock() *backendMock {
+ var cancunTime uint64 = 600
config := ¶ms.ChainConfig{
ChainID: big.NewInt(42),
HomesteadBlock: big.NewInt(0),
@@ -228,6 +278,7 @@ func newBackendMock() *backendMock {
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(1000),
+ CancunTime: &cancunTime,
}
return &backendMock{
current: &types.Header{
@@ -243,13 +294,25 @@ func newBackendMock() *backendMock {
}
}
-func (b *backendMock) activateLondon() {
- b.current.Number = big.NewInt(1100)
+func (b *backendMock) setFork(fork string) error {
+ if fork == "legacy" {
+ b.current.Number = big.NewInt(900)
+ b.current.Time = 555
+ } else if fork == "london" {
+ b.current.Number = big.NewInt(1100)
+ b.current.Time = 555
+ } else if fork == "cancun" {
+ b.current.Number = big.NewInt(1100)
+ b.current.Time = 700
+ // Blob base fee will be 2
+ excess := uint64(2314058)
+ b.current.ExcessBlobGas = &excess
+ } else {
+ return errors.New("invalid fork")
+ }
+ return nil
}
-func (b *backendMock) deactivateLondon() {
- b.current.Number = big.NewInt(900)
-}
func (b *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return big.NewInt(42), nil
}
@@ -307,8 +370,8 @@ func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number
return nil, nil
}
func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
-func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) {
- return nil, nil
+func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
+ return nil
}
func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
@@ -324,8 +387,8 @@ func (b *backendMock) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.S
return nil
}
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
-func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
- return nil, [32]byte{}, 0, 0, nil
+func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
+ return false, nil, [32]byte{}, 0, 0, nil
}
func (b *backendMock) GetPoolTransactions() (types.Transactions, error) { return nil, nil }
func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
@@ -351,3 +414,19 @@ func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent)
}
func (b *backendMock) Engine() consensus.Engine { return nil }
+
+func (b *backendMock) MevRunning() bool { return false }
+func (b *backendMock) MevParams() *types.MevParams {
+ return &types.MevParams{}
+}
+func (b *backendMock) StartMev() {}
+func (b *backendMock) StopMev() {}
+func (b *backendMock) AddBuilder(builder common.Address, builderUrl string) error { return nil }
+func (b *backendMock) RemoveBuilder(builder common.Address) error { return nil }
+func (b *backendMock) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) {
+ panic("implement me")
+}
+func (b *backendMock) MinerInTurn() bool { return false }
+func (b *backendMock) BestBidGasFee(parentHash common.Hash) *big.Int {
+ panic("implement me")
+}
diff --git a/internal/flags/categories.go b/internal/flags/categories.go
index 7fbae4efac..382f7559d9 100644
--- a/internal/flags/categories.go
+++ b/internal/flags/categories.go
@@ -36,6 +36,7 @@ const (
LoggingCategory = "LOGGING AND DEBUGGING"
MetricsCategory = "METRICS AND STATS"
MiscCategory = "MISC"
+ TestingCategory = "TESTING"
DeprecatedCategory = "ALIASED (deprecated)"
FastNodeCategory = "FAST NODE"
FastFinalityCategory = "FAST FINALITY"
diff --git a/internal/flags/flags.go b/internal/flags/flags.go
index b0756b4e0a..69e9743556 100644
--- a/internal/flags/flags.go
+++ b/internal/flags/flags.go
@@ -20,11 +20,13 @@ import (
"encoding"
"errors"
"flag"
+ "fmt"
"math/big"
"os"
"os/user"
"path/filepath"
"strings"
+ "syscall"
"github.com/ethereum/go-ethereum/common/math"
"github.com/urfave/cli/v2"
@@ -68,6 +70,7 @@ type DirectoryFlag struct {
Value DirectoryString
Aliases []string
+ EnvVars []string
}
// For cli.Flag:
@@ -79,6 +82,14 @@ func (f *DirectoryFlag) String() string { return cli.FlagStringer(f) }
// Apply called by cli library, grabs variable from environment (if in env)
// and adds variable to flag set for parsing.
func (f *DirectoryFlag) Apply(set *flag.FlagSet) error {
+ for _, envVar := range f.EnvVars {
+ envVar = strings.TrimSpace(envVar)
+ if value, found := syscall.Getenv(envVar); found {
+ f.Value.Set(value)
+ f.HasBeenSet = true
+ break
+ }
+ }
eachName(f, func(name string) {
set.Var(&f.Value, f.Name, f.Usage)
})
@@ -102,7 +113,7 @@ func (f *DirectoryFlag) GetCategory() string { return f.Category }
func (f *DirectoryFlag) TakesValue() bool { return true }
func (f *DirectoryFlag) GetUsage() string { return f.Usage }
func (f *DirectoryFlag) GetValue() string { return f.Value.String() }
-func (f *DirectoryFlag) GetEnvVars() []string { return nil } // env not supported
+func (f *DirectoryFlag) GetEnvVars() []string { return f.EnvVars }
func (f *DirectoryFlag) GetDefaultText() string {
if f.DefaultText != "" {
@@ -156,6 +167,7 @@ type TextMarshalerFlag struct {
Value TextMarshaler
Aliases []string
+ EnvVars []string
}
// For cli.Flag:
@@ -165,6 +177,16 @@ func (f *TextMarshalerFlag) IsSet() bool { return f.HasBeenSet }
func (f *TextMarshalerFlag) String() string { return cli.FlagStringer(f) }
func (f *TextMarshalerFlag) Apply(set *flag.FlagSet) error {
+ for _, envVar := range f.EnvVars {
+ envVar = strings.TrimSpace(envVar)
+ if value, found := syscall.Getenv(envVar); found {
+ if err := f.Value.UnmarshalText([]byte(value)); err != nil {
+ return fmt.Errorf("could not parse %q from environment variable %q for flag %s: %s", value, envVar, f.Name, err)
+ }
+ f.HasBeenSet = true
+ break
+ }
+ }
eachName(f, func(name string) {
set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage)
})
@@ -187,7 +209,7 @@ func (f *TextMarshalerFlag) GetCategory() string { return f.Category }
func (f *TextMarshalerFlag) TakesValue() bool { return true }
func (f *TextMarshalerFlag) GetUsage() string { return f.Usage }
-func (f *TextMarshalerFlag) GetEnvVars() []string { return nil } // env not supported
+func (f *TextMarshalerFlag) GetEnvVars() []string { return f.EnvVars }
func (f *TextMarshalerFlag) GetValue() string {
t, err := f.Value.MarshalText()
@@ -237,6 +259,7 @@ type BigFlag struct {
Value *big.Int
Aliases []string
+ EnvVars []string
}
// For cli.Flag:
@@ -246,6 +269,16 @@ func (f *BigFlag) IsSet() bool { return f.HasBeenSet }
func (f *BigFlag) String() string { return cli.FlagStringer(f) }
func (f *BigFlag) Apply(set *flag.FlagSet) error {
+ for _, envVar := range f.EnvVars {
+ envVar = strings.TrimSpace(envVar)
+ if value, found := syscall.Getenv(envVar); found {
+ if _, ok := f.Value.SetString(value, 10); !ok {
+ return fmt.Errorf("could not parse %q from environment variable %q for flag %s", value, envVar, f.Name)
+ }
+ f.HasBeenSet = true
+ break
+ }
+ }
eachName(f, func(name string) {
f.Value = new(big.Int)
set.Var((*bigValue)(f.Value), f.Name, f.Usage)
@@ -271,7 +304,7 @@ func (f *BigFlag) GetCategory() string { return f.Category }
func (f *BigFlag) TakesValue() bool { return true }
func (f *BigFlag) GetUsage() string { return f.Usage }
func (f *BigFlag) GetValue() string { return f.Value.String() }
-func (f *BigFlag) GetEnvVars() []string { return nil } // env not supported
+func (f *BigFlag) GetEnvVars() []string { return f.EnvVars }
func (f *BigFlag) GetDefaultText() string {
if f.DefaultText != "" {
diff --git a/internal/flags/helpers.go b/internal/flags/helpers.go
index f210e729dd..369a931e8a 100644
--- a/internal/flags/helpers.go
+++ b/internal/flags/helpers.go
@@ -18,13 +18,22 @@ package flags
import (
"fmt"
+ "os"
+ "regexp"
+ "sort"
"strings"
"github.com/ethereum/go-ethereum/internal/version"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
+ "github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
)
+// usecolor defines whether the CLI help should use colored output or normal dumb
+// colorless terminal formatting.
+var usecolor = (isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())) && os.Getenv("TERM") != "dumb"
+
// NewApp creates an app with sane defaults.
func NewApp(usage string) *cli.App {
git, _ := version.VCS()
@@ -32,7 +41,7 @@ func NewApp(usage string) *cli.App {
app.EnableBashCompletion = true
app.Version = params.VersionWithCommit(git.Commit, git.Date)
app.Usage = usage
- app.Copyright = "Copyright 2013-2023 The go-ethereum Authors"
+ app.Copyright = "Copyright 2013-2024 The go-ethereum Authors"
app.Before = func(ctx *cli.Context) error {
MigrateGlobalFlags(ctx)
return nil
@@ -96,7 +105,7 @@ func MigrateGlobalFlags(ctx *cli.Context) {
func doMigrateFlags(ctx *cli.Context) {
// Figure out if there are any aliases of commands. If there are, we want
// to ignore them when iterating over the flags.
- var aliases = make(map[string]bool)
+ aliases := make(map[string]bool)
for _, fl := range ctx.Command.Flags {
for _, alias := range fl.Names()[1:] {
aliases[alias] = true
@@ -129,6 +138,14 @@ func doMigrateFlags(ctx *cli.Context) {
}
func init() {
+ if usecolor {
+ // Annotate all help categories with colors
+ cli.AppHelpTemplate = regexp.MustCompile("[A-Z ]+:").ReplaceAllString(cli.AppHelpTemplate, "\u001B[33m$0\u001B[0m")
+
+ // Annotate flag categories with colors (private template, so need to
+ // copy-paste the entire thing here...)
+ cli.AppHelpTemplate = strings.ReplaceAll(cli.AppHelpTemplate, "{{template \"visibleFlagCategoryTemplate\" .}}", "{{range .VisibleFlagCategories}}\n {{if .Name}}\u001B[33m{{.Name}}\u001B[0m\n\n {{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}}\n{{else}}{{$e}}\n {{end}}{{end}}{{end}}")
+ }
cli.FlagStringer = FlagString
}
@@ -138,37 +155,31 @@ func FlagString(f cli.Flag) string {
if !ok {
return ""
}
-
needsPlaceholder := df.TakesValue()
placeholder := ""
if needsPlaceholder {
placeholder = "value"
}
- namesText := pad(cli.FlagNamePrefixer(df.Names(), placeholder), 30)
+ namesText := cli.FlagNamePrefixer(df.Names(), placeholder)
defaultValueString := ""
if s := df.GetDefaultText(); s != "" {
defaultValueString = " (default: " + s + ")"
}
-
- usage := strings.TrimSpace(df.GetUsage())
envHint := strings.TrimSpace(cli.FlagEnvHinter(df.GetEnvVars(), ""))
- if len(envHint) > 0 {
- usage += " " + envHint
+ if envHint != "" {
+ envHint = " (" + envHint[1:len(envHint)-1] + ")"
}
-
+ usage := strings.TrimSpace(df.GetUsage())
usage = wordWrap(usage, 80)
usage = indent(usage, 10)
- return fmt.Sprintf("\n %s%s\n%s", namesText, defaultValueString, usage)
-}
-
-func pad(s string, length int) string {
- if len(s) < length {
- s += strings.Repeat(" ", length-len(s))
+ if usecolor {
+ return fmt.Sprintf("\n \u001B[32m%-35s%-35s\u001B[0m%s\n%s", namesText, defaultValueString, envHint, usage)
+ } else {
+ return fmt.Sprintf("\n %-35s%-35s%s\n%s", namesText, defaultValueString, envHint, usage)
}
- return s
}
func indent(s string, nspace int) string {
@@ -213,3 +224,87 @@ func wordWrap(s string, width int) string {
return output.String()
}
+
+// AutoEnvVars extends all the specific CLI flags with automatically generated
+// env vars by capitalizing the flag, replacing . with _ and prefixing it with
+// the specified string.
+//
+// Note, the prefix should *not* contain the separator underscore, that will be
+// added automatically.
+func AutoEnvVars(flags []cli.Flag, prefix string) {
+ for _, flag := range flags {
+ envvar := strings.ToUpper(prefix + "_" + strings.ReplaceAll(strings.ReplaceAll(flag.Names()[0], ".", "_"), "-", "_"))
+
+ switch flag := flag.(type) {
+ case *cli.StringFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *cli.StringSliceFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *cli.BoolFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *cli.IntFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *cli.Int64Flag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *cli.Uint64Flag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *cli.Float64Flag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *cli.DurationFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *cli.PathFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *BigFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *TextMarshalerFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+
+ case *DirectoryFlag:
+ flag.EnvVars = append(flag.EnvVars, envvar)
+ }
+ }
+}
+
+// CheckEnvVars iterates over all the environment variables and checks if any of
+// them look like a CLI flag but is not consumed. This can be used to detect old
+// or mistyped names.
+func CheckEnvVars(ctx *cli.Context, flags []cli.Flag, prefix string) {
+ known := make(map[string]string)
+ for _, flag := range flags {
+ docflag, ok := flag.(cli.DocGenerationFlag)
+ if !ok {
+ continue
+ }
+ for _, envvar := range docflag.GetEnvVars() {
+ known[envvar] = flag.Names()[0]
+ }
+ }
+ keyvals := os.Environ()
+ sort.Strings(keyvals)
+
+ for _, keyval := range keyvals {
+ key := strings.Split(keyval, "=")[0]
+ if !strings.HasPrefix(key, prefix) {
+ continue
+ }
+ if flag, ok := known[key]; ok {
+ if ctx.Count(flag) > 0 {
+ log.Info("Config environment variable found", "envvar", key, "shadowedby", "--"+flag)
+ } else {
+ log.Info("Config environment variable found", "envvar", key)
+ }
+ } else {
+ log.Warn("Unknown config environment variable", "envvar", key)
+ }
+ }
+}
diff --git a/internal/jsre/deps/web3.js b/internal/jsre/deps/web3.js
index 64fdbe01a5..6c7270cfb8 100644
--- a/internal/jsre/deps/web3.js
+++ b/internal/jsre/deps/web3.js
@@ -1033,7 +1033,7 @@ var formatOutputInt = function (param) {
*
* @method formatOutputUInt
* @param {SolidityParam}
- * @returns {BigNumeber} right-aligned output bytes formatted to uint
+ * @returns {BigNumber} right-aligned output bytes formatted to uint
*/
var formatOutputUInt = function (param) {
var value = param.staticPart() || "0";
@@ -3994,6 +3994,8 @@ var outputSyncingFormatter = function(result) {
result.healedBytecodeBytes = utils.toDecimal(result.healedBytecodeBytes);
result.healingTrienodes = utils.toDecimal(result.healingTrienodes);
result.healingBytecode = utils.toDecimal(result.healingBytecode);
+ result.txIndexFinishedBlocks = utils.toDecimal(result.txIndexFinishedBlocks);
+ result.txIndexRemainingBlocks = utils.toDecimal(result.txIndexRemainingBlocks);
return result;
};
diff --git a/internal/reexec/reexec.go b/internal/reexec/reexec.go
new file mode 100644
index 0000000000..af8d347986
--- /dev/null
+++ b/internal/reexec/reexec.go
@@ -0,0 +1,35 @@
+// This file originates from Docker/Moby,
+// https://github.com/moby/moby/blob/master/pkg/reexec/reexec.go
+// Licensed under Apache License 2.0: https://github.com/moby/moby/blob/master/LICENSE
+// Copyright 2013-2018 Docker, Inc.
+//
+// Package reexec facilitates the busybox style reexec of the docker binary that
+// we require because of the forking limitations of using Go. Handlers can be
+// registered with a name and the argv 0 of the exec of the binary will be used
+// to find and execute custom init paths.
+package reexec
+
+import (
+ "fmt"
+ "os"
+)
+
+var registeredInitializers = make(map[string]func())
+
+// Register adds an initialization func under the specified name
+func Register(name string, initializer func()) {
+ if _, exists := registeredInitializers[name]; exists {
+ panic(fmt.Sprintf("reexec func already registered under name %q", name))
+ }
+ registeredInitializers[name] = initializer
+}
+
+// Init is called as the first part of the exec process and returns true if an
+// initialization function was called.
+func Init() bool {
+ if initializer, ok := registeredInitializers[os.Args[0]]; ok {
+ initializer()
+ return true
+ }
+ return false
+}
diff --git a/internal/reexec/self_linux.go b/internal/reexec/self_linux.go
new file mode 100644
index 0000000000..956d09326a
--- /dev/null
+++ b/internal/reexec/self_linux.go
@@ -0,0 +1,14 @@
+// This file originates from Docker/Moby,
+// https://github.com/moby/moby/blob/master/pkg/reexec/
+// Licensed under Apache License 2.0: https://github.com/moby/moby/blob/master/LICENSE
+// Copyright 2013-2018 Docker, Inc.
+
+//go:build linux
+
+package reexec
+
+// Self returns the path to the current process's binary.
+// Returns "/proc/self/exe".
+func Self() string {
+ return "/proc/self/exe"
+}
diff --git a/internal/reexec/self_others.go b/internal/reexec/self_others.go
new file mode 100644
index 0000000000..a9f502ca87
--- /dev/null
+++ b/internal/reexec/self_others.go
@@ -0,0 +1,32 @@
+// This file originates from Docker/Moby,
+// https://github.com/moby/moby/blob/master/pkg/reexec/
+// Licensed under Apache License 2.0: https://github.com/moby/moby/blob/master/LICENSE
+// Copyright 2013-2018 Docker, Inc.
+
+//go:build !linux
+
+package reexec
+
+import (
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+// Self returns the path to the current process's binary.
+// Uses os.Args[0].
+func Self() string {
+ name := os.Args[0]
+ if filepath.Base(name) == name {
+ if lp, err := exec.LookPath(name); err == nil {
+ return lp
+ }
+ }
+ // handle conversion of relative paths to absolute
+ if absName, err := filepath.Abs(name); err == nil {
+ return absName
+ }
+ // if we couldn't get absolute name, return original
+ // (NOTE: Go only errors on Abs() if os.Getwd fails)
+ return name
+}
diff --git a/internal/testlog/testlog.go b/internal/testlog/testlog.go
index 684339f16d..037b7ee9c1 100644
--- a/internal/testlog/testlog.go
+++ b/internal/testlog/testlog.go
@@ -18,26 +18,19 @@
package testlog
import (
+ "bytes"
+ "context"
+ "fmt"
"sync"
"testing"
"github.com/ethereum/go-ethereum/log"
+ "golang.org/x/exp/slog"
)
-// Handler returns a log handler which logs to the unit test log of t.
-func Handler(t *testing.T, level log.Lvl) log.Handler {
- return log.LvlFilterHandler(level, &handler{t, log.TerminalFormat(false)})
-}
-
-type handler struct {
- t *testing.T
- fmt log.Format
-}
-
-func (h *handler) Log(r *log.Record) error {
- h.t.Logf("%s", h.fmt.Format(r))
- return nil
-}
+const (
+ termTimeFormat = "01-02|15:04:05.000"
+)
// logger implements log.Logger such that all output goes to the unit test log via
// t.Logf(). All methods in between logger.Trace, logger.Debug, etc. are marked as test
@@ -51,25 +44,64 @@ type logger struct {
}
type bufHandler struct {
- buf []*log.Record
- fmt log.Format
+ buf []slog.Record
+ attrs []slog.Attr
+ level slog.Level
}
-func (h *bufHandler) Log(r *log.Record) error {
+func (h *bufHandler) Handle(_ context.Context, r slog.Record) error {
h.buf = append(h.buf, r)
return nil
}
+func (h *bufHandler) Enabled(_ context.Context, lvl slog.Level) bool {
+ return lvl <= h.level
+}
+
+func (h *bufHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+ records := make([]slog.Record, len(h.buf))
+ copy(records[:], h.buf[:])
+ return &bufHandler{
+ records,
+ append(h.attrs, attrs...),
+ h.level,
+ }
+}
+
+func (h *bufHandler) WithGroup(_ string) slog.Handler {
+ panic("not implemented")
+}
+
// Logger returns a logger which logs to the unit test log of t.
-func Logger(t *testing.T, level log.Lvl) log.Logger {
- l := &logger{
+func Logger(t *testing.T, level slog.Level) log.Logger {
+ handler := bufHandler{
+ []slog.Record{},
+ []slog.Attr{},
+ level,
+ }
+ return &logger{
+ t: t,
+ l: log.NewLogger(&handler),
+ mu: new(sync.Mutex),
+ h: &handler,
+ }
+}
+
+// LoggerWithHandler returns
+func LoggerWithHandler(t *testing.T, handler slog.Handler) log.Logger {
+ var bh bufHandler
+ return &logger{
t: t,
- l: log.New(),
+ l: log.NewLogger(handler),
mu: new(sync.Mutex),
- h: &bufHandler{fmt: log.TerminalFormat(false)},
+ h: &bh,
}
- l.l.SetHandler(log.LvlFilterHandler(level, l.h))
- return l
+}
+
+func (l *logger) Write(level slog.Level, msg string, ctx ...interface{}) {}
+
+func (l *logger) Enabled(ctx context.Context, level slog.Level) bool {
+ return l.l.Enabled(ctx, level)
}
func (l *logger) Trace(msg string, ctx ...interface{}) {
@@ -80,6 +112,14 @@ func (l *logger) Trace(msg string, ctx ...interface{}) {
l.flush()
}
+func (l *logger) Log(level slog.Level, msg string, ctx ...interface{}) {
+ l.t.Helper()
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ l.l.Log(level, msg, ctx...)
+ l.flush()
+}
+
func (l *logger) Debug(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
@@ -120,23 +160,44 @@ func (l *logger) Crit(msg string, ctx ...interface{}) {
l.flush()
}
-func (l *logger) New(ctx ...interface{}) log.Logger {
- return &logger{l.t, l.l.New(ctx...), l.mu, l.h}
+func (l *logger) With(ctx ...interface{}) log.Logger {
+ return &logger{l.t, l.l.With(ctx...), l.mu, l.h}
}
-func (l *logger) GetHandler() log.Handler {
- return l.l.GetHandler()
+func (l *logger) New(ctx ...interface{}) log.Logger {
+ return l.With(ctx...)
}
-func (l *logger) SetHandler(h log.Handler) {
- l.l.SetHandler(h)
+// terminalFormat formats a message similarly to the NewTerminalHandler in the log package.
+// The difference is that terminalFormat does not escape messages/attributes and does not pad attributes.
+func (h *bufHandler) terminalFormat(r slog.Record) string {
+ buf := &bytes.Buffer{}
+ lvl := log.LevelAlignedString(r.Level)
+ attrs := []slog.Attr{}
+ r.Attrs(func(attr slog.Attr) bool {
+ attrs = append(attrs, attr)
+ return true
+ })
+
+ attrs = append(h.attrs, attrs...)
+
+ fmt.Fprintf(buf, "%s[%s] %s ", lvl, r.Time.Format(termTimeFormat), r.Message)
+ if length := len(r.Message); length < 40 {
+ buf.Write(bytes.Repeat([]byte{' '}, 40-length))
+ }
+
+ for _, attr := range attrs {
+ fmt.Fprintf(buf, " %s=%s", attr.Key, string(log.FormatSlogValue(attr.Value, nil)))
+ }
+ buf.WriteByte('\n')
+ return buf.String()
}
// flush writes all buffered messages and clears the buffer.
func (l *logger) flush() {
l.t.Helper()
for _, r := range l.h.buf {
- l.t.Logf("%s", l.h.fmt.Format(r))
+ l.t.Logf("%s", l.h.terminalFormat(r))
}
l.h.buf = nil
}
diff --git a/internal/utesting/utesting.go b/internal/utesting/utesting.go
index ee99794c64..8260de1d76 100644
--- a/internal/utesting/utesting.go
+++ b/internal/utesting/utesting.go
@@ -35,6 +35,7 @@ import (
type Test struct {
Name string
Fn func(*T)
+ Slow bool
}
// Result is the result of a test execution.
diff --git a/log/CONTRIBUTORS b/log/CONTRIBUTORS
deleted file mode 100644
index a0866713be..0000000000
--- a/log/CONTRIBUTORS
+++ /dev/null
@@ -1,11 +0,0 @@
-Contributors to log15:
-
-- Aaron L
-- Alan Shreve
-- Chris Hines
-- Ciaran Downey
-- Dmitry Chestnykh
-- Evan Shaw
-- Péter Szilágyi
-- Trevor Gattis
-- Vincent Vanackere
diff --git a/log/LICENSE b/log/LICENSE
deleted file mode 100644
index 5f0d1fb6a7..0000000000
--- a/log/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright 2014 Alan Shreve
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/log/README.md b/log/README.md
deleted file mode 100644
index 47426806dd..0000000000
--- a/log/README.md
+++ /dev/null
@@ -1,77 +0,0 @@
-![obligatory xkcd](https://imgs.xkcd.com/comics/standards.png)
-
-# log15 [![godoc reference](https://godoc.org/github.com/inconshreveable/log15?status.png)](https://godoc.org/github.com/inconshreveable/log15) [![Build Status](https://travis-ci.org/inconshreveable/log15.svg?branch=master)](https://travis-ci.org/inconshreveable/log15)
-
-Package log15 provides an opinionated, simple toolkit for best-practice logging in Go (golang) that is both human and machine readable. It is modeled after the Go standard library's [`io`](https://golang.org/pkg/io/) and [`net/http`](https://golang.org/pkg/net/http/) packages and is an alternative to the standard library's [`log`](https://golang.org/pkg/log/) package.
-
-## Features
-- A simple, easy-to-understand API
-- Promotes structured logging by encouraging use of key/value pairs
-- Child loggers which inherit and add their own private context
-- Lazy evaluation of expensive operations
-- Simple Handler interface allowing for construction of flexible, custom logging configurations with a tiny API.
-- Color terminal support
-- Built-in support for logging to files, streams, syslog, and the network
-- Support for forking records to multiple handlers, buffering records for output, failing over from failed handler writes, + more
-
-## Versioning
-The API of the master branch of log15 should always be considered unstable. If you want to rely on a stable API,
-you must vendor the library.
-
-## Importing
-
-```go
-import log "github.com/inconshreveable/log15"
-```
-
-## Examples
-
-```go
-// all loggers can have key/value context
-srvlog := log.New("module", "app/server")
-
-// all log messages can have key/value context
-srvlog.Warn("abnormal conn rate", "rate", curRate, "low", lowRate, "high", highRate)
-
-// child loggers with inherited context
-connlog := srvlog.New("raddr", c.RemoteAddr())
-connlog.Info("connection open")
-
-// lazy evaluation
-connlog.Debug("ping remote", "latency", log.Lazy{pingRemote})
-
-// flexible configuration
-srvlog.SetHandler(log.MultiHandler(
- log.StreamHandler(os.Stderr, log.LogfmtFormat()),
- log.LvlFilterHandler(
- log.LvlError,
- log.Must.FileHandler("errors.json", log.JSONFormat()))))
-```
-
-Will result in output that looks like this:
-
-```
-WARN[06-17|21:58:10] abnormal conn rate module=app/server rate=0.500 low=0.100 high=0.800
-INFO[06-17|21:58:10] connection open module=app/server raddr=10.0.0.1
-```
-
-## Breaking API Changes
-The following commits broke API stability. This reference is intended to help you understand the consequences of updating to a newer version
-of log15.
-
-- 57a084d014d4150152b19e4e531399a7145d1540 - Added a `Get()` method to the `Logger` interface to retrieve the current handler
-- 93404652ee366648fa622b64d1e2b67d75a3094a - `Record` field `Call` changed to `stack.Call` with switch to `github.com/go-stack/stack`
-- a5e7613673c73281f58e15a87d2cf0cf111e8152 - Restored `syslog.Priority` argument to the `SyslogXxx` handler constructors
-
-## FAQ
-
-### The varargs style is brittle and error prone! Can I have type safety please?
-Yes. Use `log.Ctx`:
-
-```go
-srvlog := log.New(log.Ctx{"module": "app/server"})
-srvlog.Warn("abnormal conn rate", log.Ctx{"rate": curRate, "low": lowRate, "high": highRate})
-```
-
-## License
-Apache
diff --git a/log/README_ETHEREUM.md b/log/README_ETHEREUM.md
deleted file mode 100644
index f6c42ccc03..0000000000
--- a/log/README_ETHEREUM.md
+++ /dev/null
@@ -1,5 +0,0 @@
-This package is a fork of https://github.com/inconshreveable/log15, with some
-minor modifications required by the go-ethereum codebase:
-
- * Support for log level `trace`
- * Modified behavior to exit on `critical` failure
diff --git a/log/doc.go b/log/doc.go
deleted file mode 100644
index d2e15140e4..0000000000
--- a/log/doc.go
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
-Package log15 provides an opinionated, simple toolkit for best-practice logging that is
-both human and machine readable. It is modeled after the standard library's io and net/http
-packages.
-
-This package enforces you to only log key/value pairs. Keys must be strings. Values may be
-any type that you like. The default output format is logfmt, but you may also choose to use
-JSON instead if that suits you. Here's how you log:
-
- log.Info("page accessed", "path", r.URL.Path, "user_id", user.id)
-
-This will output a line that looks like:
-
- lvl=info t=2014-05-02T16:07:23-0700 msg="page accessed" path=/org/71/profile user_id=9
-
-# Getting Started
-
-To get started, you'll want to import the library:
-
- import log "github.com/inconshreveable/log15"
-
-Now you're ready to start logging:
-
- func main() {
- log.Info("Program starting", "args", os.Args())
- }
-
-# Convention
-
-Because recording a human-meaningful message is common and good practice, the first argument to every
-logging method is the value to the *implicit* key 'msg'.
-
-Additionally, the level you choose for a message will be automatically added with the key 'lvl', and so
-will the current timestamp with key 't'.
-
-You may supply any additional context as a set of key/value pairs to the logging function. log15 allows
-you to favor terseness, ordering, and speed over safety. This is a reasonable tradeoff for
-logging functions. You don't need to explicitly state keys/values, log15 understands that they alternate
-in the variadic argument list:
-
- log.Warn("size out of bounds", "low", lowBound, "high", highBound, "val", val)
-
-If you really do favor your type-safety, you may choose to pass a log.Ctx instead:
-
- log.Warn("size out of bounds", log.Ctx{"low": lowBound, "high": highBound, "val": val})
-
-# Context loggers
-
-Frequently, you want to add context to a logger so that you can track actions associated with it. An http
-request is a good example. You can easily create new loggers that have context that is automatically included
-with each log line:
-
- requestlogger := log.New("path", r.URL.Path)
-
- // later
- requestlogger.Debug("db txn commit", "duration", txnTimer.Finish())
-
-This will output a log line that includes the path context that is attached to the logger:
-
- lvl=dbug t=2014-05-02T16:07:23-0700 path=/repo/12/add_hook msg="db txn commit" duration=0.12
-
-# Handlers
-
-The Handler interface defines where log lines are printed to and how they are formatted. Handler is a
-single interface that is inspired by net/http's handler interface:
-
- type Handler interface {
- Log(r *Record) error
- }
-
-Handlers can filter records, format them, or dispatch to multiple other Handlers.
-This package implements a number of Handlers for common logging patterns that are
-easily composed to create flexible, custom logging structures.
-
-Here's an example handler that prints logfmt output to Stdout:
-
- handler := log.StreamHandler(os.Stdout, log.LogfmtFormat())
-
-Here's an example handler that defers to two other handlers. One handler only prints records
-from the rpc package in logfmt to standard out. The other prints records at Error level
-or above in JSON formatted output to the file /var/log/service.json
-
- handler := log.MultiHandler(
- log.LvlFilterHandler(log.LvlError, log.Must.FileHandler("/var/log/service.json", log.JSONFormat())),
- log.MatchFilterHandler("pkg", "app/rpc" log.StdoutHandler())
- )
-
-# Logging File Names and Line Numbers
-
-This package implements three Handlers that add debugging information to the
-context, CallerFileHandler, CallerFuncHandler and CallerStackHandler. Here's
-an example that adds the source file and line number of each logging call to
-the context.
-
- h := log.CallerFileHandler(log.StdoutHandler)
- log.Root().SetHandler(h)
- ...
- log.Error("open file", "err", err)
-
-This will output a line that looks like:
-
- lvl=eror t=2014-05-02T16:07:23-0700 msg="open file" err="file not found" caller=data.go:42
-
-Here's an example that logs the call stack rather than just the call site.
-
- h := log.CallerStackHandler("%+v", log.StdoutHandler)
- log.Root().SetHandler(h)
- ...
- log.Error("open file", "err", err)
-
-This will output a line that looks like:
-
- lvl=eror t=2014-05-02T16:07:23-0700 msg="open file" err="file not found" stack="[pkg/data.go:42 pkg/cmd/main.go]"
-
-The "%+v" format instructs the handler to include the path of the source file
-relative to the compile time GOPATH. The github.com/go-stack/stack package
-documents the full list of formatting verbs and modifiers available.
-
-# Custom Handlers
-
-The Handler interface is so simple that it's also trivial to write your own. Let's create an
-example handler which tries to write to one handler, but if that fails it falls back to
-writing to another handler and includes the error that it encountered when trying to write
-to the primary. This might be useful when trying to log over a network socket, but if that
-fails you want to log those records to a file on disk.
-
- type BackupHandler struct {
- Primary Handler
- Secondary Handler
- }
-
- func (h *BackupHandler) Log (r *Record) error {
- err := h.Primary.Log(r)
- if err != nil {
- r.Ctx = append(ctx, "primary_err", err)
- return h.Secondary.Log(r)
- }
- return nil
- }
-
-This pattern is so useful that a generic version that handles an arbitrary number of Handlers
-is included as part of this library called FailoverHandler.
-
-# Logging Expensive Operations
-
-Sometimes, you want to log values that are extremely expensive to compute, but you don't want to pay
-the price of computing them if you haven't turned up your logging level to a high level of detail.
-
-This package provides a simple type to annotate a logging operation that you want to be evaluated
-lazily, just when it is about to be logged, so that it would not be evaluated if an upstream Handler
-filters it out. Just wrap any function which takes no arguments with the log.Lazy type. For example:
-
- func factorRSAKey() (factors []int) {
- // return the factors of a very large number
- }
-
- log.Debug("factors", log.Lazy{factorRSAKey})
-
-If this message is not logged for any reason (like logging at the Error level), then
-factorRSAKey is never evaluated.
-
-# Dynamic context values
-
-The same log.Lazy mechanism can be used to attach context to a logger which you want to be
-evaluated when the message is logged, but not when the logger is created. For example, let's imagine
-a game where you have Player objects:
-
- type Player struct {
- name string
- alive bool
- log.Logger
- }
-
-You always want to log a player's name and whether they're alive or dead, so when you create the player
-object, you might do:
-
- p := &Player{name: name, alive: true}
- p.Logger = log.New("name", p.name, "alive", p.alive)
-
-Only now, even after a player has died, the logger will still report they are alive because the logging
-context is evaluated when the logger was created. By using the Lazy wrapper, we can defer the evaluation
-of whether the player is alive or not to each log message, so that the log records will reflect the player's
-current state no matter when the log message is written:
-
- p := &Player{name: name, alive: true}
- isAlive := func() bool { return p.alive }
- player.Logger = log.New("name", p.name, "alive", log.Lazy{isAlive})
-
-# Terminal Format
-
-If log15 detects that stdout is a terminal, it will configure the default
-handler for it (which is log.StdoutHandler) to use TerminalFormat. This format
-logs records nicely for your terminal, including color-coded output based
-on log level.
-
-# Error Handling
-
-Becasuse log15 allows you to step around the type system, there are a few ways you can specify
-invalid arguments to the logging functions. You could, for example, wrap something that is not
-a zero-argument function with log.Lazy or pass a context key that is not a string. Since logging libraries
-are typically the mechanism by which errors are reported, it would be onerous for the logging functions
-to return errors. Instead, log15 handles errors by making these guarantees to you:
-
-- Any log record containing an error will still be printed with the error explained to you as part of the log record.
-
-- Any log record containing an error will include the context key LOG15_ERROR, enabling you to easily
-(and if you like, automatically) detect if any of your logging calls are passing bad values.
-
-Understanding this, you might wonder why the Handler interface can return an error value in its Log method. Handlers
-are encouraged to return errors only if they fail to write their log records out to an external source like if the
-syslog daemon is not responding. This allows the construction of useful handlers which cope with those failures
-like the FailoverHandler.
-
-# Library Use
-
-log15 is intended to be useful for library authors as a way to provide configurable logging to
-users of their library. Best practice for use in a library is to always disable all output for your logger
-by default and to provide a public Logger instance that consumers of your library can configure. Like so:
-
- package yourlib
-
- import "github.com/inconshreveable/log15"
-
- var Log = log.New()
-
- func init() {
- Log.SetHandler(log.DiscardHandler())
- }
-
-Users of your library may then enable it if they like:
-
- import "github.com/inconshreveable/log15"
- import "example.com/yourlib"
-
- func main() {
- handler := // custom handler setup
- yourlib.Log.SetHandler(handler)
- }
-
-# Best practices attaching logger context
-
-The ability to attach context to a logger is a powerful one. Where should you do it and why?
-I favor embedding a Logger directly into any persistent object in my application and adding
-unique, tracing context keys to it. For instance, imagine I am writing a web browser:
-
- type Tab struct {
- url string
- render *RenderingContext
- // ...
-
- Logger
- }
-
- func NewTab(url string) *Tab {
- return &Tab {
- // ...
- url: url,
-
- Logger: log.New("url", url),
- }
- }
-
-When a new tab is created, I assign a logger to it with the url of
-the tab as context so it can easily be traced through the logs.
-Now, whenever we perform any operation with the tab, we'll log with its
-embedded logger and it will include the tab title automatically:
-
- tab.Debug("moved position", "idx", tab.idx)
-
-There's only one problem. What if the tab url changes? We could
-use log.Lazy to make sure the current url is always written, but that
-would mean that we couldn't trace a tab's full lifetime through our
-logs after the user navigate to a new URL.
-
-Instead, think about what values to attach to your loggers the
-same way you think about what to use as a key in a SQL database schema.
-If it's possible to use a natural key that is unique for the lifetime of the
-object, do so. But otherwise, log15's ext package has a handy RandId
-function to let you generate what you might call "surrogate keys"
-They're just random hex identifiers to use for tracing. Back to our
-Tab example, we would prefer to set up our Logger like so:
-
- import logext "github.com/inconshreveable/log15/ext"
-
- t := &Tab {
- // ...
- url: url,
- }
-
- t.Logger = log.New("id", logext.RandId(8), "url", log.Lazy{t.getUrl})
- return t
-
-Now we'll have a unique traceable identifier even across loading new urls, but
-we'll still be able to see the tab's current url in the log messages.
-
-# Must
-
-For all Handler functions which can return an error, there is a version of that
-function which will return no error but panics on failure. They are all available
-on the Must object. For example:
-
- log.Must.FileHandler("/path", log.JSONFormat)
- log.Must.NetHandler("tcp", ":1234", log.JSONFormat)
-
-# Inspiration and Credit
-
-All of the following excellent projects inspired the design of this library:
-
-code.google.com/p/log4go
-
-github.com/op/go-logging
-
-github.com/technoweenie/grohl
-
-github.com/Sirupsen/logrus
-
-github.com/kr/logfmt
-
-github.com/spacemonkeygo/spacelog
-
-golang's stdlib, notably io and net/http
-
-# The Name
-
-https://xkcd.com/927/
-*/
-package log
diff --git a/log/format.go b/log/format.go
index a45380bf1a..71bee8a6ff 100644
--- a/log/format.go
+++ b/log/format.go
@@ -2,18 +2,15 @@ package log
import (
"bytes"
- "encoding/json"
"fmt"
"math/big"
"reflect"
"strconv"
- "strings"
- "sync"
- "sync/atomic"
"time"
"unicode/utf8"
"github.com/holiman/uint256"
+ "golang.org/x/exp/slog"
)
var (
@@ -27,47 +24,8 @@ const (
termCtxMaxPadding = 40
)
-// locationTrims are trimmed for display to avoid unwieldy log lines.
-var locationTrims = []string{
- "github.com/ethereum/go-ethereum/",
-}
-
-// PrintOrigins sets or unsets log location (file:line) printing for terminal
-// format output.
-func PrintOrigins(print bool) {
- locationEnabled.Store(print)
-}
-
-// locationEnabled is an atomic flag controlling whether the terminal formatter
-// should append the log locations too when printing entries.
-var locationEnabled atomic.Bool
-
-// locationLength is the maxmimum path length encountered, which all logs are
-// padded to to aid in alignment.
-var locationLength atomic.Uint32
-
-// fieldPadding is a global map with maximum field value lengths seen until now
-// to allow padding log contexts in a bit smarter way.
-var fieldPadding = make(map[string]int)
-
-// fieldPaddingLock is a global mutex protecting the field padding map.
-var fieldPaddingLock sync.RWMutex
-
-type Format interface {
- Format(r *Record) []byte
-}
-
-// FormatFunc returns a new Format object which uses
-// the given function to perform record formatting.
-func FormatFunc(f func(*Record) []byte) Format {
- return formatFunc(f)
-}
-
-type formatFunc func(*Record) []byte
-
-func (f formatFunc) Format(r *Record) []byte {
- return f(r)
-}
+// 40 spaces
+var spaces = []byte(" ")
// TerminalStringer is an analogous interface to the stdlib stringer, allowing
// own types to have custom shortened serialization formats when printed to the
@@ -76,348 +34,172 @@ type TerminalStringer interface {
TerminalString() string
}
-// TerminalFormat formats log records optimized for human readability on
-// a terminal with color-coded level output and terser human friendly timestamp.
-// This format should only be used for interactive programs or while developing.
-//
-// [LEVEL] [TIME] MESSAGE key=value key=value ...
-//
-// Example:
-//
-// [DBUG] [May 16 20:58:45] remove route ns=haproxy addr=127.0.0.1:50002
-func TerminalFormat(usecolor bool) Format {
- return FormatFunc(func(r *Record) []byte {
- msg := escapeMessage(r.Msg)
- var color = 0
- if usecolor {
- switch r.Lvl {
- case LvlCrit:
- color = 35
- case LvlError:
- color = 31
- case LvlWarn:
- color = 33
- case LvlInfo:
- color = 32
- case LvlDebug:
- color = 36
- case LvlTrace:
- color = 34
- }
- }
-
- b := &bytes.Buffer{}
- lvl := r.Lvl.AlignedString()
- if locationEnabled.Load() {
- // Log origin printing was requested, format the location path and line number
- location := fmt.Sprintf("%+v", r.Call)
- for _, prefix := range locationTrims {
- location = strings.TrimPrefix(location, prefix)
- }
- // Maintain the maximum location length for fancyer alignment
- align := int(locationLength.Load())
- if align < len(location) {
- align = len(location)
- locationLength.Store(uint32(align))
- }
- padding := strings.Repeat(" ", align-len(location))
-
- // Assemble and print the log heading
- if color > 0 {
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s|%s]%s %s ", color, lvl, r.Time.Format(termTimeFormat), location, padding, msg)
- } else {
- fmt.Fprintf(b, "%s[%s|%s]%s %s ", lvl, r.Time.Format(termTimeFormat), location, padding, msg)
- }
- } else {
- if color > 0 {
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %s ", color, lvl, r.Time.Format(termTimeFormat), msg)
- } else {
- fmt.Fprintf(b, "%s[%s] %s ", lvl, r.Time.Format(termTimeFormat), msg)
- }
+func (h *TerminalHandler) format(buf []byte, r slog.Record, usecolor bool) []byte {
+ msg := escapeMessage(r.Message)
+ var color = ""
+ if usecolor {
+ switch r.Level {
+ case LevelCrit:
+ color = "\x1b[35m"
+ case slog.LevelError:
+ color = "\x1b[31m"
+ case slog.LevelWarn:
+ color = "\x1b[33m"
+ case slog.LevelInfo:
+ color = "\x1b[32m"
+ case slog.LevelDebug:
+ color = "\x1b[36m"
+ case LevelTrace:
+ color = "\x1b[34m"
}
- // try to justify the log output for short messages
- length := utf8.RuneCountInString(msg)
- if len(r.Ctx) > 0 && length < termMsgJust {
- b.Write(bytes.Repeat([]byte{' '}, termMsgJust-length))
- }
- // print the keys logfmt style
- logfmt(b, r.Ctx, color, true)
- return b.Bytes()
- })
-}
+ }
+ if buf == nil {
+ buf = make([]byte, 0, 30+termMsgJust)
+ }
+ b := bytes.NewBuffer(buf)
+
+ if color != "" { // Start color
+ b.WriteString(color)
+ b.WriteString(LevelAlignedString(r.Level))
+ b.WriteString("\x1b[0m")
+ } else {
+ b.WriteString(LevelAlignedString(r.Level))
+ }
+ b.WriteString("[")
+ writeTimeTermFormat(b, r.Time)
+ b.WriteString("] ")
+ b.WriteString(msg)
+
+ // try to justify the log output for short messages
+ //length := utf8.RuneCountInString(msg)
+ length := len(msg)
+ if (r.NumAttrs()+len(h.attrs)) > 0 && length < termMsgJust {
+ b.Write(spaces[:termMsgJust-length])
+ }
+ // print the attributes
+ h.formatAttributes(b, r, color)
-// LogfmtFormat prints records in logfmt format, an easy machine-parseable but human-readable
-// format for key/value pairs.
-//
-// For more details see: http://godoc.org/github.com/kr/logfmt
-func LogfmtFormat() Format {
- return FormatFunc(func(r *Record) []byte {
- common := []interface{}{r.KeyNames.Time, r.Time, r.KeyNames.Lvl, r.Lvl, r.KeyNames.Msg, r.Msg}
- buf := &bytes.Buffer{}
- logfmt(buf, append(common, r.Ctx...), 0, false)
- return buf.Bytes()
- })
+ return b.Bytes()
}
-func logfmt(buf *bytes.Buffer, ctx []interface{}, color int, term bool) {
- for i := 0; i < len(ctx); i += 2 {
- if i != 0 {
- buf.WriteByte(' ')
- }
-
- k, ok := ctx[i].(string)
- v := formatLogfmtValue(ctx[i+1], term)
- if !ok {
- k, v = errorKey, fmt.Sprintf("%+T is not a string key", ctx[i])
+func (h *TerminalHandler) formatAttributes(buf *bytes.Buffer, r slog.Record, color string) {
+ // tmp is a temporary buffer we use, until bytes.Buffer.AvailableBuffer() (1.21)
+ // can be used.
+ var tmp = make([]byte, 40)
+ writeAttr := func(attr slog.Attr, first, last bool) {
+ buf.WriteByte(' ')
+
+ if color != "" {
+ buf.WriteString(color)
+ //buf.Write(appendEscapeString(buf.AvailableBuffer(), attr.Key))
+ buf.Write(appendEscapeString(tmp[:0], attr.Key))
+ buf.WriteString("\x1b[0m=")
} else {
- k = escapeString(k)
+ //buf.Write(appendEscapeString(buf.AvailableBuffer(), attr.Key))
+ buf.Write(appendEscapeString(tmp[:0], attr.Key))
+ buf.WriteByte('=')
}
+ //val := FormatSlogValue(attr.Value, true, buf.AvailableBuffer())
+ val := FormatSlogValue(attr.Value, tmp[:0])
- // XXX: we should probably check that all of your key bytes aren't invalid
- fieldPaddingLock.RLock()
- padding := fieldPadding[k]
- fieldPaddingLock.RUnlock()
+ padding := h.fieldPadding[attr.Key]
- length := utf8.RuneCountInString(v)
+ length := utf8.RuneCount(val)
if padding < length && length <= termCtxMaxPadding {
padding = length
-
- fieldPaddingLock.Lock()
- fieldPadding[k] = padding
- fieldPaddingLock.Unlock()
+ h.fieldPadding[attr.Key] = padding
}
- if color > 0 {
- fmt.Fprintf(buf, "\x1b[%dm%s\x1b[0m=", color, k)
- } else {
- buf.WriteString(k)
- buf.WriteByte('=')
- }
- buf.WriteString(v)
- if i < len(ctx)-2 && padding > length {
- buf.Write(bytes.Repeat([]byte{' '}, padding-length))
+ buf.Write(val)
+ if !last && padding > length {
+ buf.Write(spaces[:padding-length])
}
}
- buf.WriteByte('\n')
-}
-
-// JSONFormat formats log records as JSON objects separated by newlines.
-// It is the equivalent of JSONFormatEx(false, true).
-func JSONFormat() Format {
- return JSONFormatEx(false, true)
-}
-
-// JSONFormatOrderedEx formats log records as JSON arrays. If pretty is true,
-// records will be pretty-printed. If lineSeparated is true, records
-// will be logged with a new line between each record.
-func JSONFormatOrderedEx(pretty, lineSeparated bool) Format {
- jsonMarshal := json.Marshal
- if pretty {
- jsonMarshal = func(v interface{}) ([]byte, error) {
- return json.MarshalIndent(v, "", " ")
- }
+ var n = 0
+ var nAttrs = len(h.attrs) + r.NumAttrs()
+ for _, attr := range h.attrs {
+ writeAttr(attr, n == 0, n == nAttrs-1)
+ n++
}
- return FormatFunc(func(r *Record) []byte {
- props := map[string]interface{}{
- r.KeyNames.Time: r.Time,
- r.KeyNames.Lvl: r.Lvl.String(),
- r.KeyNames.Msg: r.Msg,
- }
-
- ctx := make([]string, len(r.Ctx))
- for i := 0; i < len(r.Ctx); i += 2 {
- if k, ok := r.Ctx[i].(string); ok {
- ctx[i] = k
- ctx[i+1] = formatLogfmtValue(r.Ctx[i+1], true)
- } else {
- props[errorKey] = fmt.Sprintf("%+T is not a string key,", r.Ctx[i])
- }
- }
- props[r.KeyNames.Ctx] = ctx
-
- b, err := jsonMarshal(props)
- if err != nil {
- b, _ = jsonMarshal(map[string]string{
- errorKey: err.Error(),
- })
- return b
- }
- if lineSeparated {
- b = append(b, '\n')
- }
- return b
- })
-}
-
-// JSONFormatEx formats log records as JSON objects. If pretty is true,
-// records will be pretty-printed. If lineSeparated is true, records
-// will be logged with a new line between each record.
-func JSONFormatEx(pretty, lineSeparated bool) Format {
- jsonMarshal := json.Marshal
- if pretty {
- jsonMarshal = func(v interface{}) ([]byte, error) {
- return json.MarshalIndent(v, "", " ")
- }
- }
-
- return FormatFunc(func(r *Record) []byte {
- props := map[string]interface{}{
- r.KeyNames.Time: r.Time,
- r.KeyNames.Lvl: r.Lvl.String(),
- r.KeyNames.Msg: r.Msg,
- }
-
- for i := 0; i < len(r.Ctx); i += 2 {
- k, ok := r.Ctx[i].(string)
- if !ok {
- props[errorKey] = fmt.Sprintf("%+T is not a string key", r.Ctx[i])
- } else {
- props[k] = formatJSONValue(r.Ctx[i+1])
- }
- }
-
- b, err := jsonMarshal(props)
- if err != nil {
- b, _ = jsonMarshal(map[string]string{
- errorKey: err.Error(),
- })
- return b
- }
-
- if lineSeparated {
- b = append(b, '\n')
- }
-
- return b
+ r.Attrs(func(attr slog.Attr) bool {
+ writeAttr(attr, n == 0, n == nAttrs-1)
+ n++
+ return true
})
+ buf.WriteByte('\n')
}
-func formatShared(value interface{}) (result interface{}) {
+// FormatSlogValue formats a slog.Value for serialization to terminal.
+func FormatSlogValue(v slog.Value, tmp []byte) (result []byte) {
+ var value any
defer func() {
if err := recover(); err != nil {
if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr && v.IsNil() {
- result = "nil"
+ result = []byte("")
} else {
panic(err)
}
}
}()
- switch v := value.(type) {
- case time.Time:
- return v.Format(timeFormat)
-
- case error:
- return v.Error()
-
- case fmt.Stringer:
- return v.String()
-
- default:
- return v
- }
-}
-
-func formatJSONValue(value interface{}) interface{} {
- value = formatShared(value)
- switch value.(type) {
- case int, int8, int16, int32, int64, float32, float64, uint, uint8, uint16, uint32, uint64, string:
- return value
- default:
- return fmt.Sprintf("%+v", value)
- }
-}
-
-// formatValue formats a value for serialization
-func formatLogfmtValue(value interface{}, term bool) string {
- if value == nil {
- return "nil"
- }
-
- switch v := value.(type) {
- case time.Time:
+ switch v.Kind() {
+ case slog.KindString:
+ return appendEscapeString(tmp, v.String())
+ case slog.KindInt64: // All int-types (int8, int16 etc) wind up here
+ return appendInt64(tmp, v.Int64())
+ case slog.KindUint64: // All uint-types (uint8, uint16 etc) wind up here
+ return appendUint64(tmp, v.Uint64(), false)
+ case slog.KindFloat64:
+ return strconv.AppendFloat(tmp, v.Float64(), floatFormat, 3, 64)
+ case slog.KindBool:
+ return strconv.AppendBool(tmp, v.Bool())
+ case slog.KindDuration:
+ value = v.Duration()
+ case slog.KindTime:
// Performance optimization: No need for escaping since the provided
// timeFormat doesn't have any escape characters, and escaping is
// expensive.
- return v.Format(timeFormat)
-
- case *big.Int:
- // Big ints get consumed by the Stringer clause, so we need to handle
- // them earlier on.
- if v == nil {
- return ""
- }
- return formatLogfmtBigInt(v)
-
- case *uint256.Int:
- // Uint256s get consumed by the Stringer clause, so we need to handle
- // them earlier on.
- if v == nil {
- return ""
- }
- return formatLogfmtUint256(v)
+ return v.Time().AppendFormat(tmp, timeFormat)
+ default:
+ value = v.Any()
}
- if term {
- if s, ok := value.(TerminalStringer); ok {
- // Custom terminal stringer provided, use that
- return escapeString(s.TerminalString())
- }
+ if value == nil {
+ return []byte("")
}
- value = formatShared(value)
switch v := value.(type) {
- case bool:
- return strconv.FormatBool(v)
- case float32:
- return strconv.FormatFloat(float64(v), floatFormat, 3, 64)
- case float64:
- return strconv.FormatFloat(v, floatFormat, 3, 64)
- case int8:
- return strconv.FormatInt(int64(v), 10)
- case uint8:
- return strconv.FormatInt(int64(v), 10)
- case int16:
- return strconv.FormatInt(int64(v), 10)
- case uint16:
- return strconv.FormatInt(int64(v), 10)
- // Larger integers get thousands separators.
- case int:
- return FormatLogfmtInt64(int64(v))
- case int32:
- return FormatLogfmtInt64(int64(v))
- case int64:
- return FormatLogfmtInt64(v)
- case uint:
- return FormatLogfmtUint64(uint64(v))
- case uint32:
- return FormatLogfmtUint64(uint64(v))
- case uint64:
- return FormatLogfmtUint64(v)
- case string:
- return escapeString(v)
- default:
- return escapeString(fmt.Sprintf("%+v", value))
+ case *big.Int: // Need to be before fmt.Stringer-clause
+ return appendBigInt(tmp, v)
+ case *uint256.Int: // Need to be before fmt.Stringer-clause
+ return appendU256(tmp, v)
+ case error:
+ return appendEscapeString(tmp, v.Error())
+ case TerminalStringer:
+ return appendEscapeString(tmp, v.TerminalString())
+ case fmt.Stringer:
+ return appendEscapeString(tmp, v.String())
}
+
+ // We can use the 'tmp' as a scratch-buffer, to first format the
+ // value, and in a second step do escaping.
+ internal := fmt.Appendf(tmp, "%+v", value)
+ return appendEscapeString(tmp, string(internal))
}
-// FormatLogfmtInt64 formats n with thousand separators.
-func FormatLogfmtInt64(n int64) string {
+// appendInt64 formats n with thousand separators and writes into buffer dst.
+func appendInt64(dst []byte, n int64) []byte {
if n < 0 {
- return formatLogfmtUint64(uint64(-n), true)
+ return appendUint64(dst, uint64(-n), true)
}
- return formatLogfmtUint64(uint64(n), false)
-}
-
-// FormatLogfmtUint64 formats n with thousand separators.
-func FormatLogfmtUint64(n uint64) string {
- return formatLogfmtUint64(n, false)
+ return appendUint64(dst, uint64(n), false)
}
-func formatLogfmtUint64(n uint64, neg bool) string {
+// appendUint64 formats n with thousand separators and writes into buffer dst.
+func appendUint64(dst []byte, n uint64, neg bool) []byte {
// Small numbers are fine as is
if n < 100000 {
if neg {
- return strconv.Itoa(-int(n))
+ return strconv.AppendInt(dst, -int64(n), 10)
} else {
- return strconv.Itoa(int(n))
+ return strconv.AppendInt(dst, int64(n), 10)
}
}
// Large numbers should be split
@@ -442,16 +224,21 @@ func formatLogfmtUint64(n uint64, neg bool) string {
out[i] = '-'
i--
}
- return string(out[i+1:])
+ return append(dst, out[i+1:]...)
+}
+
+// FormatLogfmtUint64 formats n with thousand separators.
+func FormatLogfmtUint64(n uint64) string {
+ return string(appendUint64(nil, n, false))
}
-// formatLogfmtBigInt formats n with thousand separators.
-func formatLogfmtBigInt(n *big.Int) string {
+// appendBigInt formats n with thousand separators and writes to dst.
+func appendBigInt(dst []byte, n *big.Int) []byte {
if n.IsUint64() {
- return FormatLogfmtUint64(n.Uint64())
+ return appendUint64(dst, n.Uint64(), false)
}
if n.IsInt64() {
- return FormatLogfmtInt64(n.Int64())
+ return appendInt64(dst, n.Int64())
}
var (
@@ -476,54 +263,48 @@ func formatLogfmtBigInt(n *big.Int) string {
comma++
}
}
- return string(buf[i+1:])
+ return append(dst, buf[i+1:]...)
}
-// formatLogfmtUint256 formats n with thousand separators.
-func formatLogfmtUint256(n *uint256.Int) string {
+// appendU256 formats n with thousand separators.
+func appendU256(dst []byte, n *uint256.Int) []byte {
if n.IsUint64() {
- return FormatLogfmtUint64(n.Uint64())
+ return appendUint64(dst, n.Uint64(), false)
}
- var (
- text = n.Dec()
- buf = make([]byte, len(text)+len(text)/3)
- comma = 0
- i = len(buf) - 1
- )
- for j := len(text) - 1; j >= 0; j, i = j-1, i-1 {
- c := text[j]
-
- switch {
- case c == '-':
- buf[i] = c
- case comma == 3:
- buf[i] = ','
- i--
- comma = 0
- fallthrough
- default:
- buf[i] = c
- comma++
- }
- }
- return string(buf[i+1:])
+ res := []byte(n.PrettyDec(','))
+ return append(dst, res...)
}
-// escapeString checks if the provided string needs escaping/quoting, and
-// calls strconv.Quote if needed
-func escapeString(s string) string {
+// appendEscapeString writes the string s to the given writer, with
+// escaping/quoting if needed.
+func appendEscapeString(dst []byte, s string) []byte {
needsQuoting := false
+ needsEscaping := false
for _, r := range s {
- // We quote everything below " (0x22) and above~ (0x7E), plus equal-sign
- if r <= '"' || r > '~' || r == '=' {
+ // If it contains spaces or equal-sign, we need to quote it.
+ if r == ' ' || r == '=' {
needsQuoting = true
+ continue
+ }
+ // We need to escape it, if it contains
+ // - character " (0x22) and lower (except space)
+ // - characters above ~ (0x7E), plus equal-sign
+ if r <= '"' || r > '~' {
+ needsEscaping = true
break
}
}
- if !needsQuoting {
- return s
+ if needsEscaping {
+ return strconv.AppendQuote(dst, s)
}
- return strconv.Quote(s)
+ // No escaping needed, but we might have to place within quote-marks, in case
+ // it contained a space
+ if needsQuoting {
+ dst = append(dst, '"')
+ dst = append(dst, []byte(s)...)
+ return append(dst, '"')
+ }
+ return append(dst, []byte(s)...)
}
func SetTermTimeFormat(format string) {
@@ -556,3 +337,45 @@ func escapeMessage(s string) string {
}
return strconv.Quote(s)
}
+
+// writeTimeTermFormat writes on the format "01-02|15:04:05.000"
+func writeTimeTermFormat(buf *bytes.Buffer, t time.Time) {
+ _, month, day := t.Date()
+ writePosIntWidth(buf, int(month), 2)
+ buf.WriteByte('-')
+ writePosIntWidth(buf, day, 2)
+ buf.WriteByte('|')
+ hour, min, sec := t.Clock()
+ writePosIntWidth(buf, hour, 2)
+ buf.WriteByte(':')
+ writePosIntWidth(buf, min, 2)
+ buf.WriteByte(':')
+ writePosIntWidth(buf, sec, 2)
+ ns := t.Nanosecond()
+ buf.WriteByte('.')
+ writePosIntWidth(buf, ns/1e6, 3)
+}
+
+// writePosIntWidth writes non-negative integer i to the buffer, padded on the left
+// by zeroes to the given width. Use a width of 0 to omit padding.
+// Adapted from golang.org/x/exp/slog/internal/buffer/buffer.go
+func writePosIntWidth(b *bytes.Buffer, i, width int) {
+ // Cheap integer to fixed-width decimal ASCII.
+ // Copied from log/log.go.
+ if i < 0 {
+ panic("negative int")
+ }
+ // Assemble decimal in reverse order.
+ var bb [20]byte
+ bp := len(bb) - 1
+ for i >= 10 || width > 1 {
+ width--
+ q := i / 10
+ bb[bp] = byte('0' + i - q*10)
+ bp--
+ i = q
+ }
+ // i < 10
+ bb[bp] = byte('0' + i)
+ b.Write(bb[bp:])
+}
diff --git a/log/format_test.go b/log/format_test.go
index e08c1d1a4a..d4c1df4abc 100644
--- a/log/format_test.go
+++ b/log/format_test.go
@@ -1,161 +1,24 @@
package log
import (
- "fmt"
- "math"
- "math/big"
"math/rand"
- "strings"
"testing"
-
- "github.com/holiman/uint256"
)
-func TestPrettyInt64(t *testing.T) {
- tests := []struct {
- n int64
- s string
- }{
- {0, "0"},
- {10, "10"},
- {-10, "-10"},
- {100, "100"},
- {-100, "-100"},
- {1000, "1000"},
- {-1000, "-1000"},
- {10000, "10000"},
- {-10000, "-10000"},
- {99999, "99999"},
- {-99999, "-99999"},
- {100000, "100,000"},
- {-100000, "-100,000"},
- {1000000, "1,000,000"},
- {-1000000, "-1,000,000"},
- {math.MaxInt64, "9,223,372,036,854,775,807"},
- {math.MinInt64, "-9,223,372,036,854,775,808"},
- }
- for i, tt := range tests {
- if have := FormatLogfmtInt64(tt.n); have != tt.s {
- t.Errorf("test %d: format mismatch: have %s, want %s", i, have, tt.s)
- }
- }
-}
-
-func TestPrettyUint64(t *testing.T) {
- tests := []struct {
- n uint64
- s string
- }{
- {0, "0"},
- {10, "10"},
- {100, "100"},
- {1000, "1000"},
- {10000, "10000"},
- {99999, "99999"},
- {100000, "100,000"},
- {1000000, "1,000,000"},
- {math.MaxUint64, "18,446,744,073,709,551,615"},
- }
- for i, tt := range tests {
- if have := FormatLogfmtUint64(tt.n); have != tt.s {
- t.Errorf("test %d: format mismatch: have %s, want %s", i, have, tt.s)
- }
- }
-}
-
-func TestPrettyBigInt(t *testing.T) {
- tests := []struct {
- int string
- s string
- }{
- {"111222333444555678999", "111,222,333,444,555,678,999"},
- {"-111222333444555678999", "-111,222,333,444,555,678,999"},
- {"11122233344455567899900", "11,122,233,344,455,567,899,900"},
- {"-11122233344455567899900", "-11,122,233,344,455,567,899,900"},
- }
-
- for _, tt := range tests {
- v, _ := new(big.Int).SetString(tt.int, 10)
- if have := formatLogfmtBigInt(v); have != tt.s {
- t.Errorf("invalid output %s, want %s", have, tt.s)
- }
- }
-}
-
-func TestPrettyUint256(t *testing.T) {
- tests := []struct {
- int string
- s string
- }{
- {"111222333444555678999", "111,222,333,444,555,678,999"},
- {"11122233344455567899900", "11,122,233,344,455,567,899,900"},
- }
-
- for _, tt := range tests {
- v := new(uint256.Int)
- v.SetFromDecimal(tt.int)
- if have := formatLogfmtUint256(v); have != tt.s {
- t.Errorf("invalid output %s, want %s", have, tt.s)
- }
- }
-}
-
-var sink string
+var sink []byte
func BenchmarkPrettyInt64Logfmt(b *testing.B) {
+ buf := make([]byte, 100)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- sink = FormatLogfmtInt64(rand.Int63())
+ sink = appendInt64(buf, rand.Int63())
}
}
func BenchmarkPrettyUint64Logfmt(b *testing.B) {
+ buf := make([]byte, 100)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- sink = FormatLogfmtUint64(rand.Uint64())
- }
-}
-
-func TestSanitation(t *testing.T) {
- msg := "\u001b[1G\u001b[K\u001b[1A"
- msg2 := "\u001b \u0000"
- msg3 := "NiceMessage"
- msg4 := "Space Message"
- msg5 := "Enter\nMessage"
-
- for i, tt := range []struct {
- msg string
- want string
- }{
- {
- msg: msg,
- want: fmt.Sprintf("] %q %q=%q\n", msg, msg, msg),
- },
- {
- msg: msg2,
- want: fmt.Sprintf("] %q %q=%q\n", msg2, msg2, msg2),
- },
- {
- msg: msg3,
- want: fmt.Sprintf("] %s %s=%s\n", msg3, msg3, msg3),
- },
- {
- msg: msg4,
- want: fmt.Sprintf("] %s %q=%q\n", msg4, msg4, msg4),
- },
- {
- msg: msg5,
- want: fmt.Sprintf("] %s %q=%q\n", msg5, msg5, msg5),
- },
- } {
- var (
- logger = New()
- out = new(strings.Builder)
- )
- logger.SetHandler(LvlFilterHandler(LvlInfo, StreamHandler(out, TerminalFormat(false))))
- logger.Info(tt.msg, tt.msg, tt.msg)
- if have := out.String()[24:]; tt.want != have {
- t.Fatalf("test %d: want / have: \n%v\n%v", i, tt.want, have)
- }
+ sink = appendUint64(buf, rand.Uint64(), false)
}
}
diff --git a/log/handler.go b/log/handler.go
index c4b0e9bdf9..f048cba80c 100644
--- a/log/handler.go
+++ b/log/handler.go
@@ -1,372 +1,213 @@
package log
import (
+ "context"
"fmt"
"io"
- "net"
+ "math/big"
"os"
"path"
"reflect"
"sync"
+ "time"
- "github.com/go-stack/stack"
+ "github.com/holiman/uint256"
+ "golang.org/x/exp/slog"
)
-// Handler defines where and how log records are written.
-// A Logger prints its log records by writing to a Handler.
-// Handlers are composable, providing you great flexibility in combining
-// them to achieve the logging structure that suits your applications.
-type Handler interface {
- Log(r *Record) error
-}
+type discardHandler struct{}
-// FuncHandler returns a Handler that logs records with the given
-// function.
-func FuncHandler(fn func(r *Record) error) Handler {
- return funcHandler(fn)
+// DiscardHandler returns a no-op handler
+func DiscardHandler() slog.Handler {
+ return &discardHandler{}
}
-type funcHandler func(r *Record) error
-
-func (h funcHandler) Log(r *Record) error {
- return h(r)
+func (h *discardHandler) Handle(_ context.Context, r slog.Record) error {
+ return nil
}
-// StreamHandler writes log records to an io.Writer
-// with the given format. StreamHandler can be used
-// to easily begin writing log records to other
-// outputs.
-//
-// StreamHandler wraps itself with LazyHandler and SyncHandler
-// to evaluate Lazy objects and perform safe concurrent writes.
-func StreamHandler(wr io.Writer, fmtr Format) Handler {
- h := FuncHandler(func(r *Record) error {
- _, err := wr.Write(fmtr.Format(r))
- return err
- })
- return LazyHandler(SyncHandler(h))
+func (h *discardHandler) Enabled(_ context.Context, level slog.Level) bool {
+ return false
}
-// SyncHandler can be wrapped around a handler to guarantee that
-// only a single Log operation can proceed at a time. It's necessary
-// for thread-safe concurrent writes.
-func SyncHandler(h Handler) Handler {
- var mu sync.Mutex
- return FuncHandler(func(r *Record) error {
- mu.Lock()
- defer mu.Unlock()
-
- return h.Log(r)
- })
+func (h *discardHandler) WithGroup(name string) slog.Handler {
+ panic("not implemented")
}
-// FileHandler returns a handler which writes log records to the give file
-// using the given format. If the path
-// already exists, FileHandler will append to the given file. If it does not,
-// FileHandler will create the file with mode 0644.
-func FileHandler(path string, fmtr Format) (Handler, error) {
- f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
- if err != nil {
- return nil, err
- }
- return closingHandler{f, StreamHandler(f, fmtr)}, nil
+func (h *discardHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+ return &discardHandler{}
}
-// RotatingFileHandler returns a handler which writes log records to file chunks
-// at the given path. When a file's size reaches the limit, the handler creates
-// a new file named after the timestamp of the first log record it will contain.
-func RotatingFileHandler(filePath string, limit uint, maxBackups uint, formatter Format, rotateHours uint) (Handler, error) {
- if _, err := os.Stat(path.Dir(filePath)); os.IsNotExist(err) {
- err := os.MkdirAll(path.Dir(filePath), 0755)
- if err != nil {
- return nil, fmt.Errorf("could not create directory %s, %v", path.Dir(filePath), err)
- }
- }
- fileWriter := NewAsyncFileWriter(filePath, int64(limit), int(maxBackups), rotateHours)
- fileWriter.Start()
- return StreamHandler(fileWriter, formatter), nil
-}
-
-// NetHandler opens a socket to the given address and writes records
-// over the connection.
-func NetHandler(network, addr string, fmtr Format) (Handler, error) {
- conn, err := net.Dial(network, addr)
- if err != nil {
- return nil, err
- }
-
- return closingHandler{conn, StreamHandler(conn, fmtr)}, nil
-}
+type TerminalHandler struct {
+ mu sync.Mutex
+ wr io.Writer
+ lvl slog.Level
+ useColor bool
+ attrs []slog.Attr
+ // fieldPadding is a map with maximum field value lengths seen until now
+ // to allow padding log contexts in a bit smarter way.
+ fieldPadding map[string]int
-// XXX: closingHandler is essentially unused at the moment
-// it's meant for a future time when the Handler interface supports
-// a possible Close() operation
-type closingHandler struct {
- io.WriteCloser
- Handler
+ buf []byte
}
-func (h *closingHandler) Close() error {
- return h.WriteCloser.Close()
+// NewTerminalHandler returns a handler which formats log records at all levels optimized for human readability on
+// a terminal with color-coded level output and terser human friendly timestamp.
+// This format should only be used for interactive programs or while developing.
+//
+// [LEVEL] [TIME] MESSAGE key=value key=value ...
+//
+// Example:
+//
+// [DBUG] [May 16 20:58:45] remove route ns=haproxy addr=127.0.0.1:50002
+func NewTerminalHandler(wr io.Writer, useColor bool) *TerminalHandler {
+ return NewTerminalHandlerWithLevel(wr, levelMaxVerbosity, useColor)
+}
+
+// NewTerminalHandlerWithLevel returns the same handler as NewTerminalHandler but only outputs
+// records which are less than or equal to the specified verbosity level.
+func NewTerminalHandlerWithLevel(wr io.Writer, lvl slog.Level, useColor bool) *TerminalHandler {
+ return &TerminalHandler{
+ wr: wr,
+ lvl: lvl,
+ useColor: useColor,
+ fieldPadding: make(map[string]int),
+ }
}
-// CallerFileHandler returns a Handler that adds the line number and file of
-// the calling function to the context with key "caller".
-func CallerFileHandler(h Handler) Handler {
- return FuncHandler(func(r *Record) error {
- r.Ctx = append(r.Ctx, "caller", fmt.Sprint(r.Call))
- return h.Log(r)
- })
+func (h *TerminalHandler) Handle(_ context.Context, r slog.Record) error {
+ h.mu.Lock()
+ defer h.mu.Unlock()
+ buf := h.format(h.buf, r, h.useColor)
+ h.wr.Write(buf)
+ h.buf = buf[:0]
+ return nil
}
-// CallerFuncHandler returns a Handler that adds the calling function name to
-// the context with key "fn".
-func CallerFuncHandler(h Handler) Handler {
- return FuncHandler(func(r *Record) error {
- r.Ctx = append(r.Ctx, "fn", formatCall("%+n", r.Call))
- return h.Log(r)
- })
+func (h *TerminalHandler) Enabled(_ context.Context, level slog.Level) bool {
+ return level >= h.lvl
}
-// This function is here to please go vet on Go < 1.8.
-func formatCall(format string, c stack.Call) string {
- return fmt.Sprintf(format, c)
+func (h *TerminalHandler) WithGroup(name string) slog.Handler {
+ panic("not implemented")
}
-// CallerStackHandler returns a Handler that adds a stack trace to the context
-// with key "stack". The stack trace is formatted as a space separated list of
-// call sites inside matching []'s. The most recent call site is listed first.
-// Each call site is formatted according to format. See the documentation of
-// package github.com/go-stack/stack for the list of supported formats.
-func CallerStackHandler(format string, h Handler) Handler {
- return FuncHandler(func(r *Record) error {
- s := stack.Trace().TrimBelow(r.Call).TrimRuntime()
- if len(s) > 0 {
- r.Ctx = append(r.Ctx, "stack", fmt.Sprintf(format, s))
- }
- return h.Log(r)
- })
+func (h *TerminalHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+ return &TerminalHandler{
+ wr: h.wr,
+ lvl: h.lvl,
+ useColor: h.useColor,
+ attrs: append(h.attrs, attrs...),
+ fieldPadding: make(map[string]int),
+ }
}
-// FilterHandler returns a Handler that only writes records to the
-// wrapped Handler if the given function evaluates true. For example,
-// to only log records where the 'err' key is not nil:
-//
-// logger.SetHandler(FilterHandler(func(r *Record) bool {
-// for i := 0; i < len(r.Ctx); i += 2 {
-// if r.Ctx[i] == "err" {
-// return r.Ctx[i+1] != nil
-// }
-// }
-// return false
-// }, h))
-func FilterHandler(fn func(r *Record) bool, h Handler) Handler {
- return FuncHandler(func(r *Record) error {
- if fn(r) {
- return h.Log(r)
- }
- return nil
- })
+// ResetFieldPadding zeroes the field-padding for all attribute pairs.
+func (t *TerminalHandler) ResetFieldPadding() {
+ t.mu.Lock()
+ t.fieldPadding = make(map[string]int)
+ t.mu.Unlock()
}
-// MatchFilterHandler returns a Handler that only writes records
-// to the wrapped Handler if the given key in the logged
-// context matches the value. For example, to only log records
-// from your ui package:
-//
-// log.MatchFilterHandler("pkg", "app/ui", log.StdoutHandler)
-func MatchFilterHandler(key string, value interface{}, h Handler) Handler {
- return FilterHandler(func(r *Record) (pass bool) {
- switch key {
- case r.KeyNames.Lvl:
- return r.Lvl == value
- case r.KeyNames.Time:
- return r.Time == value
- case r.KeyNames.Msg:
- return r.Msg == value
- }
+type leveler struct{ minLevel slog.Level }
- for i := 0; i < len(r.Ctx); i += 2 {
- if r.Ctx[i] == key {
- return r.Ctx[i+1] == value
- }
- }
- return false
- }, h)
+func (l *leveler) Level() slog.Level {
+ return l.minLevel
}
-// LvlFilterHandler returns a Handler that only writes
-// records which are less than the given verbosity
-// level to the wrapped Handler. For example, to only
-// log Error/Crit records:
-//
-// log.LvlFilterHandler(log.LvlError, log.StdoutHandler)
-func LvlFilterHandler(maxLvl Lvl, h Handler) Handler {
- return FilterHandler(func(r *Record) (pass bool) {
- return r.Lvl <= maxLvl
- }, h)
+// JSONHandler returns a handler which prints records in JSON format.
+func JSONHandler(wr io.Writer) slog.Handler {
+ return slog.NewJSONHandler(wr, &slog.HandlerOptions{
+ ReplaceAttr: builtinReplaceJSON,
+ })
}
-// MultiHandler dispatches any write to each of its handlers.
-// This is useful for writing different types of log information
-// to different locations. For example, to log to a file and
-// standard error:
+// LogfmtHandler returns a handler which prints records in logfmt format, an easy machine-parseable but human-readable
+// format for key/value pairs.
//
-// log.MultiHandler(
-// log.Must.FileHandler("/var/log/app.log", log.LogfmtFormat()),
-// log.StderrHandler)
-func MultiHandler(hs ...Handler) Handler {
- return FuncHandler(func(r *Record) error {
- for _, h := range hs {
- // what to do about failures?
- h.Log(r)
- }
- return nil
+// For more details see: http://godoc.org/github.com/kr/logfmt
+func LogfmtHandler(wr io.Writer) slog.Handler {
+ return slog.NewTextHandler(wr, &slog.HandlerOptions{
+ ReplaceAttr: builtinReplaceLogfmt,
})
}
-// FailoverHandler writes all log records to the first handler
-// specified, but will failover and write to the second handler if
-// the first handler has failed, and so on for all handlers specified.
-// For example you might want to log to a network socket, but failover
-// to writing to a file if the network fails, and then to
-// standard out if the file write fails:
-//
-// log.FailoverHandler(
-// log.Must.NetHandler("tcp", ":9090", log.JSONFormat()),
-// log.Must.FileHandler("/var/log/app.log", log.LogfmtFormat()),
-// log.StdoutHandler)
-//
-// All writes that do not go to the first handler will add context with keys of
-// the form "failover_err_{idx}" which explain the error encountered while
-// trying to write to the handlers before them in the list.
-func FailoverHandler(hs ...Handler) Handler {
- return FuncHandler(func(r *Record) error {
- var err error
- for i, h := range hs {
- err = h.Log(r)
- if err == nil {
- return nil
- }
- r.Ctx = append(r.Ctx, fmt.Sprintf("failover_err_%d", i), err)
- }
-
- return err
+// LogfmtHandlerWithLevel returns the same handler as LogfmtHandler but it only outputs
+// records which are less than or equal to the specified verbosity level.
+func LogfmtHandlerWithLevel(wr io.Writer, level slog.Level) slog.Handler {
+ return slog.NewTextHandler(wr, &slog.HandlerOptions{
+ ReplaceAttr: builtinReplaceLogfmt,
+ Level: &leveler{level},
})
}
-// ChannelHandler writes all records to the given channel.
-// It blocks if the channel is full. Useful for async processing
-// of log messages, it's used by BufferedHandler.
-func ChannelHandler(recs chan<- *Record) Handler {
- return FuncHandler(func(r *Record) error {
- recs <- r
- return nil
- })
+func builtinReplaceLogfmt(_ []string, attr slog.Attr) slog.Attr {
+ return builtinReplace(nil, attr, true)
}
-// BufferedHandler writes all records to a buffered
-// channel of the given size which flushes into the wrapped
-// handler whenever it is available for writing. Since these
-// writes happen asynchronously, all writes to a BufferedHandler
-// never return an error and any errors from the wrapped handler are ignored.
-func BufferedHandler(bufSize int, h Handler) Handler {
- recs := make(chan *Record, bufSize)
- go func() {
- for m := range recs {
- _ = h.Log(m)
- }
- }()
- return ChannelHandler(recs)
+func builtinReplaceJSON(_ []string, attr slog.Attr) slog.Attr {
+ return builtinReplace(nil, attr, false)
}
-// LazyHandler writes all values to the wrapped handler after evaluating
-// any lazy functions in the record's context. It is already wrapped
-// around StreamHandler and SyslogHandler in this library, you'll only need
-// it if you write your own Handler.
-func LazyHandler(h Handler) Handler {
- return FuncHandler(func(r *Record) error {
- // go through the values (odd indices) and reassign
- // the values of any lazy fn to the result of its execution
- hadErr := false
- for i := 1; i < len(r.Ctx); i += 2 {
- lz, ok := r.Ctx[i].(Lazy)
- if ok {
- v, err := evaluateLazy(lz)
- if err != nil {
- hadErr = true
- r.Ctx[i] = err
- } else {
- if cs, ok := v.(stack.CallStack); ok {
- v = cs.TrimBelow(r.Call).TrimRuntime()
- }
- r.Ctx[i] = v
- }
+func builtinReplace(_ []string, attr slog.Attr, logfmt bool) slog.Attr {
+ switch attr.Key {
+ case slog.TimeKey:
+ if attr.Value.Kind() == slog.KindTime {
+ if logfmt {
+ return slog.String("t", attr.Value.Time().Format(timeFormat))
+ } else {
+ return slog.Attr{Key: "t", Value: attr.Value}
}
}
-
- if hadErr {
- r.Ctx = append(r.Ctx, errorKey, "bad lazy")
+ case slog.LevelKey:
+ if l, ok := attr.Value.Any().(slog.Level); ok {
+ attr = slog.Any("lvl", LevelString(l))
+ return attr
}
-
- return h.Log(r)
- })
-}
-
-func evaluateLazy(lz Lazy) (interface{}, error) {
- t := reflect.TypeOf(lz.Fn)
-
- if t.Kind() != reflect.Func {
- return nil, fmt.Errorf("INVALID_LAZY, not func: %+v", lz.Fn)
- }
-
- if t.NumIn() > 0 {
- return nil, fmt.Errorf("INVALID_LAZY, func takes args: %+v", lz.Fn)
}
- if t.NumOut() == 0 {
- return nil, fmt.Errorf("INVALID_LAZY, no func return val: %+v", lz.Fn)
- }
-
- value := reflect.ValueOf(lz.Fn)
- results := value.Call([]reflect.Value{})
- if len(results) == 1 {
- return results[0].Interface(), nil
- }
- values := make([]interface{}, len(results))
- for i, v := range results {
- values[i] = v.Interface()
+ switch v := attr.Value.Any().(type) {
+ case time.Time:
+ if logfmt {
+ attr = slog.String(attr.Key, v.Format(timeFormat))
+ }
+ case *big.Int:
+ if v == nil {
+ attr.Value = slog.StringValue("")
+ } else {
+ attr.Value = slog.StringValue(v.String())
+ }
+ case *uint256.Int:
+ if v == nil {
+ attr.Value = slog.StringValue("")
+ } else {
+ attr.Value = slog.StringValue(v.Dec())
+ }
+ case fmt.Stringer:
+ if v == nil || (reflect.ValueOf(v).Kind() == reflect.Pointer && reflect.ValueOf(v).IsNil()) {
+ attr.Value = slog.StringValue("")
+ } else {
+ attr.Value = slog.StringValue(v.String())
+ }
}
- return values, nil
-}
-
-// DiscardHandler reports success for all writes but does nothing.
-// It is useful for dynamically disabling logging at runtime via
-// a Logger's SetHandler method.
-func DiscardHandler() Handler {
- return FuncHandler(func(r *Record) error {
- return nil
- })
+ return attr
}
-// Must provides the following Handler creation functions
-// which instead of returning an error parameter only return a Handler
-// and panic on failure: FileHandler, NetHandler, SyslogHandler, SyslogNetHandler
-var Must muster
-
-func must(h Handler, err error) Handler {
+// RotatingFileHandler returns a handler which writes log records to file chunks
+// at the given path. When a file's size reaches the limit, the handler creates
+// a new file named after the timestamp of the first log record it will contain.
+func RotatingFileHandler(filePath string, limit uint, maxBackups uint, level string, rotateHours uint) slog.Handler {
+ if _, err := os.Stat(path.Dir(filePath)); os.IsNotExist(err) {
+ err := os.MkdirAll(path.Dir(filePath), 0755)
+ if err != nil {
+ panic(fmt.Errorf("could not create directory %s, %v", path.Dir(filePath), err))
+ }
+ }
+ logLevel, err := LevelFromString(level)
if err != nil {
panic(err)
}
- return h
-}
-
-type muster struct{}
-
-func (m muster) FileHandler(path string, fmtr Format) Handler {
- return must(FileHandler(path, fmtr))
-}
-
-func (m muster) NetHandler(network, addr string, fmtr Format) Handler {
- return must(NetHandler(network, addr, fmtr))
+ fileWriter := NewAsyncFileWriter(filePath, int64(limit), int(maxBackups), rotateHours)
+ fileWriter.Start()
+ return LogfmtHandlerWithLevel(fileWriter, logLevel)
}
diff --git a/log/handler_glog.go b/log/handler_glog.go
index 6db5f1a4c9..fb1e03c5b5 100644
--- a/log/handler_glog.go
+++ b/log/handler_glog.go
@@ -17,6 +17,7 @@
package log
import (
+ "context"
"errors"
"fmt"
"regexp"
@@ -25,54 +26,47 @@ import (
"strings"
"sync"
"sync/atomic"
+
+ "golang.org/x/exp/slog"
)
// errVmoduleSyntax is returned when a user vmodule pattern is invalid.
var errVmoduleSyntax = errors.New("expect comma-separated list of filename=N")
-// errTraceSyntax is returned when a user backtrace pattern is invalid.
-var errTraceSyntax = errors.New("expect file.go:234")
-
// GlogHandler is a log handler that mimics the filtering features of Google's
// glog logger: setting global log levels; overriding with callsite pattern
// matches; and requesting backtraces at certain positions.
type GlogHandler struct {
- origin Handler // The origin handler this wraps
+ origin slog.Handler // The origin handler this wraps
- level atomic.Uint32 // Current log level, atomically accessible
- override atomic.Bool // Flag whether overrides are used, atomically accessible
- backtrace atomic.Bool // Flag whether backtrace location is set
+ level atomic.Int32 // Current log level, atomically accessible
+ override atomic.Bool // Flag whether overrides are used, atomically accessible
- patterns []pattern // Current list of patterns to override with
- siteCache map[uintptr]Lvl // Cache of callsite pattern evaluations
- location string // file:line location where to do a stackdump at
- lock sync.RWMutex // Lock protecting the override pattern list
+ patterns []pattern // Current list of patterns to override with
+ siteCache map[uintptr]slog.Level // Cache of callsite pattern evaluations
+ location string // file:line location where to do a stackdump at
+ lock sync.RWMutex // Lock protecting the override pattern list
}
// NewGlogHandler creates a new log handler with filtering functionality similar
// to Google's glog logger. The returned handler implements Handler.
-func NewGlogHandler(h Handler) *GlogHandler {
+func NewGlogHandler(h slog.Handler) *GlogHandler {
return &GlogHandler{
origin: h,
}
}
-// SetHandler updates the handler to write records to the specified sub-handler.
-func (h *GlogHandler) SetHandler(nh Handler) {
- h.origin = nh
-}
-
// pattern contains a filter for the Vmodule option, holding a verbosity level
// and a file pattern to match.
type pattern struct {
pattern *regexp.Regexp
- level Lvl
+ level slog.Level
}
// Verbosity sets the glog verbosity ceiling. The verbosity of individual packages
// and source files can be raised using Vmodule.
-func (h *GlogHandler) Verbosity(level Lvl) {
- h.level.Store(uint32(level))
+func (h *GlogHandler) Verbosity(level slog.Level) {
+ h.level.Store(int32(level))
}
// Vmodule sets the glog verbosity pattern.
@@ -108,11 +102,13 @@ func (h *GlogHandler) Vmodule(ruleset string) error {
return errVmoduleSyntax
}
// Parse the level and if correct, assemble the filter rule
- level, err := strconv.Atoi(parts[1])
+ l, err := strconv.Atoi(parts[1])
if err != nil {
return errVmoduleSyntax
}
- if level <= 0 {
+ level := FromLegacyLevel(l)
+
+ if level == LevelCrit {
continue // Ignore. It's harmless but no point in paying the overhead.
}
// Compile the rule pattern into a regular expression
@@ -130,103 +126,84 @@ func (h *GlogHandler) Vmodule(ruleset string) error {
matcher = matcher + "$"
re, _ := regexp.Compile(matcher)
- filter = append(filter, pattern{re, Lvl(level)})
+ filter = append(filter, pattern{re, level})
}
// Swap out the vmodule pattern for the new filter system
h.lock.Lock()
defer h.lock.Unlock()
h.patterns = filter
- h.siteCache = make(map[uintptr]Lvl)
+ h.siteCache = make(map[uintptr]slog.Level)
h.override.Store(len(filter) != 0)
return nil
}
-// BacktraceAt sets the glog backtrace location. When set to a file and line
-// number holding a logging statement, a stack trace will be written to the Info
-// log whenever execution hits that statement.
-//
-// Unlike with Vmodule, the ".go" must be present.
-func (h *GlogHandler) BacktraceAt(location string) error {
- // Ensure the backtrace location contains two non-empty elements
- parts := strings.Split(location, ":")
- if len(parts) != 2 {
- return errTraceSyntax
- }
- parts[0] = strings.TrimSpace(parts[0])
- parts[1] = strings.TrimSpace(parts[1])
- if len(parts[0]) == 0 || len(parts[1]) == 0 {
- return errTraceSyntax
- }
- // Ensure the .go prefix is present and the line is valid
- if !strings.HasSuffix(parts[0], ".go") {
- return errTraceSyntax
+func (h *GlogHandler) Enabled(ctx context.Context, lvl slog.Level) bool {
+ // fast-track skipping logging if override not enabled and the provided verbosity is above configured
+ return h.override.Load() || slog.Level(h.level.Load()) <= lvl
+}
+
+func (h *GlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+ h.lock.RLock()
+ siteCache := make(map[uintptr]slog.Level)
+ for k, v := range h.siteCache {
+ siteCache[k] = v
}
- if _, err := strconv.Atoi(parts[1]); err != nil {
- return errTraceSyntax
+ h.lock.RUnlock()
+
+ patterns := []pattern{}
+ patterns = append(patterns, h.patterns...)
+
+ res := GlogHandler{
+ origin: h.origin.WithAttrs(attrs),
+ patterns: patterns,
+ siteCache: siteCache,
+ location: h.location,
}
- // All seems valid
- h.lock.Lock()
- defer h.lock.Unlock()
- h.location = location
- h.backtrace.Store(len(location) > 0)
+ res.level.Store(h.level.Load())
+ res.override.Store(h.override.Load())
+ return &res
+}
- return nil
+func (h *GlogHandler) WithGroup(name string) slog.Handler {
+ panic("not implemented")
}
// Log implements Handler.Log, filtering a log record through the global, local
// and backtrace filters, finally emitting it if either allow it through.
-func (h *GlogHandler) Log(r *Record) error {
- // If backtracing is requested, check whether this is the callsite
- if h.backtrace.Load() {
- // Everything below here is slow. Although we could cache the call sites the
- // same way as for vmodule, backtracing is so rare it's not worth the extra
- // complexity.
- h.lock.RLock()
- match := h.location == r.Call.String()
- h.lock.RUnlock()
-
- if match {
- // Callsite matched, raise the log level to info and gather the stacks
- r.Lvl = LvlInfo
-
- buf := make([]byte, 1024*1024)
- buf = buf[:runtime.Stack(buf, true)]
- r.Msg += "\n\n" + string(buf)
- }
- }
+func (h *GlogHandler) Handle(_ context.Context, r slog.Record) error {
// If the global log level allows, fast track logging
- if h.level.Load() >= uint32(r.Lvl) {
- return h.origin.Log(r)
- }
- // If no local overrides are present, fast track skipping
- if !h.override.Load() {
- return nil
+ if slog.Level(h.level.Load()) <= r.Level {
+ return h.origin.Handle(context.Background(), r)
}
+
// Check callsite cache for previously calculated log levels
h.lock.RLock()
- lvl, ok := h.siteCache[r.Call.Frame().PC]
+ lvl, ok := h.siteCache[r.PC]
h.lock.RUnlock()
// If we didn't cache the callsite yet, calculate it
if !ok {
h.lock.Lock()
+
+ fs := runtime.CallersFrames([]uintptr{r.PC})
+ frame, _ := fs.Next()
+
for _, rule := range h.patterns {
- if rule.pattern.MatchString(fmt.Sprintf("%+s", r.Call)) {
- h.siteCache[r.Call.Frame().PC], lvl, ok = rule.level, rule.level, true
- break
+ if rule.pattern.MatchString(fmt.Sprintf("%+s", frame.File)) {
+ h.siteCache[r.PC], lvl, ok = rule.level, rule.level, true
}
}
// If no rule matched, remember to drop log the next time
if !ok {
- h.siteCache[r.Call.Frame().PC] = 0
+ h.siteCache[r.PC] = 0
}
h.lock.Unlock()
}
- if lvl >= r.Lvl {
- return h.origin.Log(r)
+ if lvl <= r.Level {
+ return h.origin.Handle(context.Background(), r)
}
return nil
}
diff --git a/log/handler_go13.go b/log/handler_go13.go
deleted file mode 100644
index 4df694debe..0000000000
--- a/log/handler_go13.go
+++ /dev/null
@@ -1,27 +0,0 @@
-//go:build !go1.4
-// +build !go1.4
-
-package log
-
-import (
- "sync/atomic"
- "unsafe"
-)
-
-// swapHandler wraps another handler that may be swapped out
-// dynamically at runtime in a thread-safe fashion.
-type swapHandler struct {
- handler unsafe.Pointer
-}
-
-func (h *swapHandler) Log(r *Record) error {
- return h.Get().Log(r)
-}
-
-func (h *swapHandler) Get() Handler {
- return *(*Handler)(atomic.LoadPointer(&h.handler))
-}
-
-func (h *swapHandler) Swap(newHandler Handler) {
- atomic.StorePointer(&h.handler, unsafe.Pointer(&newHandler))
-}
diff --git a/log/handler_go14.go b/log/handler_go14.go
deleted file mode 100644
index d0cb14aa06..0000000000
--- a/log/handler_go14.go
+++ /dev/null
@@ -1,24 +0,0 @@
-//go:build go1.4
-// +build go1.4
-
-package log
-
-import "sync/atomic"
-
-// swapHandler wraps another handler that may be swapped out
-// dynamically at runtime in a thread-safe fashion.
-type swapHandler struct {
- handler atomic.Value
-}
-
-func (h *swapHandler) Log(r *Record) error {
- return (*h.handler.Load().(*Handler)).Log(r)
-}
-
-func (h *swapHandler) Swap(newHandler Handler) {
- h.handler.Store(&newHandler)
-}
-
-func (h *swapHandler) Get() Handler {
- return *h.handler.Load().(*Handler)
-}
diff --git a/log/logger.go b/log/logger.go
index 3223742ea7..91c9fed097 100644
--- a/log/logger.go
+++ b/log/logger.go
@@ -1,303 +1,232 @@
package log
import (
+ "context"
"fmt"
+ "math"
"os"
+ "runtime"
"time"
- "github.com/go-stack/stack"
+ "golang.org/x/exp/slog"
)
-const timeKey = "t"
-const lvlKey = "lvl"
-const msgKey = "msg"
-const ctxKey = "ctx"
-const errorKey = "LOG15_ERROR"
-const skipLevel = 2
+const errorKey = "LOG_ERROR"
-type Lvl int
+const (
+ legacyLevelCrit = iota
+ legacyLevelError
+ legacyLevelWarn
+ legacyLevelInfo
+ legacyLevelDebug
+ legacyLevelTrace
+)
const (
- LvlCrit Lvl = iota
- LvlError
- LvlWarn
- LvlInfo
- LvlDebug
- LvlTrace
+ levelMaxVerbosity slog.Level = math.MinInt
+ LevelTrace slog.Level = -8
+ LevelDebug = slog.LevelDebug
+ LevelInfo = slog.LevelInfo
+ LevelWarn = slog.LevelWarn
+ LevelError = slog.LevelError
+ LevelCrit slog.Level = 12
+
+ // for backward-compatibility
+ LvlTrace = LevelTrace
+ LvlInfo = LevelInfo
+ LvlDebug = LevelDebug
)
-// AlignedString returns a 5-character string containing the name of a Lvl.
-func (l Lvl) AlignedString() string {
+// convert from old Geth verbosity level constants
+// to levels defined by slog
+func FromLegacyLevel(lvl int) slog.Level {
+ switch lvl {
+ case legacyLevelCrit:
+ return LevelCrit
+ case legacyLevelError:
+ return slog.LevelError
+ case legacyLevelWarn:
+ return slog.LevelWarn
+ case legacyLevelInfo:
+ return slog.LevelInfo
+ case legacyLevelDebug:
+ return slog.LevelDebug
+ case legacyLevelTrace:
+ return LevelTrace
+ default:
+ break
+ }
+
+ // TODO: should we allow use of custom levels or force them to match existing max/min if they fall outside the range as I am doing here?
+ if lvl > legacyLevelTrace {
+ return LevelTrace
+ }
+ return LevelCrit
+}
+
+// LevelAlignedString returns a 5-character string containing the name of a Lvl.
+func LevelAlignedString(l slog.Level) string {
switch l {
- case LvlTrace:
+ case LevelTrace:
return "TRACE"
- case LvlDebug:
+ case slog.LevelDebug:
return "DEBUG"
- case LvlInfo:
+ case slog.LevelInfo:
return "INFO "
- case LvlWarn:
+ case slog.LevelWarn:
return "WARN "
- case LvlError:
+ case slog.LevelError:
return "ERROR"
- case LvlCrit:
+ case LevelCrit:
return "CRIT "
default:
- panic("bad level")
+ return "unknown level"
}
}
-// String returns the name of a Lvl.
-func (l Lvl) String() string {
+// LevelString returns a string containing the name of a Lvl.
+func LevelString(l slog.Level) string {
switch l {
- case LvlTrace:
- return "trce"
- case LvlDebug:
- return "dbug"
- case LvlInfo:
+ case LevelTrace:
+ return "trace"
+ case slog.LevelDebug:
+ return "debug"
+ case slog.LevelInfo:
return "info"
- case LvlWarn:
+ case slog.LevelWarn:
return "warn"
- case LvlError:
- return "eror"
- case LvlCrit:
+ case slog.LevelError:
+ return "error"
+ case LevelCrit:
return "crit"
default:
- panic("bad level")
+ return "unknown"
}
}
-// LvlFromString returns the appropriate Lvl from a string name.
+// LevelFromString returns the appropriate Lvl from a string name.
// Useful for parsing command line args and configuration files.
-func LvlFromString(lvlString string) (Lvl, error) {
+func LevelFromString(lvlString string) (slog.Level, error) {
switch lvlString {
case "trace", "trce":
- return LvlTrace, nil
+ return LevelTrace, nil
case "debug", "dbug":
- return LvlDebug, nil
+ return LevelDebug, nil
case "info":
- return LvlInfo, nil
+ return LevelInfo, nil
case "warn":
- return LvlWarn, nil
+ return LevelWarn, nil
case "error", "eror":
- return LvlError, nil
+ return LevelError, nil
case "crit":
- return LvlCrit, nil
+ return LevelCrit, nil
default:
return LvlDebug, fmt.Errorf("unknown level: %v", lvlString)
}
}
-// A Record is what a Logger asks its handler to write
-type Record struct {
- Time time.Time
- Lvl Lvl
- Msg string
- Ctx []interface{}
- Call stack.Call
- KeyNames RecordKeyNames
-}
-
-// RecordKeyNames gets stored in a Record when the write function is executed.
-type RecordKeyNames struct {
- Time string
- Msg string
- Lvl string
- Ctx string
-}
-
// A Logger writes key/value pairs to a Handler
type Logger interface {
- // New returns a new Logger that has this logger's context plus the given context
- New(ctx ...interface{}) Logger
+ // With returns a new Logger that has this logger's attributes plus the given attributes
+ With(ctx ...interface{}) Logger
- // GetHandler gets the handler associated with the logger.
- GetHandler() Handler
+ // With returns a new Logger that has this logger's attributes plus the given attributes. Identical to 'With'.
+ New(ctx ...interface{}) Logger
- // SetHandler updates the logger to write records to the specified handler.
- SetHandler(h Handler)
+ // Log logs a message at the specified level with context key/value pairs
+ Log(level slog.Level, msg string, ctx ...interface{})
- // Log a message at the trace level with context key/value pairs
- //
- // # Usage
- //
- // log.Trace("msg")
- // log.Trace("msg", "key1", val1)
- // log.Trace("msg", "key1", val1, "key2", val2)
+ // Trace log a message at the trace level with context key/value pairs
Trace(msg string, ctx ...interface{})
- // Log a message at the debug level with context key/value pairs
- //
- // # Usage Examples
- //
- // log.Debug("msg")
- // log.Debug("msg", "key1", val1)
- // log.Debug("msg", "key1", val1, "key2", val2)
+ // Debug logs a message at the debug level with context key/value pairs
Debug(msg string, ctx ...interface{})
- // Log a message at the info level with context key/value pairs
- //
- // # Usage Examples
- //
- // log.Info("msg")
- // log.Info("msg", "key1", val1)
- // log.Info("msg", "key1", val1, "key2", val2)
+ // Info logs a message at the info level with context key/value pairs
Info(msg string, ctx ...interface{})
- // Log a message at the warn level with context key/value pairs
- //
- // # Usage Examples
- //
- // log.Warn("msg")
- // log.Warn("msg", "key1", val1)
- // log.Warn("msg", "key1", val1, "key2", val2)
+ // Warn logs a message at the warn level with context key/value pairs
Warn(msg string, ctx ...interface{})
- // Log a message at the error level with context key/value pairs
- //
- // # Usage Examples
- //
- // log.Error("msg")
- // log.Error("msg", "key1", val1)
- // log.Error("msg", "key1", val1, "key2", val2)
+ // Error logs a message at the error level with context key/value pairs
Error(msg string, ctx ...interface{})
- // Log a message at the crit level with context key/value pairs, and then exit.
- //
- // # Usage Examples
- //
- // log.Crit("msg")
- // log.Crit("msg", "key1", val1)
- // log.Crit("msg", "key1", val1, "key2", val2)
+ // Crit logs a message at the crit level with context key/value pairs, and exits
Crit(msg string, ctx ...interface{})
-}
-type logger struct {
- ctx []interface{}
- h *swapHandler
-}
+ // Write logs a message at the specified level
+ Write(level slog.Level, msg string, attrs ...any)
-func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) {
- l.h.Log(&Record{
- Time: time.Now(),
- Lvl: lvl,
- Msg: msg,
- Ctx: newContext(l.ctx, ctx),
- Call: stack.Caller(skip),
- KeyNames: RecordKeyNames{
- Time: timeKey,
- Msg: msgKey,
- Lvl: lvlKey,
- Ctx: ctxKey,
- },
- })
+ // Enabled reports whether l emits log records at the given context and level.
+ Enabled(ctx context.Context, level slog.Level) bool
}
-func (l *logger) New(ctx ...interface{}) Logger {
- child := &logger{newContext(l.ctx, ctx), new(swapHandler)}
- child.SetHandler(l.h)
- return child
+type logger struct {
+ inner *slog.Logger
}
-func newContext(prefix []interface{}, suffix []interface{}) []interface{} {
- normalizedSuffix := normalize(suffix)
- newCtx := make([]interface{}, len(prefix)+len(normalizedSuffix))
- n := copy(newCtx, prefix)
- copy(newCtx[n:], normalizedSuffix)
- return newCtx
+// NewLogger returns a logger with the specified handler set
+func NewLogger(h slog.Handler) Logger {
+ return &logger{
+ slog.New(h),
+ }
}
-func (l *logger) Trace(msg string, ctx ...interface{}) {
- l.write(msg, LvlTrace, ctx, skipLevel)
-}
+// write logs a message at the specified level:
+func (l *logger) Write(level slog.Level, msg string, attrs ...any) {
+ if !l.inner.Enabled(context.Background(), level) {
+ return
+ }
-func (l *logger) Debug(msg string, ctx ...interface{}) {
- l.write(msg, LvlDebug, ctx, skipLevel)
-}
+ var pcs [1]uintptr
+ runtime.Callers(3, pcs[:])
-func (l *logger) Info(msg string, ctx ...interface{}) {
- l.write(msg, LvlInfo, ctx, skipLevel)
+ if len(attrs)%2 != 0 {
+ attrs = append(attrs, nil, errorKey, "Normalized odd number of arguments by adding nil")
+ }
+ r := slog.NewRecord(time.Now(), level, msg, pcs[0])
+ r.Add(attrs...)
+ l.inner.Handler().Handle(context.Background(), r)
}
-func (l *logger) Warn(msg string, ctx ...interface{}) {
- l.write(msg, LvlWarn, ctx, skipLevel)
+func (l *logger) Log(level slog.Level, msg string, attrs ...any) {
+ l.Write(level, msg, attrs...)
}
-func (l *logger) Error(msg string, ctx ...interface{}) {
- l.write(msg, LvlError, ctx, skipLevel)
+func (l *logger) With(ctx ...interface{}) Logger {
+ return &logger{l.inner.With(ctx...)}
}
-func (l *logger) Crit(msg string, ctx ...interface{}) {
- l.write(msg, LvlCrit, ctx, skipLevel)
- os.Exit(1)
+func (l *logger) New(ctx ...interface{}) Logger {
+ return l.With(ctx...)
}
-func (l *logger) GetHandler() Handler {
- return l.h.Get()
+// Enabled reports whether l emits log records at the given context and level.
+func (l *logger) Enabled(ctx context.Context, level slog.Level) bool {
+ return l.inner.Enabled(ctx, level)
}
-func (l *logger) SetHandler(h Handler) {
- l.h.Swap(h)
+func (l *logger) Trace(msg string, ctx ...interface{}) {
+ l.Write(LevelTrace, msg, ctx...)
}
-func normalize(ctx []interface{}) []interface{} {
- // if the caller passed a Ctx object, then expand it
- if len(ctx) == 1 {
- if ctxMap, ok := ctx[0].(Ctx); ok {
- ctx = ctxMap.toArray()
- }
- }
-
- // ctx needs to be even because it's a series of key/value pairs
- // no one wants to check for errors on logging functions,
- // so instead of erroring on bad input, we'll just make sure
- // that things are the right length and users can fix bugs
- // when they see the output looks wrong
- if len(ctx)%2 != 0 {
- ctx = append(ctx, nil, errorKey, "Normalized odd number of arguments by adding nil")
- }
-
- return ctx
+func (l *logger) Debug(msg string, ctx ...interface{}) {
+ l.Write(slog.LevelDebug, msg, ctx...)
}
-// Lazy allows you to defer calculation of a logged value that is expensive
-// to compute until it is certain that it must be evaluated with the given filters.
-//
-// Lazy may also be used in conjunction with a Logger's New() function
-// to generate a child logger which always reports the current value of changing
-// state.
-//
-// You may wrap any function which takes no arguments to Lazy. It may return any
-// number of values of any type.
-type Lazy struct {
- Fn interface{}
+func (l *logger) Info(msg string, ctx ...interface{}) {
+ l.Write(slog.LevelInfo, msg, ctx...)
}
-// Ctx is a map of key/value pairs to pass as context to a log function
-// Use this only if you really need greater safety around the arguments you pass
-// to the logging functions.
-type Ctx map[string]interface{}
-
-func (c Ctx) toArray() []interface{} {
- arr := make([]interface{}, len(c)*2)
-
- i := 0
- for k, v := range c {
- arr[i] = k
- arr[i+1] = v
- i += 2
- }
+func (l *logger) Warn(msg string, ctx ...any) {
+ l.Write(slog.LevelWarn, msg, ctx...)
+}
- return arr
+func (l *logger) Error(msg string, ctx ...interface{}) {
+ l.Write(slog.LevelError, msg, ctx...)
}
-func NewFileLvlHandler(logPath string, maxBytesSize uint, maxBackups uint, level string, rotateHours uint) Handler {
- rfh, err := RotatingFileHandler(logPath, maxBytesSize, maxBackups, LogfmtFormat(), rotateHours)
- if err != nil {
- panic(err)
- }
- logLevel, err := LvlFromString(level)
- if err != nil {
- panic(err)
- }
- return LvlFilterHandler(logLevel, rfh)
+func (l *logger) Crit(msg string, ctx ...interface{}) {
+ l.Write(LevelCrit, msg, ctx...)
+ os.Exit(1)
}
diff --git a/log/logger_test.go b/log/logger_test.go
new file mode 100644
index 0000000000..6d706c6cc7
--- /dev/null
+++ b/log/logger_test.go
@@ -0,0 +1,170 @@
+package log
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "math/big"
+ "os"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/holiman/uint256"
+ "golang.org/x/exp/slog"
+)
+
+// TestLoggingWithVmodule checks that vmodule works.
+func TestLoggingWithVmodule(t *testing.T) {
+ out := new(bytes.Buffer)
+ glog := NewGlogHandler(NewTerminalHandlerWithLevel(out, LevelTrace, false))
+ glog.Verbosity(LevelCrit)
+ logger := NewLogger(glog)
+ logger.Warn("This should not be seen", "ignored", "true")
+ glog.Vmodule("logger_test.go=5")
+ logger.Trace("a message", "foo", "bar")
+ have := out.String()
+ // The timestamp is locale-dependent, so we want to trim that off
+ // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..."
+ have = strings.Split(have, "]")[1]
+ want := " a message foo=bar\n"
+ if have != want {
+ t.Errorf("\nhave: %q\nwant: %q\n", have, want)
+ }
+}
+
+func TestTerminalHandlerWithAttrs(t *testing.T) {
+ out := new(bytes.Buffer)
+ glog := NewGlogHandler(NewTerminalHandlerWithLevel(out, LevelTrace, false).WithAttrs([]slog.Attr{slog.String("baz", "bat")}))
+ glog.Verbosity(LevelTrace)
+ logger := NewLogger(glog)
+ logger.Trace("a message", "foo", "bar")
+ have := out.String()
+ // The timestamp is locale-dependent, so we want to trim that off
+ // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..."
+ have = strings.Split(have, "]")[1]
+ want := " a message baz=bat foo=bar\n"
+ if have != want {
+ t.Errorf("\nhave: %q\nwant: %q\n", have, want)
+ }
+}
+
+func BenchmarkTraceLogging(b *testing.B) {
+ SetDefault(NewLogger(NewTerminalHandler(os.Stderr, true)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Trace("a message", "v", i)
+ }
+}
+
+func BenchmarkTerminalHandler(b *testing.B) {
+ l := NewLogger(NewTerminalHandler(io.Discard, false))
+ benchmarkLogger(b, l)
+}
+func BenchmarkLogfmtHandler(b *testing.B) {
+ l := NewLogger(LogfmtHandler(io.Discard))
+ benchmarkLogger(b, l)
+}
+
+func BenchmarkJSONHandler(b *testing.B) {
+ l := NewLogger(JSONHandler(io.Discard))
+ benchmarkLogger(b, l)
+}
+
+func benchmarkLogger(b *testing.B, l Logger) {
+ var (
+ bb = make([]byte, 10)
+ tt = time.Now()
+ bigint = big.NewInt(100)
+ nilbig *big.Int
+ err = fmt.Errorf("Oh nooes it's crap")
+ )
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ l.Info("This is a message",
+ "foo", int16(i),
+ "bytes", bb,
+ "bonk", "a string with text",
+ "time", tt,
+ "bigint", bigint,
+ "nilbig", nilbig,
+ "err", err)
+ }
+ b.StopTimer()
+}
+
+func TestLoggerOutput(t *testing.T) {
+ type custom struct {
+ A string
+ B int8
+ }
+ var (
+ customA = custom{"Foo", 12}
+ customB = custom{"Foo\nLinebreak", 122}
+ bb = make([]byte, 10)
+ tt = time.Time{}
+ bigint = big.NewInt(100)
+ nilbig *big.Int
+ err = fmt.Errorf("Oh nooes it's crap")
+ smallUint = uint256.NewInt(500_000)
+ bigUint = &uint256.Int{0xff, 0xff, 0xff, 0xff}
+ )
+
+ out := new(bytes.Buffer)
+ glogHandler := NewGlogHandler(NewTerminalHandler(out, false))
+ glogHandler.Verbosity(LevelInfo)
+ NewLogger(glogHandler).Info("This is a message",
+ "foo", int16(123),
+ "bytes", bb,
+ "bonk", "a string with text",
+ "time", tt,
+ "bigint", bigint,
+ "nilbig", nilbig,
+ "err", err,
+ "struct", customA,
+ "struct", customB,
+ "ptrstruct", &customA,
+ "smalluint", smallUint,
+ "bigUint", bigUint)
+
+ have := out.String()
+ t.Logf("output %v", out.String())
+ want := `INFO [11-07|19:14:33.821] This is a message foo=123 bytes="[0 0 0 0 0 0 0 0 0 0]" bonk="a string with text" time=0001-01-01T00:00:00+0000 bigint=100 nilbig= err="Oh nooes it's crap" struct="{A:Foo B:12}" struct="{A:Foo\nLinebreak B:122}" ptrstruct="&{A:Foo B:12}" smalluint=500,000 bigUint=1,600,660,942,523,603,594,864,898,306,482,794,244,293,965,082,972,225,630,372,095
+`
+ if !bytes.Equal([]byte(have)[25:], []byte(want)[25:]) {
+ t.Errorf("Error\nhave: %q\nwant: %q", have, want)
+ }
+}
+
+func BenchmarkAppendFormat(b *testing.B) {
+ var now = time.Now()
+ b.Run("fmt time.Format", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ fmt.Fprintf(io.Discard, "%s", now.Format(termTimeFormat))
+ }
+ })
+ b.Run("time.AppendFormat", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ now.AppendFormat(nil, termTimeFormat)
+ }
+ })
+ var buf = new(bytes.Buffer)
+ b.Run("time.Custom", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ writeTimeTermFormat(buf, now)
+ buf.Reset()
+ }
+ })
+}
+
+func TestTermTimeFormat(t *testing.T) {
+ var now = time.Now()
+ want := now.AppendFormat(nil, termTimeFormat)
+ var b = new(bytes.Buffer)
+ writeTimeTermFormat(b, now)
+ have := b.Bytes()
+ if !bytes.Equal(have, want) {
+ t.Errorf("have != want\nhave: %q\nwant: %q\n", have, want)
+ }
+}
diff --git a/log/root.go b/log/root.go
index c8893bf80c..355991b260 100644
--- a/log/root.go
+++ b/log/root.go
@@ -2,32 +2,33 @@ package log
import (
"os"
+ "sync/atomic"
"time"
-)
-var (
- root = &logger{[]interface{}{}, new(swapHandler)}
- StdoutHandler = StreamHandler(os.Stdout, LogfmtFormat())
- StderrHandler = StreamHandler(os.Stderr, LogfmtFormat())
+ "golang.org/x/exp/slog"
)
+var root atomic.Value
+
func init() {
- root.SetHandler(DiscardHandler())
+ root.Store(&logger{slog.New(DiscardHandler())})
}
-// New returns a new logger with the given context.
-// New is a convenient alias for Root().New
-func New(ctx ...interface{}) Logger {
- return root.New(ctx...)
+// SetDefault sets the default global logger
+func SetDefault(l Logger) {
+ root.Store(l)
+ if lg, ok := l.(*logger); ok {
+ slog.SetDefault(lg.inner)
+ }
}
// Root returns the root logger
func Root() Logger {
- return root
+ return root.Load().(Logger)
}
// The following functions bypass the exported logger methods (logger.Debug,
-// etc.) to keep the call depth the same for all paths to logger.write so
+// etc.) to keep the call depth the same for all paths to logger.Write so
// runtime.Caller(2) always refers to the call site in client code.
// Trace is a convenient alias for Root().Trace
@@ -40,7 +41,7 @@ func Root() Logger {
// log.Trace("msg", "key1", val1)
// log.Trace("msg", "key1", val1, "key2", val2)
func Trace(msg string, ctx ...interface{}) {
- root.write(msg, LvlTrace, ctx, skipLevel)
+ Root().Write(LevelTrace, msg, ctx...)
}
// Debug is a convenient alias for Root().Debug
@@ -53,7 +54,7 @@ func Trace(msg string, ctx ...interface{}) {
// log.Debug("msg", "key1", val1)
// log.Debug("msg", "key1", val1, "key2", val2)
func Debug(msg string, ctx ...interface{}) {
- root.write(msg, LvlDebug, ctx, skipLevel)
+ Root().Write(slog.LevelDebug, msg, ctx...)
}
// Info is a convenient alias for Root().Info
@@ -66,7 +67,7 @@ func Debug(msg string, ctx ...interface{}) {
// log.Info("msg", "key1", val1)
// log.Info("msg", "key1", val1, "key2", val2)
func Info(msg string, ctx ...interface{}) {
- root.write(msg, LvlInfo, ctx, skipLevel)
+ Root().Write(slog.LevelInfo, msg, ctx...)
}
// Warn is a convenient alias for Root().Warn
@@ -79,7 +80,7 @@ func Info(msg string, ctx ...interface{}) {
// log.Warn("msg", "key1", val1)
// log.Warn("msg", "key1", val1, "key2", val2)
func Warn(msg string, ctx ...interface{}) {
- root.write(msg, LvlWarn, ctx, skipLevel)
+ Root().Write(slog.LevelWarn, msg, ctx...)
}
// Error is a convenient alias for Root().Error
@@ -92,7 +93,7 @@ func Warn(msg string, ctx ...interface{}) {
// log.Error("msg", "key1", val1)
// log.Error("msg", "key1", val1, "key2", val2)
func Error(msg string, ctx ...interface{}) {
- root.write(msg, LvlError, ctx, skipLevel)
+ Root().Write(slog.LevelError, msg, ctx...)
}
// Crit is a convenient alias for Root().Crit
@@ -105,16 +106,13 @@ func Error(msg string, ctx ...interface{}) {
// log.Crit("msg", "key1", val1)
// log.Crit("msg", "key1", val1, "key2", val2)
func Crit(msg string, ctx ...interface{}) {
- root.write(msg, LvlCrit, ctx, skipLevel)
+ Root().Write(LevelCrit, msg, ctx...)
time.Sleep(3 * time.Second)
os.Exit(1)
}
-// Output is a convenient alias for write, allowing for the modification of
-// the calldepth (number of stack frames to skip).
-// calldepth influences the reported line number of the log message.
-// A calldepth of zero reports the immediate caller of Output.
-// Non-zero calldepth skips as many stack frames.
-func Output(msg string, lvl Lvl, calldepth int, ctx ...interface{}) {
- root.write(msg, lvl, ctx, calldepth+skipLevel)
+// New returns a new logger with the given context.
+// New is a convenient alias for Root().New
+func New(ctx ...interface{}) Logger {
+ return Root().With(ctx...)
}
diff --git a/log/syslog.go b/log/syslog.go
deleted file mode 100644
index 451d831b6d..0000000000
--- a/log/syslog.go
+++ /dev/null
@@ -1,58 +0,0 @@
-//go:build !windows && !plan9
-// +build !windows,!plan9
-
-package log
-
-import (
- "log/syslog"
- "strings"
-)
-
-// SyslogHandler opens a connection to the system syslog daemon by calling
-// syslog.New and writes all records to it.
-func SyslogHandler(priority syslog.Priority, tag string, fmtr Format) (Handler, error) {
- wr, err := syslog.New(priority, tag)
- return sharedSyslog(fmtr, wr, err)
-}
-
-// SyslogNetHandler opens a connection to a log daemon over the network and writes
-// all log records to it.
-func SyslogNetHandler(net, addr string, priority syslog.Priority, tag string, fmtr Format) (Handler, error) {
- wr, err := syslog.Dial(net, addr, priority, tag)
- return sharedSyslog(fmtr, wr, err)
-}
-
-func sharedSyslog(fmtr Format, sysWr *syslog.Writer, err error) (Handler, error) {
- if err != nil {
- return nil, err
- }
- h := FuncHandler(func(r *Record) error {
- var syslogFn = sysWr.Info
- switch r.Lvl {
- case LvlCrit:
- syslogFn = sysWr.Crit
- case LvlError:
- syslogFn = sysWr.Err
- case LvlWarn:
- syslogFn = sysWr.Warning
- case LvlInfo:
- syslogFn = sysWr.Info
- case LvlDebug:
- syslogFn = sysWr.Debug
- case LvlTrace:
- syslogFn = func(m string) error { return nil } // There's no syslog level for trace
- }
-
- s := strings.TrimSpace(string(fmtr.Format(r)))
- return syslogFn(s)
- })
- return LazyHandler(&closingHandler{sysWr, h}), nil
-}
-
-func (m muster) SyslogHandler(priority syslog.Priority, tag string, fmtr Format) Handler {
- return must(SyslogHandler(priority, tag, fmtr))
-}
-
-func (m muster) SyslogNetHandler(net, addr string, priority syslog.Priority, tag string, fmtr Format) Handler {
- return must(SyslogNetHandler(net, addr, priority, tag, fmtr))
-}
diff --git a/metrics/counter.go b/metrics/counter.go
index 55e1c59540..cb81599c21 100644
--- a/metrics/counter.go
+++ b/metrics/counter.go
@@ -4,13 +4,16 @@ import (
"sync/atomic"
)
+type CounterSnapshot interface {
+ Count() int64
+}
+
// Counters hold an int64 value that can be incremented and decremented.
type Counter interface {
Clear()
- Count() int64
Dec(int64)
Inc(int64)
- Snapshot() Counter
+ Snapshot() CounterSnapshot
}
// GetOrRegisterCounter returns an existing Counter or constructs and registers
@@ -38,13 +41,13 @@ func NewCounter() Counter {
if !Enabled {
return NilCounter{}
}
- return &StandardCounter{}
+ return new(StandardCounter)
}
// NewCounterForced constructs a new StandardCounter and returns it no matter if
// the global switch is enabled or not.
func NewCounterForced() Counter {
- return &StandardCounter{}
+ return new(StandardCounter)
}
// NewRegisteredCounter constructs and registers a new StandardCounter.
@@ -70,75 +73,40 @@ func NewRegisteredCounterForced(name string, r Registry) Counter {
return c
}
-// CounterSnapshot is a read-only copy of another Counter.
-type CounterSnapshot int64
-
-// Clear panics.
-func (CounterSnapshot) Clear() {
- panic("Clear called on a CounterSnapshot")
-}
+// counterSnapshot is a read-only copy of another Counter.
+type counterSnapshot int64
// Count returns the count at the time the snapshot was taken.
-func (c CounterSnapshot) Count() int64 { return int64(c) }
-
-// Dec panics.
-func (CounterSnapshot) Dec(int64) {
- panic("Dec called on a CounterSnapshot")
-}
-
-// Inc panics.
-func (CounterSnapshot) Inc(int64) {
- panic("Inc called on a CounterSnapshot")
-}
-
-// Snapshot returns the snapshot.
-func (c CounterSnapshot) Snapshot() Counter { return c }
+func (c counterSnapshot) Count() int64 { return int64(c) }
// NilCounter is a no-op Counter.
type NilCounter struct{}
-// Clear is a no-op.
-func (NilCounter) Clear() {}
-
-// Count is a no-op.
-func (NilCounter) Count() int64 { return 0 }
-
-// Dec is a no-op.
-func (NilCounter) Dec(i int64) {}
-
-// Inc is a no-op.
-func (NilCounter) Inc(i int64) {}
-
-// Snapshot is a no-op.
-func (NilCounter) Snapshot() Counter { return NilCounter{} }
+func (NilCounter) Clear() {}
+func (NilCounter) Dec(i int64) {}
+func (NilCounter) Inc(i int64) {}
+func (NilCounter) Snapshot() CounterSnapshot { return (*emptySnapshot)(nil) }
// StandardCounter is the standard implementation of a Counter and uses the
// sync/atomic package to manage a single int64 value.
-type StandardCounter struct {
- count atomic.Int64
-}
+type StandardCounter atomic.Int64
// Clear sets the counter to zero.
func (c *StandardCounter) Clear() {
- c.count.Store(0)
-}
-
-// Count returns the current count.
-func (c *StandardCounter) Count() int64 {
- return c.count.Load()
+ (*atomic.Int64)(c).Store(0)
}
// Dec decrements the counter by the given amount.
func (c *StandardCounter) Dec(i int64) {
- c.count.Add(-i)
+ (*atomic.Int64)(c).Add(-i)
}
// Inc increments the counter by the given amount.
func (c *StandardCounter) Inc(i int64) {
- c.count.Add(i)
+ (*atomic.Int64)(c).Add(i)
}
// Snapshot returns a read-only copy of the counter.
-func (c *StandardCounter) Snapshot() Counter {
- return CounterSnapshot(c.Count())
+func (c *StandardCounter) Snapshot() CounterSnapshot {
+ return counterSnapshot((*atomic.Int64)(c).Load())
}
diff --git a/metrics/counter_float64.go b/metrics/counter_float64.go
index d1197bb8e0..15c81494ef 100644
--- a/metrics/counter_float64.go
+++ b/metrics/counter_float64.go
@@ -5,13 +5,16 @@ import (
"sync/atomic"
)
+type CounterFloat64Snapshot interface {
+ Count() float64
+}
+
// CounterFloat64 holds a float64 value that can be incremented and decremented.
type CounterFloat64 interface {
Clear()
- Count() float64
Dec(float64)
Inc(float64)
- Snapshot() CounterFloat64
+ Snapshot() CounterFloat64Snapshot
}
// GetOrRegisterCounterFloat64 returns an existing CounterFloat64 or constructs and registers
@@ -71,47 +74,19 @@ func NewRegisteredCounterFloat64Forced(name string, r Registry) CounterFloat64 {
return c
}
-// CounterFloat64Snapshot is a read-only copy of another CounterFloat64.
-type CounterFloat64Snapshot float64
-
-// Clear panics.
-func (CounterFloat64Snapshot) Clear() {
- panic("Clear called on a CounterFloat64Snapshot")
-}
+// counterFloat64Snapshot is a read-only copy of another CounterFloat64.
+type counterFloat64Snapshot float64
// Count returns the value at the time the snapshot was taken.
-func (c CounterFloat64Snapshot) Count() float64 { return float64(c) }
-
-// Dec panics.
-func (CounterFloat64Snapshot) Dec(float64) {
- panic("Dec called on a CounterFloat64Snapshot")
-}
+func (c counterFloat64Snapshot) Count() float64 { return float64(c) }
-// Inc panics.
-func (CounterFloat64Snapshot) Inc(float64) {
- panic("Inc called on a CounterFloat64Snapshot")
-}
-
-// Snapshot returns the snapshot.
-func (c CounterFloat64Snapshot) Snapshot() CounterFloat64 { return c }
-
-// NilCounterFloat64 is a no-op CounterFloat64.
type NilCounterFloat64 struct{}
-// Clear is a no-op.
-func (NilCounterFloat64) Clear() {}
-
-// Count is a no-op.
-func (NilCounterFloat64) Count() float64 { return 0.0 }
-
-// Dec is a no-op.
-func (NilCounterFloat64) Dec(i float64) {}
-
-// Inc is a no-op.
-func (NilCounterFloat64) Inc(i float64) {}
-
-// Snapshot is a no-op.
-func (NilCounterFloat64) Snapshot() CounterFloat64 { return NilCounterFloat64{} }
+func (NilCounterFloat64) Clear() {}
+func (NilCounterFloat64) Count() float64 { return 0.0 }
+func (NilCounterFloat64) Dec(i float64) {}
+func (NilCounterFloat64) Inc(i float64) {}
+func (NilCounterFloat64) Snapshot() CounterFloat64Snapshot { return NilCounterFloat64{} }
// StandardCounterFloat64 is the standard implementation of a CounterFloat64 and uses the
// atomic to manage a single float64 value.
@@ -124,11 +99,6 @@ func (c *StandardCounterFloat64) Clear() {
c.floatBits.Store(0)
}
-// Count returns the current value.
-func (c *StandardCounterFloat64) Count() float64 {
- return math.Float64frombits(c.floatBits.Load())
-}
-
// Dec decrements the counter by the given amount.
func (c *StandardCounterFloat64) Dec(v float64) {
atomicAddFloat(&c.floatBits, -v)
@@ -140,8 +110,9 @@ func (c *StandardCounterFloat64) Inc(v float64) {
}
// Snapshot returns a read-only copy of the counter.
-func (c *StandardCounterFloat64) Snapshot() CounterFloat64 {
- return CounterFloat64Snapshot(c.Count())
+func (c *StandardCounterFloat64) Snapshot() CounterFloat64Snapshot {
+ v := math.Float64frombits(c.floatBits.Load())
+ return counterFloat64Snapshot(v)
}
func atomicAddFloat(fbits *atomic.Uint64, v float64) {
diff --git a/metrics/counter_float_64_test.go b/metrics/counter_float_64_test.go
index f17aca330c..c21bd3307f 100644
--- a/metrics/counter_float_64_test.go
+++ b/metrics/counter_float_64_test.go
@@ -27,7 +27,7 @@ func BenchmarkCounterFloat64Parallel(b *testing.B) {
}()
}
wg.Wait()
- if have, want := c.Count(), 10.0*float64(b.N); have != want {
+ if have, want := c.Snapshot().Count(), 10.0*float64(b.N); have != want {
b.Fatalf("have %f want %f", have, want)
}
}
@@ -36,7 +36,7 @@ func TestCounterFloat64Clear(t *testing.T) {
c := NewCounterFloat64()
c.Inc(1.0)
c.Clear()
- if count := c.Count(); count != 0 {
+ if count := c.Snapshot().Count(); count != 0 {
t.Errorf("c.Count(): 0 != %v\n", count)
}
}
@@ -44,7 +44,7 @@ func TestCounterFloat64Clear(t *testing.T) {
func TestCounterFloat64Dec1(t *testing.T) {
c := NewCounterFloat64()
c.Dec(1.0)
- if count := c.Count(); count != -1.0 {
+ if count := c.Snapshot().Count(); count != -1.0 {
t.Errorf("c.Count(): -1.0 != %v\n", count)
}
}
@@ -52,7 +52,7 @@ func TestCounterFloat64Dec1(t *testing.T) {
func TestCounterFloat64Dec2(t *testing.T) {
c := NewCounterFloat64()
c.Dec(2.0)
- if count := c.Count(); count != -2.0 {
+ if count := c.Snapshot().Count(); count != -2.0 {
t.Errorf("c.Count(): -2.0 != %v\n", count)
}
}
@@ -60,7 +60,7 @@ func TestCounterFloat64Dec2(t *testing.T) {
func TestCounterFloat64Inc1(t *testing.T) {
c := NewCounterFloat64()
c.Inc(1.0)
- if count := c.Count(); count != 1.0 {
+ if count := c.Snapshot().Count(); count != 1.0 {
t.Errorf("c.Count(): 1.0 != %v\n", count)
}
}
@@ -68,7 +68,7 @@ func TestCounterFloat64Inc1(t *testing.T) {
func TestCounterFloat64Inc2(t *testing.T) {
c := NewCounterFloat64()
c.Inc(2.0)
- if count := c.Count(); count != 2.0 {
+ if count := c.Snapshot().Count(); count != 2.0 {
t.Errorf("c.Count(): 2.0 != %v\n", count)
}
}
@@ -85,7 +85,7 @@ func TestCounterFloat64Snapshot(t *testing.T) {
func TestCounterFloat64Zero(t *testing.T) {
c := NewCounterFloat64()
- if count := c.Count(); count != 0 {
+ if count := c.Snapshot().Count(); count != 0 {
t.Errorf("c.Count(): 0 != %v\n", count)
}
}
@@ -93,7 +93,7 @@ func TestCounterFloat64Zero(t *testing.T) {
func TestGetOrRegisterCounterFloat64(t *testing.T) {
r := NewRegistry()
NewRegisteredCounterFloat64("foo", r).Inc(47.0)
- if c := GetOrRegisterCounterFloat64("foo", r); c.Count() != 47.0 {
+ if c := GetOrRegisterCounterFloat64("foo", r).Snapshot(); c.Count() != 47.0 {
t.Fatal(c)
}
}
diff --git a/metrics/counter_test.go b/metrics/counter_test.go
index af26ef1548..1b15b23f21 100644
--- a/metrics/counter_test.go
+++ b/metrics/counter_test.go
@@ -14,7 +14,7 @@ func TestCounterClear(t *testing.T) {
c := NewCounter()
c.Inc(1)
c.Clear()
- if count := c.Count(); count != 0 {
+ if count := c.Snapshot().Count(); count != 0 {
t.Errorf("c.Count(): 0 != %v\n", count)
}
}
@@ -22,7 +22,7 @@ func TestCounterClear(t *testing.T) {
func TestCounterDec1(t *testing.T) {
c := NewCounter()
c.Dec(1)
- if count := c.Count(); count != -1 {
+ if count := c.Snapshot().Count(); count != -1 {
t.Errorf("c.Count(): -1 != %v\n", count)
}
}
@@ -30,7 +30,7 @@ func TestCounterDec1(t *testing.T) {
func TestCounterDec2(t *testing.T) {
c := NewCounter()
c.Dec(2)
- if count := c.Count(); count != -2 {
+ if count := c.Snapshot().Count(); count != -2 {
t.Errorf("c.Count(): -2 != %v\n", count)
}
}
@@ -38,7 +38,7 @@ func TestCounterDec2(t *testing.T) {
func TestCounterInc1(t *testing.T) {
c := NewCounter()
c.Inc(1)
- if count := c.Count(); count != 1 {
+ if count := c.Snapshot().Count(); count != 1 {
t.Errorf("c.Count(): 1 != %v\n", count)
}
}
@@ -46,7 +46,7 @@ func TestCounterInc1(t *testing.T) {
func TestCounterInc2(t *testing.T) {
c := NewCounter()
c.Inc(2)
- if count := c.Count(); count != 2 {
+ if count := c.Snapshot().Count(); count != 2 {
t.Errorf("c.Count(): 2 != %v\n", count)
}
}
@@ -63,7 +63,7 @@ func TestCounterSnapshot(t *testing.T) {
func TestCounterZero(t *testing.T) {
c := NewCounter()
- if count := c.Count(); count != 0 {
+ if count := c.Snapshot().Count(); count != 0 {
t.Errorf("c.Count(): 0 != %v\n", count)
}
}
@@ -71,7 +71,7 @@ func TestCounterZero(t *testing.T) {
func TestGetOrRegisterCounter(t *testing.T) {
r := NewRegistry()
NewRegisteredCounter("foo", r).Inc(47)
- if c := GetOrRegisterCounter("foo", r); c.Count() != 47 {
+ if c := GetOrRegisterCounter("foo", r).Snapshot(); c.Count() != 47 {
t.Fatal(c)
}
}
diff --git a/metrics/disk_nop.go b/metrics/disk_nop.go
index 58fa4e02f8..41bbe9adb2 100644
--- a/metrics/disk_nop.go
+++ b/metrics/disk_nop.go
@@ -23,5 +23,5 @@ import "errors"
// ReadDiskStats retrieves the disk IO stats belonging to the current process.
func ReadDiskStats(stats *DiskStats) error {
- return errors.New("Not implemented")
+ return errors.New("not implemented")
}
diff --git a/metrics/doc.go b/metrics/doc.go
deleted file mode 100644
index 13f429c168..0000000000
--- a/metrics/doc.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package metrics
-
-const epsilon = 0.0000000000000001
-const epsilonPercentile = .00000000001
diff --git a/metrics/ewma.go b/metrics/ewma.go
index ed95cba19b..1d7a4f00cf 100644
--- a/metrics/ewma.go
+++ b/metrics/ewma.go
@@ -7,11 +7,14 @@ import (
"time"
)
+type EWMASnapshot interface {
+ Rate() float64
+}
+
// EWMAs continuously calculate an exponentially-weighted moving average
// based on an outside source of clock ticks.
type EWMA interface {
- Rate() float64
- Snapshot() EWMA
+ Snapshot() EWMASnapshot
Tick()
Update(int64)
}
@@ -36,40 +39,19 @@ func NewEWMA15() EWMA {
return NewEWMA(1 - math.Exp(-5.0/60.0/15))
}
-// EWMASnapshot is a read-only copy of another EWMA.
-type EWMASnapshot float64
+// ewmaSnapshot is a read-only copy of another EWMA.
+type ewmaSnapshot float64
// Rate returns the rate of events per second at the time the snapshot was
// taken.
-func (a EWMASnapshot) Rate() float64 { return float64(a) }
-
-// Snapshot returns the snapshot.
-func (a EWMASnapshot) Snapshot() EWMA { return a }
-
-// Tick panics.
-func (EWMASnapshot) Tick() {
- panic("Tick called on an EWMASnapshot")
-}
-
-// Update panics.
-func (EWMASnapshot) Update(int64) {
- panic("Update called on an EWMASnapshot")
-}
+func (a ewmaSnapshot) Rate() float64 { return float64(a) }
// NilEWMA is a no-op EWMA.
type NilEWMA struct{}
-// Rate is a no-op.
-func (NilEWMA) Rate() float64 { return 0.0 }
-
-// Snapshot is a no-op.
-func (NilEWMA) Snapshot() EWMA { return NilEWMA{} }
-
-// Tick is a no-op.
-func (NilEWMA) Tick() {}
-
-// Update is a no-op.
-func (NilEWMA) Update(n int64) {}
+func (NilEWMA) Snapshot() EWMASnapshot { return (*emptySnapshot)(nil) }
+func (NilEWMA) Tick() {}
+func (NilEWMA) Update(n int64) {}
// StandardEWMA is the standard implementation of an EWMA and tracks the number
// of uncounted events and processes them on each tick. It uses the
@@ -77,37 +59,50 @@ func (NilEWMA) Update(n int64) {}
type StandardEWMA struct {
uncounted atomic.Int64
alpha float64
- rate float64
- init bool
+ rate atomic.Uint64
+ init atomic.Bool
mutex sync.Mutex
}
-// Rate returns the moving average rate of events per second.
-func (a *StandardEWMA) Rate() float64 {
- a.mutex.Lock()
- defer a.mutex.Unlock()
- return a.rate * float64(time.Second)
-}
-
// Snapshot returns a read-only copy of the EWMA.
-func (a *StandardEWMA) Snapshot() EWMA {
- return EWMASnapshot(a.Rate())
+func (a *StandardEWMA) Snapshot() EWMASnapshot {
+ r := math.Float64frombits(a.rate.Load()) * float64(time.Second)
+ return ewmaSnapshot(r)
}
// Tick ticks the clock to update the moving average. It assumes it is called
// every five seconds.
func (a *StandardEWMA) Tick() {
- count := a.uncounted.Load()
- a.uncounted.Add(-count)
- instantRate := float64(count) / float64(5*time.Second)
+ // Optimization to avoid mutex locking in the hot-path.
+ if a.init.Load() {
+ a.updateRate(a.fetchInstantRate())
+ return
+ }
+ // Slow-path: this is only needed on the first Tick() and preserves transactional updating
+ // of init and rate in the else block. The first conditional is needed below because
+ // a different thread could have set a.init = 1 between the time of the first atomic load and when
+ // the lock was acquired.
a.mutex.Lock()
- defer a.mutex.Unlock()
- if a.init {
- a.rate += a.alpha * (instantRate - a.rate)
+ if a.init.Load() {
+ // The fetchInstantRate() uses atomic loading, which is unnecessary in this critical section
+ // but again, this section is only invoked on the first successful Tick() operation.
+ a.updateRate(a.fetchInstantRate())
} else {
- a.init = true
- a.rate = instantRate
+ a.init.Store(true)
+ a.rate.Store(math.Float64bits(a.fetchInstantRate()))
}
+ a.mutex.Unlock()
+}
+
+func (a *StandardEWMA) fetchInstantRate() float64 {
+ count := a.uncounted.Swap(0)
+ return float64(count) / float64(5*time.Second)
+}
+
+func (a *StandardEWMA) updateRate(instantRate float64) {
+ currentRate := math.Float64frombits(a.rate.Load())
+ currentRate += a.alpha * (instantRate - currentRate)
+ a.rate.Store(math.Float64bits(currentRate))
}
// Update adds n uncounted events.
diff --git a/metrics/ewma_test.go b/metrics/ewma_test.go
index 5b24419161..9a91b43db8 100644
--- a/metrics/ewma_test.go
+++ b/metrics/ewma_test.go
@@ -5,6 +5,8 @@ import (
"testing"
)
+const epsilon = 0.0000000000000001
+
func BenchmarkEWMA(b *testing.B) {
a := NewEWMA1()
b.ResetTimer()
@@ -14,72 +16,33 @@ func BenchmarkEWMA(b *testing.B) {
}
}
+func BenchmarkEWMAParallel(b *testing.B) {
+ a := NewEWMA1()
+ b.ResetTimer()
+
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ a.Update(1)
+ a.Tick()
+ }
+ })
+}
+
func TestEWMA1(t *testing.T) {
a := NewEWMA1()
a.Update(3)
a.Tick()
- if rate := a.Rate(); math.Abs(0.6-rate) > epsilon {
- t.Errorf("initial a.Rate(): 0.6 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.22072766470286553-rate) > epsilon {
- t.Errorf("1 minute a.Rate(): 0.22072766470286553 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.08120116994196772-rate) > epsilon {
- t.Errorf("2 minute a.Rate(): 0.08120116994196772 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.029872241020718428-rate) > epsilon {
- t.Errorf("3 minute a.Rate(): 0.029872241020718428 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.01098938333324054-rate) > epsilon {
- t.Errorf("4 minute a.Rate(): 0.01098938333324054 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.004042768199451294-rate) > epsilon {
- t.Errorf("5 minute a.Rate(): 0.004042768199451294 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.0014872513059998212-rate) > epsilon {
- t.Errorf("6 minute a.Rate(): 0.0014872513059998212 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.0005471291793327122-rate) > epsilon {
- t.Errorf("7 minute a.Rate(): 0.0005471291793327122 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.00020127757674150815-rate) > epsilon {
- t.Errorf("8 minute a.Rate(): 0.00020127757674150815 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(7.404588245200814e-05-rate) > epsilon {
- t.Errorf("9 minute a.Rate(): 7.404588245200814e-05 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(2.7239957857491083e-05-rate) > epsilon {
- t.Errorf("10 minute a.Rate(): 2.7239957857491083e-05 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(1.0021020474147462e-05-rate) > epsilon {
- t.Errorf("11 minute a.Rate(): 1.0021020474147462e-05 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(3.6865274119969525e-06-rate) > epsilon {
- t.Errorf("12 minute a.Rate(): 3.6865274119969525e-06 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(1.3561976441886433e-06-rate) > epsilon {
- t.Errorf("13 minute a.Rate(): 1.3561976441886433e-06 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(4.989172314621449e-07-rate) > epsilon {
- t.Errorf("14 minute a.Rate(): 4.989172314621449e-07 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(1.8354139230109722e-07-rate) > epsilon {
- t.Errorf("15 minute a.Rate(): 1.8354139230109722e-07 != %v\n", rate)
+ for i, want := range []float64{0.6,
+ 0.22072766470286553, 0.08120116994196772, 0.029872241020718428,
+ 0.01098938333324054, 0.004042768199451294, 0.0014872513059998212,
+ 0.0005471291793327122, 0.00020127757674150815, 7.404588245200814e-05,
+ 2.7239957857491083e-05, 1.0021020474147462e-05, 3.6865274119969525e-06,
+ 1.3561976441886433e-06, 4.989172314621449e-07, 1.8354139230109722e-07,
+ } {
+ if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon {
+ t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate)
+ }
+ elapseMinute(a)
}
}
@@ -87,68 +50,17 @@ func TestEWMA5(t *testing.T) {
a := NewEWMA5()
a.Update(3)
a.Tick()
- if rate := a.Rate(); math.Abs(0.6-rate) > epsilon {
- t.Errorf("initial a.Rate(): 0.6 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.49123845184678905-rate) > epsilon {
- t.Errorf("1 minute a.Rate(): 0.49123845184678905 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.4021920276213837-rate) > epsilon {
- t.Errorf("2 minute a.Rate(): 0.4021920276213837 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.32928698165641596-rate) > epsilon {
- t.Errorf("3 minute a.Rate(): 0.32928698165641596 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.269597378470333-rate) > epsilon {
- t.Errorf("4 minute a.Rate(): 0.269597378470333 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.2207276647028654-rate) > epsilon {
- t.Errorf("5 minute a.Rate(): 0.2207276647028654 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.18071652714732128-rate) > epsilon {
- t.Errorf("6 minute a.Rate(): 0.18071652714732128 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.14795817836496392-rate) > epsilon {
- t.Errorf("7 minute a.Rate(): 0.14795817836496392 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.12113791079679326-rate) > epsilon {
- t.Errorf("8 minute a.Rate(): 0.12113791079679326 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.09917933293295193-rate) > epsilon {
- t.Errorf("9 minute a.Rate(): 0.09917933293295193 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.08120116994196763-rate) > epsilon {
- t.Errorf("10 minute a.Rate(): 0.08120116994196763 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.06648189501740036-rate) > epsilon {
- t.Errorf("11 minute a.Rate(): 0.06648189501740036 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.05443077197364752-rate) > epsilon {
- t.Errorf("12 minute a.Rate(): 0.05443077197364752 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.04456414692860035-rate) > epsilon {
- t.Errorf("13 minute a.Rate(): 0.04456414692860035 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.03648603757513079-rate) > epsilon {
- t.Errorf("14 minute a.Rate(): 0.03648603757513079 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.0298722410207183831020718428-rate) > epsilon {
- t.Errorf("15 minute a.Rate(): 0.0298722410207183831020718428 != %v\n", rate)
+ for i, want := range []float64{
+ 0.6, 0.49123845184678905, 0.4021920276213837, 0.32928698165641596,
+ 0.269597378470333, 0.2207276647028654, 0.18071652714732128,
+ 0.14795817836496392, 0.12113791079679326, 0.09917933293295193,
+ 0.08120116994196763, 0.06648189501740036, 0.05443077197364752,
+ 0.04456414692860035, 0.03648603757513079, 0.0298722410207183831020718428,
+ } {
+ if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon {
+ t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate)
+ }
+ elapseMinute(a)
}
}
@@ -156,68 +68,17 @@ func TestEWMA15(t *testing.T) {
a := NewEWMA15()
a.Update(3)
a.Tick()
- if rate := a.Rate(); math.Abs(0.6-rate) > epsilon {
- t.Errorf("initial a.Rate(): 0.6 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.5613041910189706-rate) > epsilon {
- t.Errorf("1 minute a.Rate(): 0.5613041910189706 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.5251039914257684-rate) > epsilon {
- t.Errorf("2 minute a.Rate(): 0.5251039914257684 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.4912384518467888184678905-rate) > epsilon {
- t.Errorf("3 minute a.Rate(): 0.4912384518467888184678905 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.459557003018789-rate) > epsilon {
- t.Errorf("4 minute a.Rate(): 0.459557003018789 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.4299187863442732-rate) > epsilon {
- t.Errorf("5 minute a.Rate(): 0.4299187863442732 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.4021920276213831-rate) > epsilon {
- t.Errorf("6 minute a.Rate(): 0.4021920276213831 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.37625345116383313-rate) > epsilon {
- t.Errorf("7 minute a.Rate(): 0.37625345116383313 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.3519877317060185-rate) > epsilon {
- t.Errorf("8 minute a.Rate(): 0.3519877317060185 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.3292869816564153165641596-rate) > epsilon {
- t.Errorf("9 minute a.Rate(): 0.3292869816564153165641596 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.3080502714195546-rate) > epsilon {
- t.Errorf("10 minute a.Rate(): 0.3080502714195546 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.2881831806538789-rate) > epsilon {
- t.Errorf("11 minute a.Rate(): 0.2881831806538789 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.26959737847033216-rate) > epsilon {
- t.Errorf("12 minute a.Rate(): 0.26959737847033216 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.2522102307052083-rate) > epsilon {
- t.Errorf("13 minute a.Rate(): 0.2522102307052083 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.23594443252115815-rate) > epsilon {
- t.Errorf("14 minute a.Rate(): 0.23594443252115815 != %v\n", rate)
- }
- elapseMinute(a)
- if rate := a.Rate(); math.Abs(0.2207276647028646247028654470286553-rate) > epsilon {
- t.Errorf("15 minute a.Rate(): 0.2207276647028646247028654470286553 != %v\n", rate)
+ for i, want := range []float64{
+ 0.6, 0.5613041910189706, 0.5251039914257684, 0.4912384518467888184678905,
+ 0.459557003018789, 0.4299187863442732, 0.4021920276213831,
+ 0.37625345116383313, 0.3519877317060185, 0.3292869816564153165641596,
+ 0.3080502714195546, 0.2881831806538789, 0.26959737847033216,
+ 0.2522102307052083, 0.23594443252115815, 0.2207276647028646247028654470286553,
+ } {
+ if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon {
+ t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate)
+ }
+ elapseMinute(a)
}
}
diff --git a/metrics/exp/exp.go b/metrics/exp/exp.go
index a4c2b09f98..f50ad52644 100644
--- a/metrics/exp/exp.go
+++ b/metrics/exp/exp.go
@@ -109,24 +109,42 @@ func (exp *exp) getMap(name string) *expvar.Map {
return v
}
-func (exp *exp) publishCounter(name string, metric metrics.Counter) {
+func (exp *exp) getInfo(name string) *expvar.String {
+ var v *expvar.String
+ exp.expvarLock.Lock()
+ p := expvar.Get(name)
+ if p != nil {
+ v = p.(*expvar.String)
+ } else {
+ v = new(expvar.String)
+ expvar.Publish(name, v)
+ }
+ exp.expvarLock.Unlock()
+ return v
+}
+
+func (exp *exp) publishCounter(name string, metric metrics.CounterSnapshot) {
v := exp.getInt(name)
v.Set(metric.Count())
}
-func (exp *exp) publishCounterFloat64(name string, metric metrics.CounterFloat64) {
+func (exp *exp) publishCounterFloat64(name string, metric metrics.CounterFloat64Snapshot) {
v := exp.getFloat(name)
v.Set(metric.Count())
}
-func (exp *exp) publishGauge(name string, metric metrics.Gauge) {
+func (exp *exp) publishGauge(name string, metric metrics.GaugeSnapshot) {
v := exp.getInt(name)
v.Set(metric.Value())
}
-func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64) {
+func (exp *exp) publishGaugeFloat64(name string, metric metrics.GaugeFloat64Snapshot) {
exp.getFloat(name).Set(metric.Value())
}
+func (exp *exp) publishGaugeInfo(name string, metric metrics.GaugeInfoSnapshot) {
+ exp.getInfo(name).Set(metric.Value().String())
+}
+
func (exp *exp) publishHistogram(name string, metric metrics.Histogram) {
h := metric.Snapshot()
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
@@ -172,13 +190,13 @@ func (exp *exp) publishTimer(name string, metric metrics.Timer) {
func (exp *exp) publishResettingTimer(name string, metric metrics.ResettingTimer) {
t := metric.Snapshot()
- ps := t.Percentiles([]float64{50, 75, 95, 99})
- exp.getInt(name + ".count").Set(int64(len(t.Values())))
+ ps := t.Percentiles([]float64{0.50, 0.75, 0.95, 0.99})
+ exp.getInt(name + ".count").Set(int64(t.Count()))
exp.getFloat(name + ".mean").Set(t.Mean())
- exp.getInt(name + ".50-percentile").Set(ps[0])
- exp.getInt(name + ".75-percentile").Set(ps[1])
- exp.getInt(name + ".95-percentile").Set(ps[2])
- exp.getInt(name + ".99-percentile").Set(ps[3])
+ exp.getFloat(name + ".50-percentile").Set(ps[0])
+ exp.getFloat(name + ".75-percentile").Set(ps[1])
+ exp.getFloat(name + ".95-percentile").Set(ps[2])
+ exp.getFloat(name + ".99-percentile").Set(ps[3])
}
func (exp *exp) publishLabel(name string, metric metrics.Label) {
@@ -239,13 +257,15 @@ func (exp *exp) syncToExpvar() {
exp.registry.Each(func(name string, i interface{}) {
switch i := i.(type) {
case metrics.Counter:
- exp.publishCounter(name, i)
+ exp.publishCounter(name, i.Snapshot())
case metrics.CounterFloat64:
- exp.publishCounterFloat64(name, i)
+ exp.publishCounterFloat64(name, i.Snapshot())
case metrics.Gauge:
- exp.publishGauge(name, i)
+ exp.publishGauge(name, i.Snapshot())
case metrics.GaugeFloat64:
- exp.publishGaugeFloat64(name, i)
+ exp.publishGaugeFloat64(name, i.Snapshot())
+ case metrics.GaugeInfo:
+ exp.publishGaugeInfo(name, i.Snapshot())
case metrics.Histogram:
exp.publishHistogram(name, i)
case metrics.Meter:
diff --git a/metrics/gauge.go b/metrics/gauge.go
index 81137d7f7c..68f8f11abc 100644
--- a/metrics/gauge.go
+++ b/metrics/gauge.go
@@ -2,13 +2,18 @@ package metrics
import "sync/atomic"
+// gaugeSnapshot contains a readonly int64.
+type GaugeSnapshot interface {
+ Value() int64
+}
+
// Gauges hold an int64 value that can be set arbitrarily.
type Gauge interface {
- Snapshot() Gauge
+ Snapshot() GaugeSnapshot
Update(int64)
+ UpdateIfGt(int64)
Dec(int64)
Inc(int64)
- Value() int64
}
// GetOrRegisterGauge returns an existing Gauge or constructs and registers a
@@ -38,65 +43,20 @@ func NewRegisteredGauge(name string, r Registry) Gauge {
return c
}
-// NewFunctionalGauge constructs a new FunctionalGauge.
-func NewFunctionalGauge(f func() int64) Gauge {
- if !Enabled {
- return NilGauge{}
- }
- return &FunctionalGauge{value: f}
-}
-
-// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge.
-func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge {
- c := NewFunctionalGauge(f)
- if nil == r {
- r = DefaultRegistry
- }
- r.Register(name, c)
- return c
-}
-
-// GaugeSnapshot is a read-only copy of another Gauge.
-type GaugeSnapshot int64
-
-// Snapshot returns the snapshot.
-func (g GaugeSnapshot) Snapshot() Gauge { return g }
-
-// Update panics.
-func (GaugeSnapshot) Update(int64) {
- panic("Update called on a GaugeSnapshot")
-}
-
-// Dec panics.
-func (GaugeSnapshot) Dec(int64) {
- panic("Dec called on a GaugeSnapshot")
-}
-
-// Inc panics.
-func (GaugeSnapshot) Inc(int64) {
- panic("Inc called on a GaugeSnapshot")
-}
+// gaugeSnapshot is a read-only copy of another Gauge.
+type gaugeSnapshot int64
// Value returns the value at the time the snapshot was taken.
-func (g GaugeSnapshot) Value() int64 { return int64(g) }
+func (g gaugeSnapshot) Value() int64 { return int64(g) }
// NilGauge is a no-op Gauge.
type NilGauge struct{}
-// Snapshot is a no-op.
-func (NilGauge) Snapshot() Gauge { return NilGauge{} }
-
-// Update is a no-op.
-func (NilGauge) Update(v int64) {}
-
-// Dec is a no-op.
-func (NilGauge) Dec(i int64) {}
-
-// Inc is a no-op.
-func (NilGauge) Inc(i int64) {}
-
-// Value is a no-op.
-func (NilGauge) Value() int64 { return 0 }
+func (NilGauge) Snapshot() GaugeSnapshot { return (*emptySnapshot)(nil) }
+func (NilGauge) Update(v int64) {}
+func (NilGauge) UpdateIfGt(v int64) {}
+func (NilGauge) Dec(i int64) {}
+func (NilGauge) Inc(i int64) {}
// StandardGauge is the standard implementation of a Gauge and uses the
// sync/atomic package to manage a single int64 value.
@@ -105,8 +65,8 @@ type StandardGauge struct {
}
// Snapshot returns a read-only copy of the gauge.
-func (g *StandardGauge) Snapshot() Gauge {
- return GaugeSnapshot(g.Value())
+func (g *StandardGauge) Snapshot() GaugeSnapshot {
+ return gaugeSnapshot(g.value.Load())
}
// Update updates the gauge's value.
@@ -114,9 +74,17 @@ func (g *StandardGauge) Update(v int64) {
g.value.Store(v)
}
-// Value returns the gauge's current value.
-func (g *StandardGauge) Value() int64 {
- return g.value.Load()
+// Update updates the gauge's value if v is larger then the current valie.
+func (g *StandardGauge) UpdateIfGt(v int64) {
+ for {
+ exist := g.value.Load()
+ if exist >= v {
+ break
+ }
+ if g.value.CompareAndSwap(exist, v) {
+ break
+ }
+ }
}
// Dec decrements the gauge's current value by the given amount.
@@ -128,31 +96,3 @@ func (g *StandardGauge) Dec(i int64) {
func (g *StandardGauge) Inc(i int64) {
g.value.Add(i)
}
-
-// FunctionalGauge returns value from given function
-type FunctionalGauge struct {
- value func() int64
-}
-
-// Value returns the gauge's current value.
-func (g FunctionalGauge) Value() int64 {
- return g.value()
-}
-
-// Snapshot returns the snapshot.
-func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) }
-
-// Update panics.
-func (FunctionalGauge) Update(int64) {
- panic("Update called on a FunctionalGauge")
-}
-
-// Dec panics.
-func (FunctionalGauge) Dec(int64) {
- panic("Dec called on a FunctionalGauge")
-}
-
-// Inc panics.
-func (FunctionalGauge) Inc(int64) {
- panic("Inc called on a FunctionalGauge")
-}
diff --git a/metrics/gauge_float64.go b/metrics/gauge_float64.go
index 237ff8036e..967f2bc60e 100644
--- a/metrics/gauge_float64.go
+++ b/metrics/gauge_float64.go
@@ -5,11 +5,14 @@ import (
"sync/atomic"
)
-// GaugeFloat64s hold a float64 value that can be set arbitrarily.
+type GaugeFloat64Snapshot interface {
+ Value() float64
+}
+
+// GaugeFloat64 hold a float64 value that can be set arbitrarily.
type GaugeFloat64 interface {
- Snapshot() GaugeFloat64
+ Snapshot() GaugeFloat64Snapshot
Update(float64)
- Value() float64
}
// GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a
@@ -39,49 +42,18 @@ func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 {
return c
}
-// NewFunctionalGauge constructs a new FunctionalGauge.
-func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 {
- if !Enabled {
- return NilGaugeFloat64{}
- }
- return &FunctionalGaugeFloat64{value: f}
-}
-
-// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge.
-func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 {
- c := NewFunctionalGaugeFloat64(f)
- if nil == r {
- r = DefaultRegistry
- }
- r.Register(name, c)
- return c
-}
-
-// GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64.
-type GaugeFloat64Snapshot float64
-
-// Snapshot returns the snapshot.
-func (g GaugeFloat64Snapshot) Snapshot() GaugeFloat64 { return g }
-
-// Update panics.
-func (GaugeFloat64Snapshot) Update(float64) {
- panic("Update called on a GaugeFloat64Snapshot")
-}
+// gaugeFloat64Snapshot is a read-only copy of another GaugeFloat64.
+type gaugeFloat64Snapshot float64
// Value returns the value at the time the snapshot was taken.
-func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) }
+func (g gaugeFloat64Snapshot) Value() float64 { return float64(g) }
// NilGauge is a no-op Gauge.
type NilGaugeFloat64 struct{}
-// Snapshot is a no-op.
-func (NilGaugeFloat64) Snapshot() GaugeFloat64 { return NilGaugeFloat64{} }
-
-// Update is a no-op.
-func (NilGaugeFloat64) Update(v float64) {}
-
-// Value is a no-op.
-func (NilGaugeFloat64) Value() float64 { return 0.0 }
+func (NilGaugeFloat64) Snapshot() GaugeFloat64Snapshot { return NilGaugeFloat64{} }
+func (NilGaugeFloat64) Update(v float64) {}
+func (NilGaugeFloat64) Value() float64 { return 0.0 }
// StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses
// atomic to manage a single float64 value.
@@ -90,34 +62,12 @@ type StandardGaugeFloat64 struct {
}
// Snapshot returns a read-only copy of the gauge.
-func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 {
- return GaugeFloat64Snapshot(g.Value())
+func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64Snapshot {
+ v := math.Float64frombits(g.floatBits.Load())
+ return gaugeFloat64Snapshot(v)
}
// Update updates the gauge's value.
func (g *StandardGaugeFloat64) Update(v float64) {
g.floatBits.Store(math.Float64bits(v))
}
-
-// Value returns the gauge's current value.
-func (g *StandardGaugeFloat64) Value() float64 {
- return math.Float64frombits(g.floatBits.Load())
-}
-
-// FunctionalGaugeFloat64 returns value from given function
-type FunctionalGaugeFloat64 struct {
- value func() float64
-}
-
-// Value returns the gauge's current value.
-func (g FunctionalGaugeFloat64) Value() float64 {
- return g.value()
-}
-
-// Snapshot returns the snapshot.
-func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) }
-
-// Update panics.
-func (FunctionalGaugeFloat64) Update(float64) {
- panic("Update called on a FunctionalGaugeFloat64")
-}
diff --git a/metrics/gauge_float64_test.go b/metrics/gauge_float64_test.go
index 647d090009..194a18821f 100644
--- a/metrics/gauge_float64_test.go
+++ b/metrics/gauge_float64_test.go
@@ -26,25 +26,17 @@ func BenchmarkGaugeFloat64Parallel(b *testing.B) {
}()
}
wg.Wait()
- if have, want := c.Value(), float64(b.N-1); have != want {
+ if have, want := c.Snapshot().Value(), float64(b.N-1); have != want {
b.Fatalf("have %f want %f", have, want)
}
}
-func TestGaugeFloat64(t *testing.T) {
- g := NewGaugeFloat64()
- g.Update(47.0)
- if v := g.Value(); 47.0 != v {
- t.Errorf("g.Value(): 47.0 != %v\n", v)
- }
-}
-
func TestGaugeFloat64Snapshot(t *testing.T) {
g := NewGaugeFloat64()
g.Update(47.0)
snapshot := g.Snapshot()
g.Update(float64(0))
- if v := snapshot.Value(); 47.0 != v {
+ if v := snapshot.Value(); v != 47.0 {
t.Errorf("g.Value(): 47.0 != %v\n", v)
}
}
@@ -53,28 +45,7 @@ func TestGetOrRegisterGaugeFloat64(t *testing.T) {
r := NewRegistry()
NewRegisteredGaugeFloat64("foo", r).Update(47.0)
t.Logf("registry: %v", r)
- if g := GetOrRegisterGaugeFloat64("foo", r); 47.0 != g.Value() {
- t.Fatal(g)
- }
-}
-
-func TestFunctionalGaugeFloat64(t *testing.T) {
- var counter float64
- fg := NewFunctionalGaugeFloat64(func() float64 {
- counter++
- return counter
- })
- fg.Value()
- fg.Value()
- if counter != 2 {
- t.Error("counter != 2")
- }
-}
-
-func TestGetOrRegisterFunctionalGaugeFloat64(t *testing.T) {
- r := NewRegistry()
- NewRegisteredFunctionalGaugeFloat64("foo", r, func() float64 { return 47 })
- if g := GetOrRegisterGaugeFloat64("foo", r); g.Value() != 47 {
+ if g := GetOrRegisterGaugeFloat64("foo", r).Snapshot(); g.Value() != 47.0 {
t.Fatal(g)
}
}
diff --git a/metrics/gauge_info.go b/metrics/gauge_info.go
new file mode 100644
index 0000000000..c44b2d85f3
--- /dev/null
+++ b/metrics/gauge_info.go
@@ -0,0 +1,84 @@
+package metrics
+
+import (
+ "encoding/json"
+ "sync"
+)
+
+type GaugeInfoSnapshot interface {
+ Value() GaugeInfoValue
+}
+
+// GaugeInfos hold a GaugeInfoValue value that can be set arbitrarily.
+type GaugeInfo interface {
+ Update(GaugeInfoValue)
+ Snapshot() GaugeInfoSnapshot
+}
+
+// GaugeInfoValue is a mapping of keys to values
+type GaugeInfoValue map[string]string
+
+func (val GaugeInfoValue) String() string {
+ data, _ := json.Marshal(val)
+ return string(data)
+}
+
+// GetOrRegisterGaugeInfo returns an existing GaugeInfo or constructs and registers a
+// new StandardGaugeInfo.
+func GetOrRegisterGaugeInfo(name string, r Registry) GaugeInfo {
+ if nil == r {
+ r = DefaultRegistry
+ }
+ return r.GetOrRegister(name, NewGaugeInfo()).(GaugeInfo)
+}
+
+// NewGaugeInfo constructs a new StandardGaugeInfo.
+func NewGaugeInfo() GaugeInfo {
+ if !Enabled {
+ return NilGaugeInfo{}
+ }
+ return &StandardGaugeInfo{
+ value: GaugeInfoValue{},
+ }
+}
+
+// NewRegisteredGaugeInfo constructs and registers a new StandardGaugeInfo.
+func NewRegisteredGaugeInfo(name string, r Registry) GaugeInfo {
+ c := NewGaugeInfo()
+ if nil == r {
+ r = DefaultRegistry
+ }
+ r.Register(name, c)
+ return c
+}
+
+// gaugeInfoSnapshot is a read-only copy of another GaugeInfo.
+type gaugeInfoSnapshot GaugeInfoValue
+
+// Value returns the value at the time the snapshot was taken.
+func (g gaugeInfoSnapshot) Value() GaugeInfoValue { return GaugeInfoValue(g) }
+
+type NilGaugeInfo struct{}
+
+func (NilGaugeInfo) Snapshot() GaugeInfoSnapshot { return NilGaugeInfo{} }
+func (NilGaugeInfo) Update(v GaugeInfoValue) {}
+func (NilGaugeInfo) Value() GaugeInfoValue { return GaugeInfoValue{} }
+
+// StandardGaugeInfo is the standard implementation of a GaugeInfo and uses
+// sync.Mutex to manage a single string value.
+type StandardGaugeInfo struct {
+ mutex sync.Mutex
+ value GaugeInfoValue
+}
+
+// Snapshot returns a read-only copy of the gauge.
+func (g *StandardGaugeInfo) Snapshot() GaugeInfoSnapshot {
+ return gaugeInfoSnapshot(g.value)
+}
+
+// Update updates the gauge's value.
+func (g *StandardGaugeInfo) Update(v GaugeInfoValue) {
+ g.mutex.Lock()
+ defer g.mutex.Unlock()
+ g.value = v
+}
diff --git a/metrics/gauge_info_test.go b/metrics/gauge_info_test.go
new file mode 100644
index 0000000000..319afbf92e
--- /dev/null
+++ b/metrics/gauge_info_test.go
@@ -0,0 +1,36 @@
+package metrics
+
+import (
+ "testing"
+)
+
+func TestGaugeInfoJsonString(t *testing.T) {
+ g := NewGaugeInfo()
+ g.Update(GaugeInfoValue{
+ "chain_id": "5",
+ "anotherKey": "any_string_value",
+ "third_key": "anything",
+ },
+ )
+ want := `{"anotherKey":"any_string_value","chain_id":"5","third_key":"anything"}`
+
+ original := g.Snapshot()
+ g.Update(GaugeInfoValue{"value": "updated"})
+
+ if have := original.Value().String(); have != want {
+ t.Errorf("\nhave: %v\nwant: %v\n", have, want)
+ }
+ if have, want := g.Snapshot().Value().String(), `{"value":"updated"}`; have != want {
+ t.Errorf("\nhave: %v\nwant: %v\n", have, want)
+ }
+}
+
+func TestGetOrRegisterGaugeInfo(t *testing.T) {
+ r := NewRegistry()
+ NewRegisteredGaugeInfo("foo", r).Update(
+ GaugeInfoValue{"chain_id": "5"})
+ g := GetOrRegisterGaugeInfo("foo", r).Snapshot()
+ if have, want := g.Value().String(), `{"chain_id":"5"}`; have != want {
+ t.Errorf("have\n%v\nwant\n%v\n", have, want)
+ }
+}
diff --git a/metrics/gauge_test.go b/metrics/gauge_test.go
index a98fe985d8..f2ba930bc4 100644
--- a/metrics/gauge_test.go
+++ b/metrics/gauge_test.go
@@ -1,7 +1,6 @@
package metrics
import (
- "fmt"
"testing"
)
@@ -13,14 +12,6 @@ func BenchmarkGauge(b *testing.B) {
}
}
-func TestGauge(t *testing.T) {
- g := NewGauge()
- g.Update(int64(47))
- if v := g.Value(); v != 47 {
- t.Errorf("g.Value(): 47 != %v\n", v)
- }
-}
-
func TestGaugeSnapshot(t *testing.T) {
g := NewGauge()
g.Update(int64(47))
@@ -34,35 +25,7 @@ func TestGaugeSnapshot(t *testing.T) {
func TestGetOrRegisterGauge(t *testing.T) {
r := NewRegistry()
NewRegisteredGauge("foo", r).Update(47)
- if g := GetOrRegisterGauge("foo", r); g.Value() != 47 {
- t.Fatal(g)
- }
-}
-
-func TestFunctionalGauge(t *testing.T) {
- var counter int64
- fg := NewFunctionalGauge(func() int64 {
- counter++
- return counter
- })
- fg.Value()
- fg.Value()
- if counter != 2 {
- t.Error("counter != 2")
- }
-}
-
-func TestGetOrRegisterFunctionalGauge(t *testing.T) {
- r := NewRegistry()
- NewRegisteredFunctionalGauge("foo", r, func() int64 { return 47 })
- if g := GetOrRegisterGauge("foo", r); g.Value() != 47 {
+ if g := GetOrRegisterGauge("foo", r); g.Snapshot().Value() != 47 {
t.Fatal(g)
}
}
-
-func ExampleGetOrRegisterGauge() {
- m := "server.bytes_sent"
- g := GetOrRegisterGauge(m, nil)
- g.Update(47)
- fmt.Println(g.Value()) // Output: 47
-}
diff --git a/metrics/graphite.go b/metrics/graphite.go
index 29f72b0c41..aba752e0ed 100644
--- a/metrics/graphite.go
+++ b/metrics/graphite.go
@@ -66,13 +66,15 @@ func graphite(c *GraphiteConfig) error {
c.Registry.Each(func(name string, i interface{}) {
switch metric := i.(type) {
case Counter:
- fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now)
+ fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Snapshot().Count(), now)
case CounterFloat64:
- fmt.Fprintf(w, "%s.%s.count %f %d\n", c.Prefix, name, metric.Count(), now)
+ fmt.Fprintf(w, "%s.%s.count %f %d\n", c.Prefix, name, metric.Snapshot().Count(), now)
case Gauge:
- fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now)
+ fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Snapshot().Value(), now)
case GaugeFloat64:
- fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now)
+ fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Snapshot().Value(), now)
+ case GaugeInfo:
+ fmt.Fprintf(w, "%s.%s.value %s %d\n", c.Prefix, name, metric.Snapshot().Value().String(), now)
case Histogram:
h := metric.Snapshot()
ps := h.Percentiles(c.Percentiles)
diff --git a/metrics/histogram.go b/metrics/histogram.go
index 2c54ce8b40..44de588bc1 100644
--- a/metrics/histogram.go
+++ b/metrics/histogram.go
@@ -1,20 +1,14 @@
package metrics
+type HistogramSnapshot interface {
+ SampleSnapshot
+}
+
// Histograms calculate distribution statistics from a series of int64 values.
type Histogram interface {
Clear()
- Count() int64
- Max() int64
- Mean() float64
- Min() int64
- Percentile(float64) float64
- Percentiles([]float64) []float64
- Sample() Sample
- Snapshot() Histogram
- StdDev() float64
- Sum() int64
Update(int64)
- Variance() float64
+ Snapshot() HistogramSnapshot
}
// GetOrRegisterHistogram returns an existing Histogram or constructs and
@@ -54,108 +48,12 @@ func NewRegisteredHistogram(name string, r Registry, s Sample) Histogram {
return c
}
-// HistogramSnapshot is a read-only copy of another Histogram.
-type HistogramSnapshot struct {
- sample *SampleSnapshot
-}
-
-// Clear panics.
-func (*HistogramSnapshot) Clear() {
- panic("Clear called on a HistogramSnapshot")
-}
-
-// Count returns the number of samples recorded at the time the snapshot was
-// taken.
-func (h *HistogramSnapshot) Count() int64 { return h.sample.Count() }
-
-// Max returns the maximum value in the sample at the time the snapshot was
-// taken.
-func (h *HistogramSnapshot) Max() int64 { return h.sample.Max() }
-
-// Mean returns the mean of the values in the sample at the time the snapshot
-// was taken.
-func (h *HistogramSnapshot) Mean() float64 { return h.sample.Mean() }
-
-// Min returns the minimum value in the sample at the time the snapshot was
-// taken.
-func (h *HistogramSnapshot) Min() int64 { return h.sample.Min() }
-
-// Percentile returns an arbitrary percentile of values in the sample at the
-// time the snapshot was taken.
-func (h *HistogramSnapshot) Percentile(p float64) float64 {
- return h.sample.Percentile(p)
-}
-
-// Percentiles returns a slice of arbitrary percentiles of values in the sample
-// at the time the snapshot was taken.
-func (h *HistogramSnapshot) Percentiles(ps []float64) []float64 {
- return h.sample.Percentiles(ps)
-}
-
-// Sample returns the Sample underlying the histogram.
-func (h *HistogramSnapshot) Sample() Sample { return h.sample }
-
-// Snapshot returns the snapshot.
-func (h *HistogramSnapshot) Snapshot() Histogram { return h }
-
-// StdDev returns the standard deviation of the values in the sample at the
-// time the snapshot was taken.
-func (h *HistogramSnapshot) StdDev() float64 { return h.sample.StdDev() }
-
-// Sum returns the sum in the sample at the time the snapshot was taken.
-func (h *HistogramSnapshot) Sum() int64 { return h.sample.Sum() }
-
-// Update panics.
-func (*HistogramSnapshot) Update(int64) {
- panic("Update called on a HistogramSnapshot")
-}
-
-// Variance returns the variance of inputs at the time the snapshot was taken.
-func (h *HistogramSnapshot) Variance() float64 { return h.sample.Variance() }
-
// NilHistogram is a no-op Histogram.
type NilHistogram struct{}
-// Clear is a no-op.
-func (NilHistogram) Clear() {}
-
-// Count is a no-op.
-func (NilHistogram) Count() int64 { return 0 }
-
-// Max is a no-op.
-func (NilHistogram) Max() int64 { return 0 }
-
-// Mean is a no-op.
-func (NilHistogram) Mean() float64 { return 0.0 }
-
-// Min is a no-op.
-func (NilHistogram) Min() int64 { return 0 }
-
-// Percentile is a no-op.
-func (NilHistogram) Percentile(p float64) float64 { return 0.0 }
-
-// Percentiles is a no-op.
-func (NilHistogram) Percentiles(ps []float64) []float64 {
- return make([]float64, len(ps))
-}
-
-// Sample is a no-op.
-func (NilHistogram) Sample() Sample { return NilSample{} }
-
-// Snapshot is a no-op.
-func (NilHistogram) Snapshot() Histogram { return NilHistogram{} }
-
-// StdDev is a no-op.
-func (NilHistogram) StdDev() float64 { return 0.0 }
-
-// Sum is a no-op.
-func (NilHistogram) Sum() int64 { return 0 }
-
-// Update is a no-op.
-func (NilHistogram) Update(v int64) {}
-
-// Variance is a no-op.
-func (NilHistogram) Variance() float64 { return 0.0 }
+func (NilHistogram) Clear() {}
+func (NilHistogram) Snapshot() HistogramSnapshot { return (*emptySnapshot)(nil) }
+func (NilHistogram) Update(v int64) {}
// StandardHistogram is the standard implementation of a Histogram and uses a
// Sample to bound its memory use.
@@ -166,46 +64,10 @@ type StandardHistogram struct {
// Clear clears the histogram and its sample.
func (h *StandardHistogram) Clear() { h.sample.Clear() }
-// Count returns the number of samples recorded since the histogram was last
-// cleared.
-func (h *StandardHistogram) Count() int64 { return h.sample.Count() }
-
-// Max returns the maximum value in the sample.
-func (h *StandardHistogram) Max() int64 { return h.sample.Max() }
-
-// Mean returns the mean of the values in the sample.
-func (h *StandardHistogram) Mean() float64 { return h.sample.Mean() }
-
-// Min returns the minimum value in the sample.
-func (h *StandardHistogram) Min() int64 { return h.sample.Min() }
-
-// Percentile returns an arbitrary percentile of the values in the sample.
-func (h *StandardHistogram) Percentile(p float64) float64 {
- return h.sample.Percentile(p)
-}
-
-// Percentiles returns a slice of arbitrary percentiles of the values in the
-// sample.
-func (h *StandardHistogram) Percentiles(ps []float64) []float64 {
- return h.sample.Percentiles(ps)
-}
-
-// Sample returns the Sample underlying the histogram.
-func (h *StandardHistogram) Sample() Sample { return h.sample }
-
// Snapshot returns a read-only copy of the histogram.
-func (h *StandardHistogram) Snapshot() Histogram {
- return &HistogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)}
+func (h *StandardHistogram) Snapshot() HistogramSnapshot {
+ return h.sample.Snapshot()
}
-// StdDev returns the standard deviation of the values in the sample.
-func (h *StandardHistogram) StdDev() float64 { return h.sample.StdDev() }
-
-// Sum returns the sum in the sample.
-func (h *StandardHistogram) Sum() int64 { return h.sample.Sum() }
-
// Update samples a new value.
func (h *StandardHistogram) Update(v int64) { h.sample.Update(v) }
-
-// Variance returns the variance of the values in the sample.
-func (h *StandardHistogram) Variance() float64 { return h.sample.Variance() }
diff --git a/metrics/histogram_test.go b/metrics/histogram_test.go
index 7c9f42fcec..22fc5468b0 100644
--- a/metrics/histogram_test.go
+++ b/metrics/histogram_test.go
@@ -14,7 +14,7 @@ func TestGetOrRegisterHistogram(t *testing.T) {
r := NewRegistry()
s := NewUniformSample(100)
NewRegisteredHistogram("foo", r, s).Update(47)
- if h := GetOrRegisterHistogram("foo", r, s); h.Count() != 1 {
+ if h := GetOrRegisterHistogram("foo", r, s).Snapshot(); h.Count() != 1 {
t.Fatal(h)
}
}
@@ -24,11 +24,11 @@ func TestHistogram10000(t *testing.T) {
for i := 1; i <= 10000; i++ {
h.Update(int64(i))
}
- testHistogram10000(t, h)
+ testHistogram10000(t, h.Snapshot())
}
func TestHistogramEmpty(t *testing.T) {
- h := NewHistogram(NewUniformSample(100))
+ h := NewHistogram(NewUniformSample(100)).Snapshot()
if count := h.Count(); count != 0 {
t.Errorf("h.Count(): 0 != %v\n", count)
}
@@ -66,7 +66,7 @@ func TestHistogramSnapshot(t *testing.T) {
testHistogram10000(t, snapshot)
}
-func testHistogram10000(t *testing.T, h Histogram) {
+func testHistogram10000(t *testing.T, h HistogramSnapshot) {
if count := h.Count(); count != 10000 {
t.Errorf("h.Count(): 10000 != %v\n", count)
}
diff --git a/metrics/inactive.go b/metrics/inactive.go
new file mode 100644
index 0000000000..1f47f0210a
--- /dev/null
+++ b/metrics/inactive.go
@@ -0,0 +1,48 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package metrics
+
+// compile-time checks that interfaces are implemented.
+var (
+ _ SampleSnapshot = (*emptySnapshot)(nil)
+ _ HistogramSnapshot = (*emptySnapshot)(nil)
+ _ CounterSnapshot = (*emptySnapshot)(nil)
+ _ GaugeSnapshot = (*emptySnapshot)(nil)
+ _ MeterSnapshot = (*emptySnapshot)(nil)
+ _ EWMASnapshot = (*emptySnapshot)(nil)
+ _ TimerSnapshot = (*emptySnapshot)(nil)
+)
+
+type emptySnapshot struct{}
+
+func (*emptySnapshot) Count() int64 { return 0 }
+func (*emptySnapshot) Max() int64 { return 0 }
+func (*emptySnapshot) Mean() float64 { return 0.0 }
+func (*emptySnapshot) Min() int64 { return 0 }
+func (*emptySnapshot) Percentile(p float64) float64 { return 0.0 }
+func (*emptySnapshot) Percentiles(ps []float64) []float64 { return make([]float64, len(ps)) }
+func (*emptySnapshot) Size() int { return 0 }
+func (*emptySnapshot) StdDev() float64 { return 0.0 }
+func (*emptySnapshot) Sum() int64 { return 0 }
+func (*emptySnapshot) Values() []int64 { return []int64{} }
+func (*emptySnapshot) Variance() float64 { return 0.0 }
+func (*emptySnapshot) Value() int64 { return 0 }
+func (*emptySnapshot) Rate() float64 { return 0.0 }
+func (*emptySnapshot) Rate1() float64 { return 0.0 }
+func (*emptySnapshot) Rate5() float64 { return 0.0 }
+func (*emptySnapshot) Rate15() float64 { return 0.0 }
+func (*emptySnapshot) RateMean() float64 { return 0.0 }
diff --git a/metrics/influxdb/influxdb.go b/metrics/influxdb/influxdb.go
index 5dfbbab3ed..bbc4fc024b 100644
--- a/metrics/influxdb/influxdb.go
+++ b/metrics/influxdb/influxdb.go
@@ -11,13 +11,13 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf
case metrics.Counter:
measurement := fmt.Sprintf("%s%s.count", namespace, name)
fields := map[string]interface{}{
- "value": metric.Count(),
+ "value": metric.Snapshot().Count(),
}
return measurement, fields
case metrics.CounterFloat64:
measurement := fmt.Sprintf("%s%s.count", namespace, name)
fields := map[string]interface{}{
- "value": metric.Count(),
+ "value": metric.Snapshot().Count(),
}
return measurement, fields
case metrics.Gauge:
@@ -32,6 +32,13 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf
"value": metric.Snapshot().Value(),
}
return measurement, fields
+ case metrics.GaugeInfo:
+ ms := metric.Snapshot()
+ measurement := fmt.Sprintf("%s%s.gauge", namespace, name)
+ fields := map[string]interface{}{
+ "value": ms.Value().String(),
+ }
+ return measurement, fields
case metrics.Histogram:
ms := metric.Snapshot()
if ms.Count() <= 0 {
@@ -92,20 +99,19 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf
return measurement, fields
case metrics.ResettingTimer:
t := metric.Snapshot()
- if len(t.Values()) == 0 {
+ if t.Count() == 0 {
break
}
- ps := t.Percentiles([]float64{50, 95, 99})
- val := t.Values()
+ ps := t.Percentiles([]float64{0.50, 0.95, 0.99})
measurement := fmt.Sprintf("%s%s.span", namespace, name)
fields := map[string]interface{}{
- "count": len(val),
- "max": val[len(val)-1],
+ "count": t.Count(),
+ "max": t.Max(),
"mean": t.Mean(),
- "min": val[0],
- "p50": ps[0],
- "p95": ps[1],
- "p99": ps[2],
+ "min": t.Min(),
+ "p50": int(ps[0]),
+ "p95": int(ps[1]),
+ "p99": int(ps[2]),
}
return measurement, fields
}
diff --git a/metrics/influxdb/influxdb_test.go b/metrics/influxdb/influxdb_test.go
new file mode 100644
index 0000000000..6daeb1aa03
--- /dev/null
+++ b/metrics/influxdb/influxdb_test.go
@@ -0,0 +1,115 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package influxdb
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "os"
+ "runtime"
+ "strings"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/metrics/internal"
+ influxdb2 "github.com/influxdata/influxdb-client-go/v2"
+)
+
+func TestMain(m *testing.M) {
+ metrics.Enabled = true
+ os.Exit(m.Run())
+}
+
+func TestExampleV1(t *testing.T) {
+ r := internal.ExampleMetrics()
+ var have, want string
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ haveB, _ := io.ReadAll(r.Body)
+ have = string(haveB)
+ r.Body.Close()
+ }))
+ defer ts.Close()
+ u, _ := url.Parse(ts.URL)
+ rep := &reporter{
+ reg: r,
+ url: *u,
+ namespace: "goth.",
+ }
+ if err := rep.makeClient(); err != nil {
+ t.Fatal(err)
+ }
+ if err := rep.send(978307200); err != nil {
+ t.Fatal(err)
+ }
+ if wantB, err := os.ReadFile("./testdata/influxdbv1.want"); err != nil {
+ t.Fatal(err)
+ } else {
+ want = string(wantB)
+ }
+ if runtime.GOARCH == "amd64" && have != want {
+ t.Errorf("\nhave:\n%v\nwant:\n%v\n", have, want)
+ t.Logf("have vs want:\n%v", findFirstDiffPos(have, want))
+ }
+}
+
+func TestExampleV2(t *testing.T) {
+ r := internal.ExampleMetrics()
+ var have, want string
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ haveB, _ := io.ReadAll(r.Body)
+ have = string(haveB)
+ r.Body.Close()
+ }))
+ defer ts.Close()
+
+ rep := &v2Reporter{
+ reg: r,
+ endpoint: ts.URL,
+ namespace: "goth.",
+ }
+ rep.client = influxdb2.NewClient(rep.endpoint, rep.token)
+ defer rep.client.Close()
+ rep.write = rep.client.WriteAPI(rep.organization, rep.bucket)
+
+ rep.send(978307200)
+
+ if wantB, err := os.ReadFile("./testdata/influxdbv2.want"); err != nil {
+ t.Fatal(err)
+ } else {
+ want = string(wantB)
+ }
+ if runtime.GOARCH == "amd64" && have != want {
+ t.Errorf("\nhave:\n%v\nwant:\n%v\n", have, want)
+ t.Logf("have vs want:\n%v", findFirstDiffPos(have, want))
+ }
+}
+
+func findFirstDiffPos(a, b string) string {
+ yy := strings.Split(b, "\n")
+ for i, x := range strings.Split(a, "\n") {
+ if i >= len(yy) {
+ return fmt.Sprintf("have:%d: %s\nwant:%d: ", i, x, i)
+ }
+ if y := yy[i]; x != y {
+ return fmt.Sprintf("have:%d: %s\nwant:%d: %s", i, x, i, y)
+ }
+ }
+ return ""
+}
diff --git a/metrics/influxdb/influxdbv1.go b/metrics/influxdb/influxdbv1.go
index f65d30ef95..ac58280803 100644
--- a/metrics/influxdb/influxdbv1.go
+++ b/metrics/influxdb/influxdbv1.go
@@ -79,7 +79,7 @@ func InfluxDBWithTagsOnce(r metrics.Registry, url, database, username, password,
return fmt.Errorf("unable to make InfluxDB client. err: %v", err)
}
- if err := rep.send(); err != nil {
+ if err := rep.send(0); err != nil {
return fmt.Errorf("unable to send to InfluxDB. err: %v", err)
}
@@ -107,7 +107,7 @@ func (r *reporter) run() {
for {
select {
case <-intervalTicker.C:
- if err := r.send(); err != nil {
+ if err := r.send(0); err != nil {
log.Warn("Unable to send to InfluxDB", "err", err)
}
case <-pingTicker.C:
@@ -123,7 +123,9 @@ func (r *reporter) run() {
}
}
-func (r *reporter) send() error {
+// send sends the measurements. If provided tstamp is >0, it is used. Otherwise,
+// a 'fresh' timestamp is used.
+func (r *reporter) send(tstamp int64) error {
bps, err := client.NewBatchPoints(
client.BatchPointsConfig{
Database: r.database,
@@ -132,7 +134,12 @@ func (r *reporter) send() error {
return err
}
r.reg.Each(func(name string, i interface{}) {
- now := time.Now()
+ var now time.Time
+ if tstamp <= 0 {
+ now = time.Now()
+ } else {
+ now = time.Unix(tstamp, 0)
+ }
measurement, fields := readMeter(r.namespace, name, i)
if fields == nil {
return
diff --git a/metrics/influxdb/influxdbv2.go b/metrics/influxdb/influxdbv2.go
index 7984898f32..0be5137d5e 100644
--- a/metrics/influxdb/influxdbv2.go
+++ b/metrics/influxdb/influxdbv2.go
@@ -64,7 +64,7 @@ func (r *v2Reporter) run() {
for {
select {
case <-intervalTicker.C:
- r.send()
+ r.send(0)
case <-pingTicker.C:
_, err := r.client.Health(context.Background())
if err != nil {
@@ -74,9 +74,16 @@ func (r *v2Reporter) run() {
}
}
-func (r *v2Reporter) send() {
+// send sends the measurements. If provided tstamp is >0, it is used. Otherwise,
+// a 'fresh' timestamp is used.
+func (r *v2Reporter) send(tstamp int64) {
r.reg.Each(func(name string, i interface{}) {
- now := time.Now()
+ var now time.Time
+ if tstamp <= 0 {
+ now = time.Now()
+ } else {
+ now = time.Unix(tstamp, 0)
+ }
measurement, fields := readMeter(r.namespace, name, i)
if fields == nil {
return
diff --git a/metrics/influxdb/testdata/influxdbv1.want b/metrics/influxdb/testdata/influxdbv1.want
new file mode 100644
index 0000000000..9443faedc5
--- /dev/null
+++ b/metrics/influxdb/testdata/influxdbv1.want
@@ -0,0 +1,11 @@
+goth.system/cpu/schedlatency.histogram count=5645i,max=41943040i,mean=1819544.0410983171,min=0i,p25=0,p50=0,p75=7168,p95=16777216,p99=29360128,p999=33554432,p9999=33554432,stddev=6393570.217198883,variance=40877740122252.57 978307200000000000
+goth.system/memory/pauses.histogram count=14i,max=229376i,mean=50066.28571428572,min=5120i,p25=10240,p50=32768,p75=57344,p95=196608,p99=196608,p999=196608,p9999=196608,stddev=54726.062410783874,variance=2994941906.9890113 978307200000000000
+goth.test/counter.count value=12345 978307200000000000
+goth.test/counter_float64.count value=54321.98 978307200000000000
+goth.test/gauge.gauge value=23456i 978307200000000000
+goth.test/gauge_float64.gauge value=34567.89 978307200000000000
+goth.test/gauge_info.gauge value="{\"arch\":\"amd64\",\"commit\":\"7caa2d8163ae3132c1c2d6978c76610caee2d949\",\"os\":\"linux\",\"protocol_versions\":\"64 65 66\",\"version\":\"1.10.18-unstable\"}" 978307200000000000
+goth.test/histogram.histogram count=3i,max=3i,mean=2,min=1i,p25=1,p50=2,p75=3,p95=3,p99=3,p999=3,p9999=3,stddev=0.816496580927726,variance=0.6666666666666666 978307200000000000
+goth.test/meter.meter count=0i,m1=0,m15=0,m5=0,mean=0 978307200000000000
+goth.test/resetting_timer.span count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000i,p95=120000000i,p99=120000000i 978307200000000000
+goth.test/timer.timer count=6i,m1=0,m15=0,m5=0,max=120000000i,mean=38333333.333333336,meanrate=0,min=20000000i,p50=22500000,p75=48000000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000,stddev=36545253.529775314,variance=1335555555555555.2 978307200000000000
diff --git a/metrics/influxdb/testdata/influxdbv2.want b/metrics/influxdb/testdata/influxdbv2.want
new file mode 100644
index 0000000000..9443faedc5
--- /dev/null
+++ b/metrics/influxdb/testdata/influxdbv2.want
@@ -0,0 +1,11 @@
+goth.system/cpu/schedlatency.histogram count=5645i,max=41943040i,mean=1819544.0410983171,min=0i,p25=0,p50=0,p75=7168,p95=16777216,p99=29360128,p999=33554432,p9999=33554432,stddev=6393570.217198883,variance=40877740122252.57 978307200000000000
+goth.system/memory/pauses.histogram count=14i,max=229376i,mean=50066.28571428572,min=5120i,p25=10240,p50=32768,p75=57344,p95=196608,p99=196608,p999=196608,p9999=196608,stddev=54726.062410783874,variance=2994941906.9890113 978307200000000000
+goth.test/counter.count value=12345 978307200000000000
+goth.test/counter_float64.count value=54321.98 978307200000000000
+goth.test/gauge.gauge value=23456i 978307200000000000
+goth.test/gauge_float64.gauge value=34567.89 978307200000000000
+goth.test/gauge_info.gauge value="{\"arch\":\"amd64\",\"commit\":\"7caa2d8163ae3132c1c2d6978c76610caee2d949\",\"os\":\"linux\",\"protocol_versions\":\"64 65 66\",\"version\":\"1.10.18-unstable\"}" 978307200000000000
+goth.test/histogram.histogram count=3i,max=3i,mean=2,min=1i,p25=1,p50=2,p75=3,p95=3,p99=3,p999=3,p9999=3,stddev=0.816496580927726,variance=0.6666666666666666 978307200000000000
+goth.test/meter.meter count=0i,m1=0,m15=0,m5=0,mean=0 978307200000000000
+goth.test/resetting_timer.span count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000i,p95=120000000i,p99=120000000i 978307200000000000
+goth.test/timer.timer count=6i,m1=0,m15=0,m5=0,max=120000000i,mean=38333333.333333336,meanrate=0,min=20000000i,p50=22500000,p75=48000000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000,stddev=36545253.529775314,variance=1335555555555555.2 978307200000000000
diff --git a/metrics/internal/sampledata.go b/metrics/internal/sampledata.go
new file mode 100644
index 0000000000..de9b207b6d
--- /dev/null
+++ b/metrics/internal/sampledata.go
@@ -0,0 +1,95 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package internal
+
+import (
+ "bytes"
+ "encoding/gob"
+ metrics2 "runtime/metrics"
+ "time"
+
+ "github.com/ethereum/go-ethereum/metrics"
+)
+
+// ExampleMetrics returns an ordered registry populated with a sample of metrics.
+func ExampleMetrics() metrics.Registry {
+ var registry = metrics.NewOrderedRegistry()
+
+ metrics.NewRegisteredCounterFloat64("test/counter", registry).Inc(12345)
+ metrics.NewRegisteredCounterFloat64("test/counter_float64", registry).Inc(54321.98)
+ metrics.NewRegisteredGauge("test/gauge", registry).Update(23456)
+ metrics.NewRegisteredGaugeFloat64("test/gauge_float64", registry).Update(34567.89)
+ metrics.NewRegisteredGaugeInfo("test/gauge_info", registry).Update(
+ metrics.GaugeInfoValue{
+ "version": "1.10.18-unstable",
+ "arch": "amd64",
+ "os": "linux",
+ "commit": "7caa2d8163ae3132c1c2d6978c76610caee2d949",
+ "protocol_versions": "64 65 66",
+ })
+
+ {
+ s := metrics.NewUniformSample(3)
+ s.Update(1)
+ s.Update(2)
+ s.Update(3)
+ //metrics.NewRegisteredHistogram("test/histogram", registry, metrics.NewSampleSnapshot(3, []int64{1, 2, 3}))
+ metrics.NewRegisteredHistogram("test/histogram", registry, s)
+ }
+ registry.Register("test/meter", metrics.NewInactiveMeter())
+ {
+ timer := metrics.NewRegisteredResettingTimer("test/resetting_timer", registry)
+ timer.Update(10 * time.Millisecond)
+ timer.Update(11 * time.Millisecond)
+ timer.Update(12 * time.Millisecond)
+ timer.Update(120 * time.Millisecond)
+ timer.Update(13 * time.Millisecond)
+ timer.Update(14 * time.Millisecond)
+ }
+ {
+ timer := metrics.NewRegisteredTimer("test/timer", registry)
+ timer.Update(20 * time.Millisecond)
+ timer.Update(21 * time.Millisecond)
+ timer.Update(22 * time.Millisecond)
+ timer.Update(120 * time.Millisecond)
+ timer.Update(23 * time.Millisecond)
+ timer.Update(24 * time.Millisecond)
+ timer.Stop()
+ }
+ registry.Register("test/empty_resetting_timer", metrics.NewResettingTimer().Snapshot())
+
+ { // go runtime metrics
+ var sLatency = "7\xff\x81\x03\x01\x01\x10Float64Histogram\x01\xff\x82\x00\x01\x02\x01\x06Counts\x01\xff\x84\x00\x01\aBuckets\x01\xff\x86\x00\x00\x00\x16\xff\x83\x02\x01\x01\b[]uint64\x01\xff\x84\x00\x01\x06\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00\xfe\x06T\xff\x82\x01\xff\xa2\x00\xfe\r\xef\x00\x01\x02\x02\x04\x05\x04\b\x15\x17 B?6.L;$!2) \x1a? \x190aH7FY6#\x190\x1d\x14\x10\x1b\r\t\x04\x03\x01\x01\x00\x03\x02\x00\x03\x05\x05\x02\x02\x06\x04\v\x06\n\x15\x18\x13'&.\x12=H/L&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xa3\xfe\xf0\xff\x00\xf8\x95\xd6&\xe8\v.q>\xf8\x95\xd6&\xe8\v.\x81>\xf8\xdfA:\xdc\x11ʼn>\xf8\x95\xd6&\xe8\v.\x91>\xf8:\x8c0\xe2\x8ey\x95>\xf8\xdfA:\xdc\x11ř>\xf8\x84\xf7C֔\x10\x9e>\xf8\x95\xd6&\xe8\v.\xa1>\xf8:\x8c0\xe2\x8ey\xa5>\xf8\xdfA:\xdc\x11ũ>\xf8\x84\xf7C֔\x10\xae>\xf8\x95\xd6&\xe8\v.\xb1>\xf8:\x8c0\xe2\x8ey\xb5>\xf8\xdfA:\xdc\x11Ź>\xf8\x84\xf7C֔\x10\xbe>\xf8\x95\xd6&\xe8\v.\xc1>\xf8:\x8c0\xe2\x8ey\xc5>\xf8\xdfA:\xdc\x11\xc5\xc9>\xf8\x84\xf7C֔\x10\xce>\xf8\x95\xd6&\xe8\v.\xd1>\xf8:\x8c0\xe2\x8ey\xd5>\xf8\xdfA:\xdc\x11\xc5\xd9>\xf8\x84\xf7C֔\x10\xde>\xf8\x95\xd6&\xe8\v.\xe1>\xf8:\x8c0\xe2\x8ey\xe5>\xf8\xdfA:\xdc\x11\xc5\xe9>\xf8\x84\xf7C֔\x10\xee>\xf8\x95\xd6&\xe8\v.\xf1>\xf8:\x8c0\xe2\x8ey\xf5>\xf8\xdfA:\xdc\x11\xc5\xf9>\xf8\x84\xf7C֔\x10\xfe>\xf8\x95\xd6&\xe8\v.\x01?\xf8:\x8c0\xe2\x8ey\x05?\xf8\xdfA:\xdc\x11\xc5\t?\xf8\x84\xf7C֔\x10\x0e?\xf8\x95\xd6&\xe8\v.\x11?\xf8:\x8c0\xe2\x8ey\x15?\xf8\xdfA:\xdc\x11\xc5\x19?\xf8\x84\xf7C֔\x10\x1e?\xf8\x95\xd6&\xe8\v.!?\xf8:\x8c0\xe2\x8ey%?\xf8\xdfA:\xdc\x11\xc5)?\xf8\x84\xf7C֔\x10.?\xf8\x95\xd6&\xe8\v.1?\xf8:\x8c0\xe2\x8ey5?\xf8\xdfA:\xdc\x11\xc59?\xf8\x84\xf7C֔\x10>?\xf8\x95\xd6&\xe8\v.A?\xf8:\x8c0\xe2\x8eyE?\xf8\xdfA:\xdc\x11\xc5I?\xf8\x84\xf7C֔\x10N?\xf8\x95\xd6&\xe8\v.Q?\xf8:\x8c0\xe2\x8eyU?\xf8\xdfA:\xdc\x11\xc5Y?\xf8\x84\xf7C֔\x10^?\xf8\x95\xd6&\xe8\v.a?\xf8:\x8c0\xe2\x8eye?\xf8\xdfA:\xdc\x11\xc5i?\xf8\x84\xf7C֔\x10n?\xf8\x95\xd6&\xe8\v.q?\xf8:\x8c0\xe2\x8eyu?\xf8\xdfA:\xdc\x11\xc5y?\xf8\x84\xf7C֔\x10~?\xf8\x95\xd6&\xe8\v.\x81?\xf8:\x8c0\xe2\x8ey\x85?\xf8\xdfA:\xdc\x11ʼn?\xf8\x84\xf7C֔\x10\x8e?\xf8\x95\xd6&\xe8\v.\x91?\xf8:\x8c0\xe2\x8ey\x95?\xf8\xdfA:\xdc\x11ř?\xf8\x84\xf7C֔\x10\x9e?\xf8\x95\xd6&\xe8\v.\xa1?\xf8:\x8c0\xe2\x8ey\xa5?\xf8\xdfA:\xdc\x11ũ?\xf8\x84\xf7C֔\x10\xae?\xf8\x95\xd6&\xe8\v.\xb1?\xf8:\x8c0\xe2\x8ey\xb5?\xf8\xdfA:\xdc\x11Ź?\xf8\x84\xf7C֔\x10\xbe?\xf8\x95\xd6&\xe8\v.\xc1?\xf8:\x8c0\xe2\x8ey\xc5?\xf8\xdfA:\xdc\x11\xc5\xc9?\xf8\x84\xf7C֔\x10\xce?\xf8\x95\xd6&\xe8\v.\xd1?\xf8:\x8c0\xe2\x8ey\xd5?\xf8\xdfA:\xdc\x11\xc5\xd9?\xf8\x84\xf7C֔\x10\xde?\xf8\x95\xd6&\xe8\v.\xe1?\xf8:\x8c0\xe2\x8ey\xe5?\xf8\xdfA:\xdc\x11\xc5\xe9?\xf8\x84\xf7C֔\x10\xee?\xf8\x95\xd6&\xe8\v.\xf1?\xf8:\x8c0\xe2\x8ey\xf5?\xf8\xdfA:\xdc\x11\xc5\xf9?\xf8\x84\xf7C֔\x10\xfe?\xf8\x95\xd6&\xe8\v.\x01@\xf8:\x8c0\xe2\x8ey\x05@\xf8\xdfA:\xdc\x11\xc5\t@\xf8\x84\xf7C֔\x10\x0e@\xf8\x95\xd6&\xe8\v.\x11@\xf8:\x8c0\xe2\x8ey\x15@\xf8\xdfA:\xdc\x11\xc5\x19@\xf8\x84\xf7C֔\x10\x1e@\xf8\x95\xd6&\xe8\v.!@\xf8:\x8c0\xe2\x8ey%@\xf8\xdfA:\xdc\x11\xc5)@\xf8\x84\xf7C֔\x10.@\xf8\x95\xd6&\xe8\v.1@\xf8:\x8c0\xe2\x8ey5@\xf8\xdfA:\xdc\x11\xc59@\xf8\x84\xf7C֔\x10>@\xf8\x95\xd6&\xe8\v.A@\xf8:\x8c0\xe2\x8eyE@\xf8\xdfA:\xdc\x11\xc5I@\xf8\x84\xf7C֔\x10N@\xf8\x95\xd6&\xe8\v.Q@\xf8:\x8c0\xe2\x8eyU@\xf8\xdfA:\xdc\x11\xc5Y@\xf8\x84\xf7C֔\x10^@\xf8\x95\xd6&\xe8\v.a@\xf8:\x8c0\xe2\x8eye@\xf8\xdfA:\xdc\x11\xc5i@\xf8\x84\xf7C֔\x10n@\xf8\x95\xd6&\xe8\v.q@\xf8:\x8c0\xe2\x8eyu@\xf8\xdfA:\xdc\x11\xc5y@\xf8\x84\xf7C֔\x10~@\xf8\x95\xd6&\xe8\v.\x81@\xf8:\x8c0\xe2\x8ey\x85@\xf8\xdfA:\xdc\x11ʼn@\xf8\x84\xf7C֔\x10\x8e@\xf8\x95\xd6&\xe8\v.\x91@\xf8:\x8c0\xe2\x8ey\x95@\xf8\xdfA:\xdc\x11ř@\xf8\x84\xf7C֔\x10\x9e@\xf8\x95\xd6&\xe8\v.\xa1@\xf8:\x8c0\xe2\x8ey\xa5@\xf8\xdfA:\xdc\x11ũ@\xf8\x84\xf7C֔\x10\xae@\xf8\x95\xd6&\xe8\v.\xb1@\xf8:\x8c0\xe2\x8ey\xb5@\xf8\xdfA:\xdc\x11Ź@\xf8\x84\xf7C֔\x10\xbe@\xf8\x95\xd6&\xe8\v.\xc1@\xf8:\x8c0\xe2\x8ey\xc5@\xf8\xdfA:\xdc\x11\xc5\xc9@\xf8\x84\xf7C֔\x10\xce@\xf8\x95\xd6&\xe8\v.\xd1@\xf8:\x8c0\xe2\x8ey\xd5@\xf8\xdfA:\xdc\x11\xc5\xd9@\xf8\x84\xf7C֔\x10\xde@\xf8\x95\xd6&\xe8\v.\xe1@\xf8:\x8c0\xe2\x8ey\xe5@\xf8\xdfA:\xdc\x11\xc5\xe9@\xf8\x84\xf7C֔\x10\xee@\xf8\x95\xd6&\xe8\v.\xf1@\xf8:\x8c0\xe2\x8ey\xf5@\xf8\xdfA:\xdc\x11\xc5\xf9@\xf8\x84\xf7C֔\x10\xfe@\xf8\x95\xd6&\xe8\v.\x01A\xfe\xf0\x7f\x00"
+ var gcPauses = "7\xff\x81\x03\x01\x01\x10Float64Histogram\x01\xff\x82\x00\x01\x02\x01\x06Counts\x01\xff\x84\x00\x01\aBuckets\x01\xff\x86\x00\x00\x00\x16\xff\x83\x02\x01\x01\b[]uint64\x01\xff\x84\x00\x01\x06\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00\xfe\x06R\xff\x82\x01\xff\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x00\x01\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xa3\xfe\xf0\xff\x00\xf8\x95\xd6&\xe8\v.q>\xf8\x95\xd6&\xe8\v.\x81>\xf8\xdfA:\xdc\x11ʼn>\xf8\x95\xd6&\xe8\v.\x91>\xf8:\x8c0\xe2\x8ey\x95>\xf8\xdfA:\xdc\x11ř>\xf8\x84\xf7C֔\x10\x9e>\xf8\x95\xd6&\xe8\v.\xa1>\xf8:\x8c0\xe2\x8ey\xa5>\xf8\xdfA:\xdc\x11ũ>\xf8\x84\xf7C֔\x10\xae>\xf8\x95\xd6&\xe8\v.\xb1>\xf8:\x8c0\xe2\x8ey\xb5>\xf8\xdfA:\xdc\x11Ź>\xf8\x84\xf7C֔\x10\xbe>\xf8\x95\xd6&\xe8\v.\xc1>\xf8:\x8c0\xe2\x8ey\xc5>\xf8\xdfA:\xdc\x11\xc5\xc9>\xf8\x84\xf7C֔\x10\xce>\xf8\x95\xd6&\xe8\v.\xd1>\xf8:\x8c0\xe2\x8ey\xd5>\xf8\xdfA:\xdc\x11\xc5\xd9>\xf8\x84\xf7C֔\x10\xde>\xf8\x95\xd6&\xe8\v.\xe1>\xf8:\x8c0\xe2\x8ey\xe5>\xf8\xdfA:\xdc\x11\xc5\xe9>\xf8\x84\xf7C֔\x10\xee>\xf8\x95\xd6&\xe8\v.\xf1>\xf8:\x8c0\xe2\x8ey\xf5>\xf8\xdfA:\xdc\x11\xc5\xf9>\xf8\x84\xf7C֔\x10\xfe>\xf8\x95\xd6&\xe8\v.\x01?\xf8:\x8c0\xe2\x8ey\x05?\xf8\xdfA:\xdc\x11\xc5\t?\xf8\x84\xf7C֔\x10\x0e?\xf8\x95\xd6&\xe8\v.\x11?\xf8:\x8c0\xe2\x8ey\x15?\xf8\xdfA:\xdc\x11\xc5\x19?\xf8\x84\xf7C֔\x10\x1e?\xf8\x95\xd6&\xe8\v.!?\xf8:\x8c0\xe2\x8ey%?\xf8\xdfA:\xdc\x11\xc5)?\xf8\x84\xf7C֔\x10.?\xf8\x95\xd6&\xe8\v.1?\xf8:\x8c0\xe2\x8ey5?\xf8\xdfA:\xdc\x11\xc59?\xf8\x84\xf7C֔\x10>?\xf8\x95\xd6&\xe8\v.A?\xf8:\x8c0\xe2\x8eyE?\xf8\xdfA:\xdc\x11\xc5I?\xf8\x84\xf7C֔\x10N?\xf8\x95\xd6&\xe8\v.Q?\xf8:\x8c0\xe2\x8eyU?\xf8\xdfA:\xdc\x11\xc5Y?\xf8\x84\xf7C֔\x10^?\xf8\x95\xd6&\xe8\v.a?\xf8:\x8c0\xe2\x8eye?\xf8\xdfA:\xdc\x11\xc5i?\xf8\x84\xf7C֔\x10n?\xf8\x95\xd6&\xe8\v.q?\xf8:\x8c0\xe2\x8eyu?\xf8\xdfA:\xdc\x11\xc5y?\xf8\x84\xf7C֔\x10~?\xf8\x95\xd6&\xe8\v.\x81?\xf8:\x8c0\xe2\x8ey\x85?\xf8\xdfA:\xdc\x11ʼn?\xf8\x84\xf7C֔\x10\x8e?\xf8\x95\xd6&\xe8\v.\x91?\xf8:\x8c0\xe2\x8ey\x95?\xf8\xdfA:\xdc\x11ř?\xf8\x84\xf7C֔\x10\x9e?\xf8\x95\xd6&\xe8\v.\xa1?\xf8:\x8c0\xe2\x8ey\xa5?\xf8\xdfA:\xdc\x11ũ?\xf8\x84\xf7C֔\x10\xae?\xf8\x95\xd6&\xe8\v.\xb1?\xf8:\x8c0\xe2\x8ey\xb5?\xf8\xdfA:\xdc\x11Ź?\xf8\x84\xf7C֔\x10\xbe?\xf8\x95\xd6&\xe8\v.\xc1?\xf8:\x8c0\xe2\x8ey\xc5?\xf8\xdfA:\xdc\x11\xc5\xc9?\xf8\x84\xf7C֔\x10\xce?\xf8\x95\xd6&\xe8\v.\xd1?\xf8:\x8c0\xe2\x8ey\xd5?\xf8\xdfA:\xdc\x11\xc5\xd9?\xf8\x84\xf7C֔\x10\xde?\xf8\x95\xd6&\xe8\v.\xe1?\xf8:\x8c0\xe2\x8ey\xe5?\xf8\xdfA:\xdc\x11\xc5\xe9?\xf8\x84\xf7C֔\x10\xee?\xf8\x95\xd6&\xe8\v.\xf1?\xf8:\x8c0\xe2\x8ey\xf5?\xf8\xdfA:\xdc\x11\xc5\xf9?\xf8\x84\xf7C֔\x10\xfe?\xf8\x95\xd6&\xe8\v.\x01@\xf8:\x8c0\xe2\x8ey\x05@\xf8\xdfA:\xdc\x11\xc5\t@\xf8\x84\xf7C֔\x10\x0e@\xf8\x95\xd6&\xe8\v.\x11@\xf8:\x8c0\xe2\x8ey\x15@\xf8\xdfA:\xdc\x11\xc5\x19@\xf8\x84\xf7C֔\x10\x1e@\xf8\x95\xd6&\xe8\v.!@\xf8:\x8c0\xe2\x8ey%@\xf8\xdfA:\xdc\x11\xc5)@\xf8\x84\xf7C֔\x10.@\xf8\x95\xd6&\xe8\v.1@\xf8:\x8c0\xe2\x8ey5@\xf8\xdfA:\xdc\x11\xc59@\xf8\x84\xf7C֔\x10>@\xf8\x95\xd6&\xe8\v.A@\xf8:\x8c0\xe2\x8eyE@\xf8\xdfA:\xdc\x11\xc5I@\xf8\x84\xf7C֔\x10N@\xf8\x95\xd6&\xe8\v.Q@\xf8:\x8c0\xe2\x8eyU@\xf8\xdfA:\xdc\x11\xc5Y@\xf8\x84\xf7C֔\x10^@\xf8\x95\xd6&\xe8\v.a@\xf8:\x8c0\xe2\x8eye@\xf8\xdfA:\xdc\x11\xc5i@\xf8\x84\xf7C֔\x10n@\xf8\x95\xd6&\xe8\v.q@\xf8:\x8c0\xe2\x8eyu@\xf8\xdfA:\xdc\x11\xc5y@\xf8\x84\xf7C֔\x10~@\xf8\x95\xd6&\xe8\v.\x81@\xf8:\x8c0\xe2\x8ey\x85@\xf8\xdfA:\xdc\x11ʼn@\xf8\x84\xf7C֔\x10\x8e@\xf8\x95\xd6&\xe8\v.\x91@\xf8:\x8c0\xe2\x8ey\x95@\xf8\xdfA:\xdc\x11ř@\xf8\x84\xf7C֔\x10\x9e@\xf8\x95\xd6&\xe8\v.\xa1@\xf8:\x8c0\xe2\x8ey\xa5@\xf8\xdfA:\xdc\x11ũ@\xf8\x84\xf7C֔\x10\xae@\xf8\x95\xd6&\xe8\v.\xb1@\xf8:\x8c0\xe2\x8ey\xb5@\xf8\xdfA:\xdc\x11Ź@\xf8\x84\xf7C֔\x10\xbe@\xf8\x95\xd6&\xe8\v.\xc1@\xf8:\x8c0\xe2\x8ey\xc5@\xf8\xdfA:\xdc\x11\xc5\xc9@\xf8\x84\xf7C֔\x10\xce@\xf8\x95\xd6&\xe8\v.\xd1@\xf8:\x8c0\xe2\x8ey\xd5@\xf8\xdfA:\xdc\x11\xc5\xd9@\xf8\x84\xf7C֔\x10\xde@\xf8\x95\xd6&\xe8\v.\xe1@\xf8:\x8c0\xe2\x8ey\xe5@\xf8\xdfA:\xdc\x11\xc5\xe9@\xf8\x84\xf7C֔\x10\xee@\xf8\x95\xd6&\xe8\v.\xf1@\xf8:\x8c0\xe2\x8ey\xf5@\xf8\xdfA:\xdc\x11\xc5\xf9@\xf8\x84\xf7C֔\x10\xfe@\xf8\x95\xd6&\xe8\v.\x01A\xfe\xf0\x7f\x00"
+
+ var secondsToNs = float64(time.Second)
+
+ dserialize := func(data string) *metrics2.Float64Histogram {
+ var res metrics2.Float64Histogram
+ if err := gob.NewDecoder(bytes.NewReader([]byte(data))).Decode(&res); err != nil {
+ panic(err)
+ }
+ return &res
+ }
+ cpuSchedLatency := metrics.RuntimeHistogramFromData(secondsToNs, dserialize(sLatency))
+ registry.Register("system/cpu/schedlatency", cpuSchedLatency)
+
+ memPauses := metrics.RuntimeHistogramFromData(secondsToNs, dserialize(gcPauses))
+ registry.Register("system/memory/pauses", memPauses)
+ }
+ return registry
+}
diff --git a/metrics/internal/sampledata_test.go b/metrics/internal/sampledata_test.go
new file mode 100644
index 0000000000..0013299406
--- /dev/null
+++ b/metrics/internal/sampledata_test.go
@@ -0,0 +1,27 @@
+package internal
+
+import (
+ "bytes"
+ "encoding/gob"
+ "fmt"
+ metrics2 "runtime/metrics"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/metrics"
+)
+
+func TestCollectRuntimeMetrics(t *testing.T) {
+ t.Skip("Only used for generating testdata")
+ serialize := func(path string, histogram *metrics2.Float64Histogram) {
+ var f = new(bytes.Buffer)
+ if err := gob.NewEncoder(f).Encode(histogram); err != nil {
+ panic(err)
+ }
+ fmt.Printf("var %v = %q\n", path, f.Bytes())
+ }
+ time.Sleep(2 * time.Second)
+ stats := metrics.ReadRuntimeStats()
+ serialize("schedlatency", stats.SchedLatency)
+ serialize("gcpauses", stats.GCPauses)
+}
diff --git a/metrics/librato/librato.go b/metrics/librato/librato.go
index 3d45f4c7be..a86f758637 100644
--- a/metrics/librato/librato.go
+++ b/metrics/librato/librato.go
@@ -61,16 +61,16 @@ func (rep *Reporter) Run() {
// calculate sum of squares from data provided by metrics.Histogram
// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
-func sumSquares(s metrics.Sample) float64 {
- count := float64(s.Count())
- sumSquared := math.Pow(count*s.Mean(), 2)
- sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count
+func sumSquares(icount int64, mean, stDev float64) float64 {
+ count := float64(icount)
+ sumSquared := math.Pow(count*mean, 2)
+ sumSquares := math.Pow(count*stDev, 2) + sumSquared/count
if math.IsNaN(sumSquares) {
return 0.0
}
return sumSquares
}
-func sumSquaresTimer(t metrics.Timer) float64 {
+func sumSquaresTimer(t metrics.TimerSnapshot) float64 {
count := float64(t.Count())
sumSquared := math.Pow(count*t.Mean(), 2)
sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
@@ -97,9 +97,10 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
measurement[Period] = rep.Interval.Seconds()
switch m := metric.(type) {
case metrics.Counter:
- if m.Count() > 0 {
+ ms := m.Snapshot()
+ if ms.Count() > 0 {
measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
- measurement[Value] = float64(m.Count())
+ measurement[Value] = float64(ms.Count())
measurement[Attributes] = map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
@@ -108,9 +109,9 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
snapshot.Counters = append(snapshot.Counters, measurement)
}
case metrics.CounterFloat64:
- if m.Count() > 0 {
+ if count := m.Snapshot().Count(); count > 0 {
measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
- measurement[Value] = m.Count()
+ measurement[Value] = count
measurement[Attributes] = map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
@@ -120,40 +121,45 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
}
case metrics.Gauge:
measurement[Name] = name
- measurement[Value] = float64(m.Value())
+ measurement[Value] = float64(m.Snapshot().Value())
snapshot.Gauges = append(snapshot.Gauges, measurement)
case metrics.GaugeFloat64:
measurement[Name] = name
- measurement[Value] = m.Value()
+ measurement[Value] = m.Snapshot().Value()
+ snapshot.Gauges = append(snapshot.Gauges, measurement)
+ case metrics.GaugeInfo:
+ measurement[Name] = name
+ measurement[Value] = m.Snapshot().Value()
snapshot.Gauges = append(snapshot.Gauges, measurement)
case metrics.Histogram:
- if m.Count() > 0 {
+ ms := m.Snapshot()
+ if ms.Count() > 0 {
gauges := make([]Measurement, histogramGaugeCount)
- s := m.Sample()
measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
- measurement[Count] = uint64(s.Count())
- measurement[Max] = float64(s.Max())
- measurement[Min] = float64(s.Min())
- measurement[Sum] = float64(s.Sum())
- measurement[SumSquares] = sumSquares(s)
+ measurement[Count] = uint64(ms.Count())
+ measurement[Max] = float64(ms.Max())
+ measurement[Min] = float64(ms.Min())
+ measurement[Sum] = float64(ms.Sum())
+ measurement[SumSquares] = sumSquares(ms.Count(), ms.Mean(), ms.StdDev())
gauges[0] = measurement
for i, p := range rep.Percentiles {
gauges[i+1] = Measurement{
Name: fmt.Sprintf("%s.%.2f", measurement[Name], p),
- Value: s.Percentile(p),
+ Value: ms.Percentile(p),
Period: measurement[Period],
}
}
snapshot.Gauges = append(snapshot.Gauges, gauges...)
}
case metrics.Meter:
+ ms := m.Snapshot()
measurement[Name] = name
- measurement[Value] = float64(m.Count())
+ measurement[Value] = float64(ms.Count())
snapshot.Counters = append(snapshot.Counters, measurement)
snapshot.Gauges = append(snapshot.Gauges,
Measurement{
Name: fmt.Sprintf("%s.%s", name, "1min"),
- Value: m.Rate1(),
+ Value: ms.Rate1(),
Period: int64(rep.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
@@ -163,7 +169,7 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
},
Measurement{
Name: fmt.Sprintf("%s.%s", name, "5min"),
- Value: m.Rate5(),
+ Value: ms.Rate5(),
Period: int64(rep.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
@@ -173,7 +179,7 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
},
Measurement{
Name: fmt.Sprintf("%s.%s", name, "15min"),
- Value: m.Rate15(),
+ Value: ms.Rate15(),
Period: int64(rep.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
@@ -183,26 +189,27 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
},
)
case metrics.Timer:
+ ms := m.Snapshot()
measurement[Name] = name
- measurement[Value] = float64(m.Count())
+ measurement[Value] = float64(ms.Count())
snapshot.Counters = append(snapshot.Counters, measurement)
- if m.Count() > 0 {
+ if ms.Count() > 0 {
libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
gauges := make([]Measurement, histogramGaugeCount)
gauges[0] = Measurement{
Name: libratoName,
- Count: uint64(m.Count()),
- Sum: m.Mean() * float64(m.Count()),
- Max: float64(m.Max()),
- Min: float64(m.Min()),
- SumSquares: sumSquaresTimer(m),
+ Count: uint64(ms.Count()),
+ Sum: ms.Mean() * float64(ms.Count()),
+ Max: float64(ms.Max()),
+ Min: float64(ms.Min()),
+ SumSquares: sumSquaresTimer(ms),
Period: int64(rep.Interval.Seconds()),
Attributes: rep.TimerAttributes,
}
for i, p := range rep.Percentiles {
gauges[i+1] = Measurement{
Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100),
- Value: m.Percentile(p),
+ Value: ms.Percentile(p),
Period: int64(rep.Interval.Seconds()),
Attributes: rep.TimerAttributes,
}
@@ -211,7 +218,7 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
snapshot.Gauges = append(snapshot.Gauges,
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.1min"),
- Value: m.Rate1(),
+ Value: ms.Rate1(),
Period: int64(rep.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
@@ -221,7 +228,7 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
},
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.5min"),
- Value: m.Rate5(),
+ Value: ms.Rate5(),
Period: int64(rep.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
@@ -231,7 +238,7 @@ func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot B
},
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.15min"),
- Value: m.Rate15(),
+ Value: ms.Rate15(),
Period: int64(rep.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
diff --git a/metrics/log.go b/metrics/log.go
index d1ce627a83..3b9773faa7 100644
--- a/metrics/log.go
+++ b/metrics/log.go
@@ -23,16 +23,19 @@ func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) {
switch metric := i.(type) {
case Counter:
l.Printf("counter %s\n", name)
- l.Printf(" count: %9d\n", metric.Count())
+ l.Printf(" count: %9d\n", metric.Snapshot().Count())
case CounterFloat64:
l.Printf("counter %s\n", name)
- l.Printf(" count: %f\n", metric.Count())
+ l.Printf(" count: %f\n", metric.Snapshot().Count())
case Gauge:
l.Printf("gauge %s\n", name)
- l.Printf(" value: %9d\n", metric.Value())
+ l.Printf(" value: %9d\n", metric.Snapshot().Value())
case GaugeFloat64:
l.Printf("gauge %s\n", name)
- l.Printf(" value: %f\n", metric.Value())
+ l.Printf(" value: %f\n", metric.Snapshot().Value())
+ case GaugeInfo:
+ l.Printf("gauge %s\n", name)
+ l.Printf(" value: %s\n", metric.Snapshot().Value())
case Healthcheck:
metric.Check()
l.Printf("healthcheck %s\n", name)
diff --git a/metrics/meter.go b/metrics/meter.go
index e8564d6a5e..22475ef6eb 100644
--- a/metrics/meter.go
+++ b/metrics/meter.go
@@ -1,21 +1,25 @@
package metrics
import (
+ "math"
"sync"
"sync/atomic"
"time"
)
-// Meters count events to produce exponentially-weighted moving average rates
-// at one-, five-, and fifteen-minutes and a mean rate.
-type Meter interface {
+type MeterSnapshot interface {
Count() int64
- Mark(int64)
Rate1() float64
Rate5() float64
Rate15() float64
RateMean() float64
- Snapshot() Meter
+}
+
+// Meters count events to produce exponentially-weighted moving average rates
+// at one-, five-, and fifteen-minutes and a mean rate.
+type Meter interface {
+ Mark(int64)
+ Snapshot() MeterSnapshot
Stop()
}
@@ -30,17 +34,6 @@ func GetOrRegisterMeter(name string, r Registry) Meter {
return r.GetOrRegister(name, NewMeter).(Meter)
}
-// GetOrRegisterMeterForced returns an existing Meter or constructs and registers a
-// new StandardMeter no matter the global switch is enabled or not.
-// Be sure to unregister the meter from the registry once it is of no use to
-// allow for garbage collection.
-func GetOrRegisterMeterForced(name string, r Registry) Meter {
- if nil == r {
- r = DefaultRegistry
- }
- return r.GetOrRegister(name, NewMeterForced).(Meter)
-}
-
// NewMeter constructs a new StandardMeter and launches a goroutine.
// Be sure to call Stop() once the meter is of no use to allow for garbage collection.
func NewMeter() Meter {
@@ -58,18 +51,13 @@ func NewMeter() Meter {
return m
}
-// NewMeterForced constructs a new StandardMeter and launches a goroutine no matter
-// the global switch is enabled or not.
-// Be sure to call Stop() once the meter is of no use to allow for garbage collection.
-func NewMeterForced() Meter {
- m := newStandardMeter()
- arbiter.Lock()
- defer arbiter.Unlock()
- arbiter.meters[m] = struct{}{}
- if !arbiter.started {
- arbiter.started = true
- go arbiter.tick()
+// NewInactiveMeter returns a meter but does not start any goroutines. This
+// method is mainly intended for testing.
+func NewInactiveMeter() Meter {
+ if !Enabled {
+ return NilMeter{}
}
+ m := newStandardMeter()
return m
}
@@ -78,95 +66,48 @@ func NewMeterForced() Meter {
// Be sure to unregister the meter from the registry once it is of no use to
// allow for garbage collection.
func NewRegisteredMeter(name string, r Registry) Meter {
- c := NewMeter()
- if nil == r {
- r = DefaultRegistry
- }
- r.Register(name, c)
- return c
-}
-
-// NewRegisteredMeterForced constructs and registers a new StandardMeter
-// and launches a goroutine no matter the global switch is enabled or not.
-// Be sure to unregister the meter from the registry once it is of no use to
-// allow for garbage collection.
-func NewRegisteredMeterForced(name string, r Registry) Meter {
- c := NewMeterForced()
- if nil == r {
- r = DefaultRegistry
- }
- r.Register(name, c)
- return c
+ return GetOrRegisterMeter(name, r)
}
-// MeterSnapshot is a read-only copy of another Meter.
-type MeterSnapshot struct {
- temp atomic.Int64
+// meterSnapshot is a read-only copy of the meter's internal values.
+type meterSnapshot struct {
count int64
rate1, rate5, rate15, rateMean float64
}
// Count returns the count of events at the time the snapshot was taken.
-func (m *MeterSnapshot) Count() int64 { return m.count }
-
-// Mark panics.
-func (*MeterSnapshot) Mark(n int64) {
- panic("Mark called on a MeterSnapshot")
-}
+func (m *meterSnapshot) Count() int64 { return m.count }
// Rate1 returns the one-minute moving average rate of events per second at the
// time the snapshot was taken.
-func (m *MeterSnapshot) Rate1() float64 { return m.rate1 }
+func (m *meterSnapshot) Rate1() float64 { return m.rate1 }
// Rate5 returns the five-minute moving average rate of events per second at
// the time the snapshot was taken.
-func (m *MeterSnapshot) Rate5() float64 { return m.rate5 }
+func (m *meterSnapshot) Rate5() float64 { return m.rate5 }
// Rate15 returns the fifteen-minute moving average rate of events per second
// at the time the snapshot was taken.
-func (m *MeterSnapshot) Rate15() float64 { return m.rate15 }
+func (m *meterSnapshot) Rate15() float64 { return m.rate15 }
// RateMean returns the meter's mean rate of events per second at the time the
// snapshot was taken.
-func (m *MeterSnapshot) RateMean() float64 { return m.rateMean }
-
-// Snapshot returns the snapshot.
-func (m *MeterSnapshot) Snapshot() Meter { return m }
-
-// Stop is a no-op.
-func (m *MeterSnapshot) Stop() {}
+func (m *meterSnapshot) RateMean() float64 { return m.rateMean }
// NilMeter is a no-op Meter.
type NilMeter struct{}
-// Count is a no-op.
-func (NilMeter) Count() int64 { return 0 }
-
-// Mark is a no-op.
-func (NilMeter) Mark(n int64) {}
-
-// Rate1 is a no-op.
-func (NilMeter) Rate1() float64 { return 0.0 }
-
-// Rate5 is a no-op.
-func (NilMeter) Rate5() float64 { return 0.0 }
-
-// Rate15 is a no-op.
-func (NilMeter) Rate15() float64 { return 0.0 }
-
-// RateMean is a no-op.
-func (NilMeter) RateMean() float64 { return 0.0 }
-
-// Snapshot is a no-op.
-func (NilMeter) Snapshot() Meter { return NilMeter{} }
-
-// Stop is a no-op.
-func (NilMeter) Stop() {}
+func (NilMeter) Count() int64 { return 0 }
+func (NilMeter) Mark(n int64) {}
+func (NilMeter) Snapshot() MeterSnapshot { return (*emptySnapshot)(nil) }
+func (NilMeter) Stop() {}
// StandardMeter is the standard implementation of a Meter.
type StandardMeter struct {
- lock sync.RWMutex
- snapshot *MeterSnapshot
+ count atomic.Int64
+ uncounted atomic.Int64 // not yet added to the EWMAs
+ rateMean atomic.Uint64
+
a1, a5, a15 EWMA
startTime time.Time
stopped atomic.Bool
@@ -174,7 +115,6 @@ type StandardMeter struct {
func newStandardMeter() *StandardMeter {
return &StandardMeter{
- snapshot: &MeterSnapshot{},
a1: NewEWMA1(),
a5: NewEWMA5(),
a15: NewEWMA15(),
@@ -184,97 +124,42 @@ func newStandardMeter() *StandardMeter {
// Stop stops the meter, Mark() will be a no-op if you use it after being stopped.
func (m *StandardMeter) Stop() {
- stopped := m.stopped.Swap(true)
- if !stopped {
+ if stopped := m.stopped.Swap(true); !stopped {
arbiter.Lock()
delete(arbiter.meters, m)
arbiter.Unlock()
}
}
-// Count returns the number of events recorded.
-// It updates the meter to be as accurate as possible
-func (m *StandardMeter) Count() int64 {
- m.lock.Lock()
- defer m.lock.Unlock()
- m.updateMeter()
- return m.snapshot.count
-}
-
// Mark records the occurrence of n events.
func (m *StandardMeter) Mark(n int64) {
- m.snapshot.temp.Add(n)
-}
-
-// Rate1 returns the one-minute moving average rate of events per second.
-func (m *StandardMeter) Rate1() float64 {
- m.lock.RLock()
- defer m.lock.RUnlock()
- return m.snapshot.rate1
-}
-
-// Rate5 returns the five-minute moving average rate of events per second.
-func (m *StandardMeter) Rate5() float64 {
- m.lock.RLock()
- defer m.lock.RUnlock()
- return m.snapshot.rate5
-}
-
-// Rate15 returns the fifteen-minute moving average rate of events per second.
-func (m *StandardMeter) Rate15() float64 {
- m.lock.RLock()
- defer m.lock.RUnlock()
- return m.snapshot.rate15
-}
-
-// RateMean returns the meter's mean rate of events per second.
-func (m *StandardMeter) RateMean() float64 {
- m.lock.RLock()
- defer m.lock.RUnlock()
- return m.snapshot.rateMean
+ m.uncounted.Add(n)
}
// Snapshot returns a read-only copy of the meter.
-func (m *StandardMeter) Snapshot() Meter {
- m.lock.RLock()
- snapshot := MeterSnapshot{
- count: m.snapshot.count,
- rate1: m.snapshot.rate1,
- rate5: m.snapshot.rate5,
- rate15: m.snapshot.rate15,
- rateMean: m.snapshot.rateMean,
+func (m *StandardMeter) Snapshot() MeterSnapshot {
+ return &meterSnapshot{
+ count: m.count.Load() + m.uncounted.Load(),
+ rate1: m.a1.Snapshot().Rate(),
+ rate5: m.a5.Snapshot().Rate(),
+ rate15: m.a15.Snapshot().Rate(),
+ rateMean: math.Float64frombits(m.rateMean.Load()),
}
- snapshot.temp.Store(m.snapshot.temp.Load())
- m.lock.RUnlock()
- return &snapshot
-}
-
-func (m *StandardMeter) updateSnapshot() {
- // should run with write lock held on m.lock
- snapshot := m.snapshot
- snapshot.rate1 = m.a1.Rate()
- snapshot.rate5 = m.a5.Rate()
- snapshot.rate15 = m.a15.Rate()
- snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds()
}
-func (m *StandardMeter) updateMeter() {
- // should only run with write lock held on m.lock
- n := m.snapshot.temp.Swap(0)
- m.snapshot.count += n
+func (m *StandardMeter) tick() {
+ // Take the uncounted values, add to count
+ n := m.uncounted.Swap(0)
+ count := m.count.Add(n)
+ m.rateMean.Store(math.Float64bits(float64(count) / time.Since(m.startTime).Seconds()))
+ // Update the EWMA's internal state
m.a1.Update(n)
m.a5.Update(n)
m.a15.Update(n)
-}
-
-func (m *StandardMeter) tick() {
- m.lock.Lock()
- defer m.lock.Unlock()
- m.updateMeter()
+ // And trigger them to calculate the rates
m.a1.Tick()
m.a5.Tick()
m.a15.Tick()
- m.updateSnapshot()
}
// meterArbiter ticks meters every 5s from a single goroutine.
diff --git a/metrics/meter_test.go b/metrics/meter_test.go
index b3f6cb8c0c..019c4d765b 100644
--- a/metrics/meter_test.go
+++ b/metrics/meter_test.go
@@ -12,11 +12,17 @@ func BenchmarkMeter(b *testing.B) {
m.Mark(1)
}
}
-
+func TestMeter(t *testing.T) {
+ m := NewMeter()
+ m.Mark(47)
+ if v := m.Snapshot().Count(); v != 47 {
+ t.Fatalf("have %d want %d", v, 47)
+ }
+}
func TestGetOrRegisterMeter(t *testing.T) {
r := NewRegistry()
NewRegisteredMeter("foo", r).Mark(47)
- if m := GetOrRegisterMeter("foo", r); m.Count() != 47 {
+ if m := GetOrRegisterMeter("foo", r).Snapshot(); m.Count() != 47 {
t.Fatal(m.Count())
}
}
@@ -31,10 +37,10 @@ func TestMeterDecay(t *testing.T) {
ma.meters[m] = struct{}{}
m.Mark(1)
ma.tickMeters()
- rateMean := m.RateMean()
+ rateMean := m.Snapshot().RateMean()
time.Sleep(100 * time.Millisecond)
ma.tickMeters()
- if m.RateMean() >= rateMean {
+ if m.Snapshot().RateMean() >= rateMean {
t.Error("m.RateMean() didn't decrease")
}
}
@@ -42,7 +48,7 @@ func TestMeterDecay(t *testing.T) {
func TestMeterNonzero(t *testing.T) {
m := NewMeter()
m.Mark(3)
- if count := m.Count(); count != 3 {
+ if count := m.Snapshot().Count(); count != 3 {
t.Errorf("m.Count(): 3 != %v\n", count)
}
}
@@ -59,16 +65,8 @@ func TestMeterStop(t *testing.T) {
}
}
-func TestMeterSnapshot(t *testing.T) {
- m := NewMeter()
- m.Mark(1)
- if snapshot := m.Snapshot(); m.RateMean() != snapshot.RateMean() {
- t.Fatal(snapshot)
- }
-}
-
func TestMeterZero(t *testing.T) {
- m := NewMeter()
+ m := NewMeter().Snapshot()
if count := m.Count(); count != 0 {
t.Errorf("m.Count(): 0 != %v\n", count)
}
@@ -79,13 +77,13 @@ func TestMeterRepeat(t *testing.T) {
for i := 0; i < 101; i++ {
m.Mark(int64(i))
}
- if count := m.Count(); count != 5050 {
+ if count := m.Snapshot().Count(); count != 5050 {
t.Errorf("m.Count(): 5050 != %v\n", count)
}
for i := 0; i < 101; i++ {
m.Mark(int64(i))
}
- if count := m.Count(); count != 10100 {
+ if count := m.Snapshot().Count(); count != 10100 {
t.Errorf("m.Count(): 10100 != %v\n", count)
}
}
diff --git a/metrics/metrics.go b/metrics/metrics.go
index c206f16924..9ca8f115c0 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -9,7 +9,9 @@ import (
"os"
"runtime/metrics"
"runtime/pprof"
+ "strconv"
"strings"
+ "syscall"
"time"
"github.com/ethereum/go-ethereum/log"
@@ -30,13 +32,35 @@ var EnabledExpensive = false
// enablerFlags is the CLI flag names to use to enable metrics collections.
var enablerFlags = []string{"metrics"}
+// enablerEnvVars is the env var names to use to enable metrics collections.
+var enablerEnvVars = []string{"GETH_METRICS"}
+
// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections.
var expensiveEnablerFlags = []string{"metrics.expensive"}
+// expensiveEnablerEnvVars is the env var names to use to enable metrics collections.
+var expensiveEnablerEnvVars = []string{"GETH_METRICS_EXPENSIVE"}
+
// Init enables or disables the metrics system. Since we need this to run before
// any other code gets to create meters and timers, we'll actually do an ugly hack
// and peek into the command line args for the metrics flag.
func init() {
+ for _, enabler := range enablerEnvVars {
+ if val, found := syscall.Getenv(enabler); found && !Enabled {
+ if enable, _ := strconv.ParseBool(val); enable { // ignore error, flag parser will choke on it later
+ log.Info("Enabling metrics collection")
+ Enabled = true
+ }
+ }
+ }
+ for _, enabler := range expensiveEnablerEnvVars {
+ if val, found := syscall.Getenv(enabler); found && !EnabledExpensive {
+ if enable, _ := strconv.ParseBool(val); enable { // ignore error, flag parser will choke on it later
+ log.Info("Enabling expensive metrics collection")
+ EnabledExpensive = true
+ }
+ }
+ }
for _, arg := range os.Args {
flag := strings.TrimLeft(arg, "-")
@@ -85,6 +109,12 @@ var runtimeSamples = []metrics.Sample{
{Name: "/sched/latencies:seconds"}, // histogram
}
+func ReadRuntimeStats() *runtimeStats {
+ r := new(runtimeStats)
+ readRuntimeStats(r)
+ return r
+}
+
func readRuntimeStats(v *runtimeStats) {
metrics.Read(runtimeSamples)
for _, s := range runtimeSamples {
diff --git a/metrics/metrics_test.go b/metrics/metrics_test.go
index 534c44139b..2861d5f2ca 100644
--- a/metrics/metrics_test.go
+++ b/metrics/metrics_test.go
@@ -98,8 +98,8 @@ func Example() {
t.Time(func() { time.Sleep(10 * time.Millisecond) })
t.Update(1)
- fmt.Println(c.Count())
- fmt.Println(t.Min())
+ fmt.Println(c.Snapshot().Count())
+ fmt.Println(t.Snapshot().Min())
// Output: 17
// 1
}
diff --git a/metrics/opentsdb.go b/metrics/opentsdb.go
index c9fd2e75d5..e81690f943 100644
--- a/metrics/opentsdb.go
+++ b/metrics/opentsdb.go
@@ -3,6 +3,7 @@ package metrics
import (
"bufio"
"fmt"
+ "io"
"log"
"net"
"os"
@@ -57,26 +58,22 @@ func getShortHostname() string {
return shortHostName
}
-func openTSDB(c *OpenTSDBConfig) error {
- shortHostname := getShortHostname()
- now := time.Now().Unix()
+// writeRegistry writes the registry-metrics on the opentsb format.
+func (c *OpenTSDBConfig) writeRegistry(w io.Writer, now int64, shortHostname string) {
du := float64(c.DurationUnit)
- conn, err := net.DialTCP("tcp", nil, c.Addr)
- if nil != err {
- return err
- }
- defer conn.Close()
- w := bufio.NewWriter(conn)
+
c.Registry.Each(func(name string, i interface{}) {
switch metric := i.(type) {
case Counter:
- fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname)
+ fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Snapshot().Count(), shortHostname)
case CounterFloat64:
- fmt.Fprintf(w, "put %s.%s.count %d %f host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname)
+ fmt.Fprintf(w, "put %s.%s.count %d %f host=%s\n", c.Prefix, name, now, metric.Snapshot().Count(), shortHostname)
case Gauge:
- fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
+ fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Snapshot().Value(), shortHostname)
case GaugeFloat64:
- fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
+ fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Snapshot().Value(), shortHostname)
+ case GaugeInfo:
+ fmt.Fprintf(w, "put %s.%s.value %d %s host=%s\n", c.Prefix, name, now, metric.Snapshot().Value().String(), shortHostname)
case Histogram:
h := metric.Snapshot()
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
@@ -115,7 +112,17 @@ func openTSDB(c *OpenTSDBConfig) error {
fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname)
fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname)
}
- w.Flush()
})
+}
+
+func openTSDB(c *OpenTSDBConfig) error {
+ conn, err := net.DialTCP("tcp", nil, c.Addr)
+ if nil != err {
+ return err
+ }
+ defer conn.Close()
+ w := bufio.NewWriter(conn)
+ c.writeRegistry(w, time.Now().Unix(), getShortHostname())
+ w.Flush()
return nil
}
diff --git a/metrics/opentsdb_test.go b/metrics/opentsdb_test.go
index c43728960e..4548309f9c 100644
--- a/metrics/opentsdb_test.go
+++ b/metrics/opentsdb_test.go
@@ -1,7 +1,11 @@
package metrics
import (
+ "fmt"
"net"
+ "os"
+ "strings"
+ "testing"
"time"
)
@@ -19,3 +23,44 @@ func ExampleOpenTSDBWithConfig() {
DurationUnit: time.Millisecond,
})
}
+
+func TestExampleOpenTSB(t *testing.T) {
+ r := NewOrderedRegistry()
+ NewRegisteredGaugeInfo("foo", r).Update(GaugeInfoValue{"chain_id": "5"})
+ NewRegisteredGaugeFloat64("pi", r).Update(3.14)
+ NewRegisteredCounter("months", r).Inc(12)
+ NewRegisteredCounterFloat64("tau", r).Inc(1.57)
+ NewRegisteredMeter("elite", r).Mark(1337)
+ NewRegisteredTimer("second", r).Update(time.Second)
+ NewRegisteredCounterFloat64("tau", r).Inc(1.57)
+ NewRegisteredCounterFloat64("tau", r).Inc(1.57)
+
+ w := new(strings.Builder)
+ (&OpenTSDBConfig{
+ Registry: r,
+ DurationUnit: time.Millisecond,
+ Prefix: "pre",
+ }).writeRegistry(w, 978307200, "hal9000")
+
+ wantB, err := os.ReadFile("./testdata/opentsb.want")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if have, want := w.String(), string(wantB); have != want {
+ t.Errorf("\nhave:\n%v\nwant:\n%v\n", have, want)
+ t.Logf("have vs want:\n%v", findFirstDiffPos(have, want))
+ }
+}
+
+func findFirstDiffPos(a, b string) string {
+ yy := strings.Split(b, "\n")
+ for i, x := range strings.Split(a, "\n") {
+ if i >= len(yy) {
+ return fmt.Sprintf("have:%d: %s\nwant:%d: ", i, x, i)
+ }
+ if y := yy[i]; x != y {
+ return fmt.Sprintf("have:%d: %s\nwant:%d: %s", i, x, i, y)
+ }
+ }
+ return ""
+}
diff --git a/metrics/prometheus/collector.go b/metrics/prometheus/collector.go
index 6fa7292e35..a6a93ce0ee 100644
--- a/metrics/prometheus/collector.go
+++ b/metrics/prometheus/collector.go
@@ -19,6 +19,7 @@ package prometheus
import (
"bytes"
"fmt"
+ "sort"
"strconv"
"strings"
@@ -47,23 +48,57 @@ func newCollector() *collector {
}
}
-func (c *collector) addCounter(name string, m metrics.Counter) {
+// Add adds the metric i to the collector. This method returns an error if the
+// metric type is not supported/known.
+func (c *collector) Add(name string, i any) error {
+ switch m := i.(type) {
+ case metrics.Counter:
+ c.addCounter(name, m.Snapshot())
+ case metrics.CounterFloat64:
+ c.addCounterFloat64(name, m.Snapshot())
+ case metrics.Gauge:
+ c.addGauge(name, m.Snapshot())
+ case metrics.GaugeFloat64:
+ c.addGaugeFloat64(name, m.Snapshot())
+ case metrics.GaugeInfo:
+ c.addGaugeInfo(name, m.Snapshot())
+ case metrics.Histogram:
+ c.addHistogram(name, m.Snapshot())
+ case metrics.Meter:
+ c.addMeter(name, m.Snapshot())
+ case metrics.Timer:
+ c.addTimer(name, m.Snapshot())
+ case metrics.ResettingTimer:
+ c.addResettingTimer(name, m.Snapshot())
+ case metrics.Label:
+ c.addLabel(name, m)
+ default:
+ return fmt.Errorf("unknown prometheus metric type %T", i)
+ }
+ return nil
+}
+
+func (c *collector) addCounter(name string, m metrics.CounterSnapshot) {
c.writeGaugeCounter(name, m.Count())
}
-func (c *collector) addCounterFloat64(name string, m metrics.CounterFloat64) {
+func (c *collector) addCounterFloat64(name string, m metrics.CounterFloat64Snapshot) {
c.writeGaugeCounter(name, m.Count())
}
-func (c *collector) addGauge(name string, m metrics.Gauge) {
+func (c *collector) addGauge(name string, m metrics.GaugeSnapshot) {
c.writeGaugeCounter(name, m.Value())
}
-func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64) {
+func (c *collector) addGaugeFloat64(name string, m metrics.GaugeFloat64Snapshot) {
c.writeGaugeCounter(name, m.Value())
}
-func (c *collector) addHistogram(name string, m metrics.Histogram) {
+func (c *collector) addGaugeInfo(name string, m metrics.GaugeInfoSnapshot) {
+ c.writeGaugeInfo(name, m.Value())
+}
+
+func (c *collector) addHistogram(name string, m metrics.HistogramSnapshot) {
pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}
ps := m.Percentiles(pv)
c.writeSummaryCounter(name, m.Count())
@@ -74,11 +109,11 @@ func (c *collector) addHistogram(name string, m metrics.Histogram) {
c.buff.WriteRune('\n')
}
-func (c *collector) addMeter(name string, m metrics.Meter) {
+func (c *collector) addMeter(name string, m metrics.MeterSnapshot) {
c.writeGaugeCounter(name, m.Count())
}
-func (c *collector) addTimer(name string, m metrics.Timer) {
+func (c *collector) addTimer(name string, m metrics.TimerSnapshot) {
pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}
ps := m.Percentiles(pv)
c.writeSummaryCounter(name, m.Count())
@@ -89,13 +124,12 @@ func (c *collector) addTimer(name string, m metrics.Timer) {
c.buff.WriteRune('\n')
}
-func (c *collector) addResettingTimer(name string, m metrics.ResettingTimer) {
- if len(m.Values()) <= 0 {
+func (c *collector) addResettingTimer(name string, m metrics.ResettingTimerSnapshot) {
+ if m.Count() <= 0 {
return
}
- ps := m.Percentiles([]float64{50, 95, 99})
- val := m.Values()
- c.writeSummaryCounter(name, len(val))
+ ps := m.Percentiles([]float64{0.50, 0.95, 0.99})
+ c.writeSummaryCounter(name, m.Count())
c.buff.WriteString(fmt.Sprintf(typeSummaryTpl, mutateKey(name)))
c.writeSummaryPercentile(name, "0.50", ps[0])
c.writeSummaryPercentile(name, "0.95", ps[1])
@@ -116,6 +150,19 @@ func (c *collector) writeLabel(name string, value interface{}) {
c.buff.WriteString(fmt.Sprintf(keyLabelValueTpl, name, value, 1))
}
+func (c *collector) writeGaugeInfo(name string, value metrics.GaugeInfoValue) {
+ name = mutateKey(name)
+ c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name))
+ c.buff.WriteString(name)
+ c.buff.WriteString(" ")
+ var kvs []string
+ for k, v := range value {
+ kvs = append(kvs, fmt.Sprintf("%v=%q", k, v))
+ }
+ sort.Strings(kvs)
+ c.buff.WriteString(fmt.Sprintf("{%v} 1\n\n", strings.Join(kvs, ", ")))
+}
+
func (c *collector) writeGaugeCounter(name string, value interface{}) {
name = mutateKey(name)
c.buff.WriteString(fmt.Sprintf(typeGaugeTpl, name))
diff --git a/metrics/prometheus/collector_test.go b/metrics/prometheus/collector_test.go
index ff87c8e765..ea17aac458 100644
--- a/metrics/prometheus/collector_test.go
+++ b/metrics/prometheus/collector_test.go
@@ -1,11 +1,29 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
package prometheus
import (
+ "fmt"
"os"
+ "strings"
"testing"
- "time"
"github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/metrics/internal"
)
func TestMain(m *testing.M) {
@@ -14,104 +32,34 @@ func TestMain(m *testing.M) {
}
func TestCollector(t *testing.T) {
- c := newCollector()
-
- counter := metrics.NewCounter()
- counter.Inc(12345)
- c.addCounter("test/counter", counter)
-
- counterfloat64 := metrics.NewCounterFloat64()
- counterfloat64.Inc(54321.98)
- c.addCounterFloat64("test/counter_float64", counterfloat64)
-
- gauge := metrics.NewGauge()
- gauge.Update(23456)
- c.addGauge("test/gauge", gauge)
-
- gaugeFloat64 := metrics.NewGaugeFloat64()
- gaugeFloat64.Update(34567.89)
- c.addGaugeFloat64("test/gauge_float64", gaugeFloat64)
-
- histogram := metrics.NewHistogram(&metrics.NilSample{})
- c.addHistogram("test/histogram", histogram)
-
- meter := metrics.NewMeter()
- defer meter.Stop()
- meter.Mark(9999999)
- c.addMeter("test/meter", meter)
-
- timer := metrics.NewTimer()
- defer timer.Stop()
- timer.Update(20 * time.Millisecond)
- timer.Update(21 * time.Millisecond)
- timer.Update(22 * time.Millisecond)
- timer.Update(120 * time.Millisecond)
- timer.Update(23 * time.Millisecond)
- timer.Update(24 * time.Millisecond)
- c.addTimer("test/timer", timer)
-
- resettingTimer := metrics.NewResettingTimer()
- resettingTimer.Update(10 * time.Millisecond)
- resettingTimer.Update(11 * time.Millisecond)
- resettingTimer.Update(12 * time.Millisecond)
- resettingTimer.Update(120 * time.Millisecond)
- resettingTimer.Update(13 * time.Millisecond)
- resettingTimer.Update(14 * time.Millisecond)
- c.addResettingTimer("test/resetting_timer", resettingTimer.Snapshot())
-
- emptyResettingTimer := metrics.NewResettingTimer().Snapshot()
- c.addResettingTimer("test/empty_resetting_timer", emptyResettingTimer)
-
- const expectedOutput = `# TYPE test_counter gauge
-test_counter 12345
-
-# TYPE test_counter_float64 gauge
-test_counter_float64 54321.98
-
-# TYPE test_gauge gauge
-test_gauge 23456
-
-# TYPE test_gauge_float64 gauge
-test_gauge_float64 34567.89
-
-# TYPE test_histogram_count counter
-test_histogram_count 0
-
-# TYPE test_histogram summary
-test_histogram {quantile="0.5"} 0
-test_histogram {quantile="0.75"} 0
-test_histogram {quantile="0.95"} 0
-test_histogram {quantile="0.99"} 0
-test_histogram {quantile="0.999"} 0
-test_histogram {quantile="0.9999"} 0
-
-# TYPE test_meter gauge
-test_meter 9999999
-
-# TYPE test_timer_count counter
-test_timer_count 6
-
-# TYPE test_timer summary
-test_timer {quantile="0.5"} 2.25e+07
-test_timer {quantile="0.75"} 4.8e+07
-test_timer {quantile="0.95"} 1.2e+08
-test_timer {quantile="0.99"} 1.2e+08
-test_timer {quantile="0.999"} 1.2e+08
-test_timer {quantile="0.9999"} 1.2e+08
-
-# TYPE test_resetting_timer_count counter
-test_resetting_timer_count 6
-
-# TYPE test_resetting_timer summary
-test_resetting_timer {quantile="0.50"} 12000000
-test_resetting_timer {quantile="0.95"} 120000000
-test_resetting_timer {quantile="0.99"} 120000000
+ var (
+ c = newCollector()
+ want string
+ )
+ internal.ExampleMetrics().Each(func(name string, i interface{}) {
+ c.Add(name, i)
+ })
+ if wantB, err := os.ReadFile("./testdata/prometheus.want"); err != nil {
+ t.Fatal(err)
+ } else {
+ want = string(wantB)
+ }
+ if have := c.buff.String(); have != want {
+ t.Logf("have\n%v", have)
+ t.Logf("have vs want:\n%v", findFirstDiffPos(have, want))
+ t.Fatalf("unexpected collector output")
+ }
+}
-`
- exp := c.buff.String()
- if exp != expectedOutput {
- t.Log("Expected Output:\n", expectedOutput)
- t.Log("Actual Output:\n", exp)
- t.Fatal("unexpected collector output")
+func findFirstDiffPos(a, b string) string {
+ yy := strings.Split(b, "\n")
+ for i, x := range strings.Split(a, "\n") {
+ if i >= len(yy) {
+ return fmt.Sprintf("have:%d: %s\nwant:%d: ", i, x, i)
+ }
+ if y := yy[i]; x != y {
+ return fmt.Sprintf("have:%d: %s\nwant:%d: %s", i, x, i, y)
+ }
}
+ return ""
}
diff --git a/metrics/prometheus/prometheus.go b/metrics/prometheus/prometheus.go
index 6b57cf5e73..dbdeae6c7f 100644
--- a/metrics/prometheus/prometheus.go
+++ b/metrics/prometheus/prometheus.go
@@ -41,27 +41,7 @@ func Handler(reg metrics.Registry) http.Handler {
for _, name := range names {
i := reg.Get(name)
-
- switch m := i.(type) {
- case metrics.Counter:
- c.addCounter(name, m.Snapshot())
- case metrics.CounterFloat64:
- c.addCounterFloat64(name, m.Snapshot())
- case metrics.Gauge:
- c.addGauge(name, m.Snapshot())
- case metrics.GaugeFloat64:
- c.addGaugeFloat64(name, m.Snapshot())
- case metrics.Histogram:
- c.addHistogram(name, m.Snapshot())
- case metrics.Meter:
- c.addMeter(name, m.Snapshot())
- case metrics.Timer:
- c.addTimer(name, m.Snapshot())
- case metrics.ResettingTimer:
- c.addResettingTimer(name, m.Snapshot())
- case metrics.Label:
- c.addLabel(name, m)
- default:
+ if err := c.Add(name, i); err != nil {
log.Warn("Unknown Prometheus metric type", "type", fmt.Sprintf("%T", i))
}
}
diff --git a/metrics/prometheus/testdata/prometheus.want b/metrics/prometheus/testdata/prometheus.want
new file mode 100644
index 0000000000..861c5f5cf0
--- /dev/null
+++ b/metrics/prometheus/testdata/prometheus.want
@@ -0,0 +1,70 @@
+# TYPE system_cpu_schedlatency_count counter
+system_cpu_schedlatency_count 5645
+
+# TYPE system_cpu_schedlatency summary
+system_cpu_schedlatency {quantile="0.5"} 0
+system_cpu_schedlatency {quantile="0.75"} 7168
+system_cpu_schedlatency {quantile="0.95"} 1.6777216e+07
+system_cpu_schedlatency {quantile="0.99"} 2.9360128e+07
+system_cpu_schedlatency {quantile="0.999"} 3.3554432e+07
+system_cpu_schedlatency {quantile="0.9999"} 3.3554432e+07
+
+# TYPE system_memory_pauses_count counter
+system_memory_pauses_count 14
+
+# TYPE system_memory_pauses summary
+system_memory_pauses {quantile="0.5"} 32768
+system_memory_pauses {quantile="0.75"} 57344
+system_memory_pauses {quantile="0.95"} 196608
+system_memory_pauses {quantile="0.99"} 196608
+system_memory_pauses {quantile="0.999"} 196608
+system_memory_pauses {quantile="0.9999"} 196608
+
+# TYPE test_counter gauge
+test_counter 12345
+
+# TYPE test_counter_float64 gauge
+test_counter_float64 54321.98
+
+# TYPE test_gauge gauge
+test_gauge 23456
+
+# TYPE test_gauge_float64 gauge
+test_gauge_float64 34567.89
+
+# TYPE test_gauge_info gauge
+test_gauge_info {arch="amd64", commit="7caa2d8163ae3132c1c2d6978c76610caee2d949", os="linux", protocol_versions="64 65 66", version="1.10.18-unstable"} 1
+
+# TYPE test_histogram_count counter
+test_histogram_count 3
+
+# TYPE test_histogram summary
+test_histogram {quantile="0.5"} 2
+test_histogram {quantile="0.75"} 3
+test_histogram {quantile="0.95"} 3
+test_histogram {quantile="0.99"} 3
+test_histogram {quantile="0.999"} 3
+test_histogram {quantile="0.9999"} 3
+
+# TYPE test_meter gauge
+test_meter 0
+
+# TYPE test_resetting_timer_count counter
+test_resetting_timer_count 6
+
+# TYPE test_resetting_timer summary
+test_resetting_timer {quantile="0.50"} 1.25e+07
+test_resetting_timer {quantile="0.95"} 1.2e+08
+test_resetting_timer {quantile="0.99"} 1.2e+08
+
+# TYPE test_timer_count counter
+test_timer_count 6
+
+# TYPE test_timer summary
+test_timer {quantile="0.5"} 2.25e+07
+test_timer {quantile="0.75"} 4.8e+07
+test_timer {quantile="0.95"} 1.2e+08
+test_timer {quantile="0.99"} 1.2e+08
+test_timer {quantile="0.999"} 1.2e+08
+test_timer {quantile="0.9999"} 1.2e+08
+
diff --git a/metrics/registry.go b/metrics/registry.go
index 5261631402..0dd7cf9bba 100644
--- a/metrics/registry.go
+++ b/metrics/registry.go
@@ -3,6 +3,7 @@ package metrics
import (
"fmt"
"reflect"
+ "sort"
"strings"
"sync"
)
@@ -47,17 +48,39 @@ type Registry interface {
Unregister(string)
}
+type orderedRegistry struct {
+ StandardRegistry
+}
+
+// Call the given function for each registered metric.
+func (r *orderedRegistry) Each(f func(string, interface{})) {
+ var names []string
+ reg := r.registered()
+ for name := range reg {
+ names = append(names, name)
+ }
+ sort.Strings(names)
+ for _, name := range names {
+ f(name, reg[name])
+ }
+}
+
+// NewRegistry creates a new registry.
+func NewRegistry() Registry {
+ return new(StandardRegistry)
+}
+
+// NewOrderedRegistry creates a new ordered registry (for testing).
+func NewOrderedRegistry() Registry {
+ return new(orderedRegistry)
+}
+
// The standard implementation of a Registry uses sync.map
// of names to metrics.
type StandardRegistry struct {
metrics sync.Map
}
-// Create a new registry.
-func NewRegistry() Registry {
- return &StandardRegistry{}
-}
-
// Call the given function for each registered metric.
func (r *StandardRegistry) Each(f func(string, interface{})) {
for name, i := range r.registered() {
@@ -127,13 +150,13 @@ func (r *StandardRegistry) GetAll() map[string]map[string]interface{} {
values := make(map[string]interface{})
switch metric := i.(type) {
case Counter:
- values["count"] = metric.Count()
+ values["count"] = metric.Snapshot().Count()
case CounterFloat64:
- values["count"] = metric.Count()
+ values["count"] = metric.Snapshot().Count()
case Gauge:
- values["value"] = metric.Value()
+ values["value"] = metric.Snapshot().Value()
case GaugeFloat64:
- values["value"] = metric.Value()
+ values["value"] = metric.Snapshot().Value()
case Healthcheck:
values["error"] = nil
metric.Check()
@@ -191,7 +214,7 @@ func (r *StandardRegistry) Unregister(name string) {
func (r *StandardRegistry) loadOrRegister(name string, i interface{}) (interface{}, bool, bool) {
switch i.(type) {
- case Counter, CounterFloat64, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer, ResettingTimer, Label:
+ case Counter, CounterFloat64, Gauge, GaugeFloat64, GaugeInfo, Healthcheck, Histogram, Meter, Timer, ResettingTimer, Label:
default:
return nil, false, false
}
diff --git a/metrics/registry_test.go b/metrics/registry_test.go
index 7cc5cf14fe..75012dd4ac 100644
--- a/metrics/registry_test.go
+++ b/metrics/registry_test.go
@@ -85,11 +85,11 @@ func TestRegistryDuplicate(t *testing.T) {
func TestRegistryGet(t *testing.T) {
r := NewRegistry()
r.Register("foo", NewCounter())
- if count := r.Get("foo").(Counter).Count(); count != 0 {
+ if count := r.Get("foo").(Counter).Snapshot().Count(); count != 0 {
t.Fatal(count)
}
r.Get("foo").(Counter).Inc(1)
- if count := r.Get("foo").(Counter).Count(); count != 1 {
+ if count := r.Get("foo").(Counter).Snapshot().Count(); count != 1 {
t.Fatal(count)
}
}
diff --git a/metrics/resetting_sample.go b/metrics/resetting_sample.go
index 43c1129cd0..c38ffcd3ec 100644
--- a/metrics/resetting_sample.go
+++ b/metrics/resetting_sample.go
@@ -17,7 +17,7 @@ type resettingSample struct {
}
// Snapshot returns a read-only copy of the sample with the original reset.
-func (rs *resettingSample) Snapshot() Sample {
+func (rs *resettingSample) Snapshot() SampleSnapshot {
s := rs.Sample.Snapshot()
rs.Sample.Clear()
return s
diff --git a/metrics/resetting_timer.go b/metrics/resetting_timer.go
index 8e23c8eeea..6802e3fcea 100644
--- a/metrics/resetting_timer.go
+++ b/metrics/resetting_timer.go
@@ -1,22 +1,24 @@
package metrics
import (
- "math"
"sync"
"time"
-
- "golang.org/x/exp/slices"
)
// Initial slice capacity for the values stored in a ResettingTimer
const InitialResettingTimerSliceCap = 10
+type ResettingTimerSnapshot interface {
+ Count() int
+ Mean() float64
+ Max() int64
+ Min() int64
+ Percentiles([]float64) []float64
+}
+
// ResettingTimer is used for storing aggregated values for timers, which are reset on every flush interval.
type ResettingTimer interface {
- Values() []int64
- Snapshot() ResettingTimer
- Percentiles([]float64) []int64
- Mean() float64
+ Snapshot() ResettingTimerSnapshot
Time(func())
Update(time.Duration)
UpdateSince(time.Time)
@@ -52,70 +54,40 @@ func NewResettingTimer() ResettingTimer {
}
// NilResettingTimer is a no-op ResettingTimer.
-type NilResettingTimer struct {
-}
-
-// Values is a no-op.
-func (NilResettingTimer) Values() []int64 { return nil }
-
-// Snapshot is a no-op.
-func (NilResettingTimer) Snapshot() ResettingTimer {
- return &ResettingTimerSnapshot{
- values: []int64{},
- }
-}
-
-// Time is a no-op.
-func (NilResettingTimer) Time(f func()) { f() }
-
-// Update is a no-op.
-func (NilResettingTimer) Update(time.Duration) {}
-
-// Percentiles panics.
-func (NilResettingTimer) Percentiles([]float64) []int64 {
- panic("Percentiles called on a NilResettingTimer")
-}
-
-// Mean panics.
-func (NilResettingTimer) Mean() float64 {
- panic("Mean called on a NilResettingTimer")
-}
-
-// UpdateSince is a no-op.
-func (NilResettingTimer) UpdateSince(time.Time) {}
+type NilResettingTimer struct{}
+
+func (NilResettingTimer) Values() []int64 { return nil }
+func (n NilResettingTimer) Snapshot() ResettingTimerSnapshot { return n }
+func (NilResettingTimer) Time(f func()) { f() }
+func (NilResettingTimer) Update(time.Duration) {}
+func (NilResettingTimer) Percentiles([]float64) []float64 { return nil }
+func (NilResettingTimer) Mean() float64 { return 0.0 }
+func (NilResettingTimer) Max() int64 { return 0 }
+func (NilResettingTimer) Min() int64 { return 0 }
+func (NilResettingTimer) UpdateSince(time.Time) {}
+func (NilResettingTimer) Count() int { return 0 }
// StandardResettingTimer is the standard implementation of a ResettingTimer.
// and Meter.
type StandardResettingTimer struct {
values []int64
- mutex sync.Mutex
-}
+ sum int64 // sum is a running count of the total sum, used later to calculate mean
-// Values returns a slice with all measurements.
-func (t *StandardResettingTimer) Values() []int64 {
- return t.values
+ mutex sync.Mutex
}
// Snapshot resets the timer and returns a read-only copy of its contents.
-func (t *StandardResettingTimer) Snapshot() ResettingTimer {
+func (t *StandardResettingTimer) Snapshot() ResettingTimerSnapshot {
t.mutex.Lock()
defer t.mutex.Unlock()
- currentValues := t.values
- t.values = make([]int64, 0, InitialResettingTimerSliceCap)
-
- return &ResettingTimerSnapshot{
- values: currentValues,
+ snapshot := &resettingTimerSnapshot{}
+ if len(t.values) > 0 {
+ snapshot.mean = float64(t.sum) / float64(len(t.values))
+ snapshot.values = t.values
+ t.values = make([]int64, 0, InitialResettingTimerSliceCap)
}
-}
-
-// Percentiles panics.
-func (t *StandardResettingTimer) Percentiles([]float64) []int64 {
- panic("Percentiles called on a StandardResettingTimer")
-}
-
-// Mean panics.
-func (t *StandardResettingTimer) Mean() float64 {
- panic("Mean called on a StandardResettingTimer")
+ t.sum = 0
+ return snapshot
}
// Record the duration of the execution of the given function.
@@ -130,106 +102,70 @@ func (t *StandardResettingTimer) Update(d time.Duration) {
t.mutex.Lock()
defer t.mutex.Unlock()
t.values = append(t.values, int64(d))
+ t.sum += int64(d)
}
// Record the duration of an event that started at a time and ends now.
func (t *StandardResettingTimer) UpdateSince(ts time.Time) {
- t.mutex.Lock()
- defer t.mutex.Unlock()
- t.values = append(t.values, int64(time.Since(ts)))
+ t.Update(time.Since(ts))
}
-// ResettingTimerSnapshot is a point-in-time copy of another ResettingTimer.
-type ResettingTimerSnapshot struct {
+// resettingTimerSnapshot is a point-in-time copy of another ResettingTimer.
+type resettingTimerSnapshot struct {
values []int64
mean float64
- thresholdBoundaries []int64
+ max int64
+ min int64
+ thresholdBoundaries []float64
calculated bool
}
-// Snapshot returns the snapshot.
-func (t *ResettingTimerSnapshot) Snapshot() ResettingTimer { return t }
-
-// Time panics.
-func (*ResettingTimerSnapshot) Time(func()) {
- panic("Time called on a ResettingTimerSnapshot")
-}
-
-// Update panics.
-func (*ResettingTimerSnapshot) Update(time.Duration) {
- panic("Update called on a ResettingTimerSnapshot")
-}
-
-// UpdateSince panics.
-func (*ResettingTimerSnapshot) UpdateSince(time.Time) {
- panic("UpdateSince called on a ResettingTimerSnapshot")
-}
-
-// Values returns all values from snapshot.
-func (t *ResettingTimerSnapshot) Values() []int64 {
- return t.values
+// Count return the length of the values from snapshot.
+func (t *resettingTimerSnapshot) Count() int {
+ return len(t.values)
}
// Percentiles returns the boundaries for the input percentiles.
-func (t *ResettingTimerSnapshot) Percentiles(percentiles []float64) []int64 {
+// note: this method is not thread safe
+func (t *resettingTimerSnapshot) Percentiles(percentiles []float64) []float64 {
t.calc(percentiles)
-
return t.thresholdBoundaries
}
// Mean returns the mean of the snapshotted values
-func (t *ResettingTimerSnapshot) Mean() float64 {
+// note: this method is not thread safe
+func (t *resettingTimerSnapshot) Mean() float64 {
if !t.calculated {
- t.calc([]float64{})
+ t.calc(nil)
}
return t.mean
}
-func (t *ResettingTimerSnapshot) calc(percentiles []float64) {
- slices.Sort(t.values)
-
- count := len(t.values)
- if count > 0 {
- min := t.values[0]
- max := t.values[count-1]
-
- cumulativeValues := make([]int64, count)
- cumulativeValues[0] = min
- for i := 1; i < count; i++ {
- cumulativeValues[i] = t.values[i] + cumulativeValues[i-1]
- }
-
- t.thresholdBoundaries = make([]int64, len(percentiles))
-
- thresholdBoundary := max
-
- for i, pct := range percentiles {
- if count > 1 {
- var abs float64
- if pct >= 0 {
- abs = pct
- } else {
- abs = 100 + pct
- }
- // poor man's math.Round(x):
- // math.Floor(x + 0.5)
- indexOfPerc := int(math.Floor(((abs / 100.0) * float64(count)) + 0.5))
- if pct >= 0 && indexOfPerc > 0 {
- indexOfPerc -= 1 // index offset=0
- }
- thresholdBoundary = t.values[indexOfPerc]
- }
-
- t.thresholdBoundaries[i] = thresholdBoundary
- }
-
- sum := cumulativeValues[count-1]
- t.mean = float64(sum) / float64(count)
- } else {
- t.thresholdBoundaries = make([]int64, len(percentiles))
- t.mean = 0
+// Max returns the max of the snapshotted values
+// note: this method is not thread safe
+func (t *resettingTimerSnapshot) Max() int64 {
+ if !t.calculated {
+ t.calc(nil)
+ }
+ return t.max
+}
+
+// Min returns the min of the snapshotted values
+// note: this method is not thread safe
+func (t *resettingTimerSnapshot) Min() int64 {
+ if !t.calculated {
+ t.calc(nil)
}
+ return t.min
+}
- t.calculated = true
+func (t *resettingTimerSnapshot) calc(percentiles []float64) {
+ scores := CalculatePercentiles(t.values, percentiles)
+ t.thresholdBoundaries = scores
+ if len(t.values) == 0 {
+ return
+ }
+ t.min = t.values[0]
+ t.max = t.values[len(t.values)-1]
}
diff --git a/metrics/resetting_timer_test.go b/metrics/resetting_timer_test.go
index 77c49dc386..4571fc8eb0 100644
--- a/metrics/resetting_timer_test.go
+++ b/metrics/resetting_timer_test.go
@@ -10,9 +10,9 @@ func TestResettingTimer(t *testing.T) {
values []int64
start int
end int
- wantP50 int64
- wantP95 int64
- wantP99 int64
+ wantP50 float64
+ wantP95 float64
+ wantP99 float64
wantMean float64
wantMin int64
wantMax int64
@@ -21,14 +21,14 @@ func TestResettingTimer(t *testing.T) {
values: []int64{},
start: 1,
end: 11,
- wantP50: 5, wantP95: 10, wantP99: 10,
+ wantP50: 5.5, wantP95: 10, wantP99: 10,
wantMin: 1, wantMax: 10, wantMean: 5.5,
},
{
values: []int64{},
start: 1,
end: 101,
- wantP50: 50, wantP95: 95, wantP99: 99,
+ wantP50: 50.5, wantP95: 95.94999999999999, wantP99: 99.99,
wantMin: 1, wantMax: 100, wantMean: 50.5,
},
{
@@ -56,11 +56,11 @@ func TestResettingTimer(t *testing.T) {
values: []int64{1, 10},
start: 0,
end: 0,
- wantP50: 1, wantP95: 10, wantP99: 10,
+ wantP50: 5.5, wantP95: 10, wantP99: 10,
wantMin: 1, wantMax: 10, wantMean: 5.5,
},
}
- for ind, tt := range tests {
+ for i, tt := range tests {
timer := NewResettingTimer()
for i := tt.start; i < tt.end; i++ {
@@ -70,37 +70,27 @@ func TestResettingTimer(t *testing.T) {
for _, v := range tt.values {
timer.Update(time.Duration(v))
}
-
snap := timer.Snapshot()
- ps := snap.Percentiles([]float64{50, 95, 99})
-
- val := snap.Values()
+ ps := snap.Percentiles([]float64{0.50, 0.95, 0.99})
- if len(val) > 0 {
- if tt.wantMin != val[0] {
- t.Fatalf("%d: min: got %d, want %d", ind, val[0], tt.wantMin)
- }
-
- if tt.wantMax != val[len(val)-1] {
- t.Fatalf("%d: max: got %d, want %d", ind, val[len(val)-1], tt.wantMax)
- }
+ if have, want := snap.Min(), tt.wantMin; have != want {
+ t.Fatalf("%d: min: have %d, want %d", i, have, want)
}
-
- if tt.wantMean != snap.Mean() {
- t.Fatalf("%d: mean: got %.2f, want %.2f", ind, snap.Mean(), tt.wantMean)
+ if have, want := snap.Max(), tt.wantMax; have != want {
+ t.Fatalf("%d: max: have %d, want %d", i, have, want)
}
-
- if tt.wantP50 != ps[0] {
- t.Fatalf("%d: p50: got %d, want %d", ind, ps[0], tt.wantP50)
+ if have, want := snap.Mean(), tt.wantMean; have != want {
+ t.Fatalf("%d: mean: have %v, want %v", i, have, want)
}
-
- if tt.wantP95 != ps[1] {
- t.Fatalf("%d: p95: got %d, want %d", ind, ps[1], tt.wantP95)
+ if have, want := ps[0], tt.wantP50; have != want {
+ t.Errorf("%d: p50: have %v, want %v", i, have, want)
}
-
- if tt.wantP99 != ps[2] {
- t.Fatalf("%d: p99: got %d, want %d", ind, ps[2], tt.wantP99)
+ if have, want := ps[1], tt.wantP95; have != want {
+ t.Errorf("%d: p95: have %v, want %v", i, have, want)
+ }
+ if have, want := ps[2], tt.wantP99; have != want {
+ t.Errorf("%d: p99: have %v, want %v", i, have, want)
}
}
}
@@ -110,11 +100,11 @@ func TestResettingTimerWithFivePercentiles(t *testing.T) {
values []int64
start int
end int
- wantP05 int64
- wantP20 int64
- wantP50 int64
- wantP95 int64
- wantP99 int64
+ wantP05 float64
+ wantP20 float64
+ wantP50 float64
+ wantP95 float64
+ wantP99 float64
wantMean float64
wantMin int64
wantMax int64
@@ -123,14 +113,14 @@ func TestResettingTimerWithFivePercentiles(t *testing.T) {
values: []int64{},
start: 1,
end: 11,
- wantP05: 1, wantP20: 2, wantP50: 5, wantP95: 10, wantP99: 10,
+ wantP05: 1, wantP20: 2.2, wantP50: 5.5, wantP95: 10, wantP99: 10,
wantMin: 1, wantMax: 10, wantMean: 5.5,
},
{
values: []int64{},
start: 1,
end: 101,
- wantP05: 5, wantP20: 20, wantP50: 50, wantP95: 95, wantP99: 99,
+ wantP05: 5.050000000000001, wantP20: 20.200000000000003, wantP50: 50.5, wantP95: 95.94999999999999, wantP99: 99.99,
wantMin: 1, wantMax: 100, wantMean: 50.5,
},
{
@@ -158,7 +148,7 @@ func TestResettingTimerWithFivePercentiles(t *testing.T) {
values: []int64{1, 10},
start: 0,
end: 0,
- wantP05: 1, wantP20: 1, wantP50: 1, wantP95: 10, wantP99: 10,
+ wantP05: 1, wantP20: 1, wantP50: 5.5, wantP95: 10, wantP99: 10,
wantMin: 1, wantMax: 10, wantMean: 5.5,
},
}
@@ -175,42 +165,33 @@ func TestResettingTimerWithFivePercentiles(t *testing.T) {
snap := timer.Snapshot()
- ps := snap.Percentiles([]float64{5, 20, 50, 95, 99})
-
- val := snap.Values()
+ ps := snap.Percentiles([]float64{0.05, 0.20, 0.50, 0.95, 0.99})
- if len(val) > 0 {
- if tt.wantMin != val[0] {
- t.Fatalf("%d: min: got %d, want %d", ind, val[0], tt.wantMin)
- }
+ if tt.wantMin != snap.Min() {
+ t.Errorf("%d: min: got %d, want %d", ind, snap.Min(), tt.wantMin)
+ }
- if tt.wantMax != val[len(val)-1] {
- t.Fatalf("%d: max: got %d, want %d", ind, val[len(val)-1], tt.wantMax)
- }
+ if tt.wantMax != snap.Max() {
+ t.Errorf("%d: max: got %d, want %d", ind, snap.Max(), tt.wantMax)
}
if tt.wantMean != snap.Mean() {
- t.Fatalf("%d: mean: got %.2f, want %.2f", ind, snap.Mean(), tt.wantMean)
+ t.Errorf("%d: mean: got %.2f, want %.2f", ind, snap.Mean(), tt.wantMean)
}
-
if tt.wantP05 != ps[0] {
- t.Fatalf("%d: p05: got %d, want %d", ind, ps[0], tt.wantP05)
+ t.Errorf("%d: p05: got %v, want %v", ind, ps[0], tt.wantP05)
}
-
if tt.wantP20 != ps[1] {
- t.Fatalf("%d: p20: got %d, want %d", ind, ps[1], tt.wantP20)
+ t.Errorf("%d: p20: got %v, want %v", ind, ps[1], tt.wantP20)
}
-
if tt.wantP50 != ps[2] {
- t.Fatalf("%d: p50: got %d, want %d", ind, ps[2], tt.wantP50)
+ t.Errorf("%d: p50: got %v, want %v", ind, ps[2], tt.wantP50)
}
-
if tt.wantP95 != ps[3] {
- t.Fatalf("%d: p95: got %d, want %d", ind, ps[3], tt.wantP95)
+ t.Errorf("%d: p95: got %v, want %v", ind, ps[3], tt.wantP95)
}
-
if tt.wantP99 != ps[4] {
- t.Fatalf("%d: p99: got %d, want %d", ind, ps[4], tt.wantP99)
+ t.Errorf("%d: p99: got %v, want %v", ind, ps[4], tt.wantP99)
}
}
}
diff --git a/metrics/runtimehistogram.go b/metrics/runtimehistogram.go
index c68939af1e..92fcbcc281 100644
--- a/metrics/runtimehistogram.go
+++ b/metrics/runtimehistogram.go
@@ -17,13 +17,19 @@ func getOrRegisterRuntimeHistogram(name string, scale float64, r Registry) *runt
// runtimeHistogram wraps a runtime/metrics histogram.
type runtimeHistogram struct {
- v atomic.Value
+ v atomic.Value // v is a pointer to a metrics.Float64Histogram
scaleFactor float64
}
func newRuntimeHistogram(scale float64) *runtimeHistogram {
h := &runtimeHistogram{scaleFactor: scale}
- h.update(&metrics.Float64Histogram{})
+ h.update(new(metrics.Float64Histogram))
+ return h
+}
+
+func RuntimeHistogramFromData(scale float64, hist *metrics.Float64Histogram) *runtimeHistogram {
+ h := &runtimeHistogram{scaleFactor: scale}
+ h.update(hist)
return h
}
@@ -35,130 +41,107 @@ func (h *runtimeHistogram) update(mh *metrics.Float64Histogram) {
return
}
- s := runtimeHistogramSnapshot{
+ s := metrics.Float64Histogram{
Counts: make([]uint64, len(mh.Counts)),
Buckets: make([]float64, len(mh.Buckets)),
}
copy(s.Counts, mh.Counts)
- copy(s.Buckets, mh.Buckets)
- for i, b := range s.Buckets {
+ for i, b := range mh.Buckets {
s.Buckets[i] = b * h.scaleFactor
}
h.v.Store(&s)
}
-func (h *runtimeHistogram) load() *runtimeHistogramSnapshot {
- return h.v.Load().(*runtimeHistogramSnapshot)
-}
-
func (h *runtimeHistogram) Clear() {
panic("runtimeHistogram does not support Clear")
}
func (h *runtimeHistogram) Update(int64) {
panic("runtimeHistogram does not support Update")
}
-func (h *runtimeHistogram) Sample() Sample {
- return NilSample{}
-}
-
-// Snapshot returns a non-changing cop of the histogram.
-func (h *runtimeHistogram) Snapshot() Histogram {
- return h.load()
-}
-
-// Count returns the sample count.
-func (h *runtimeHistogram) Count() int64 {
- return h.load().Count()
-}
-
-// Mean returns an approximation of the mean.
-func (h *runtimeHistogram) Mean() float64 {
- return h.load().Mean()
-}
-
-// StdDev approximates the standard deviation of the histogram.
-func (h *runtimeHistogram) StdDev() float64 {
- return h.load().StdDev()
-}
-
-// Variance approximates the variance of the histogram.
-func (h *runtimeHistogram) Variance() float64 {
- return h.load().Variance()
-}
-
-// Percentile computes the p'th percentile value.
-func (h *runtimeHistogram) Percentile(p float64) float64 {
- return h.load().Percentile(p)
-}
-// Percentiles computes all requested percentile values.
-func (h *runtimeHistogram) Percentiles(ps []float64) []float64 {
- return h.load().Percentiles(ps)
-}
-
-// Max returns the highest sample value.
-func (h *runtimeHistogram) Max() int64 {
- return h.load().Max()
+// Snapshot returns a non-changing copy of the histogram.
+func (h *runtimeHistogram) Snapshot() HistogramSnapshot {
+ hist := h.v.Load().(*metrics.Float64Histogram)
+ return newRuntimeHistogramSnapshot(hist)
}
-// Min returns the lowest sample value.
-func (h *runtimeHistogram) Min() int64 {
- return h.load().Min()
-}
-
-// Sum returns the sum of all sample values.
-func (h *runtimeHistogram) Sum() int64 {
- return h.load().Sum()
+type runtimeHistogramSnapshot struct {
+ internal *metrics.Float64Histogram
+ calculated bool
+ // The following fields are (lazily) calculated based on 'internal'
+ mean float64
+ count int64
+ min int64 // min is the lowest sample value.
+ max int64 // max is the highest sample value.
+ variance float64
}
-type runtimeHistogramSnapshot metrics.Float64Histogram
-
-func (h *runtimeHistogramSnapshot) Clear() {
- panic("runtimeHistogram does not support Clear")
-}
-func (h *runtimeHistogramSnapshot) Update(int64) {
- panic("runtimeHistogram does not support Update")
-}
-func (h *runtimeHistogramSnapshot) Sample() Sample {
- return NilSample{}
+func newRuntimeHistogramSnapshot(h *metrics.Float64Histogram) *runtimeHistogramSnapshot {
+ return &runtimeHistogramSnapshot{
+ internal: h,
+ }
}
-func (h *runtimeHistogramSnapshot) Snapshot() Histogram {
- return h
+// calc calculates the values for the snapshot. This method is not threadsafe.
+func (h *runtimeHistogramSnapshot) calc() {
+ h.calculated = true
+ var (
+ count int64 // number of samples
+ sum float64 // approx sum of all sample values
+ min int64
+ max float64
+ )
+ if len(h.internal.Counts) == 0 {
+ return
+ }
+ for i, c := range h.internal.Counts {
+ if c == 0 {
+ continue
+ }
+ if count == 0 { // Set min only first loop iteration
+ min = int64(math.Floor(h.internal.Buckets[i]))
+ }
+ count += int64(c)
+ sum += h.midpoint(i) * float64(c)
+ // Set max on every iteration
+ edge := h.internal.Buckets[i+1]
+ if math.IsInf(edge, 1) {
+ edge = h.internal.Buckets[i]
+ }
+ if edge > max {
+ max = edge
+ }
+ }
+ h.min = min
+ h.max = int64(max)
+ h.mean = sum / float64(count)
+ h.count = count
}
// Count returns the sample count.
func (h *runtimeHistogramSnapshot) Count() int64 {
- var count int64
- for _, c := range h.Counts {
- count += int64(c)
+ if !h.calculated {
+ h.calc()
}
- return count
+ return h.count
}
-// Mean returns an approximation of the mean.
-func (h *runtimeHistogramSnapshot) Mean() float64 {
- if len(h.Counts) == 0 {
- return 0
- }
- mean, _ := h.mean()
- return mean
+// Size returns the size of the sample at the time the snapshot was taken.
+func (h *runtimeHistogramSnapshot) Size() int {
+ return len(h.internal.Counts)
}
-// mean computes the mean and also the total sample count.
-func (h *runtimeHistogramSnapshot) mean() (mean, totalCount float64) {
- var sum float64
- for i, c := range h.Counts {
- midpoint := h.midpoint(i)
- sum += midpoint * float64(c)
- totalCount += float64(c)
+// Mean returns an approximation of the mean.
+func (h *runtimeHistogramSnapshot) Mean() float64 {
+ if !h.calculated {
+ h.calc()
}
- return sum / totalCount, totalCount
+ return h.mean
}
func (h *runtimeHistogramSnapshot) midpoint(bucket int) float64 {
- high := h.Buckets[bucket+1]
- low := h.Buckets[bucket]
+ high := h.internal.Buckets[bucket+1]
+ low := h.internal.Buckets[bucket]
if math.IsInf(high, 1) {
// The edge of the highest bucket can be +Inf, and it's supposed to mean that this
// bucket contains all remaining samples > low. We can't get the middle of an
@@ -180,23 +163,31 @@ func (h *runtimeHistogramSnapshot) StdDev() float64 {
// Variance approximates the variance of the histogram.
func (h *runtimeHistogramSnapshot) Variance() float64 {
- if len(h.Counts) == 0 {
+ if len(h.internal.Counts) == 0 {
return 0
}
-
- mean, totalCount := h.mean()
- if totalCount <= 1 {
+ if !h.calculated {
+ h.calc()
+ }
+ if h.count <= 1 {
// There is no variance when there are zero or one items.
return 0
}
-
+ // Variance is not calculated in 'calc', because it requires a second iteration.
+ // Therefore we calculate it lazily in this method, triggered either by
+ // a direct call to Variance or via StdDev.
+ if h.variance != 0.0 {
+ return h.variance
+ }
var sum float64
- for i, c := range h.Counts {
+
+ for i, c := range h.internal.Counts {
midpoint := h.midpoint(i)
- d := midpoint - mean
+ d := midpoint - h.mean
sum += float64(c) * (d * d)
}
- return sum / (totalCount - 1)
+ h.variance = sum / float64(h.count-1)
+ return h.variance
}
// Percentile computes the p'th percentile value.
@@ -231,11 +222,11 @@ func (h *runtimeHistogramSnapshot) Percentiles(ps []float64) []float64 {
func (h *runtimeHistogramSnapshot) computePercentiles(thresh []float64) {
var totalCount float64
- for i, count := range h.Counts {
+ for i, count := range h.internal.Counts {
totalCount += float64(count)
for len(thresh) > 0 && thresh[0] < totalCount {
- thresh[0] = h.Buckets[i]
+ thresh[0] = h.internal.Buckets[i]
thresh = thresh[1:]
}
if len(thresh) == 0 {
@@ -250,34 +241,25 @@ func (h *runtimeHistogramSnapshot) computePercentiles(thresh []float64) {
// Max returns the highest sample value.
func (h *runtimeHistogramSnapshot) Max() int64 {
- for i := len(h.Counts) - 1; i >= 0; i-- {
- count := h.Counts[i]
- if count > 0 {
- edge := h.Buckets[i+1]
- if math.IsInf(edge, 1) {
- edge = h.Buckets[i]
- }
- return int64(math.Ceil(edge))
- }
+ if !h.calculated {
+ h.calc()
}
- return 0
+ return h.max
}
// Min returns the lowest sample value.
func (h *runtimeHistogramSnapshot) Min() int64 {
- for i, count := range h.Counts {
- if count > 0 {
- return int64(math.Floor(h.Buckets[i]))
- }
+ if !h.calculated {
+ h.calc()
}
- return 0
+ return h.min
}
// Sum returns the sum of all sample values.
func (h *runtimeHistogramSnapshot) Sum() int64 {
var sum float64
- for i := range h.Counts {
- sum += h.Buckets[i] * float64(h.Counts[i])
+ for i := range h.internal.Counts {
+ sum += h.internal.Buckets[i] * float64(h.internal.Counts[i])
}
return int64(math.Ceil(sum))
}
diff --git a/metrics/runtimehistogram_test.go b/metrics/runtimehistogram_test.go
index d53a014383..cf7e36420a 100644
--- a/metrics/runtimehistogram_test.go
+++ b/metrics/runtimehistogram_test.go
@@ -1,11 +1,14 @@
package metrics
import (
+ "bytes"
+ "encoding/gob"
"fmt"
"math"
"reflect"
"runtime/metrics"
"testing"
+ "time"
)
var _ Histogram = (*runtimeHistogram)(nil)
@@ -74,7 +77,7 @@ func TestRuntimeHistogramStats(t *testing.T) {
for i, test := range tests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
- s := runtimeHistogramSnapshot(test.h)
+ s := RuntimeHistogramFromData(1.0, &test.h).Snapshot()
if v := s.Count(); v != test.Count {
t.Errorf("Count() = %v, want %v", v, test.Count)
@@ -121,13 +124,39 @@ func approxEqual(x, y, ε float64) bool {
// This test verifies that requesting Percentiles in unsorted order
// returns them in the requested order.
func TestRuntimeHistogramStatsPercentileOrder(t *testing.T) {
- p := runtimeHistogramSnapshot{
+ s := RuntimeHistogramFromData(1.0, &metrics.Float64Histogram{
Counts: []uint64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
Buckets: []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
- }
- result := p.Percentiles([]float64{1, 0.2, 0.5, 0.1, 0.2})
+ }).Snapshot()
+ result := s.Percentiles([]float64{1, 0.2, 0.5, 0.1, 0.2})
expected := []float64{10, 2, 5, 1, 2}
if !reflect.DeepEqual(result, expected) {
t.Fatal("wrong result:", result)
}
}
+
+func BenchmarkRuntimeHistogramSnapshotRead(b *testing.B) {
+ var sLatency = "7\xff\x81\x03\x01\x01\x10Float64Histogram\x01\xff\x82\x00\x01\x02\x01\x06Counts\x01\xff\x84\x00\x01\aBuckets\x01\xff\x86\x00\x00\x00\x16\xff\x83\x02\x01\x01\b[]uint64\x01\xff\x84\x00\x01\x06\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00\xfe\x06T\xff\x82\x01\xff\xa2\x00\xfe\r\xef\x00\x01\x02\x02\x04\x05\x04\b\x15\x17 B?6.L;$!2) \x1a? \x190aH7FY6#\x190\x1d\x14\x10\x1b\r\t\x04\x03\x01\x01\x00\x03\x02\x00\x03\x05\x05\x02\x02\x06\x04\v\x06\n\x15\x18\x13'&.\x12=H/L&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xa3\xfe\xf0\xff\x00\xf8\x95\xd6&\xe8\v.q>\xf8\x95\xd6&\xe8\v.\x81>\xf8\xdfA:\xdc\x11ʼn>\xf8\x95\xd6&\xe8\v.\x91>\xf8:\x8c0\xe2\x8ey\x95>\xf8\xdfA:\xdc\x11ř>\xf8\x84\xf7C֔\x10\x9e>\xf8\x95\xd6&\xe8\v.\xa1>\xf8:\x8c0\xe2\x8ey\xa5>\xf8\xdfA:\xdc\x11ũ>\xf8\x84\xf7C֔\x10\xae>\xf8\x95\xd6&\xe8\v.\xb1>\xf8:\x8c0\xe2\x8ey\xb5>\xf8\xdfA:\xdc\x11Ź>\xf8\x84\xf7C֔\x10\xbe>\xf8\x95\xd6&\xe8\v.\xc1>\xf8:\x8c0\xe2\x8ey\xc5>\xf8\xdfA:\xdc\x11\xc5\xc9>\xf8\x84\xf7C֔\x10\xce>\xf8\x95\xd6&\xe8\v.\xd1>\xf8:\x8c0\xe2\x8ey\xd5>\xf8\xdfA:\xdc\x11\xc5\xd9>\xf8\x84\xf7C֔\x10\xde>\xf8\x95\xd6&\xe8\v.\xe1>\xf8:\x8c0\xe2\x8ey\xe5>\xf8\xdfA:\xdc\x11\xc5\xe9>\xf8\x84\xf7C֔\x10\xee>\xf8\x95\xd6&\xe8\v.\xf1>\xf8:\x8c0\xe2\x8ey\xf5>\xf8\xdfA:\xdc\x11\xc5\xf9>\xf8\x84\xf7C֔\x10\xfe>\xf8\x95\xd6&\xe8\v.\x01?\xf8:\x8c0\xe2\x8ey\x05?\xf8\xdfA:\xdc\x11\xc5\t?\xf8\x84\xf7C֔\x10\x0e?\xf8\x95\xd6&\xe8\v.\x11?\xf8:\x8c0\xe2\x8ey\x15?\xf8\xdfA:\xdc\x11\xc5\x19?\xf8\x84\xf7C֔\x10\x1e?\xf8\x95\xd6&\xe8\v.!?\xf8:\x8c0\xe2\x8ey%?\xf8\xdfA:\xdc\x11\xc5)?\xf8\x84\xf7C֔\x10.?\xf8\x95\xd6&\xe8\v.1?\xf8:\x8c0\xe2\x8ey5?\xf8\xdfA:\xdc\x11\xc59?\xf8\x84\xf7C֔\x10>?\xf8\x95\xd6&\xe8\v.A?\xf8:\x8c0\xe2\x8eyE?\xf8\xdfA:\xdc\x11\xc5I?\xf8\x84\xf7C֔\x10N?\xf8\x95\xd6&\xe8\v.Q?\xf8:\x8c0\xe2\x8eyU?\xf8\xdfA:\xdc\x11\xc5Y?\xf8\x84\xf7C֔\x10^?\xf8\x95\xd6&\xe8\v.a?\xf8:\x8c0\xe2\x8eye?\xf8\xdfA:\xdc\x11\xc5i?\xf8\x84\xf7C֔\x10n?\xf8\x95\xd6&\xe8\v.q?\xf8:\x8c0\xe2\x8eyu?\xf8\xdfA:\xdc\x11\xc5y?\xf8\x84\xf7C֔\x10~?\xf8\x95\xd6&\xe8\v.\x81?\xf8:\x8c0\xe2\x8ey\x85?\xf8\xdfA:\xdc\x11ʼn?\xf8\x84\xf7C֔\x10\x8e?\xf8\x95\xd6&\xe8\v.\x91?\xf8:\x8c0\xe2\x8ey\x95?\xf8\xdfA:\xdc\x11ř?\xf8\x84\xf7C֔\x10\x9e?\xf8\x95\xd6&\xe8\v.\xa1?\xf8:\x8c0\xe2\x8ey\xa5?\xf8\xdfA:\xdc\x11ũ?\xf8\x84\xf7C֔\x10\xae?\xf8\x95\xd6&\xe8\v.\xb1?\xf8:\x8c0\xe2\x8ey\xb5?\xf8\xdfA:\xdc\x11Ź?\xf8\x84\xf7C֔\x10\xbe?\xf8\x95\xd6&\xe8\v.\xc1?\xf8:\x8c0\xe2\x8ey\xc5?\xf8\xdfA:\xdc\x11\xc5\xc9?\xf8\x84\xf7C֔\x10\xce?\xf8\x95\xd6&\xe8\v.\xd1?\xf8:\x8c0\xe2\x8ey\xd5?\xf8\xdfA:\xdc\x11\xc5\xd9?\xf8\x84\xf7C֔\x10\xde?\xf8\x95\xd6&\xe8\v.\xe1?\xf8:\x8c0\xe2\x8ey\xe5?\xf8\xdfA:\xdc\x11\xc5\xe9?\xf8\x84\xf7C֔\x10\xee?\xf8\x95\xd6&\xe8\v.\xf1?\xf8:\x8c0\xe2\x8ey\xf5?\xf8\xdfA:\xdc\x11\xc5\xf9?\xf8\x84\xf7C֔\x10\xfe?\xf8\x95\xd6&\xe8\v.\x01@\xf8:\x8c0\xe2\x8ey\x05@\xf8\xdfA:\xdc\x11\xc5\t@\xf8\x84\xf7C֔\x10\x0e@\xf8\x95\xd6&\xe8\v.\x11@\xf8:\x8c0\xe2\x8ey\x15@\xf8\xdfA:\xdc\x11\xc5\x19@\xf8\x84\xf7C֔\x10\x1e@\xf8\x95\xd6&\xe8\v.!@\xf8:\x8c0\xe2\x8ey%@\xf8\xdfA:\xdc\x11\xc5)@\xf8\x84\xf7C֔\x10.@\xf8\x95\xd6&\xe8\v.1@\xf8:\x8c0\xe2\x8ey5@\xf8\xdfA:\xdc\x11\xc59@\xf8\x84\xf7C֔\x10>@\xf8\x95\xd6&\xe8\v.A@\xf8:\x8c0\xe2\x8eyE@\xf8\xdfA:\xdc\x11\xc5I@\xf8\x84\xf7C֔\x10N@\xf8\x95\xd6&\xe8\v.Q@\xf8:\x8c0\xe2\x8eyU@\xf8\xdfA:\xdc\x11\xc5Y@\xf8\x84\xf7C֔\x10^@\xf8\x95\xd6&\xe8\v.a@\xf8:\x8c0\xe2\x8eye@\xf8\xdfA:\xdc\x11\xc5i@\xf8\x84\xf7C֔\x10n@\xf8\x95\xd6&\xe8\v.q@\xf8:\x8c0\xe2\x8eyu@\xf8\xdfA:\xdc\x11\xc5y@\xf8\x84\xf7C֔\x10~@\xf8\x95\xd6&\xe8\v.\x81@\xf8:\x8c0\xe2\x8ey\x85@\xf8\xdfA:\xdc\x11ʼn@\xf8\x84\xf7C֔\x10\x8e@\xf8\x95\xd6&\xe8\v.\x91@\xf8:\x8c0\xe2\x8ey\x95@\xf8\xdfA:\xdc\x11ř@\xf8\x84\xf7C֔\x10\x9e@\xf8\x95\xd6&\xe8\v.\xa1@\xf8:\x8c0\xe2\x8ey\xa5@\xf8\xdfA:\xdc\x11ũ@\xf8\x84\xf7C֔\x10\xae@\xf8\x95\xd6&\xe8\v.\xb1@\xf8:\x8c0\xe2\x8ey\xb5@\xf8\xdfA:\xdc\x11Ź@\xf8\x84\xf7C֔\x10\xbe@\xf8\x95\xd6&\xe8\v.\xc1@\xf8:\x8c0\xe2\x8ey\xc5@\xf8\xdfA:\xdc\x11\xc5\xc9@\xf8\x84\xf7C֔\x10\xce@\xf8\x95\xd6&\xe8\v.\xd1@\xf8:\x8c0\xe2\x8ey\xd5@\xf8\xdfA:\xdc\x11\xc5\xd9@\xf8\x84\xf7C֔\x10\xde@\xf8\x95\xd6&\xe8\v.\xe1@\xf8:\x8c0\xe2\x8ey\xe5@\xf8\xdfA:\xdc\x11\xc5\xe9@\xf8\x84\xf7C֔\x10\xee@\xf8\x95\xd6&\xe8\v.\xf1@\xf8:\x8c0\xe2\x8ey\xf5@\xf8\xdfA:\xdc\x11\xc5\xf9@\xf8\x84\xf7C֔\x10\xfe@\xf8\x95\xd6&\xe8\v.\x01A\xfe\xf0\x7f\x00"
+
+ dserialize := func(data string) *metrics.Float64Histogram {
+ var res metrics.Float64Histogram
+ if err := gob.NewDecoder(bytes.NewReader([]byte(data))).Decode(&res); err != nil {
+ panic(err)
+ }
+ return &res
+ }
+ latency := RuntimeHistogramFromData(float64(time.Second), dserialize(sLatency))
+ b.ResetTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ snap := latency.Snapshot()
+ // These are the fields that influxdb accesses
+ _ = snap.Count()
+ _ = snap.Max()
+ _ = snap.Mean()
+ _ = snap.Min()
+ _ = snap.StdDev()
+ _ = snap.Variance()
+ _ = snap.Percentiles([]float64{0.25, 0.5, 0.75, 0.95, 0.99, 0.999, 0.9999})
+ }
+}
diff --git a/metrics/sample.go b/metrics/sample.go
index 252a878f58..5398dd42d5 100644
--- a/metrics/sample.go
+++ b/metrics/sample.go
@@ -11,10 +11,7 @@ import (
const rescaleThreshold = time.Hour
-// Samples maintain a statistically-significant selection of values from
-// a stream.
-type Sample interface {
- Clear()
+type SampleSnapshot interface {
Count() int64
Max() int64
Mean() float64
@@ -22,14 +19,19 @@ type Sample interface {
Percentile(float64) float64
Percentiles([]float64) []float64
Size() int
- Snapshot() Sample
StdDev() float64
Sum() int64
- Update(int64)
- Values() []int64
Variance() float64
}
+// Samples maintain a statistically-significant selection of values from
+// a stream.
+type Sample interface {
+ Snapshot() SampleSnapshot
+ Clear()
+ Update(int64)
+}
+
// ExpDecaySample is an exponentially-decaying sample using a forward-decaying
// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time
// Decay Model for Streaming Systems".
@@ -77,72 +79,29 @@ func (s *ExpDecaySample) Clear() {
s.values.Clear()
}
-// Count returns the number of samples recorded, which may exceed the
-// reservoir size.
-func (s *ExpDecaySample) Count() int64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return s.count
-}
-
-// Max returns the maximum value in the sample, which may not be the maximum
-// value ever to be part of the sample.
-func (s *ExpDecaySample) Max() int64 {
- return SampleMax(s.Values())
-}
-
-// Mean returns the mean of the values in the sample.
-func (s *ExpDecaySample) Mean() float64 {
- return SampleMean(s.Values())
-}
-
-// Min returns the minimum value in the sample, which may not be the minimum
-// value ever to be part of the sample.
-func (s *ExpDecaySample) Min() int64 {
- return SampleMin(s.Values())
-}
-
-// Percentile returns an arbitrary percentile of values in the sample.
-func (s *ExpDecaySample) Percentile(p float64) float64 {
- return SamplePercentile(s.Values(), p)
-}
-
-// Percentiles returns a slice of arbitrary percentiles of values in the
-// sample.
-func (s *ExpDecaySample) Percentiles(ps []float64) []float64 {
- return SamplePercentiles(s.Values(), ps)
-}
-
-// Size returns the size of the sample, which is at most the reservoir size.
-func (s *ExpDecaySample) Size() int {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return s.values.Size()
-}
-
// Snapshot returns a read-only copy of the sample.
-func (s *ExpDecaySample) Snapshot() Sample {
+func (s *ExpDecaySample) Snapshot() SampleSnapshot {
s.mutex.Lock()
defer s.mutex.Unlock()
- vals := s.values.Values()
- values := make([]int64, len(vals))
- for i, v := range vals {
- values[i] = v.v
- }
- return &SampleSnapshot{
- count: s.count,
- values: values,
+ var (
+ samples = s.values.Values()
+ values = make([]int64, len(samples))
+ max int64 = math.MinInt64
+ min int64 = math.MaxInt64
+ sum int64
+ )
+ for i, item := range samples {
+ v := item.v
+ values[i] = v
+ sum += v
+ if v > max {
+ max = v
+ }
+ if v < min {
+ min = v
+ }
}
-}
-
-// StdDev returns the standard deviation of the values in the sample.
-func (s *ExpDecaySample) StdDev() float64 {
- return SampleStdDev(s.Values())
-}
-
-// Sum returns the sum of the values in the sample.
-func (s *ExpDecaySample) Sum() int64 {
- return SampleSum(s.Values())
+ return newSampleSnapshotPrecalculated(s.count, values, min, max, sum)
}
// Update samples a new value.
@@ -150,23 +109,6 @@ func (s *ExpDecaySample) Update(v int64) {
s.update(time.Now(), v)
}
-// Values returns a copy of the values in the sample.
-func (s *ExpDecaySample) Values() []int64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- vals := s.values.Values()
- values := make([]int64, len(vals))
- for i, v := range vals {
- values[i] = v.v
- }
- return values
-}
-
-// Variance returns the variance of the values in the sample.
-func (s *ExpDecaySample) Variance() float64 {
- return SampleVariance(s.Values())
-}
-
// update samples a new value at a particular timestamp. This is a method all
// its own to facilitate testing.
func (s *ExpDecaySample) update(t time.Time, v int64) {
@@ -202,207 +144,160 @@ func (s *ExpDecaySample) update(t time.Time, v int64) {
// NilSample is a no-op Sample.
type NilSample struct{}
-// Clear is a no-op.
-func (NilSample) Clear() {}
-
-// Count is a no-op.
-func (NilSample) Count() int64 { return 0 }
-
-// Max is a no-op.
-func (NilSample) Max() int64 { return 0 }
-
-// Mean is a no-op.
-func (NilSample) Mean() float64 { return 0.0 }
-
-// Min is a no-op.
-func (NilSample) Min() int64 { return 0 }
-
-// Percentile is a no-op.
-func (NilSample) Percentile(p float64) float64 { return 0.0 }
-
-// Percentiles is a no-op.
-func (NilSample) Percentiles(ps []float64) []float64 {
- return make([]float64, len(ps))
-}
-
-// Size is a no-op.
-func (NilSample) Size() int { return 0 }
-
-// Sample is a no-op.
-func (NilSample) Snapshot() Sample { return NilSample{} }
-
-// StdDev is a no-op.
-func (NilSample) StdDev() float64 { return 0.0 }
-
-// Sum is a no-op.
-func (NilSample) Sum() int64 { return 0 }
-
-// Update is a no-op.
-func (NilSample) Update(v int64) {}
-
-// Values is a no-op.
-func (NilSample) Values() []int64 { return []int64{} }
-
-// Variance is a no-op.
-func (NilSample) Variance() float64 { return 0.0 }
-
-// SampleMax returns the maximum value of the slice of int64.
-func SampleMax(values []int64) int64 {
- if len(values) == 0 {
- return 0
- }
- var max int64 = math.MinInt64
- for _, v := range values {
- if max < v {
- max = v
- }
- }
- return max
-}
-
-// SampleMean returns the mean value of the slice of int64.
-func SampleMean(values []int64) float64 {
- if len(values) == 0 {
- return 0.0
- }
- return float64(SampleSum(values)) / float64(len(values))
-}
-
-// SampleMin returns the minimum value of the slice of int64.
-func SampleMin(values []int64) int64 {
- if len(values) == 0 {
- return 0
- }
- var min int64 = math.MaxInt64
- for _, v := range values {
- if min > v {
- min = v
- }
- }
- return min
-}
+func (NilSample) Clear() {}
+func (NilSample) Snapshot() SampleSnapshot { return (*emptySnapshot)(nil) }
+func (NilSample) Update(v int64) {}
// SamplePercentiles returns an arbitrary percentile of the slice of int64.
func SamplePercentile(values []int64, p float64) float64 {
- return SamplePercentiles(values, []float64{p})[0]
+ return CalculatePercentiles(values, []float64{p})[0]
}
-// SamplePercentiles returns a slice of arbitrary percentiles of the slice of
-// int64.
-func SamplePercentiles(values []int64, ps []float64) []float64 {
+// CalculatePercentiles returns a slice of arbitrary percentiles of the slice of
+// int64. This method returns interpolated results, so e.g if there are only two
+// values, [0, 10], a 50% percentile will land between them.
+//
+// Note: As a side-effect, this method will also sort the slice of values.
+// Note2: The input format for percentiles is NOT percent! To express 50%, use 0.5, not 50.
+func CalculatePercentiles(values []int64, ps []float64) []float64 {
scores := make([]float64, len(ps))
size := len(values)
- if size > 0 {
- slices.Sort(values)
- for i, p := range ps {
- pos := p * float64(size+1)
- if pos < 1.0 {
- scores[i] = float64(values[0])
- } else if pos >= float64(size) {
- scores[i] = float64(values[size-1])
- } else {
- lower := float64(values[int(pos)-1])
- upper := float64(values[int(pos)])
- scores[i] = lower + (pos-math.Floor(pos))*(upper-lower)
- }
+ if size == 0 {
+ return scores
+ }
+ slices.Sort(values)
+ for i, p := range ps {
+ pos := p * float64(size+1)
+
+ if pos < 1.0 {
+ scores[i] = float64(values[0])
+ } else if pos >= float64(size) {
+ scores[i] = float64(values[size-1])
+ } else {
+ lower := float64(values[int(pos)-1])
+ upper := float64(values[int(pos)])
+ scores[i] = lower + (pos-math.Floor(pos))*(upper-lower)
}
}
return scores
}
-// SampleSnapshot is a read-only copy of another Sample.
-type SampleSnapshot struct {
+// sampleSnapshot is a read-only copy of another Sample.
+type sampleSnapshot struct {
count int64
values []int64
+
+ max int64
+ min int64
+ mean float64
+ sum int64
+ variance float64
}
-func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot {
- return &SampleSnapshot{
+// newSampleSnapshotPrecalculated creates a read-only sampleSnapShot, using
+// precalculated sums to avoid iterating the values
+func newSampleSnapshotPrecalculated(count int64, values []int64, min, max, sum int64) *sampleSnapshot {
+ if len(values) == 0 {
+ return &sampleSnapshot{
+ count: count,
+ values: values,
+ }
+ }
+ return &sampleSnapshot{
count: count,
values: values,
+ max: max,
+ min: min,
+ mean: float64(sum) / float64(len(values)),
+ sum: sum,
}
}
-// Clear panics.
-func (*SampleSnapshot) Clear() {
- panic("Clear called on a SampleSnapshot")
+// newSampleSnapshot creates a read-only sampleSnapShot, and calculates some
+// numbers.
+func newSampleSnapshot(count int64, values []int64) *sampleSnapshot {
+ var (
+ max int64 = math.MinInt64
+ min int64 = math.MaxInt64
+ sum int64
+ )
+ for _, v := range values {
+ sum += v
+ if v > max {
+ max = v
+ }
+ if v < min {
+ min = v
+ }
+ }
+ return newSampleSnapshotPrecalculated(count, values, min, max, sum)
}
// Count returns the count of inputs at the time the snapshot was taken.
-func (s *SampleSnapshot) Count() int64 { return s.count }
+func (s *sampleSnapshot) Count() int64 { return s.count }
// Max returns the maximal value at the time the snapshot was taken.
-func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) }
+func (s *sampleSnapshot) Max() int64 { return s.max }
// Mean returns the mean value at the time the snapshot was taken.
-func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) }
+func (s *sampleSnapshot) Mean() float64 { return s.mean }
// Min returns the minimal value at the time the snapshot was taken.
-func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) }
+func (s *sampleSnapshot) Min() int64 { return s.min }
// Percentile returns an arbitrary percentile of values at the time the
// snapshot was taken.
-func (s *SampleSnapshot) Percentile(p float64) float64 {
+func (s *sampleSnapshot) Percentile(p float64) float64 {
return SamplePercentile(s.values, p)
}
// Percentiles returns a slice of arbitrary percentiles of values at the time
// the snapshot was taken.
-func (s *SampleSnapshot) Percentiles(ps []float64) []float64 {
- return SamplePercentiles(s.values, ps)
+func (s *sampleSnapshot) Percentiles(ps []float64) []float64 {
+ return CalculatePercentiles(s.values, ps)
}
// Size returns the size of the sample at the time the snapshot was taken.
-func (s *SampleSnapshot) Size() int { return len(s.values) }
+func (s *sampleSnapshot) Size() int { return len(s.values) }
// Snapshot returns the snapshot.
-func (s *SampleSnapshot) Snapshot() Sample { return s }
+func (s *sampleSnapshot) Snapshot() SampleSnapshot { return s }
// StdDev returns the standard deviation of values at the time the snapshot was
// taken.
-func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) }
+func (s *sampleSnapshot) StdDev() float64 {
+ if s.variance == 0.0 {
+ s.variance = SampleVariance(s.mean, s.values)
+ }
+ return math.Sqrt(s.variance)
+}
// Sum returns the sum of values at the time the snapshot was taken.
-func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) }
-
-// Update panics.
-func (*SampleSnapshot) Update(int64) {
- panic("Update called on a SampleSnapshot")
-}
+func (s *sampleSnapshot) Sum() int64 { return s.sum }
// Values returns a copy of the values in the sample.
-func (s *SampleSnapshot) Values() []int64 {
+func (s *sampleSnapshot) Values() []int64 {
values := make([]int64, len(s.values))
copy(values, s.values)
return values
}
// Variance returns the variance of values at the time the snapshot was taken.
-func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) }
-
-// SampleStdDev returns the standard deviation of the slice of int64.
-func SampleStdDev(values []int64) float64 {
- return math.Sqrt(SampleVariance(values))
-}
-
-// SampleSum returns the sum of the slice of int64.
-func SampleSum(values []int64) int64 {
- var sum int64
- for _, v := range values {
- sum += v
+func (s *sampleSnapshot) Variance() float64 {
+ if s.variance == 0.0 {
+ s.variance = SampleVariance(s.mean, s.values)
}
- return sum
+ return s.variance
}
// SampleVariance returns the variance of the slice of int64.
-func SampleVariance(values []int64) float64 {
+func SampleVariance(mean float64, values []int64) float64 {
if len(values) == 0 {
return 0.0
}
- m := SampleMean(values)
var sum float64
for _, v := range values {
- d := float64(v) - m
+ d := float64(v) - mean
sum += d * d
}
return sum / float64(len(values))
@@ -445,83 +340,14 @@ func (s *UniformSample) Clear() {
s.values = make([]int64, 0, s.reservoirSize)
}
-// Count returns the number of samples recorded, which may exceed the
-// reservoir size.
-func (s *UniformSample) Count() int64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return s.count
-}
-
-// Max returns the maximum value in the sample, which may not be the maximum
-// value ever to be part of the sample.
-func (s *UniformSample) Max() int64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return SampleMax(s.values)
-}
-
-// Mean returns the mean of the values in the sample.
-func (s *UniformSample) Mean() float64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return SampleMean(s.values)
-}
-
-// Min returns the minimum value in the sample, which may not be the minimum
-// value ever to be part of the sample.
-func (s *UniformSample) Min() int64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return SampleMin(s.values)
-}
-
-// Percentile returns an arbitrary percentile of values in the sample.
-func (s *UniformSample) Percentile(p float64) float64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return SamplePercentile(s.values, p)
-}
-
-// Percentiles returns a slice of arbitrary percentiles of values in the
-// sample.
-func (s *UniformSample) Percentiles(ps []float64) []float64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return SamplePercentiles(s.values, ps)
-}
-
-// Size returns the size of the sample, which is at most the reservoir size.
-func (s *UniformSample) Size() int {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return len(s.values)
-}
-
// Snapshot returns a read-only copy of the sample.
-func (s *UniformSample) Snapshot() Sample {
+func (s *UniformSample) Snapshot() SampleSnapshot {
s.mutex.Lock()
- defer s.mutex.Unlock()
values := make([]int64, len(s.values))
copy(values, s.values)
- return &SampleSnapshot{
- count: s.count,
- values: values,
- }
-}
-
-// StdDev returns the standard deviation of the values in the sample.
-func (s *UniformSample) StdDev() float64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return SampleStdDev(s.values)
-}
-
-// Sum returns the sum of the values in the sample.
-func (s *UniformSample) Sum() int64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return SampleSum(s.values)
+ count := s.count
+ s.mutex.Unlock()
+ return newSampleSnapshot(count, values)
}
// Update samples a new value.
@@ -544,22 +370,6 @@ func (s *UniformSample) Update(v int64) {
}
}
-// Values returns a copy of the values in the sample.
-func (s *UniformSample) Values() []int64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- values := make([]int64, len(s.values))
- copy(values, s.values)
- return values
-}
-
-// Variance returns the variance of the values in the sample.
-func (s *UniformSample) Variance() float64 {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return SampleVariance(s.values)
-}
-
// expDecaySample represents an individual sample in a heap.
type expDecaySample struct {
k float64
diff --git a/metrics/sample_test.go b/metrics/sample_test.go
index 3ae128d56f..7967357055 100644
--- a/metrics/sample_test.go
+++ b/metrics/sample_test.go
@@ -8,28 +8,36 @@ import (
"time"
)
+const epsilonPercentile = .00000000001
+
// Benchmark{Compute,Copy}{1000,1000000} demonstrate that, even for relatively
// expensive computations like Variance, the cost of copying the Sample, as
// approximated by a make and copy, is much greater than the cost of the
// computation for small samples and only slightly less for large samples.
func BenchmarkCompute1000(b *testing.B) {
s := make([]int64, 1000)
+ var sum int64
for i := 0; i < len(s); i++ {
s[i] = int64(i)
+ sum += int64(i)
}
+ mean := float64(sum) / float64(len(s))
b.ResetTimer()
for i := 0; i < b.N; i++ {
- SampleVariance(s)
+ SampleVariance(mean, s)
}
}
func BenchmarkCompute1000000(b *testing.B) {
s := make([]int64, 1000000)
+ var sum int64
for i := 0; i < len(s); i++ {
s[i] = int64(i)
+ sum += int64(i)
}
+ mean := float64(sum) / float64(len(s))
b.ResetTimer()
for i := 0; i < b.N; i++ {
- SampleVariance(s)
+ SampleVariance(mean, s)
}
}
func BenchmarkCopy1000(b *testing.B) {
@@ -79,65 +87,42 @@ func BenchmarkUniformSample1028(b *testing.B) {
benchmarkSample(b, NewUniformSample(1028))
}
-func TestExpDecaySample10(t *testing.T) {
- s := NewExpDecaySample(100, 0.99)
- for i := 0; i < 10; i++ {
- s.Update(int64(i))
- }
- if size := s.Count(); size != 10 {
- t.Errorf("s.Count(): 10 != %v\n", size)
- }
- if size := s.Size(); size != 10 {
- t.Errorf("s.Size(): 10 != %v\n", size)
- }
- if l := len(s.Values()); l != 10 {
- t.Errorf("len(s.Values()): 10 != %v\n", l)
- }
- for _, v := range s.Values() {
- if v > 10 || v < 0 {
- t.Errorf("out of range [0, 10): %v\n", v)
- }
+func min(a, b int) int {
+ if a < b {
+ return a
}
+ return b
}
-func TestExpDecaySample100(t *testing.T) {
- s := NewExpDecaySample(1000, 0.01)
- for i := 0; i < 100; i++ {
- s.Update(int64(i))
- }
- if size := s.Count(); size != 100 {
- t.Errorf("s.Count(): 100 != %v\n", size)
- }
- if size := s.Size(); size != 100 {
- t.Errorf("s.Size(): 100 != %v\n", size)
- }
- if l := len(s.Values()); l != 100 {
- t.Errorf("len(s.Values()): 100 != %v\n", l)
- }
- for _, v := range s.Values() {
- if v > 100 || v < 0 {
- t.Errorf("out of range [0, 100): %v\n", v)
+func TestExpDecaySample(t *testing.T) {
+ for _, tc := range []struct {
+ reservoirSize int
+ alpha float64
+ updates int
+ }{
+ {100, 0.99, 10},
+ {1000, 0.01, 100},
+ {100, 0.99, 1000},
+ } {
+ sample := NewExpDecaySample(tc.reservoirSize, tc.alpha)
+ for i := 0; i < tc.updates; i++ {
+ sample.Update(int64(i))
}
- }
-}
-
-func TestExpDecaySample1000(t *testing.T) {
- s := NewExpDecaySample(100, 0.99)
- for i := 0; i < 1000; i++ {
- s.Update(int64(i))
- }
- if size := s.Count(); size != 1000 {
- t.Errorf("s.Count(): 1000 != %v\n", size)
- }
- if size := s.Size(); size != 100 {
- t.Errorf("s.Size(): 100 != %v\n", size)
- }
- if l := len(s.Values()); l != 100 {
- t.Errorf("len(s.Values()): 100 != %v\n", l)
- }
- for _, v := range s.Values() {
- if v > 1000 || v < 0 {
- t.Errorf("out of range [0, 1000): %v\n", v)
+ snap := sample.Snapshot()
+ if have, want := int(snap.Count()), tc.updates; have != want {
+ t.Errorf("have %d want %d", have, want)
+ }
+ if have, want := snap.Size(), min(tc.updates, tc.reservoirSize); have != want {
+ t.Errorf("have %d want %d", have, want)
+ }
+ values := snap.(*sampleSnapshot).values
+ if have, want := len(values), min(tc.updates, tc.reservoirSize); have != want {
+ t.Errorf("have %d want %d", have, want)
+ }
+ for _, v := range values {
+ if v > int64(tc.updates) || v < 0 {
+ t.Errorf("out of range [0, %d): %v", tc.updates, v)
+ }
}
}
}
@@ -147,15 +132,16 @@ func TestExpDecaySample1000(t *testing.T) {
// The priority becomes +Inf quickly after starting if this is done,
// effectively freezing the set of samples until a rescale step happens.
func TestExpDecaySampleNanosecondRegression(t *testing.T) {
- s := NewExpDecaySample(100, 0.99)
+ sw := NewExpDecaySample(100, 0.99)
for i := 0; i < 100; i++ {
- s.Update(10)
+ sw.Update(10)
}
time.Sleep(1 * time.Millisecond)
for i := 0; i < 100; i++ {
- s.Update(20)
+ sw.Update(20)
}
- v := s.Values()
+ s := sw.Snapshot()
+ v := s.(*sampleSnapshot).values
avg := float64(0)
for i := 0; i < len(v); i++ {
avg += float64(v[i])
@@ -194,24 +180,27 @@ func TestExpDecaySampleStatistics(t *testing.T) {
for i := 1; i <= 10000; i++ {
s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i))
}
- testExpDecaySampleStatistics(t, s)
+ testExpDecaySampleStatistics(t, s.Snapshot())
}
func TestUniformSample(t *testing.T) {
- s := NewUniformSample(100)
+ sw := NewUniformSample(100)
for i := 0; i < 1000; i++ {
- s.Update(int64(i))
+ sw.Update(int64(i))
}
+ s := sw.Snapshot()
if size := s.Count(); size != 1000 {
t.Errorf("s.Count(): 1000 != %v\n", size)
}
if size := s.Size(); size != 100 {
t.Errorf("s.Size(): 100 != %v\n", size)
}
- if l := len(s.Values()); l != 100 {
+ values := s.(*sampleSnapshot).values
+
+ if l := len(values); l != 100 {
t.Errorf("len(s.Values()): 100 != %v\n", l)
}
- for _, v := range s.Values() {
+ for _, v := range values {
if v > 1000 || v < 0 {
t.Errorf("out of range [0, 100): %v\n", v)
}
@@ -219,12 +208,13 @@ func TestUniformSample(t *testing.T) {
}
func TestUniformSampleIncludesTail(t *testing.T) {
- s := NewUniformSample(100)
+ sw := NewUniformSample(100)
max := 100
for i := 0; i < max; i++ {
- s.Update(int64(i))
+ sw.Update(int64(i))
}
- v := s.Values()
+ s := sw.Snapshot()
+ v := s.(*sampleSnapshot).values
sum := 0
exp := (max - 1) * max / 2
for i := 0; i < len(v); i++ {
@@ -250,7 +240,7 @@ func TestUniformSampleStatistics(t *testing.T) {
for i := 1; i <= 10000; i++ {
s.Update(int64(i))
}
- testUniformSampleStatistics(t, s)
+ testUniformSampleStatistics(t, s.Snapshot())
}
func benchmarkSample(b *testing.B, s Sample) {
@@ -267,7 +257,7 @@ func benchmarkSample(b *testing.B, s Sample) {
b.Logf("GC cost: %d ns/op", int(memStats.PauseTotalNs-pauseTotalNs)/b.N)
}
-func testExpDecaySampleStatistics(t *testing.T, s Sample) {
+func testExpDecaySampleStatistics(t *testing.T, s SampleSnapshot) {
if count := s.Count(); count != 10000 {
t.Errorf("s.Count(): 10000 != %v\n", count)
}
@@ -295,7 +285,7 @@ func testExpDecaySampleStatistics(t *testing.T, s Sample) {
}
}
-func testUniformSampleStatistics(t *testing.T, s Sample) {
+func testUniformSampleStatistics(t *testing.T, s SampleSnapshot) {
if count := s.Count(); count != 10000 {
t.Errorf("s.Count(): 10000 != %v\n", count)
}
@@ -349,8 +339,22 @@ func TestUniformSampleConcurrentUpdateCount(t *testing.T) {
}
}()
for i := 0; i < 1000; i++ {
- s.Count()
+ s.Snapshot().Count()
time.Sleep(5 * time.Millisecond)
}
quit <- struct{}{}
}
+
+func BenchmarkCalculatePercentiles(b *testing.B) {
+ pss := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}
+ var vals []int64
+ for i := 0; i < 1000; i++ {
+ vals = append(vals, int64(rand.Int31()))
+ }
+ v := make([]int64, len(vals))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ copy(v, vals)
+ _ = CalculatePercentiles(v, pss)
+ }
+}
diff --git a/metrics/syslog.go b/metrics/syslog.go
index f23b07e199..fd856d6973 100644
--- a/metrics/syslog.go
+++ b/metrics/syslog.go
@@ -16,13 +16,15 @@ func Syslog(r Registry, d time.Duration, w *syslog.Writer) {
r.Each(func(name string, i interface{}) {
switch metric := i.(type) {
case Counter:
- w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Count()))
+ w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Snapshot().Count()))
case CounterFloat64:
- w.Info(fmt.Sprintf("counter %s: count: %f", name, metric.Count()))
+ w.Info(fmt.Sprintf("counter %s: count: %f", name, metric.Snapshot().Count()))
case Gauge:
- w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value()))
+ w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Snapshot().Value()))
case GaugeFloat64:
- w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value()))
+ w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Snapshot().Value()))
+ case GaugeInfo:
+ w.Info(fmt.Sprintf("gauge %s: value: %s", name, metric.Snapshot().Value()))
case Healthcheck:
metric.Check()
w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error()))
diff --git a/metrics/testdata/opentsb.want b/metrics/testdata/opentsb.want
new file mode 100644
index 0000000000..43fe1b2ac2
--- /dev/null
+++ b/metrics/testdata/opentsb.want
@@ -0,0 +1,23 @@
+put pre.elite.count 978307200 1337 host=hal9000
+put pre.elite.one-minute 978307200 0.00 host=hal9000
+put pre.elite.five-minute 978307200 0.00 host=hal9000
+put pre.elite.fifteen-minute 978307200 0.00 host=hal9000
+put pre.elite.mean 978307200 0.00 host=hal9000
+put pre.foo.value 978307200 {"chain_id":"5"} host=hal9000
+put pre.months.count 978307200 12 host=hal9000
+put pre.pi.value 978307200 3.140000 host=hal9000
+put pre.second.count 978307200 1 host=hal9000
+put pre.second.min 978307200 1000 host=hal9000
+put pre.second.max 978307200 1000 host=hal9000
+put pre.second.mean 978307200 1000.00 host=hal9000
+put pre.second.std-dev 978307200 0.00 host=hal9000
+put pre.second.50-percentile 978307200 1000.00 host=hal9000
+put pre.second.75-percentile 978307200 1000.00 host=hal9000
+put pre.second.95-percentile 978307200 1000.00 host=hal9000
+put pre.second.99-percentile 978307200 1000.00 host=hal9000
+put pre.second.999-percentile 978307200 1000.00 host=hal9000
+put pre.second.one-minute 978307200 0.00 host=hal9000
+put pre.second.five-minute 978307200 0.00 host=hal9000
+put pre.second.fifteen-minute 978307200 0.00 host=hal9000
+put pre.second.mean-rate 978307200 0.00 host=hal9000
+put pre.tau.count 978307200 1.570000 host=hal9000
diff --git a/metrics/timer.go b/metrics/timer.go
index 4fcc297d24..bb8def82fb 100644
--- a/metrics/timer.go
+++ b/metrics/timer.go
@@ -5,26 +5,18 @@ import (
"time"
)
+type TimerSnapshot interface {
+ HistogramSnapshot
+ MeterSnapshot
+}
+
// Timers capture the duration and rate of events.
type Timer interface {
- Count() int64
- Max() int64
- Mean() float64
- Min() int64
- Percentile(float64) float64
- Percentiles([]float64) []float64
- Rate1() float64
- Rate5() float64
- Rate15() float64
- RateMean() float64
- Snapshot() Timer
- StdDev() float64
+ Snapshot() TimerSnapshot
Stop()
- Sum() int64
Time(func())
- Update(time.Duration)
UpdateSince(time.Time)
- Variance() float64
+ Update(time.Duration)
}
// GetOrRegisterTimer returns an existing Timer or constructs and registers a
@@ -78,61 +70,11 @@ func NewTimer() Timer {
// NilTimer is a no-op Timer.
type NilTimer struct{}
-// Count is a no-op.
-func (NilTimer) Count() int64 { return 0 }
-
-// Max is a no-op.
-func (NilTimer) Max() int64 { return 0 }
-
-// Mean is a no-op.
-func (NilTimer) Mean() float64 { return 0.0 }
-
-// Min is a no-op.
-func (NilTimer) Min() int64 { return 0 }
-
-// Percentile is a no-op.
-func (NilTimer) Percentile(p float64) float64 { return 0.0 }
-
-// Percentiles is a no-op.
-func (NilTimer) Percentiles(ps []float64) []float64 {
- return make([]float64, len(ps))
-}
-
-// Rate1 is a no-op.
-func (NilTimer) Rate1() float64 { return 0.0 }
-
-// Rate5 is a no-op.
-func (NilTimer) Rate5() float64 { return 0.0 }
-
-// Rate15 is a no-op.
-func (NilTimer) Rate15() float64 { return 0.0 }
-
-// RateMean is a no-op.
-func (NilTimer) RateMean() float64 { return 0.0 }
-
-// Snapshot is a no-op.
-func (NilTimer) Snapshot() Timer { return NilTimer{} }
-
-// StdDev is a no-op.
-func (NilTimer) StdDev() float64 { return 0.0 }
-
-// Stop is a no-op.
-func (NilTimer) Stop() {}
-
-// Sum is a no-op.
-func (NilTimer) Sum() int64 { return 0 }
-
-// Time is a no-op.
-func (NilTimer) Time(f func()) { f() }
-
-// Update is a no-op.
-func (NilTimer) Update(time.Duration) {}
-
-// UpdateSince is a no-op.
-func (NilTimer) UpdateSince(time.Time) {}
-
-// Variance is a no-op.
-func (NilTimer) Variance() float64 { return 0.0 }
+func (NilTimer) Snapshot() TimerSnapshot { return (*emptySnapshot)(nil) }
+func (NilTimer) Stop() {}
+func (NilTimer) Time(f func()) { f() }
+func (NilTimer) Update(time.Duration) {}
+func (NilTimer) UpdateSince(time.Time) {}
// StandardTimer is the standard implementation of a Timer and uses a Histogram
// and Meter.
@@ -142,82 +84,21 @@ type StandardTimer struct {
mutex sync.Mutex
}
-// Count returns the number of events recorded.
-func (t *StandardTimer) Count() int64 {
- return t.histogram.Count()
-}
-
-// Max returns the maximum value in the sample.
-func (t *StandardTimer) Max() int64 {
- return t.histogram.Max()
-}
-
-// Mean returns the mean of the values in the sample.
-func (t *StandardTimer) Mean() float64 {
- return t.histogram.Mean()
-}
-
-// Min returns the minimum value in the sample.
-func (t *StandardTimer) Min() int64 {
- return t.histogram.Min()
-}
-
-// Percentile returns an arbitrary percentile of the values in the sample.
-func (t *StandardTimer) Percentile(p float64) float64 {
- return t.histogram.Percentile(p)
-}
-
-// Percentiles returns a slice of arbitrary percentiles of the values in the
-// sample.
-func (t *StandardTimer) Percentiles(ps []float64) []float64 {
- return t.histogram.Percentiles(ps)
-}
-
-// Rate1 returns the one-minute moving average rate of events per second.
-func (t *StandardTimer) Rate1() float64 {
- return t.meter.Rate1()
-}
-
-// Rate5 returns the five-minute moving average rate of events per second.
-func (t *StandardTimer) Rate5() float64 {
- return t.meter.Rate5()
-}
-
-// Rate15 returns the fifteen-minute moving average rate of events per second.
-func (t *StandardTimer) Rate15() float64 {
- return t.meter.Rate15()
-}
-
-// RateMean returns the meter's mean rate of events per second.
-func (t *StandardTimer) RateMean() float64 {
- return t.meter.RateMean()
-}
-
// Snapshot returns a read-only copy of the timer.
-func (t *StandardTimer) Snapshot() Timer {
+func (t *StandardTimer) Snapshot() TimerSnapshot {
t.mutex.Lock()
defer t.mutex.Unlock()
- return &TimerSnapshot{
- histogram: t.histogram.Snapshot().(*HistogramSnapshot),
- meter: t.meter.Snapshot().(*MeterSnapshot),
+ return &timerSnapshot{
+ histogram: t.histogram.Snapshot(),
+ meter: t.meter.Snapshot(),
}
}
-// StdDev returns the standard deviation of the values in the sample.
-func (t *StandardTimer) StdDev() float64 {
- return t.histogram.StdDev()
-}
-
// Stop stops the meter.
func (t *StandardTimer) Stop() {
t.meter.Stop()
}
-// Sum returns the sum in the sample.
-func (t *StandardTimer) Sum() int64 {
- return t.histogram.Sum()
-}
-
// Record the duration of the execution of the given function.
func (t *StandardTimer) Time(f func()) {
ts := time.Now()
@@ -239,86 +120,63 @@ func (t *StandardTimer) UpdateSince(ts time.Time) {
t.Update(time.Since(ts))
}
-// Variance returns the variance of the values in the sample.
-func (t *StandardTimer) Variance() float64 {
- return t.histogram.Variance()
-}
-
-// TimerSnapshot is a read-only copy of another Timer.
-type TimerSnapshot struct {
- histogram *HistogramSnapshot
- meter *MeterSnapshot
+// timerSnapshot is a read-only copy of another Timer.
+type timerSnapshot struct {
+ histogram HistogramSnapshot
+ meter MeterSnapshot
}
// Count returns the number of events recorded at the time the snapshot was
// taken.
-func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() }
+func (t *timerSnapshot) Count() int64 { return t.histogram.Count() }
// Max returns the maximum value at the time the snapshot was taken.
-func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() }
+func (t *timerSnapshot) Max() int64 { return t.histogram.Max() }
+
+// Size returns the size of the sample at the time the snapshot was taken.
+func (t *timerSnapshot) Size() int { return t.histogram.Size() }
// Mean returns the mean value at the time the snapshot was taken.
-func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() }
+func (t *timerSnapshot) Mean() float64 { return t.histogram.Mean() }
// Min returns the minimum value at the time the snapshot was taken.
-func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() }
+func (t *timerSnapshot) Min() int64 { return t.histogram.Min() }
// Percentile returns an arbitrary percentile of sampled values at the time the
// snapshot was taken.
-func (t *TimerSnapshot) Percentile(p float64) float64 {
+func (t *timerSnapshot) Percentile(p float64) float64 {
return t.histogram.Percentile(p)
}
// Percentiles returns a slice of arbitrary percentiles of sampled values at
// the time the snapshot was taken.
-func (t *TimerSnapshot) Percentiles(ps []float64) []float64 {
+func (t *timerSnapshot) Percentiles(ps []float64) []float64 {
return t.histogram.Percentiles(ps)
}
// Rate1 returns the one-minute moving average rate of events per second at the
// time the snapshot was taken.
-func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() }
+func (t *timerSnapshot) Rate1() float64 { return t.meter.Rate1() }
// Rate5 returns the five-minute moving average rate of events per second at
// the time the snapshot was taken.
-func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() }
+func (t *timerSnapshot) Rate5() float64 { return t.meter.Rate5() }
// Rate15 returns the fifteen-minute moving average rate of events per second
// at the time the snapshot was taken.
-func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() }
+func (t *timerSnapshot) Rate15() float64 { return t.meter.Rate15() }
// RateMean returns the meter's mean rate of events per second at the time the
// snapshot was taken.
-func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() }
-
-// Snapshot returns the snapshot.
-func (t *TimerSnapshot) Snapshot() Timer { return t }
+func (t *timerSnapshot) RateMean() float64 { return t.meter.RateMean() }
// StdDev returns the standard deviation of the values at the time the snapshot
// was taken.
-func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() }
-
-// Stop is a no-op.
-func (t *TimerSnapshot) Stop() {}
+func (t *timerSnapshot) StdDev() float64 { return t.histogram.StdDev() }
// Sum returns the sum at the time the snapshot was taken.
-func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() }
-
-// Time panics.
-func (*TimerSnapshot) Time(func()) {
- panic("Time called on a TimerSnapshot")
-}
-
-// Update panics.
-func (*TimerSnapshot) Update(time.Duration) {
- panic("Update called on a TimerSnapshot")
-}
-
-// UpdateSince panics.
-func (*TimerSnapshot) UpdateSince(time.Time) {
- panic("UpdateSince called on a TimerSnapshot")
-}
+func (t *timerSnapshot) Sum() int64 { return t.histogram.Sum() }
// Variance returns the variance of the values at the time the snapshot was
// taken.
-func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() }
+func (t *timerSnapshot) Variance() float64 { return t.histogram.Variance() }
diff --git a/metrics/timer_test.go b/metrics/timer_test.go
index 903e8e8d49..f10de16c9c 100644
--- a/metrics/timer_test.go
+++ b/metrics/timer_test.go
@@ -18,7 +18,7 @@ func BenchmarkTimer(b *testing.B) {
func TestGetOrRegisterTimer(t *testing.T) {
r := NewRegistry()
NewRegisteredTimer("foo", r).Update(47)
- if tm := GetOrRegisterTimer("foo", r); tm.Count() != 1 {
+ if tm := GetOrRegisterTimer("foo", r).Snapshot(); tm.Count() != 1 {
t.Fatal(tm)
}
}
@@ -27,7 +27,7 @@ func TestTimerExtremes(t *testing.T) {
tm := NewTimer()
tm.Update(math.MaxInt64)
tm.Update(0)
- if stdDev := tm.StdDev(); stdDev != 4.611686018427388e+18 {
+ if stdDev := tm.Snapshot().StdDev(); stdDev != 4.611686018427388e+18 {
t.Errorf("tm.StdDev(): 4.611686018427388e+18 != %v\n", stdDev)
}
}
@@ -56,7 +56,7 @@ func TestTimerFunc(t *testing.T) {
})
var (
drift = time.Millisecond * 2
- measured = time.Duration(tm.Max())
+ measured = time.Duration(tm.Snapshot().Max())
ceil = actualTime + drift
floor = actualTime - drift
)
@@ -66,7 +66,7 @@ func TestTimerFunc(t *testing.T) {
}
func TestTimerZero(t *testing.T) {
- tm := NewTimer()
+ tm := NewTimer().Snapshot()
if count := tm.Count(); count != 0 {
t.Errorf("tm.Count(): 0 != %v\n", count)
}
@@ -110,5 +110,5 @@ func ExampleGetOrRegisterTimer() {
m := "account.create.latency"
t := GetOrRegisterTimer(m, nil)
t.Update(47)
- fmt.Println(t.Max()) // Output: 47
+ fmt.Println(t.Snapshot().Max()) // Output: 47
}
diff --git a/metrics/writer.go b/metrics/writer.go
index 82434e9d1d..098da45c27 100644
--- a/metrics/writer.go
+++ b/metrics/writer.go
@@ -29,16 +29,19 @@ func WriteOnce(r Registry, w io.Writer) {
switch metric := namedMetric.m.(type) {
case Counter:
fmt.Fprintf(w, "counter %s\n", namedMetric.name)
- fmt.Fprintf(w, " count: %9d\n", metric.Count())
+ fmt.Fprintf(w, " count: %9d\n", metric.Snapshot().Count())
case CounterFloat64:
fmt.Fprintf(w, "counter %s\n", namedMetric.name)
- fmt.Fprintf(w, " count: %f\n", metric.Count())
+ fmt.Fprintf(w, " count: %f\n", metric.Snapshot().Count())
case Gauge:
fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
- fmt.Fprintf(w, " value: %9d\n", metric.Value())
+ fmt.Fprintf(w, " value: %9d\n", metric.Snapshot().Value())
case GaugeFloat64:
fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
- fmt.Fprintf(w, " value: %f\n", metric.Value())
+ fmt.Fprintf(w, " value: %f\n", metric.Snapshot().Value())
+ case GaugeInfo:
+ fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
+ fmt.Fprintf(w, " value: %s\n", metric.Snapshot().Value().String())
case Healthcheck:
metric.Check()
fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name)
diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go
new file mode 100644
index 0000000000..51dcf58355
--- /dev/null
+++ b/miner/bid_simulator.go
@@ -0,0 +1,688 @@
+package miner
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math/big"
+ "net"
+ "net/http"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/bidutil"
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/miner/builderclient"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+const (
+ // maxBidPerBuilderPerBlock is the max bid number per builder
+ maxBidPerBuilderPerBlock = 3
+
+ commitInterruptBetterBid = 1
+
+ // leftOverTimeRate is the rate of left over time to simulate a bid
+ leftOverTimeRate = 11
+ // leftOverTimeScale is the scale of left over time to simulate a bid
+ leftOverTimeScale = 10
+)
+
+var (
+ diffInTurn = big.NewInt(2) // the difficulty of a block that proposed by an in-turn validator
+)
+
+var (
+ dialer = &net.Dialer{
+ Timeout: time.Second,
+ KeepAlive: 60 * time.Second,
+ }
+
+ transport = &http.Transport{
+ DialContext: dialer.DialContext,
+ MaxIdleConnsPerHost: 50,
+ MaxConnsPerHost: 50,
+ IdleConnTimeout: 90 * time.Second,
+ }
+
+ client = &http.Client{
+ Timeout: 5 * time.Second,
+ Transport: transport,
+ }
+)
+
+type WorkPreparer interface {
+ prepareWork(params *generateParams) (*environment, error)
+ etherbase() common.Address
+}
+
+// simBidReq is the request for simulating a bid
+type simBidReq struct {
+ bid *BidRuntime
+ interruptCh chan int32
+}
+
+// bidSimulator is in charge of receiving bid from builders, reporting issue to builders.
+// And take care of bid simulation, rewards computing, best bid maintaining.
+type bidSimulator struct {
+ config *MevConfig
+ delayLeftOver time.Duration
+ chain *core.BlockChain
+ chainConfig *params.ChainConfig
+ workPreparer WorkPreparer
+
+ running atomic.Bool // controlled by miner
+ exitCh chan struct{}
+
+ bidReceiving atomic.Bool // controlled by config and eth.AdminAPI
+
+ chainHeadCh chan core.ChainHeadEvent
+ chainHeadSub event.Subscription
+
+ sentryCli *builderclient.Client
+
+ // builder info (warning: only keep status in memory!)
+ buildersMu sync.RWMutex
+ builders map[common.Address]*builderclient.Client
+
+ // channels
+ simBidCh chan *simBidReq
+ newBidCh chan *types.Bid
+
+ pendingMu sync.RWMutex
+ pending map[uint64]map[common.Address]map[common.Hash]struct{} // blockNumber -> builder -> bidHash -> struct{}
+
+ bestBidMu sync.RWMutex
+ bestBid map[common.Hash]*BidRuntime // prevBlockHash -> bidRuntime
+
+ simBidMu sync.RWMutex
+ simulatingBid map[common.Hash]*BidRuntime // prevBlockHash -> bidRuntime, in the process of simulation
+}
+
+func newBidSimulator(
+ config *MevConfig,
+ delayLeftOver time.Duration,
+ chainConfig *params.ChainConfig,
+ chain *core.BlockChain,
+ workPreparer WorkPreparer,
+) *bidSimulator {
+ b := &bidSimulator{
+ config: config,
+ delayLeftOver: delayLeftOver,
+ chainConfig: chainConfig,
+ chain: chain,
+ workPreparer: workPreparer,
+ exitCh: make(chan struct{}),
+ chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
+ builders: make(map[common.Address]*builderclient.Client),
+ simBidCh: make(chan *simBidReq),
+ newBidCh: make(chan *types.Bid, 100),
+ pending: make(map[uint64]map[common.Address]map[common.Hash]struct{}),
+ bestBid: make(map[common.Hash]*BidRuntime),
+ simulatingBid: make(map[common.Hash]*BidRuntime),
+ }
+
+ b.chainHeadSub = chain.SubscribeChainHeadEvent(b.chainHeadCh)
+
+ if config.Enabled {
+ b.bidReceiving.Store(true)
+ b.dialSentryAndBuilders()
+
+ if len(b.builders) == 0 {
+ log.Warn("BidSimulator: no valid builders")
+ }
+ }
+
+ go b.clearLoop()
+ go b.mainLoop()
+ go b.newBidLoop()
+
+ return b
+}
+
+func (b *bidSimulator) dialSentryAndBuilders() {
+ var sentryCli *builderclient.Client
+ var err error
+
+ if b.config.SentryURL != "" {
+ sentryCli, err = builderclient.DialOptions(context.Background(), b.config.SentryURL, rpc.WithHTTPClient(client))
+ if err != nil {
+ log.Error("BidSimulator: failed to dial sentry", "url", b.config.SentryURL, "err", err)
+ }
+ }
+
+ b.sentryCli = sentryCli
+
+ for _, v := range b.config.Builders {
+ _ = b.AddBuilder(v.Address, v.URL)
+ }
+}
+
+func (b *bidSimulator) start() {
+ b.running.Store(true)
+}
+
+func (b *bidSimulator) stop() {
+ b.running.Store(false)
+}
+
+func (b *bidSimulator) close() {
+ b.running.Store(false)
+ close(b.exitCh)
+}
+
+func (b *bidSimulator) isRunning() bool {
+ return b.running.Load()
+}
+
+func (b *bidSimulator) receivingBid() bool {
+ return b.bidReceiving.Load()
+}
+
+func (b *bidSimulator) startReceivingBid() {
+ b.dialSentryAndBuilders()
+ b.bidReceiving.Store(true)
+}
+
+func (b *bidSimulator) stopReceivingBid() {
+ b.bidReceiving.Store(false)
+}
+
+func (b *bidSimulator) AddBuilder(builder common.Address, url string) error {
+ b.buildersMu.Lock()
+ defer b.buildersMu.Unlock()
+
+ if b.sentryCli != nil {
+ b.builders[builder] = b.sentryCli
+ } else {
+ var builderCli *builderclient.Client
+
+ if url != "" {
+ var err error
+
+ builderCli, err = builderclient.DialOptions(context.Background(), url, rpc.WithHTTPClient(client))
+ if err != nil {
+ log.Error("BidSimulator: failed to dial builder", "url", url, "err", err)
+ return err
+ }
+ }
+
+ b.builders[builder] = builderCli
+ }
+
+ return nil
+}
+
+func (b *bidSimulator) RemoveBuilder(builder common.Address) error {
+ b.buildersMu.Lock()
+ defer b.buildersMu.Unlock()
+
+ delete(b.builders, builder)
+
+ return nil
+}
+
+func (b *bidSimulator) ExistBuilder(builder common.Address) bool {
+ b.buildersMu.RLock()
+ defer b.buildersMu.RUnlock()
+
+ _, ok := b.builders[builder]
+
+ return ok
+}
+
+func (b *bidSimulator) SetBestBid(prevBlockHash common.Hash, bid *BidRuntime) {
+ b.bestBidMu.Lock()
+ defer b.bestBidMu.Unlock()
+
+ b.bestBid[prevBlockHash] = bid
+}
+
+func (b *bidSimulator) GetBestBid(prevBlockHash common.Hash) *BidRuntime {
+ b.bestBidMu.RLock()
+ defer b.bestBidMu.RUnlock()
+
+ return b.bestBid[prevBlockHash]
+}
+
+func (b *bidSimulator) SetSimulatingBid(prevBlockHash common.Hash, bid *BidRuntime) {
+ b.simBidMu.Lock()
+ defer b.simBidMu.Unlock()
+
+ b.simulatingBid[prevBlockHash] = bid
+}
+
+func (b *bidSimulator) GetSimulatingBid(prevBlockHash common.Hash) *BidRuntime {
+ b.simBidMu.RLock()
+ defer b.simBidMu.RUnlock()
+
+ return b.simulatingBid[prevBlockHash]
+}
+
+func (b *bidSimulator) RemoveSimulatingBid(prevBlockHash common.Hash) {
+ b.simBidMu.Lock()
+ defer b.simBidMu.Unlock()
+
+ delete(b.simulatingBid, prevBlockHash)
+}
+
+func (b *bidSimulator) mainLoop() {
+ defer b.chainHeadSub.Unsubscribe()
+
+ for {
+ select {
+ case req := <-b.simBidCh:
+ if !b.isRunning() {
+ continue
+ }
+
+ b.simBid(req.interruptCh, req.bid)
+
+ // System stopped
+ case <-b.exitCh:
+ return
+
+ case <-b.chainHeadSub.Err():
+ return
+ }
+ }
+}
+
+func (b *bidSimulator) newBidLoop() {
+ var (
+ interruptCh chan int32
+ )
+
+ // commit aborts in-flight bid execution with given signal and resubmits a new one.
+ commit := func(reason int32, bidRuntime *BidRuntime) {
+ // if the left time is not enough to do simulation, return
+ var simDuration time.Duration
+ if lastBid := b.GetBestBid(bidRuntime.bid.ParentHash); lastBid != nil && lastBid.duration != 0 {
+ simDuration = lastBid.duration
+ }
+
+ if time.Until(b.bidMustBefore(bidRuntime.bid.ParentHash)) <= simDuration*leftOverTimeRate/leftOverTimeScale {
+ return
+ }
+
+ if interruptCh != nil {
+ // each commit work will have its own interruptCh to stop work with a reason
+ interruptCh <- reason
+ close(interruptCh)
+ }
+ interruptCh = make(chan int32, 1)
+ select {
+ case b.simBidCh <- &simBidReq{interruptCh: interruptCh, bid: bidRuntime}:
+ case <-b.exitCh:
+ return
+ }
+ }
+
+ for {
+ select {
+ case newBid := <-b.newBidCh:
+ if !b.isRunning() {
+ continue
+ }
+
+ // check the block reward and validator reward of the newBid
+ expectedBlockReward := newBid.GasFee
+ expectedValidatorReward := new(big.Int).Mul(expectedBlockReward, big.NewInt(int64(b.config.ValidatorCommission)))
+ expectedValidatorReward.Div(expectedValidatorReward, big.NewInt(10000))
+ expectedValidatorReward.Sub(expectedValidatorReward, newBid.BuilderFee)
+
+ if expectedValidatorReward.Cmp(big.NewInt(0)) < 0 {
+ // damage self profit, ignore
+ continue
+ }
+
+ bidRuntime := &BidRuntime{
+ bid: newBid,
+ expectedBlockReward: expectedBlockReward,
+ expectedValidatorReward: expectedValidatorReward,
+ packedBlockReward: big.NewInt(0),
+ packedValidatorReward: big.NewInt(0),
+ }
+
+ // TODO(renee-) opt bid comparation
+
+ simulatingBid := b.GetSimulatingBid(newBid.ParentHash)
+ // simulatingBid is nil means there is no bid in simulation
+ if simulatingBid == nil {
+ // bestBid is nil means bid is the first bid
+ bestBid := b.GetBestBid(newBid.ParentHash)
+ if bestBid == nil {
+ commit(commitInterruptBetterBid, bidRuntime)
+ continue
+ }
+
+ // if bestBid is not nil, check if newBid is better than bestBid
+ if bidRuntime.expectedBlockReward.Cmp(bestBid.expectedBlockReward) > 0 &&
+ bidRuntime.expectedValidatorReward.Cmp(bestBid.expectedValidatorReward) > 0 {
+ // if both reward are better than last simulating newBid, commit for simulation
+ commit(commitInterruptBetterBid, bidRuntime)
+ continue
+ }
+
+ continue
+ }
+
+ // simulatingBid must be better than bestBid, if newBid is better than simulatingBid, commit for simulation
+ if bidRuntime.expectedBlockReward.Cmp(simulatingBid.expectedBlockReward) > 0 &&
+ bidRuntime.expectedValidatorReward.Cmp(simulatingBid.expectedValidatorReward) > 0 {
+ // if both reward are better than last simulating newBid, commit for simulation
+ commit(commitInterruptBetterBid, bidRuntime)
+ continue
+ }
+
+ case <-b.exitCh:
+ return
+ }
+ }
+}
+
+func (b *bidSimulator) bidMustBefore(parentHash common.Hash) time.Time {
+ parentHeader := b.chain.GetHeaderByHash(parentHash)
+ return bidutil.BidMustBefore(parentHeader, b.chainConfig.Parlia.Period, b.delayLeftOver)
+}
+
+func (b *bidSimulator) bidBetterBefore(parentHash common.Hash) time.Time {
+ parentHeader := b.chain.GetHeaderByHash(parentHash)
+ return bidutil.BidBetterBefore(parentHeader, b.chainConfig.Parlia.Period, b.delayLeftOver, b.config.BidSimulationLeftOver)
+}
+
+func (b *bidSimulator) clearLoop() {
+ clearFn := func(parentHash common.Hash, blockNumber uint64) {
+ b.pendingMu.Lock()
+ delete(b.pending, blockNumber)
+ b.pendingMu.Unlock()
+
+ b.bestBidMu.Lock()
+ if bid, ok := b.bestBid[parentHash]; ok {
+ bid.env.discard()
+ }
+ delete(b.bestBid, parentHash)
+ for k, v := range b.bestBid {
+ if v.bid.BlockNumber <= blockNumber-core.TriesInMemory {
+ v.env.discard()
+ delete(b.bestBid, k)
+ }
+ }
+ b.bestBidMu.Unlock()
+
+ b.simBidMu.Lock()
+ if bid, ok := b.simulatingBid[parentHash]; ok {
+ bid.env.discard()
+ }
+ delete(b.simulatingBid, parentHash)
+ for k, v := range b.simulatingBid {
+ if v.bid.BlockNumber <= blockNumber-core.TriesInMemory {
+ v.env.discard()
+ delete(b.simulatingBid, k)
+ }
+ }
+ b.simBidMu.Unlock()
+ }
+
+ for head := range b.chainHeadCh {
+ if !b.isRunning() {
+ continue
+ }
+
+ clearFn(head.Block.ParentHash(), head.Block.NumberU64())
+ }
+}
+
+// sendBid checks if the bid is already exists or if the builder sends too many bids,
+// if yes, return error, if not, add bid into newBid chan waiting for judge profit.
+func (b *bidSimulator) sendBid(_ context.Context, bid *types.Bid) error {
+ timer := time.NewTimer(1 * time.Second)
+ defer timer.Stop()
+ select {
+ case b.newBidCh <- bid:
+ b.AddPending(bid.BlockNumber, bid.Builder, bid.Hash())
+ return nil
+ case <-timer.C:
+ return types.ErrMevBusy
+ }
+}
+
+func (b *bidSimulator) CheckPending(blockNumber uint64, builder common.Address, bidHash common.Hash) error {
+ b.pendingMu.Lock()
+ defer b.pendingMu.Unlock()
+
+ // check if bid exists or if builder sends too many bids
+ if _, ok := b.pending[blockNumber]; !ok {
+ b.pending[blockNumber] = make(map[common.Address]map[common.Hash]struct{})
+ }
+
+ if _, ok := b.pending[blockNumber][builder]; !ok {
+ b.pending[blockNumber][builder] = make(map[common.Hash]struct{})
+ }
+
+ if _, ok := b.pending[blockNumber][builder][bidHash]; ok {
+ return errors.New("bid already exists")
+ }
+
+ if len(b.pending[blockNumber][builder]) >= maxBidPerBuilderPerBlock {
+ return errors.New("too many bids")
+ }
+
+ return nil
+}
+
+func (b *bidSimulator) AddPending(blockNumber uint64, builder common.Address, bidHash common.Hash) {
+ b.pendingMu.Lock()
+ defer b.pendingMu.Unlock()
+
+ b.pending[blockNumber][builder][bidHash] = struct{}{}
+}
+
+// simBid simulates a newBid with txs.
+// simBid does not enable state prefetching when commit transaction.
+func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
+ // prevent from stopping happen in time interval from sendBid to simBid
+ if !b.isRunning() || !b.receivingBid() {
+ return
+ }
+
+ var (
+ blockNumber = bidRuntime.bid.BlockNumber
+ parentHash = bidRuntime.bid.ParentHash
+ builder = bidRuntime.bid.Builder
+ err error
+ success bool
+ )
+
+ // ensure simulation exited then start next simulation
+ b.SetSimulatingBid(parentHash, bidRuntime)
+
+ defer func(simStart time.Time) {
+ logCtx := []any{
+ "blockNumber", blockNumber,
+ "parentHash", parentHash,
+ "builder", builder,
+ "gasUsed", bidRuntime.bid.GasUsed,
+ }
+
+ if bidRuntime.env != nil {
+ logCtx = append(logCtx, "gasLimit", bidRuntime.env.header.GasLimit)
+
+ if err != nil || !success {
+ bidRuntime.env.discard()
+ }
+ }
+
+ if err != nil {
+ logCtx = append(logCtx, "err", err)
+ log.Debug("bid simulation failed", logCtx...)
+
+ go b.reportIssue(bidRuntime, err)
+ }
+
+ if success {
+ bidRuntime.duration = time.Since(simStart)
+ }
+
+ b.RemoveSimulatingBid(parentHash)
+ }(time.Now())
+
+ // prepareWork will configure header with a suitable time according to consensus
+ // prepareWork will start trie prefetching
+ if bidRuntime.env, err = b.workPreparer.prepareWork(&generateParams{
+ parentHash: bidRuntime.bid.ParentHash,
+ coinbase: b.workPreparer.etherbase(),
+ }); err != nil {
+ return
+ }
+
+ gasLimit := bidRuntime.env.header.GasLimit
+ if bidRuntime.env.gasPool == nil {
+ bidRuntime.env.gasPool = new(core.GasPool).AddGas(gasLimit)
+ bidRuntime.env.gasPool.SubGas(params.SystemTxsGas)
+ }
+
+ if bidRuntime.bid.GasUsed > bidRuntime.env.gasPool.Gas() {
+ err = errors.New("gas used exceeds gas limit")
+ return
+ }
+
+ for _, tx := range bidRuntime.bid.Txs {
+ select {
+ case <-interruptCh:
+ err = errors.New("simulation abort due to better bid arrived")
+ return
+
+ case <-b.exitCh:
+ err = errors.New("miner exit")
+ return
+
+ default:
+ }
+
+ // Start executing the transaction
+ bidRuntime.env.state.SetTxContext(tx.Hash(), bidRuntime.env.tcount)
+
+ err = bidRuntime.commitTransaction(b.chain, b.chainConfig, tx)
+ if err != nil {
+ log.Error("BidSimulator: failed to commit tx", "bidHash", bidRuntime.bid.Hash(), "tx", tx.Hash(), "err", err)
+ err = fmt.Errorf("invalid tx in bid, %v", err)
+ return
+ }
+
+ bidRuntime.env.tcount++
+ }
+
+ bidRuntime.packReward(b.config.ValidatorCommission)
+
+ // return if bid is invalid, reportIssue issue to mev-sentry/builder if simulation is fully done
+ if !bidRuntime.validReward() {
+ err = errors.New("reward does not achieve the expectation")
+ return
+ }
+
+ bestBid := b.GetBestBid(parentHash)
+
+ if bestBid == nil {
+ b.SetBestBid(bidRuntime.bid.ParentHash, bidRuntime)
+ success = true
+ return
+ }
+
+ // this is the simplest strategy: best for all the delegators.
+ if bidRuntime.packedBlockReward.Cmp(bestBid.packedBlockReward) > 0 {
+ b.SetBestBid(bidRuntime.bid.ParentHash, bidRuntime)
+ success = true
+ return
+ }
+}
+
+// reportIssue reports the issue to the mev-sentry
+func (b *bidSimulator) reportIssue(bidRuntime *BidRuntime, err error) {
+ cli := b.builders[bidRuntime.bid.Builder]
+ if cli != nil {
+ cli.ReportIssue(context.Background(), &types.BidIssue{
+ Validator: bidRuntime.env.header.Coinbase,
+ Builder: bidRuntime.bid.Builder,
+ Message: err.Error(),
+ })
+ }
+}
+
+type BidRuntime struct {
+ bid *types.Bid
+
+ env *environment
+
+ expectedBlockReward *big.Int
+ expectedValidatorReward *big.Int
+
+ packedBlockReward *big.Int
+ packedValidatorReward *big.Int
+
+ duration time.Duration
+}
+
+func (r *BidRuntime) validReward() bool {
+ return r.packedBlockReward.Cmp(r.expectedBlockReward) >= 0 &&
+ r.packedValidatorReward.Cmp(r.expectedValidatorReward) >= 0
+}
+
+// packReward calculates packedBlockReward and packedValidatorReward
+func (r *BidRuntime) packReward(validatorCommission uint64) {
+ r.packedBlockReward = r.env.state.GetBalance(consensus.SystemAddress).ToBig()
+ r.packedValidatorReward = new(big.Int).Mul(r.packedBlockReward, big.NewInt(int64(validatorCommission)))
+ r.packedValidatorReward.Div(r.packedValidatorReward, big.NewInt(10000))
+ r.packedValidatorReward.Sub(r.packedValidatorReward, r.bid.BuilderFee)
+}
+
+func (r *BidRuntime) commitTransaction(chain *core.BlockChain, chainConfig *params.ChainConfig, tx *types.Transaction) error {
+ var (
+ env = r.env
+ snap = env.state.Snapshot()
+ gp = env.gasPool.Gas()
+ sc *types.BlobTxSidecar
+ )
+
+ if tx.Type() == types.BlobTxType {
+ sc := tx.BlobTxSidecar()
+ if sc == nil {
+ return errors.New("blob transaction without blobs in miner")
+ }
+ // Checking against blob gas limit: It's kind of ugly to perform this check here, but there
+ // isn't really a better place right now. The blob gas limit is checked at block validation time
+ // and not during execution. This means core.ApplyTransaction will not return an error if the
+ // tx has too many blobs. So we have to explicitly check it here.
+ if (env.blobs+len(sc.Blobs))*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
+ return errors.New("max data blobs reached")
+ }
+ }
+
+ receipt, err := core.ApplyTransaction(chainConfig, chain, &env.coinbase, env.gasPool, env.state, env.header, tx,
+ &env.header.GasUsed, *chain.GetVMConfig(), core.NewReceiptBloomGenerator())
+ if err != nil {
+ env.state.RevertToSnapshot(snap)
+ env.gasPool.SetGas(gp)
+ return err
+ }
+
+ if tx.Type() == types.BlobTxType {
+ env.txs = append(env.txs, tx.WithoutBlobTxSidecar())
+ env.receipts = append(env.receipts, receipt)
+ env.sidecars = append(env.sidecars, sc)
+ env.blobs += len(sc.Blobs)
+ *env.header.BlobGasUsed += receipt.BlobGasUsed
+ } else {
+ env.txs = append(env.txs, tx)
+ env.receipts = append(env.receipts, receipt)
+ }
+
+ return nil
+}
diff --git a/miner/builderclient/builderclient.go b/miner/builderclient/builderclient.go
new file mode 100644
index 0000000000..9606a92d95
--- /dev/null
+++ b/miner/builderclient/builderclient.go
@@ -0,0 +1,33 @@
+package builderclient
+
+import (
+ "context"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// Client defines typed wrappers for the Ethereum RPC API.
+type Client struct {
+ c *rpc.Client
+}
+
+// DialOptions creates a new RPC client for the given URL. You can supply any of the
+// pre-defined client options to configure the underlying transport.
+func DialOptions(ctx context.Context, rawurl string, opts ...rpc.ClientOption) (*Client, error) {
+ c, err := rpc.DialOptions(ctx, rawurl, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return newClient(c), nil
+}
+
+// newClient creates a client that uses the given RPC client.
+func newClient(c *rpc.Client) *Client {
+ return &Client{c}
+}
+
+// ReportIssue reports an issue
+func (ec *Client) ReportIssue(ctx context.Context, args *types.BidIssue) error {
+ return ec.c.CallContext(ctx, nil, "mev_reportIssue", args)
+}
diff --git a/miner/miner.go b/miner/miner.go
index 4db6140803..a05da63e5b 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -56,6 +56,8 @@ type Config struct {
NewPayloadTimeout time.Duration // The maximum time allowance for creating a new payload
DisableVoteAttestation bool // Whether to skip assembling vote attestation
+
+ Mev MevConfig // Mev configuration
}
// DefaultConfig contains default settings for miner.
@@ -70,6 +72,8 @@ var DefaultConfig = Config{
Recommit: 3 * time.Second,
NewPayloadTimeout: 2 * time.Second,
DelayLeftOver: 50 * time.Millisecond,
+
+ Mev: DefaultMevConfig,
}
// Miner creates blocks and searches for proof-of-work values.
@@ -82,6 +86,8 @@ type Miner struct {
stopCh chan struct{}
worker *worker
+ bidSimulator *bidSimulator
+
wg sync.WaitGroup
}
@@ -95,6 +101,10 @@ func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *even
stopCh: make(chan struct{}),
worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock, false),
}
+
+ miner.bidSimulator = newBidSimulator(&config.Mev, config.DelayLeftOver, chainConfig, eth.BlockChain(), miner.worker)
+ miner.worker.setBestBidFetcher(miner.bidSimulator)
+
miner.wg.Add(1)
go miner.update()
return miner
@@ -129,6 +139,7 @@ func (miner *Miner) update() {
case downloader.StartEvent:
wasMining := miner.Mining()
miner.worker.stop()
+ miner.bidSimulator.stop()
canStart = false
if wasMining {
// Resume mining after sync was finished
@@ -141,6 +152,7 @@ func (miner *Miner) update() {
canStart = true
if shouldStart {
miner.worker.start()
+ miner.bidSimulator.start()
}
miner.worker.syncing.Store(false)
@@ -148,6 +160,7 @@ func (miner *Miner) update() {
canStart = true
if shouldStart {
miner.worker.start()
+ miner.bidSimulator.start()
}
miner.worker.syncing.Store(false)
@@ -157,13 +170,16 @@ func (miner *Miner) update() {
case <-miner.startCh:
if canStart {
miner.worker.start()
+ miner.bidSimulator.start()
}
shouldStart = true
case <-miner.stopCh:
shouldStart = false
miner.worker.stop()
+ miner.bidSimulator.stop()
case <-miner.exitCh:
miner.worker.close()
+ miner.bidSimulator.close()
return
}
}
@@ -186,6 +202,10 @@ func (miner *Miner) Mining() bool {
return miner.worker.isRunning()
}
+func (miner *Miner) InTurn() bool {
+ return miner.worker.inTurn()
+}
+
func (miner *Miner) Hashrate() uint64 {
if pow, ok := miner.engine.(consensus.PoW); ok {
return uint64(pow.Hashrate())
diff --git a/miner/miner_mev.go b/miner/miner_mev.go
new file mode 100644
index 0000000000..c499d0387d
--- /dev/null
+++ b/miner/miner_mev.go
@@ -0,0 +1,111 @@
+package miner
+
+import (
+ "context"
+ "fmt"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+)
+
+type BuilderConfig struct {
+ Address common.Address
+ URL string
+}
+
+type MevConfig struct {
+ Enabled bool // Whether to enable Mev or not
+ SentryURL string // The url of Mev sentry
+ Builders []BuilderConfig // The list of builders
+ ValidatorCommission uint64 // 100 means 1%
+ BidSimulationLeftOver time.Duration
+}
+
+var DefaultMevConfig = MevConfig{
+ Enabled: false,
+ SentryURL: "",
+ Builders: nil,
+ ValidatorCommission: 100,
+ BidSimulationLeftOver: 50 * time.Millisecond,
+}
+
+// MevRunning return true if mev is running.
+func (miner *Miner) MevRunning() bool {
+ return miner.bidSimulator.isRunning() && miner.bidSimulator.receivingBid()
+}
+
+// StartMev starts mev.
+func (miner *Miner) StartMev() {
+ miner.bidSimulator.startReceivingBid()
+}
+
+// StopMev stops mev.
+func (miner *Miner) StopMev() {
+ miner.bidSimulator.stopReceivingBid()
+}
+
+// AddBuilder adds a builder to the bid simulator.
+func (miner *Miner) AddBuilder(builder common.Address, url string) error {
+ return miner.bidSimulator.AddBuilder(builder, url)
+}
+
+// RemoveBuilder removes a builder from the bid simulator.
+func (miner *Miner) RemoveBuilder(builderAddr common.Address) error {
+ return miner.bidSimulator.RemoveBuilder(builderAddr)
+}
+
+func (miner *Miner) SendBid(ctx context.Context, bidArgs *types.BidArgs) (common.Hash, error) {
+ builder, err := bidArgs.EcrecoverSender()
+ if err != nil {
+ return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("invalid signature:%v", err))
+ }
+
+ if !miner.bidSimulator.ExistBuilder(builder) {
+ return common.Hash{}, types.NewInvalidBidError("builder is not registered")
+ }
+
+ err = miner.bidSimulator.CheckPending(bidArgs.RawBid.BlockNumber, builder, bidArgs.RawBid.Hash())
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ signer := types.MakeSigner(miner.worker.chainConfig, big.NewInt(int64(bidArgs.RawBid.BlockNumber)), uint64(time.Now().Unix()))
+ bid, err := bidArgs.ToBid(builder, signer)
+ if err != nil {
+ return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("fail to convert bidArgs to bid, %v", err))
+ }
+
+ bidBetterBefore := miner.bidSimulator.bidBetterBefore(bidArgs.RawBid.ParentHash)
+ timeout := time.Until(bidBetterBefore)
+
+ if timeout <= 0 {
+ return common.Hash{}, fmt.Errorf("too late, expected befor %s, appeared %s later", bidBetterBefore,
+ common.PrettyDuration(timeout))
+ }
+
+ err = miner.bidSimulator.sendBid(ctx, bid)
+
+ if err != nil {
+ return common.Hash{}, err
+ }
+
+ return bid.Hash(), nil
+}
+
+func (miner *Miner) BestPackedBlockReward(parentHash common.Hash) *big.Int {
+ bidRuntime := miner.bidSimulator.GetBestBid(parentHash)
+ if bidRuntime == nil {
+ return big.NewInt(0)
+ }
+
+ return bidRuntime.packedBlockReward
+}
+
+func (miner *Miner) MevParams() *types.MevParams {
+ return &types.MevParams{
+ ValidatorCommission: miner.worker.config.Mev.ValidatorCommission,
+ BidSimulationLeftOver: miner.worker.config.Mev.BidSimulationLeftOver,
+ }
+}
diff --git a/miner/miner_test.go b/miner/miner_test.go
index 489bc46a91..411d6026ce 100644
--- a/miner/miner_test.go
+++ b/miner/miner_test.go
@@ -64,6 +64,7 @@ func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *stat
}
type testBlockChain struct {
+ root common.Hash
config *params.ChainConfig
statedb *state.StateDB
gasLimit uint64
@@ -89,11 +90,16 @@ func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
return bc.statedb, nil
}
+func (bc *testBlockChain) HasState(root common.Hash) bool {
+ return bc.root == root
+}
+
func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
return bc.chainHeadFeed.Subscribe(ch)
}
func TestMiner(t *testing.T) {
+ t.Parallel()
miner, mux, cleanup := createMiner(t)
defer cleanup(false)
@@ -123,6 +129,7 @@ func TestMiner(t *testing.T) {
// An initial FailedEvent should allow mining to stop on a subsequent
// downloader StartEvent.
func TestMinerDownloaderFirstFails(t *testing.T) {
+ t.Parallel()
miner, mux, cleanup := createMiner(t)
defer cleanup(false)
@@ -156,6 +163,7 @@ func TestMinerDownloaderFirstFails(t *testing.T) {
}
func TestMinerStartStopAfterDownloaderEvents(t *testing.T) {
+ t.Parallel()
miner, mux, cleanup := createMiner(t)
defer cleanup(false)
@@ -180,6 +188,7 @@ func TestMinerStartStopAfterDownloaderEvents(t *testing.T) {
}
func TestStartWhileDownload(t *testing.T) {
+ t.Parallel()
miner, mux, cleanup := createMiner(t)
defer cleanup(false)
waitForMiningState(t, miner, false)
@@ -194,6 +203,7 @@ func TestStartWhileDownload(t *testing.T) {
}
func TestStartStopMiner(t *testing.T) {
+ t.Parallel()
miner, _, cleanup := createMiner(t)
defer cleanup(false)
waitForMiningState(t, miner, false)
@@ -204,6 +214,7 @@ func TestStartStopMiner(t *testing.T) {
}
func TestCloseMiner(t *testing.T) {
+ t.Parallel()
miner, _, cleanup := createMiner(t)
defer cleanup(true)
waitForMiningState(t, miner, false)
@@ -217,6 +228,7 @@ func TestCloseMiner(t *testing.T) {
// TestMinerSetEtherbase checks that etherbase becomes set even if mining isn't
// possible at the moment
func TestMinerSetEtherbase(t *testing.T) {
+ t.Parallel()
miner, mux, cleanup := createMiner(t)
defer cleanup(false)
miner.Start()
@@ -302,7 +314,7 @@ func createMiner(t *testing.T) (*Miner, *event.TypeMux, func(skipMiner bool)) {
t.Fatalf("can't create new chain %v", err)
}
statedb, _ := state.New(bc.Genesis().Root(), bc.StateCache(), nil)
- blockchain := &testBlockChain{chainConfig, statedb, 10000000, new(event.Feed)}
+ blockchain := &testBlockChain{bc.Genesis().Root(), chainConfig, statedb, 10000000, new(event.Feed)}
pool := legacypool.New(testTxPoolConfig, blockchain)
txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain, []txpool.SubPool{pool})
diff --git a/miner/ordering.go b/miner/ordering.go
index 7e3640a455..fa47e93172 100644
--- a/miner/ordering.go
+++ b/miner/ordering.go
@@ -149,7 +149,7 @@ func (t *transactionsByPriceAndNonce) Peek() *txpool.LazyTransaction {
// Peek returns the next transaction by price.
func (t *transactionsByPriceAndNonce) PeekWithUnwrap() *types.Transaction {
if len(t.heads) > 0 && t.heads[0].tx != nil && t.heads[0].tx.Resolve() != nil {
- return t.heads[0].tx.Tx.Tx
+ return t.heads[0].tx.Tx
}
return nil
}
@@ -189,7 +189,7 @@ func (t *transactionsByPriceAndNonce) Forward(tx *types.Transaction) {
//check whether target tx exists in t.heads
for _, head := range t.heads {
if head.tx != nil && head.tx.Resolve() != nil {
- if tx == head.tx.Tx.Tx {
+ if tx == head.tx.Tx {
//shift t to the position one after tx
txTmp := t.PeekWithUnwrap()
for txTmp != tx {
@@ -208,7 +208,7 @@ func (t *transactionsByPriceAndNonce) Forward(tx *types.Transaction) {
for _, txLazyTmp := range txs {
if txLazyTmp != nil && txLazyTmp.Resolve() != nil {
//found the same pointer in t.txs as tx and then shift t to the position one after tx
- if tx == txLazyTmp.Tx.Tx {
+ if tx == txLazyTmp.Tx {
txTmp := t.PeekWithUnwrap()
for txTmp != tx {
t.Shift()
diff --git a/miner/ordering_test.go b/miner/ordering_test.go
index 589633e0b8..e5868d7a06 100644
--- a/miner/ordering_test.go
+++ b/miner/ordering_test.go
@@ -30,10 +30,12 @@ import (
)
func TestTransactionPriceNonceSortLegacy(t *testing.T) {
+ t.Parallel()
testTransactionPriceNonceSort(t, nil)
}
func TestTransactionPriceNonceSort1559(t *testing.T) {
+ t.Parallel()
testTransactionPriceNonceSort(t, big.NewInt(0))
testTransactionPriceNonceSort(t, big.NewInt(5))
testTransactionPriceNonceSort(t, big.NewInt(50))
@@ -88,10 +90,12 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
}
groups[addr] = append(groups[addr], &txpool.LazyTransaction{
Hash: tx.Hash(),
- Tx: &txpool.Transaction{Tx: tx},
+ Tx: tx,
Time: tx.Time(),
GasFeeCap: tx.GasFeeCap(),
GasTipCap: tx.GasTipCap(),
+ Gas: tx.Gas(),
+ BlobGas: tx.BlobGas(),
})
}
expectedCount += count
@@ -101,7 +105,7 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
txs := types.Transactions{}
for tx := txset.Peek(); tx != nil; tx = txset.Peek() {
- txs = append(txs, tx.Tx.Tx)
+ txs = append(txs, tx.Tx)
txset.Shift()
}
if len(txs) != expectedCount {
@@ -136,6 +140,7 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
// Tests that if multiple transactions have the same price, the ones seen earlier
// are prioritized to avoid network spam attacks aiming for a specific ordering.
func TestTransactionTimeSort(t *testing.T) {
+ t.Parallel()
// Generate a batch of accounts to start with
keys := make([]*ecdsa.PrivateKey, 5)
for i := 0; i < len(keys); i++ {
@@ -153,10 +158,12 @@ func TestTransactionTimeSort(t *testing.T) {
groups[addr] = append(groups[addr], &txpool.LazyTransaction{
Hash: tx.Hash(),
- Tx: &txpool.Transaction{Tx: tx},
+ Tx: tx,
Time: tx.Time(),
GasFeeCap: tx.GasFeeCap(),
GasTipCap: tx.GasTipCap(),
+ Gas: tx.Gas(),
+ BlobGas: tx.BlobGas(),
})
}
// Sort the transactions and cross check the nonce ordering
@@ -164,7 +171,7 @@ func TestTransactionTimeSort(t *testing.T) {
txs := types.Transactions{}
for tx := txset.Peek(); tx != nil; tx = txset.Peek() {
- txs = append(txs, tx.Tx.Tx)
+ txs = append(txs, tx.Tx)
txset.Shift()
}
if len(txs) != len(keys) {
diff --git a/miner/payload_building.go b/miner/payload_building.go
index 299196a3cd..719736c479 100644
--- a/miner/payload_building.go
+++ b/miner/payload_building.go
@@ -33,13 +33,15 @@ import (
// BuildPayloadArgs contains the provided parameters for building payload.
// Check engine-api specification for more details.
-// https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1
+// https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3
type BuildPayloadArgs struct {
- Parent common.Hash // The parent block to build payload on top
- Timestamp uint64 // The provided timestamp of generated payload
- FeeRecipient common.Address // The provided recipient address for collecting transaction fee
- Random common.Hash // The provided randomness value
- Withdrawals types.Withdrawals // The provided withdrawals
+ Parent common.Hash // The parent block to build payload on top
+ Timestamp uint64 // The provided timestamp of generated payload
+ FeeRecipient common.Address // The provided recipient address for collecting transaction fee
+ Random common.Hash // The provided randomness value
+ Withdrawals types.Withdrawals // The provided withdrawals
+ BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
+ Version engine.PayloadVersion // Versioning byte for payload id calculation.
}
// Id computes an 8-byte identifier by hashing the components of the payload arguments.
@@ -51,8 +53,12 @@ func (args *BuildPayloadArgs) Id() engine.PayloadID {
hasher.Write(args.Random[:])
hasher.Write(args.FeeRecipient[:])
rlp.Encode(hasher, args.Withdrawals)
+ if args.BeaconRoot != nil {
+ hasher.Write(args.BeaconRoot[:])
+ }
var out engine.PayloadID
copy(out[:], hasher.Sum(nil)[:8])
+ out[0] = byte(args.Version)
return out
}
@@ -65,6 +71,7 @@ type Payload struct {
id engine.PayloadID
empty *types.Block
full *types.Block
+ sidecars []*types.BlobTxSidecar
fullFees *big.Int
stop chan struct{}
lock sync.Mutex
@@ -84,7 +91,7 @@ func newPayload(empty *types.Block, id engine.PayloadID) *Payload {
}
// update updates the full-block with latest built version.
-func (payload *Payload) update(block *types.Block, fees *big.Int, elapsed time.Duration) {
+func (payload *Payload) update(r *newPayloadResult, elapsed time.Duration) {
payload.lock.Lock()
defer payload.lock.Unlock()
@@ -96,14 +103,23 @@ func (payload *Payload) update(block *types.Block, fees *big.Int, elapsed time.D
// Ensure the newly provided full block has a higher transaction fee.
// In post-merge stage, there is no uncle reward anymore and transaction
// fee(apart from the mev revenue) is the only indicator for comparison.
- if payload.full == nil || fees.Cmp(payload.fullFees) > 0 {
- payload.full = block
- payload.fullFees = fees
-
- feesInEther := new(big.Float).Quo(new(big.Float).SetInt(fees), big.NewFloat(params.Ether))
- log.Info("Updated payload", "id", payload.id, "number", block.NumberU64(), "hash", block.Hash(),
- "txs", len(block.Transactions()), "withdrawals", len(block.Withdrawals()), "gas", block.GasUsed(),
- "fees", feesInEther, "root", block.Root(), "elapsed", common.PrettyDuration(elapsed))
+ if payload.full == nil || r.fees.Cmp(payload.fullFees) > 0 {
+ payload.full = r.block
+ payload.fullFees = r.fees
+ payload.sidecars = r.sidecars
+
+ feesInEther := new(big.Float).Quo(new(big.Float).SetInt(r.fees), big.NewFloat(params.Ether))
+ log.Info("Updated payload",
+ "id", payload.id,
+ "number", r.block.NumberU64(),
+ "hash", r.block.Hash(),
+ "txs", len(r.block.Transactions()),
+ "withdrawals", len(r.block.Withdrawals()),
+ "gas", r.block.GasUsed(),
+ "fees", feesInEther,
+ "root", r.block.Root(),
+ "elapsed", common.PrettyDuration(elapsed),
+ )
}
payload.cond.Broadcast() // fire signal for notifying full block
}
@@ -120,9 +136,9 @@ func (payload *Payload) Resolve() *engine.ExecutionPayloadEnvelope {
close(payload.stop)
}
if payload.full != nil {
- return engine.BlockToExecutableData(payload.full, payload.fullFees, nil, nil, nil)
+ return engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars)
}
- return engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil, nil, nil)
+ return engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil)
}
// ResolveEmpty is basically identical to Resolve, but it expects empty block only.
@@ -131,7 +147,7 @@ func (payload *Payload) ResolveEmpty() *engine.ExecutionPayloadEnvelope {
payload.lock.Lock()
defer payload.lock.Unlock()
- return engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil, nil, nil)
+ return engine.BlockToExecutableData(payload.empty, big.NewInt(0), nil)
}
// ResolveFull is basically identical to Resolve, but it expects full block only.
@@ -157,7 +173,7 @@ func (payload *Payload) ResolveFull() *engine.ExecutionPayloadEnvelope {
default:
close(payload.stop)
}
- return engine.BlockToExecutableData(payload.full, payload.fullFees, nil, nil, nil)
+ return engine.BlockToExecutableData(payload.full, payload.fullFees, payload.sidecars)
}
// buildPayload builds the payload according to the provided parameters.
@@ -165,12 +181,23 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
// Build the initial version with no transaction included. It should be fast
// enough to run. The empty payload can at least make sure there is something
// to deliver for not missing slot.
- empty, _, err := w.getSealingBlock(args.Parent, args.Timestamp, args.FeeRecipient, args.Random, args.Withdrawals, true)
- if err != nil {
- return nil, err
+ emptyParams := &generateParams{
+ timestamp: args.Timestamp,
+ forceTime: true,
+ parentHash: args.Parent,
+ coinbase: args.FeeRecipient,
+ random: args.Random,
+ withdrawals: args.Withdrawals,
+ beaconRoot: args.BeaconRoot,
+ noTxs: true,
+ }
+ empty := w.getSealingBlock(emptyParams)
+ if empty.err != nil {
+ return nil, empty.err
}
+
// Construct a payload object for return.
- payload := newPayload(empty, args.Id())
+ payload := newPayload(empty.block, args.Id())
// Spin up a routine for updating the payload in background. This strategy
// can maximum the revenue for including transactions with highest fee.
@@ -185,13 +212,24 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
// by the timestamp parameter.
endTimer := time.NewTimer(time.Second * 12)
+ fullParams := &generateParams{
+ timestamp: args.Timestamp,
+ forceTime: true,
+ parentHash: args.Parent,
+ coinbase: args.FeeRecipient,
+ random: args.Random,
+ withdrawals: args.Withdrawals,
+ beaconRoot: args.BeaconRoot,
+ noTxs: false,
+ }
+
for {
select {
case <-timer.C:
start := time.Now()
- block, fees, err := w.getSealingBlock(args.Parent, args.Timestamp, args.FeeRecipient, args.Random, args.Withdrawals, false)
- if err == nil {
- payload.update(block, fees, time.Since(start))
+ r := w.getSealingBlock(fullParams)
+ if r.err == nil {
+ payload.update(r, time.Since(start))
}
timer.Reset(w.recommit)
case <-payload.stop:
diff --git a/miner/payload_building_test.go b/miner/payload_building_test.go
index 6f57363441..708072b5ec 100644
--- a/miner/payload_building_test.go
+++ b/miner/payload_building_test.go
@@ -30,6 +30,7 @@ import (
)
func TestBuildPayload(t *testing.T) {
+ t.Parallel()
var (
db = rawdb.NewMemoryDatabase()
recipient = common.HexToAddress("0xdeadbeef")
@@ -51,19 +52,19 @@ func TestBuildPayload(t *testing.T) {
verify := func(outer *engine.ExecutionPayloadEnvelope, txs int) {
payload := outer.ExecutionPayload
if payload.ParentHash != b.chain.CurrentBlock().Hash() {
- t.Fatal("Unexpect parent hash")
+ t.Fatal("Unexpected parent hash")
}
if payload.Random != (common.Hash{}) {
- t.Fatal("Unexpect random value")
+ t.Fatal("Unexpected random value")
}
if payload.Timestamp != timestamp {
- t.Fatal("Unexpect timestamp")
+ t.Fatal("Unexpected timestamp")
}
if payload.FeeRecipient != recipient {
- t.Fatal("Unexpect fee recipient")
+ t.Fatal("Unexpected fee recipient")
}
if len(payload.Transactions) != txs {
- t.Fatal("Unexpect transaction set")
+ t.Fatal("Unexpected transaction set")
}
}
empty := payload.ResolveEmpty()
@@ -82,6 +83,7 @@ func TestBuildPayload(t *testing.T) {
}
func TestPayloadId(t *testing.T) {
+ t.Parallel()
ids := make(map[string]int)
for i, tt := range []*BuildPayloadArgs{
{
diff --git a/miner/stress/clique/main.go b/miner/stress/clique/main.go
index ddc92ff7a5..ead3d8df35 100644
--- a/miner/stress/clique/main.go
+++ b/miner/stress/clique/main.go
@@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
@@ -46,7 +45,7 @@ import (
)
func main() {
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
fdlimit.Raise(2048)
// Generate a batch of accounts to seal and fund with
@@ -133,7 +132,7 @@ func main() {
if err != nil {
panic(err)
}
- if err := backend.TxPool().Add([]*txpool.Transaction{{Tx: tx}}, true, false); err != nil {
+ if err := backend.TxPool().Add([]*types.Transaction{tx}, true, false); err != nil {
panic(err)
}
nonces[index]++
diff --git a/miner/worker.go b/miner/worker.go
index 0b8f248742..4a473107d1 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -24,21 +24,25 @@ import (
"sync/atomic"
"time"
+ lru "github.com/hashicorp/golang-lru"
+ "github.com/holiman/uint256"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/consensus/parlia"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/systemcontracts"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
- lru "github.com/hashicorp/golang-lru"
)
const (
@@ -86,6 +90,8 @@ type environment struct {
header *types.Header
txs []*types.Transaction
receipts []*types.Receipt
+ sidecars []*types.BlobTxSidecar
+ blobs int
}
// copy creates a deep copy of environment.
@@ -104,6 +110,10 @@ func (env *environment) copy() *environment {
}
cpy.txs = make([]*types.Transaction, len(env.txs))
copy(cpy.txs, env.txs)
+
+ cpy.sidecars = make([]*types.BlobTxSidecar, len(env.sidecars))
+ copy(cpy.sidecars, env.sidecars)
+
return cpy
}
@@ -139,11 +149,12 @@ type newWorkReq struct {
timestamp int64
}
-// newPayloadResult represents a result struct corresponds to payload generation.
+// newPayloadResult is the result of payload generation.
type newPayloadResult struct {
- err error
- block *types.Block
- fees *big.Int
+ err error
+ block *types.Block
+ fees *big.Int // total block fees
+ sidecars []*types.BlobTxSidecar // collected blobs of blob transactions
}
// getWorkReq represents a request for getting a new sealing work with provided parameters.
@@ -152,9 +163,14 @@ type getWorkReq struct {
result chan *newPayloadResult // non-blocking channel
}
+type bidFetcher interface {
+ GetBestBid(parentHash common.Hash) *BidRuntime
+}
+
// worker is the main object which takes care of submitting new work to consensus engine
// and gathering the sealing result.
type worker struct {
+ bidFetcher bidFetcher
prefetcher core.Prefetcher
config *Config
chainConfig *params.ChainConfig
@@ -277,9 +293,14 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
if init {
worker.startCh <- struct{}{}
}
+
return worker
}
+func (w *worker) setBestBidFetcher(fetcher bidFetcher) {
+ w.bidFetcher = fetcher
+}
+
// setEtherbase sets the etherbase used to initialize the block coinbase field.
func (w *worker) setEtherbase(addr common.Address) {
w.mu.Lock()
@@ -477,12 +498,7 @@ func (w *worker) mainLoop() {
w.commitWork(req.interruptCh, req.timestamp)
case req := <-w.getWorkCh:
- block, fees, err := w.generateWork(req.params)
- req.result <- &newPayloadResult{
- err: err,
- block: block,
- fees: fees,
- }
+ req.result <- w.generateWork(req.params)
// System stopped
case <-w.exitCh:
@@ -688,22 +704,58 @@ func (w *worker) updateSnapshot(env *environment) {
w.snapshotState = env.state.Copy()
}
-func (w *worker) commitTransaction(env *environment, tx *txpool.Transaction, receiptProcessors ...core.ReceiptProcessor) ([]*types.Log, error) {
+func (w *worker) commitTransaction(env *environment, tx *types.Transaction, receiptProcessors ...core.ReceiptProcessor) ([]*types.Log, error) {
+ if tx.Type() == types.BlobTxType {
+ return w.commitBlobTransaction(env, tx, receiptProcessors...)
+ }
+
+ receipt, err := w.applyTransaction(env, tx, receiptProcessors...)
+ if err != nil {
+ return nil, err
+ }
+ env.txs = append(env.txs, tx)
+ env.receipts = append(env.receipts, receipt)
+ return receipt.Logs, nil
+}
+
+func (w *worker) commitBlobTransaction(env *environment, tx *types.Transaction, receiptProcessors ...core.ReceiptProcessor) ([]*types.Log, error) {
+ sc := tx.BlobTxSidecar()
+ if sc == nil {
+ panic("blob transaction without blobs in miner")
+ }
+ // Checking against blob gas limit: It's kind of ugly to perform this check here, but there
+ // isn't really a better place right now. The blob gas limit is checked at block validation time
+ // and not during execution. This means core.ApplyTransaction will not return an error if the
+ // tx has too many blobs. So we have to explicitly check it here.
+ if (env.blobs+len(sc.Blobs))*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
+ return nil, errors.New("max data blobs reached")
+ }
+
+ receipt, err := w.applyTransaction(env, tx, receiptProcessors...)
+ if err != nil {
+ return nil, err
+ }
+ env.txs = append(env.txs, tx.WithoutBlobTxSidecar())
+ env.receipts = append(env.receipts, receipt)
+ env.sidecars = append(env.sidecars, sc)
+ env.blobs += len(sc.Blobs)
+ *env.header.BlobGasUsed += receipt.BlobGasUsed
+ return receipt.Logs, nil
+}
+
+// applyTransaction runs the transaction. If execution fails, state and gas pool are reverted.
+func (w *worker) applyTransaction(env *environment, tx *types.Transaction, receiptProcessors ...core.ReceiptProcessor) (*types.Receipt, error) {
var (
snap = env.state.Snapshot()
gp = env.gasPool.Gas()
)
- receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx.Tx, &env.header.GasUsed, *w.chain.GetVMConfig(), receiptProcessors...)
+ receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig(), receiptProcessors...)
if err != nil {
env.state.RevertToSnapshot(snap)
env.gasPool.SetGas(gp)
- return nil, err
}
- env.txs = append(env.txs, tx.Tx)
- env.receipts = append(env.receipts, receipt)
-
- return receipt.Logs, nil
+ return receipt, err
}
func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce,
@@ -724,7 +776,7 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
stopPrefetchCh := make(chan struct{})
defer close(stopPrefetchCh)
- //prefetch txs from all pending txs
+ // prefetch txs from all pending txs
txsPrefetch := txs.Copy()
tx := txsPrefetch.PeekWithUnwrap()
if tx != nil {
@@ -773,33 +825,43 @@ LOOP:
if ltx == nil {
break
}
+ // If we don't have enough space for the next transaction, skip the account.
+ if env.gasPool.Gas() < ltx.Gas {
+ log.Trace("Not enough gas left for transaction", "hash", ltx.Hash, "left", env.gasPool.Gas(), "needed", ltx.Gas)
+ txs.Pop()
+ continue
+ }
+ if left := uint64(params.MaxBlobGasPerBlock - env.blobs*params.BlobTxBlobGasPerBlob); left < ltx.BlobGas {
+ log.Trace("Not enough blob gas left for transaction", "hash", ltx.Hash, "left", left, "needed", ltx.BlobGas)
+ txs.Pop()
+ continue
+ }
+ // Transaction seems to fit, pull it up from the pool
tx := ltx.Resolve()
if tx == nil {
- log.Warn("Ignoring evicted transaction")
-
+ log.Trace("Ignoring evicted transaction", "hash", ltx.Hash)
txs.Pop()
continue
}
// Error may be ignored here. The error has already been checked
// during transaction acceptance is the transaction pool.
- from, _ := types.Sender(env.signer, tx.Tx)
+ from, _ := types.Sender(env.signer, tx)
// Check whether the tx is replay protected. If we're not in the EIP155 hf
// phase, start ignoring the sender until we do.
- if tx.Tx.Protected() && !w.chainConfig.IsEIP155(env.header.Number) {
- log.Trace("Ignoring reply protected transaction", "hash", tx.Tx.Hash(), "eip155", w.chainConfig.EIP155Block)
-
+ if tx.Protected() && !w.chainConfig.IsEIP155(env.header.Number) {
+ log.Trace("Ignoring replay protected transaction", "hash", ltx.Hash, "eip155", w.chainConfig.EIP155Block)
txs.Pop()
continue
}
// Start executing the transaction
- env.state.SetTxContext(tx.Tx.Hash(), env.tcount)
+ env.state.SetTxContext(tx.Hash(), env.tcount)
logs, err := w.commitTransaction(env, tx, bloomProcessors)
switch {
case errors.Is(err, core.ErrNonceTooLow):
// New head notification data race between the transaction pool and miner, shift
- log.Trace("Skipping transaction with low nonce", "sender", from, "nonce", tx.Tx.Nonce())
+ log.Trace("Skipping transaction with low nonce", "hash", ltx.Hash, "sender", from, "nonce", tx.Nonce())
txs.Shift()
case errors.Is(err, nil):
@@ -811,7 +873,7 @@ LOOP:
default:
// Transaction is regarded as invalid, drop all consecutive transactions from
// the same sender because of `nonce-too-high` clause.
- log.Debug("Transaction failed, account skipped", "hash", tx.Tx.Hash(), "err", err)
+ log.Debug("Transaction failed, account skipped", "hash", ltx.Hash, "err", err)
txs.Pop()
}
}
@@ -843,7 +905,8 @@ type generateParams struct {
random common.Hash // The randomness generated by beacon chain, empty before the merge
withdrawals types.Withdrawals // List of withdrawals to include in block.
prevWork *environment
- noTxs bool // Flag whether an empty block without any transaction is expected
+ beaconRoot *common.Hash // The beacon root (cancun field).
+ noTxs bool // Flag whether an empty block without any transaction is expected
}
// prepareWork constructs the sealing task according to the given parameters,
@@ -895,6 +958,19 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil)
}
}
+ // Apply EIP-4844, EIP-4788.
+ if w.chainConfig.IsCancun(header.Number, header.Time) {
+ var excessBlobGas uint64
+ if w.chainConfig.IsCancun(parent.Number, parent.Time) {
+ excessBlobGas = eip4844.CalcExcessBlobGas(*parent.ExcessBlobGas, *parent.BlobGasUsed)
+ } else {
+ // For the first post-fork block, both parent.data_gas_used and parent.excess_data_gas are evaluated as 0
+ excessBlobGas = eip4844.CalcExcessBlobGas(0, 0)
+ }
+ header.BlobGasUsed = new(uint64)
+ header.ExcessBlobGas = &excessBlobGas
+ header.ParentBeaconRoot = genParams.beaconRoot
+ }
// Run the consensus preparation with the default or customized consensus engine.
if err := w.engine.Prepare(w.chain, header); err != nil {
log.Error("Failed to prepare header for sealing", "err", err)
@@ -909,9 +985,16 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
return nil, err
}
- // Handle upgrade build-in system contract code
- systemcontracts.UpgradeBuildInSystemContract(w.chainConfig, header.Number, parent.Time, header.Time, env.state)
+ if !w.chainConfig.IsFeynman(header.Number, header.Time) {
+ // Handle upgrade build-in system contract code
+ systemcontracts.UpgradeBuildInSystemContract(w.chainConfig, header.Number, parent.Time, header.Time, env.state)
+ }
+ if header.ParentBeaconRoot != nil {
+ context := core.NewEVMBlockContext(header, w.chain, nil)
+ vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{})
+ core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, env.state)
+ }
return env, nil
}
@@ -923,6 +1006,7 @@ func (w *worker) fillTransactions(interruptCh chan int32, env *environment, stop
// Fill the block with all available pending transactions.
pending := w.eth.TxPool().Pending(false)
+ // Split the pending transactions into locals and remotes.
localTxs, remoteTxs := make(map[common.Address][]*txpool.LazyTransaction), pending
for _, account := range w.eth.TxPool().Locals() {
if txs := remoteTxs[account]; len(txs) > 0 {
@@ -931,7 +1015,7 @@ func (w *worker) fillTransactions(interruptCh chan int32, env *environment, stop
}
}
- err = nil
+ // Fill the block with all available pending transactions.
if len(localTxs) > 0 {
txs := newTransactionsByPriceAndNonce(env.signer, localTxs, env.header.BaseFee)
err = w.commitTransactions(env, txs, interruptCh, stopTimer)
@@ -954,10 +1038,10 @@ func (w *worker) fillTransactions(interruptCh chan int32, env *environment, stop
}
// generateWork generates a sealing block based on the given parameters.
-func (w *worker) generateWork(params *generateParams) (*types.Block, *big.Int, error) {
+func (w *worker) generateWork(params *generateParams) *newPayloadResult {
work, err := w.prepareWork(params)
if err != nil {
- return nil, nil, err
+ return &newPayloadResult{err: err}
}
defer work.discard()
@@ -970,9 +1054,13 @@ func (w *worker) generateWork(params *generateParams) (*types.Block, *big.Int, e
fees := work.state.GetBalance(consensus.SystemAddress)
block, _, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, nil, work.receipts, params.withdrawals)
if err != nil {
- return nil, nil, err
+ return &newPayloadResult{err: err}
+ }
+ return &newPayloadResult{
+ block: block,
+ fees: fees.ToBig(),
+ sidecars: work.sidecars,
}
- return block, fees, nil
}
// commitWork generates several new sealing tasks based on the parent block
@@ -1046,10 +1134,11 @@ LOOP:
// subscribe before fillTransactions
txsCh := make(chan core.NewTxsEvent, txChanSize)
- sub := w.eth.TxPool().SubscribeNewTxsEvent(txsCh)
+ // Subscribe for transaction insertion events (whether from network or resurrects)
+ sub := w.eth.TxPool().SubscribeTransactions(txsCh, true)
// if TxPool has been stopped, `sub` would be nil, it could happen on shutdown.
if sub == nil {
- log.Info("commitWork SubscribeNewTxsEvent return nil")
+ log.Info("commitWork SubscribeTransactions return nil")
} else {
defer sub.Unsubscribe()
}
@@ -1131,7 +1220,7 @@ LOOP:
}
// get the most profitable work
bestWork := workList[0]
- bestReward := new(big.Int)
+ bestReward := new(uint256.Int)
for i, wk := range workList {
balance := wk.state.GetBalance(consensus.SystemAddress)
log.Debug("Get the most profitable work", "index", i, "balance", balance, "bestReward", bestReward)
@@ -1140,6 +1229,24 @@ LOOP:
bestReward = balance
}
}
+
+ // when out-turn, use bestWork to prevent bundle leakage.
+ // when in-turn, compare with remote work.
+ if w.bidFetcher != nil && bestWork.header.Difficulty.Cmp(diffInTurn) == 0 {
+ bestBid := w.bidFetcher.GetBestBid(bestWork.header.ParentHash)
+
+ if bestBid != nil && bestReward.CmpBig(bestBid.packedBlockReward) < 0 {
+ // localValidatorReward is the reward for the validator self by the local block.
+ localValidatorReward := new(uint256.Int).Mul(bestReward, uint256.NewInt(w.config.Mev.ValidatorCommission))
+ localValidatorReward.Div(localValidatorReward, uint256.NewInt(10000))
+
+ // blockReward(benefits delegators) and validatorReward(benefits the validator) are both optimal
+ if localValidatorReward.CmpBig(bestBid.packedValidatorReward) < 0 {
+ bestWork = bestBid.env
+ }
+ }
+ }
+
w.commit(bestWork, w.fullTaskHook, true, start)
// Swap out the old work with the new one, terminating any leftover
@@ -1150,6 +1257,12 @@ LOOP:
w.current = bestWork
}
+// inTurn return true if the current worker is in turn.
+func (w *worker) inTurn() bool {
+ validator, _ := w.engine.NextInTurnValidator(w.chain, w.chain.CurrentBlock())
+ return validator != common.Address{} && validator == w.etherbase()
+}
+
// commit runs any post-transaction state modifications, assembles the final block
// and commits new work if consensus engine is running.
// Note the assumption is held that the mutation is allowed to the passed env, do
@@ -1168,6 +1281,8 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti
env.state.CorrectAccountsRoot(w.chain.CurrentBlock().Root)
*/
+ fees := env.state.GetBalance(consensus.SystemAddress).ToBig()
+ feesInEther := new(big.Float).Quo(new(big.Float).SetInt(fees), big.NewFloat(params.Ether))
// Withdrawals are set to nil here, because this is only called in PoW.
finalizeStart := time.Now()
block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(env.header), env.state, env.txs, nil, env.receipts, nil)
@@ -1185,8 +1300,6 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti
if !w.isTTDReached(block.Header()) {
select {
case w.taskCh <- &task{receipts: receipts, state: env.state, block: block, createdAt: time.Now()}:
- fees := env.state.GetBalance(consensus.SystemAddress)
- feesInEther := new(big.Float).Quo(new(big.Float).SetInt(fees), big.NewFloat(params.Ether))
log.Info("Commit new sealing work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()),
"txs", env.tcount, "gas", block.GasUsed(), "fees", feesInEther, "elapsed", common.PrettyDuration(time.Since(start)))
@@ -1204,28 +1317,16 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti
// getSealingBlock generates the sealing block based on the given parameters.
// The generation result will be passed back via the given channel no matter
// the generation itself succeeds or not.
-func (w *worker) getSealingBlock(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash, withdrawals types.Withdrawals, noTxs bool) (*types.Block, *big.Int, error) {
+func (w *worker) getSealingBlock(params *generateParams) *newPayloadResult {
req := &getWorkReq{
- params: &generateParams{
- timestamp: timestamp,
- forceTime: true,
- parentHash: parent,
- coinbase: coinbase,
- random: random,
- withdrawals: withdrawals,
- noTxs: noTxs,
- },
+ params: params,
result: make(chan *newPayloadResult, 1),
}
select {
case w.getWorkCh <- req:
- result := <-req.result
- if result.err != nil {
- return nil, nil, result.err
- }
- return result.block, result.fees, nil
+ return <-req.result
case <-w.exitCh:
- return nil, nil, errors.New("miner closed")
+ return &newPayloadResult{err: errors.New("miner closed")}
}
}
diff --git a/miner/worker_test.go b/miner/worker_test.go
index c0ce5f96c5..1bd22a646c 100644
--- a/miner/worker_test.go
+++ b/miner/worker_test.go
@@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
const (
@@ -62,7 +63,7 @@ var (
testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey)
// Test transactions
- pendingTxs []*txpool.Transaction
+ pendingTxs []*types.Transaction
newTxs []*types.Transaction
testConfig = &Config{
@@ -92,7 +93,7 @@ func init() {
Gas: params.TxGas,
GasPrice: big.NewInt(params.InitialBaseFee),
})
- pendingTxs = append(pendingTxs, &txpool.Transaction{Tx: tx1})
+ pendingTxs = append(pendingTxs, tx1)
tx2 := types.MustSignNewTx(testBankKey, signer, &types.LegacyTx{
Nonce: 1,
@@ -166,6 +167,7 @@ func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consens
}
func TestGenerateAndImportBlock(t *testing.T) {
+ t.Parallel()
var (
db = rawdb.NewMemoryDatabase()
config = *params.AllCliqueProtocolChanges
@@ -193,8 +195,8 @@ func TestGenerateAndImportBlock(t *testing.T) {
w.start()
for i := 0; i < 5; i++ {
- b.txPool.Add([]*txpool.Transaction{{Tx: b.newRandomTx(true)}}, true, false)
- b.txPool.Add([]*txpool.Transaction{{Tx: b.newRandomTx(false)}}, true, false)
+ b.txPool.Add([]*types.Transaction{b.newRandomTx(true)}, true, false)
+ b.txPool.Add([]*types.Transaction{b.newRandomTx(false)}, true, false)
select {
case ev := <-sub.Chan():
@@ -209,9 +211,11 @@ func TestGenerateAndImportBlock(t *testing.T) {
}
func TestEmptyWorkEthash(t *testing.T) {
+ t.Parallel()
testEmptyWork(t, ethashChainConfig, ethash.NewFaker())
}
func TestEmptyWorkClique(t *testing.T) {
+ t.Parallel()
testEmptyWork(t, cliqueChainConfig, clique.New(cliqueChainConfig.Clique, rawdb.NewMemoryDatabase()))
}
@@ -224,7 +228,7 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens
taskCh := make(chan struct{}, 2)
checkEqual := func(t *testing.T, task *task) {
// The work should contain 1 tx
- receiptLen, balance := 1, big.NewInt(1000)
+ receiptLen, balance := 1, uint256.NewInt(1000)
if len(task.receipts) != receiptLen {
t.Fatalf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen)
}
@@ -251,14 +255,17 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens
}
func TestGetSealingWorkEthash(t *testing.T) {
+ t.Parallel()
testGetSealingWork(t, ethashChainConfig, ethash.NewFaker())
}
func TestGetSealingWorkClique(t *testing.T) {
+ t.Parallel()
testGetSealingWork(t, cliqueChainConfig, clique.New(cliqueChainConfig.Clique, rawdb.NewMemoryDatabase()))
}
func TestGetSealingWorkPostMerge(t *testing.T) {
+ t.Parallel()
local := new(params.ChainConfig)
*local = *ethashChainConfig
local.TerminalTotalDifficulty = big.NewInt(0)
@@ -357,32 +364,50 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
// This API should work even when the automatic sealing is not enabled
for _, c := range cases {
- block, _, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random, nil, false)
+ r := w.getSealingBlock(&generateParams{
+ parentHash: c.parent,
+ timestamp: timestamp,
+ coinbase: c.coinbase,
+ random: c.random,
+ withdrawals: nil,
+ beaconRoot: nil,
+ noTxs: false,
+ forceTime: true,
+ })
if c.expectErr {
- if err == nil {
+ if r.err == nil {
t.Error("Expect error but get nil")
}
} else {
- if err != nil {
- t.Errorf("Unexpected error %v", err)
+ if r.err != nil {
+ t.Errorf("Unexpected error %v", r.err)
}
- assertBlock(block, c.expectNumber, c.coinbase, c.random)
+ assertBlock(r.block, c.expectNumber, c.coinbase, c.random)
}
}
// This API should work even when the automatic sealing is enabled
w.start()
for _, c := range cases {
- block, _, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random, nil, false)
+ r := w.getSealingBlock(&generateParams{
+ parentHash: c.parent,
+ timestamp: timestamp,
+ coinbase: c.coinbase,
+ random: c.random,
+ withdrawals: nil,
+ beaconRoot: nil,
+ noTxs: false,
+ forceTime: true,
+ })
if c.expectErr {
- if err == nil {
+ if r.err == nil {
t.Error("Expect error but get nil")
}
} else {
- if err != nil {
- t.Errorf("Unexpected error %v", err)
+ if r.err != nil {
+ t.Errorf("Unexpected error %v", r.err)
}
- assertBlock(block, c.expectNumber, c.coinbase, c.random)
+ assertBlock(r.block, c.expectNumber, c.coinbase, c.random)
}
}
}
diff --git a/node/defaults.go b/node/defaults.go
index 4ad89b59e3..8b03e24c28 100644
--- a/node/defaults.go
+++ b/node/defaults.go
@@ -36,6 +36,13 @@ const (
DefaultAuthPort = 8551 // Default port for the authenticated apis
)
+const (
+ // Engine API batch limits: these are not configurable by users, and should cover the
+ // needs of all CLs.
+ engineAPIBatchItemLimit = 2000
+ engineAPIBatchResponseSizeLimit = 250 * 1000 * 1000
+)
+
var (
DefaultAuthCors = []string{"localhost"} // Default cors domain for the authenticated apis
DefaultAuthVhosts = []string{"localhost"} // Default virtual hosts for the authenticated apis
diff --git a/node/node.go b/node/node.go
index 7f8872f9cf..2c8e6f0f88 100644
--- a/node/node.go
+++ b/node/node.go
@@ -123,7 +123,7 @@ func New(conf *Config) (*Node, error) {
maxBackups = *conf.LogConfig.MaxBackups
}
- log.Root().SetHandler(log.NewFileLvlHandler(logFilePath, *conf.LogConfig.MaxBytesSize, maxBackups, *conf.LogConfig.Level, rotateHours))
+ log.SetDefault(log.NewLogger(log.RotatingFileHandler(logFilePath, *conf.LogConfig.MaxBytesSize, maxBackups, *conf.LogConfig.Level, rotateHours)))
}
}
if conf.Logger == nil {
@@ -489,8 +489,11 @@ func (n *Node) startRPC() error {
if err := server.setListenAddr(n.config.AuthAddr, port); err != nil {
return err
}
- sharedConfig := rpcConfig
- sharedConfig.jwtSecret = secret
+ sharedConfig := rpcEndpointConfig{
+ jwtSecret: secret,
+ batchItemLimit: engineAPIBatchItemLimit,
+ batchResponseSizeLimit: engineAPIBatchResponseSizeLimit,
+ }
if err := server.enableRPC(allAPIs, httpConfig{
CorsAllowedOrigins: DefaultAuthCors,
Vhosts: n.config.AuthVirtualHosts,
diff --git a/oss-fuzz.sh b/oss-fuzz.sh
index 745a5ba7c7..8978de70dd 100644
--- a/oss-fuzz.sh
+++ b/oss-fuzz.sh
@@ -1,5 +1,5 @@
-#/bin/bash -eu
-# Copyright 2020 Google Inc.
+#!/bin/bash -eu
+# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,17 +15,6 @@
#
################################################################################
-# This file is for integration with Google OSS-Fuzz.
-# The following ENV variables are available when executing on OSS-fuzz:
-#
-# /out/ $OUT Directory to store build artifacts (fuzz targets, dictionaries, options files, seed corpus archives).
-# /src/ $SRC Directory to checkout source files.
-# /work/ $WORK Directory to store intermediate files.
-#
-# $CC, $CXX, $CCC The C and C++ compiler binaries.
-# $CFLAGS, $CXXFLAGS C and C++ compiler flags.
-# $LIB_FUZZING_ENGINE C++ compiler argument to link fuzz target against the prebuilt engine library (e.g. libFuzzer).
-
# This sets the -coverpgk for the coverage report when the corpus is executed through go test
coverpkg="github.com/ethereum/go-ethereum/..."
@@ -59,26 +48,27 @@ DOG
cd -
}
-function compile_fuzzer {
- # Inputs:
- # $1: The package to fuzz, within go-ethereum
- # $2: The name of the fuzzing function
- # $3: The name to give to the final fuzzing-binary
-
- path=$GOPATH/src/github.com/ethereum/go-ethereum/$1
- func=$2
+function compile_fuzzer() {
+ package=$1
+ function=$2
fuzzer=$3
+ file=$4
+
+ path=$GOPATH/src/$package
echo "Building $fuzzer"
+ cd $path
- # Do a coverage-build or a regular build
- if [[ $SANITIZER = *coverage* ]]; then
- coverbuild $path $func $fuzzer $coverpkg
- else
- (cd $path && \
- go-fuzz -func $func -o $WORK/$fuzzer.a . && \
- $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $WORK/$fuzzer.a -o $OUT/$fuzzer)
- fi
+ # Install build dependencies
+ go mod tidy
+ go get github.com/holiman/gofuzz-shim/testing
+
+ if [[ $SANITIZER == *coverage* ]]; then
+ coverbuild $path $function $fuzzer $coverpkg
+ else
+ gofuzz-shim --func $function --package $package -f $file -o $fuzzer.a
+ $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer
+ fi
## Check if there exists a seed corpus file
corpusfile="${path}/testdata/${fuzzer}_seed_corpus.zip"
@@ -87,43 +77,143 @@ function compile_fuzzer {
cp $corpusfile $OUT/
echo "Found seed corpus: $corpusfile"
fi
+ cd -
}
-compile_fuzzer tests/fuzzers/bitutil Fuzz fuzzBitutilCompress
-compile_fuzzer tests/fuzzers/bn256 FuzzAdd fuzzBn256Add
-compile_fuzzer tests/fuzzers/bn256 FuzzMul fuzzBn256Mul
-compile_fuzzer tests/fuzzers/bn256 FuzzPair fuzzBn256Pair
-compile_fuzzer tests/fuzzers/runtime Fuzz fuzzVmRuntime
-compile_fuzzer tests/fuzzers/keystore Fuzz fuzzKeystore
-compile_fuzzer tests/fuzzers/txfetcher Fuzz fuzzTxfetcher
-compile_fuzzer tests/fuzzers/rlp Fuzz fuzzRlp
-compile_fuzzer tests/fuzzers/trie Fuzz fuzzTrie
-compile_fuzzer tests/fuzzers/stacktrie Fuzz fuzzStackTrie
-compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty
-compile_fuzzer tests/fuzzers/abi Fuzz fuzzAbi
-compile_fuzzer tests/fuzzers/les Fuzz fuzzLes
-compile_fuzzer tests/fuzzers/secp256k1 Fuzz fuzzSecp256k1
-compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool
-
-compile_fuzzer tests/fuzzers/bls12381 FuzzG1Add fuzz_g1_add
-compile_fuzzer tests/fuzzers/bls12381 FuzzG1Mul fuzz_g1_mul
-compile_fuzzer tests/fuzzers/bls12381 FuzzG1MultiExp fuzz_g1_multiexp
-compile_fuzzer tests/fuzzers/bls12381 FuzzG2Add fuzz_g2_add
-compile_fuzzer tests/fuzzers/bls12381 FuzzG2Mul fuzz_g2_mul
-compile_fuzzer tests/fuzzers/bls12381 FuzzG2MultiExp fuzz_g2_multiexp
-compile_fuzzer tests/fuzzers/bls12381 FuzzPairing fuzz_pairing
-compile_fuzzer tests/fuzzers/bls12381 FuzzMapG1 fuzz_map_g1
-compile_fuzzer tests/fuzzers/bls12381 FuzzMapG2 fuzz_map_g2
-
-compile_fuzzer tests/fuzzers/bls12381 FuzzCrossG1Add fuzz_cross_g1_add
-compile_fuzzer tests/fuzzers/bls12381 FuzzCrossG1MultiExp fuzz_cross_g1_multiexp
-compile_fuzzer tests/fuzzers/bls12381 FuzzCrossG2Add fuzz_cross_g2_add
-compile_fuzzer tests/fuzzers/bls12381 FuzzCrossPairing fuzz_cross_pairing
-
-compile_fuzzer tests/fuzzers/snap FuzzARange fuzz_account_range
-compile_fuzzer tests/fuzzers/snap FuzzSRange fuzz_storage_range
-compile_fuzzer tests/fuzzers/snap FuzzByteCodes fuzz_byte_codes
-compile_fuzzer tests/fuzzers/snap FuzzTrieNodes fuzz_trie_nodes
-
-#TODO: move this to tests/fuzzers, if possible
-compile_fuzzer crypto/blake2b Fuzz fuzzBlake2b
+go install github.com/holiman/gofuzz-shim@latest
+repo=$GOPATH/src/github.com/ethereum/go-ethereum
+compile_fuzzer github.com/ethereum/go-ethereum/accounts/abi \
+ FuzzABI fuzzAbi \
+ $repo/accounts/abi/abifuzzer_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/common/bitutil \
+ FuzzEncoder fuzzBitutilEncoder \
+ $repo/common/bitutil/compress_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/common/bitutil \
+ FuzzDecoder fuzzBitutilDecoder \
+ $repo/common/bitutil/compress_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/core/vm/runtime \
+ FuzzVmRuntime fuzzVmRuntime\
+ $repo/core/vm/runtime/runtime_fuzz_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/core/vm \
+ FuzzPrecompiledContracts fuzzPrecompiledContracts\
+ $repo/core/vm/contracts_fuzz_test.go,$repo/core/vm/contracts_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/core/types \
+ FuzzRLP fuzzRlp \
+ $repo/core/types/rlp_fuzzer_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/crypto/blake2b \
+ Fuzz fuzzBlake2b \
+ $repo/crypto/blake2b/blake2b_f_fuzz_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/accounts/keystore \
+ FuzzPassword fuzzKeystore \
+ $repo/accounts/keystore/keystore_fuzzing_test.go
+
+pkg=$repo/trie/
+compile_fuzzer github.com/ethereum/go-ethereum/trie \
+ FuzzTrie fuzzTrie \
+ $pkg/trie_test.go,$pkg/database_test.go,$pkg/tracer_test.go,$pkg/proof_test.go,$pkg/iterator_test.go,$pkg/sync_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/trie \
+ FuzzStackTrie fuzzStackTrie \
+ $pkg/stacktrie_fuzzer_test.go,$pkg/iterator_test.go,$pkg/trie_test.go,$pkg/database_test.go,$pkg/tracer_test.go,$pkg/proof_test.go,$pkg/sync_test.go
+
+#compile_fuzzer tests/fuzzers/snap FuzzARange fuzz_account_range
+compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/snap \
+ FuzzARange fuzz_account_range \
+ $repo/eth/protocols/snap/handler_fuzzing_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/snap \
+ FuzzSRange fuzz_storage_range \
+ $repo/eth/protocols/snap/handler_fuzzing_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/snap \
+ FuzzByteCodes fuzz_byte_codes \
+ $repo/eth/protocols/snap/handler_fuzzing_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/snap \
+ FuzzTrieNodes fuzz_trie_nodes\
+ $repo/eth/protocols/snap/handler_fuzzing_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bn256 \
+ FuzzAdd fuzzBn256Add\
+ $repo/tests/fuzzers/bn256/bn256_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bn256 \
+ FuzzMul fuzzBn256Mul \
+ $repo/tests/fuzzers/bn256/bn256_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bn256 \
+ FuzzPair fuzzBn256Pair \
+ $repo/tests/fuzzers/bn256/bn256_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/txfetcher \
+ Fuzz fuzzTxfetcher \
+ $repo/tests/fuzzers/txfetcher/txfetcher_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzG1Add fuzz_g1_add\
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzG1Mul fuzz_g1_mul\
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzG1MultiExp fuzz_g1_multiexp \
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzG2Add fuzz_g2_add \
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzG2Mul fuzz_g2_mul\
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzG2MultiExp fuzz_g2_multiexp \
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzPairing fuzz_pairing \
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzMapG1 fuzz_map_g1\
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzMapG2 fuzz_map_g2 \
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzCrossG1Add fuzz_cross_g1_add \
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzCrossG1MultiExp fuzz_cross_g1_multiexp \
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzCrossG2Add fuzz_cross_g2_add \
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzCrossPairing fuzz_cross_pairing\
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/secp256k1 \
+ Fuzz fuzzSecp256k1\
+ $repo/tests/fuzzers/secp256k1/secp_test.go
+
+
+#compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool
+#compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty
+#compile_fuzzer tests/fuzzers/les Fuzz fuzzLes
+
diff --git a/p2p/discover/common.go b/p2p/discover/common.go
index e9212026b2..d09479269c 100644
--- a/p2p/discover/common.go
+++ b/p2p/discover/common.go
@@ -23,6 +23,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common/mclock"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
@@ -46,11 +47,9 @@ func ParseEthFilter(chain string) (NodeFilterFunc, error) {
var filter forkid.Filter
switch chain {
case "bsc":
- filter = forkid.NewStaticFilter(params.BSCChainConfig, params.BSCGenesisHash)
+ filter = forkid.NewStaticFilter(params.BSCChainConfig, core.DefaultBSCGenesisBlock().ToBlock())
case "chapel":
- filter = forkid.NewStaticFilter(params.ChapelChainConfig, params.ChapelGenesisHash)
- case "rialto":
- filter = forkid.NewStaticFilter(params.RialtoChainConfig, params.RialtoGenesisHash)
+ filter = forkid.NewStaticFilter(params.ChapelChainConfig, core.DefaultChapelGenesisBlock().ToBlock())
default:
return nil, fmt.Errorf("unknown network %q", chain)
}
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index 5baef9c894..9c1570d51d 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -23,6 +23,7 @@
package discover
import (
+ "context"
crand "crypto/rand"
"encoding/binary"
"fmt"
@@ -351,8 +352,10 @@ func (tab *Table) loadSeedNodes() {
seeds = append(seeds, tab.nursery...)
for i := range seeds {
seed := seeds[i]
- age := log.Lazy{Fn: func() interface{} { return time.Since(tab.db.LastPongReceived(seed.ID(), seed.IP())) }}
- tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", seed.addr(), "age", age)
+ if tab.log.Enabled(context.Background(), log.LevelTrace) {
+ age := time.Since(tab.db.LastPongReceived(seed.ID(), seed.IP()))
+ tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", seed.addr(), "age", age)
+ }
tab.addSeenNode(seed)
}
}
@@ -483,6 +486,26 @@ func (tab *Table) findnodeByID(target enode.ID, nresults int, preferLive bool) *
return nodes
}
+// appendLiveNodes adds nodes at the given distance to the result slice.
+func (tab *Table) appendLiveNodes(dist uint, result []*enode.Node) []*enode.Node {
+ if dist > 256 {
+ return result
+ }
+ if dist == 0 {
+ return append(result, tab.self())
+ }
+
+ tab.mutex.Lock()
+ defer tab.mutex.Unlock()
+ for _, n := range tab.bucketAtDistance(int(dist)).entries {
+ if n.livenessChecks >= 1 {
+ node := n.Node // avoid handing out pointer to struct field
+ result = append(result, &node)
+ }
+ }
+ return result
+}
+
// len returns the number of nodes in the table.
func (tab *Table) len() (n int) {
tab.mutex.Lock()
diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go
index 0729da16e5..ffe055e843 100644
--- a/p2p/discover/table_test.go
+++ b/p2p/discover/table_test.go
@@ -27,6 +27,7 @@ import (
"testing/quick"
"time"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
@@ -202,7 +203,7 @@ func TestTable_findnodeByID(t *testing.T) {
tab, db := newTestTable(transport)
defer db.Close()
defer tab.close()
- fillTable(tab, test.All)
+ fillTable(tab, test.All, true)
// check that closest(Target, N) returns nodes
result := tab.findnodeByID(test.Target, test.N, false).entries
@@ -384,7 +385,7 @@ func TestTable_filterNode(t *testing.T) {
// Check wrong genesis ENR record
var r2 enr.Record
- r2.Set(enr.WithEntry("eth", eth{ForkID: forkid.NewID(params.BSCChainConfig, params.ChapelGenesisHash, uint64(0), uint64(0))}))
+ r2.Set(enr.WithEntry("eth", eth{ForkID: forkid.NewID(params.BSCChainConfig, core.DefaultChapelGenesisBlock().ToBlock(), uint64(0), uint64(0))}))
if enrFilter(&r2) {
t.Fatalf("filterNode doesn't work correctly for wrong genesis entry")
}
@@ -392,7 +393,7 @@ func TestTable_filterNode(t *testing.T) {
// Check correct genesis ENR record
var r3 enr.Record
- r3.Set(enr.WithEntry("eth", eth{ForkID: forkid.NewID(params.BSCChainConfig, params.BSCGenesisHash, uint64(0), uint64(0))}))
+ r3.Set(enr.WithEntry("eth", eth{ForkID: forkid.NewID(params.BSCChainConfig, core.DefaultBSCGenesisBlock().ToBlock(), uint64(0), uint64(0))}))
if !enrFilter(&r3) {
t.Fatalf("filterNode doesn't work correctly for correct genesis entry")
}
diff --git a/p2p/discover/table_util_test.go b/p2p/discover/table_util_test.go
index 5c5b1fa258..0ac25f957c 100644
--- a/p2p/discover/table_util_test.go
+++ b/p2p/discover/table_util_test.go
@@ -110,8 +110,11 @@ func fillBucket(tab *Table, n *node) (last *node) {
// fillTable adds nodes the table to the end of their corresponding bucket
// if the bucket is not full. The caller must not hold tab.mutex.
-func fillTable(tab *Table, nodes []*node) {
+func fillTable(tab *Table, nodes []*node, setLive bool) {
for _, n := range nodes {
+ if setLive {
+ n.livenessChecks = 1
+ }
tab.addSeenNodeSync(n)
}
}
diff --git a/p2p/discover/v4_lookup_test.go b/p2p/discover/v4_lookup_test.go
index 1f9ad69d0a..8867a5a8ac 100644
--- a/p2p/discover/v4_lookup_test.go
+++ b/p2p/discover/v4_lookup_test.go
@@ -40,7 +40,7 @@ func TestUDPv4_Lookup(t *testing.T) {
}
// Seed table with initial node.
- fillTable(test.table, []*node{wrapNode(lookupTestnet.node(256, 0))})
+ fillTable(test.table, []*node{wrapNode(lookupTestnet.node(256, 0))}, true)
// Start the lookup.
resultC := make(chan []*enode.Node, 1)
@@ -74,7 +74,7 @@ func TestUDPv4_LookupIterator(t *testing.T) {
for i := range lookupTestnet.dists[256] {
bootnodes[i] = wrapNode(lookupTestnet.node(256, i))
}
- fillTable(test.table, bootnodes)
+ fillTable(test.table, bootnodes, true)
go serveTestnet(test, lookupTestnet)
// Create the iterator and collect the nodes it yields.
@@ -109,7 +109,7 @@ func TestUDPv4_LookupIteratorClose(t *testing.T) {
for i := range lookupTestnet.dists[256] {
bootnodes[i] = wrapNode(lookupTestnet.node(256, i))
}
- fillTable(test.table, bootnodes)
+ fillTable(test.table, bootnodes, true)
go serveTestnet(test, lookupTestnet)
it := test.udp.RandomNodes()
diff --git a/p2p/discover/v4_udp_test.go b/p2p/discover/v4_udp_test.go
index 5add9cefa1..361e379626 100644
--- a/p2p/discover/v4_udp_test.go
+++ b/p2p/discover/v4_udp_test.go
@@ -269,7 +269,7 @@ func TestUDPv4_findnode(t *testing.T) {
}
nodes.push(n, numCandidates)
}
- fillTable(test.table, nodes.entries)
+ fillTable(test.table, nodes.entries, false)
// ensure there's a bond with the test node,
// findnode won't be accepted otherwise.
@@ -557,12 +557,7 @@ func startLocalhostV4(t *testing.T, cfg Config) *UDPv4 {
// Prefix logs with node ID.
lprefix := fmt.Sprintf("(%s)", ln.ID().TerminalString())
- lfmt := log.TerminalFormat(false)
- cfg.Log = testlog.Logger(t, log.LvlTrace)
- cfg.Log.SetHandler(log.FuncHandler(func(r *log.Record) error {
- t.Logf("%s %s", lprefix, lfmt.Format(r))
- return nil
- }))
+ cfg.Log = testlog.Logger(t, log.LevelTrace).With("node-id", lprefix)
// Listen.
socket, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IP{127, 0, 0, 1}})
diff --git a/p2p/discover/v4wire/v4wire.go b/p2p/discover/v4wire/v4wire.go
index 3935068cd9..9c59359fb2 100644
--- a/p2p/discover/v4wire/v4wire.go
+++ b/p2p/discover/v4wire/v4wire.go
@@ -238,6 +238,8 @@ func Decode(input []byte) (Packet, Pubkey, []byte, error) {
default:
return nil, fromKey, hash, fmt.Errorf("unknown type: %d", ptype)
}
+ // Here we use NewStream to allow for additional data after the first
+ // RLP object (forward-compatibility).
s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0)
err = s.Decode(req)
return req, fromKey, hash, err
diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go
index 6ba7a90618..8b3e33d37c 100644
--- a/p2p/discover/v5_udp.go
+++ b/p2p/discover/v5_udp.go
@@ -851,6 +851,7 @@ func (t *UDPv5) handleFindnode(p *v5wire.Findnode, fromID enode.ID, fromAddr *ne
// collectTableNodes creates a FINDNODE result set for the given distances.
func (t *UDPv5) collectTableNodes(rip net.IP, distances []uint, limit int) []*enode.Node {
+ var bn []*enode.Node
var nodes []*enode.Node
var processed = make(map[uint]struct{})
for _, dist := range distances {
@@ -859,21 +860,11 @@ func (t *UDPv5) collectTableNodes(rip net.IP, distances []uint, limit int) []*en
if seen || dist > 256 {
continue
}
-
- // Get the nodes.
- var bn []*enode.Node
- if dist == 0 {
- bn = []*enode.Node{t.Self()}
- } else if dist <= 256 {
- t.tab.mutex.Lock()
- bn = unwrapNodes(t.tab.bucketAtDistance(int(dist)).entries)
- t.tab.mutex.Unlock()
- }
processed[dist] = struct{}{}
- // Apply some pre-checks to avoid sending invalid nodes.
- for _, n := range bn {
- // TODO livenessChecks > 1
+ for _, n := range t.tab.appendLiveNodes(dist, bn[:0]) {
+ // Apply some pre-checks to avoid sending invalid nodes.
+ // Note liveness is checked by appendLiveNodes.
if netutil.CheckRelayIP(rip, n.IP()) != nil {
continue
}
diff --git a/p2p/discover/v5_udp_test.go b/p2p/discover/v5_udp_test.go
index da09cae0b2..54e84d08b8 100644
--- a/p2p/discover/v5_udp_test.go
+++ b/p2p/discover/v5_udp_test.go
@@ -79,12 +79,7 @@ func startLocalhostV5(t *testing.T, cfg Config) *UDPv5 {
// Prefix logs with node ID.
lprefix := fmt.Sprintf("(%s)", ln.ID().TerminalString())
- lfmt := log.TerminalFormat(false)
- cfg.Log = testlog.Logger(t, log.LvlTrace)
- cfg.Log.SetHandler(log.FuncHandler(func(r *log.Record) error {
- t.Logf("%s %s", lprefix, lfmt.Format(r))
- return nil
- }))
+ cfg.Log = testlog.Logger(t, log.LevelTrace).With("node-id", lprefix)
// Listen.
socket, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IP{127, 0, 0, 1}})
@@ -164,9 +159,9 @@ func TestUDPv5_findnodeHandling(t *testing.T) {
nodes253 := nodesAtDistance(test.table.self().ID(), 253, 16)
nodes249 := nodesAtDistance(test.table.self().ID(), 249, 4)
nodes248 := nodesAtDistance(test.table.self().ID(), 248, 10)
- fillTable(test.table, wrapNodes(nodes253))
- fillTable(test.table, wrapNodes(nodes249))
- fillTable(test.table, wrapNodes(nodes248))
+ fillTable(test.table, wrapNodes(nodes253), true)
+ fillTable(test.table, wrapNodes(nodes249), true)
+ fillTable(test.table, wrapNodes(nodes248), true)
// Requesting with distance zero should return the node's own record.
test.packetIn(&v5wire.Findnode{ReqID: []byte{0}, Distances: []uint{0}})
@@ -594,7 +589,7 @@ func TestUDPv5_lookup(t *testing.T) {
// Seed table with initial node.
initialNode := lookupTestnet.node(256, 0)
- fillTable(test.table, []*node{wrapNode(initialNode)})
+ fillTable(test.table, []*node{wrapNode(initialNode)}, true)
// Start the lookup.
resultC := make(chan []*enode.Node, 1)
diff --git a/p2p/dnsdisc/tree.go b/p2p/dnsdisc/tree.go
index 06b7681f18..7d9703a345 100644
--- a/p2p/dnsdisc/tree.go
+++ b/p2p/dnsdisc/tree.go
@@ -344,11 +344,11 @@ func parseLink(e string) (*linkEntry, error) {
return nil, fmt.Errorf("wrong/missing scheme 'enrtree' in URL")
}
e = e[len(linkPrefix):]
- pos := strings.IndexByte(e, '@')
- if pos == -1 {
+
+ keystring, domain, found := strings.Cut(e, "@")
+ if !found {
return nil, entryError{"link", errNoPubkey}
}
- keystring, domain := e[:pos], e[pos+1:]
keybytes, err := b32format.DecodeString(keystring)
if err != nil {
return nil, entryError{"link", errBadPubkey}
diff --git a/p2p/msgrate/msgrate.go b/p2p/msgrate/msgrate.go
index 4f08792242..de1a3177db 100644
--- a/p2p/msgrate/msgrate.go
+++ b/p2p/msgrate/msgrate.go
@@ -18,6 +18,7 @@
package msgrate
import (
+ "context"
"errors"
"math"
"sort"
@@ -410,7 +411,9 @@ func (t *Trackers) tune() {
t.tuned = time.Now()
t.log.Debug("Recalculated msgrate QoS values", "rtt", t.roundtrip, "confidence", t.confidence, "ttl", t.targetTimeout(), "next", t.tuned.Add(t.roundtrip))
- t.log.Trace("Debug dump of mean capacities", "caps", log.Lazy{Fn: t.meanCapacities})
+ if t.log.Enabled(context.Background(), log.LevelTrace) {
+ t.log.Trace("Debug dump of mean capacities", "caps", t.meanCapacities())
+ }
}
// detune reduces the tracker's confidence in order to make fresh measurements
diff --git a/p2p/nat/nat.go b/p2p/nat/nat.go
index a2b98140fc..46b786a42c 100644
--- a/p2p/nat/nat.go
+++ b/p2p/nat/nat.go
@@ -63,12 +63,12 @@ type Interface interface {
// "pmp:192.168.0.1" uses NAT-PMP with the given gateway address
func Parse(spec string) (Interface, error) {
var (
- parts = strings.SplitN(spec, ":", 2)
- mech = strings.ToLower(parts[0])
- ip net.IP
+ before, after, found = strings.Cut(spec, ":")
+ mech = strings.ToLower(before)
+ ip net.IP
)
- if len(parts) > 1 {
- ip = net.ParseIP(parts[1])
+ if found {
+ ip = net.ParseIP(after)
if ip == nil {
return nil, errors.New("invalid IP address")
}
@@ -88,7 +88,7 @@ func Parse(spec string) (Interface, error) {
case "pmp", "natpmp", "nat-pmp":
return PMP(ip), nil
default:
- return nil, fmt.Errorf("unknown mechanism %q", parts[0])
+ return nil, fmt.Errorf("unknown mechanism %q", before)
}
}
diff --git a/p2p/rlpx/rlpx_test.go b/p2p/rlpx/rlpx_test.go
index 28759f2b49..136cb1b5bf 100644
--- a/p2p/rlpx/rlpx_test.go
+++ b/p2p/rlpx/rlpx_test.go
@@ -421,7 +421,7 @@ func BenchmarkThroughput(b *testing.B) {
}
conn2.SetSnappy(true)
if err := <-handshakeDone; err != nil {
- b.Fatal("server hanshake error:", err)
+ b.Fatal("server handshake error:", err)
}
// Read N messages.
diff --git a/p2p/simulations/adapters/exec.go b/p2p/simulations/adapters/exec.go
index 1d812514de..63cc4936c1 100644
--- a/p2p/simulations/adapters/exec.go
+++ b/p2p/simulations/adapters/exec.go
@@ -34,13 +34,14 @@ import (
"syscall"
"time"
- "github.com/docker/docker/pkg/reexec"
+ "github.com/ethereum/go-ethereum/internal/reexec"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/websocket"
+ "golang.org/x/exp/slog"
)
func init() {
@@ -375,9 +376,11 @@ type execNodeConfig struct {
func initLogging() {
// Initialize the logging by default first.
- glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.LogfmtFormat()))
- glogger.Verbosity(log.LvlInfo)
- log.Root().SetHandler(glogger)
+ var innerHandler slog.Handler
+ innerHandler = slog.NewTextHandler(os.Stderr, nil)
+ glogger := log.NewGlogHandler(innerHandler)
+ glogger.Verbosity(log.LevelInfo)
+ log.SetDefault(log.NewLogger(glogger))
confEnv := os.Getenv(envNodeConfig)
if confEnv == "" {
@@ -395,14 +398,15 @@ func initLogging() {
}
writer = logWriter
}
- var verbosity = log.LvlInfo
- if conf.Node.LogVerbosity <= log.LvlTrace && conf.Node.LogVerbosity >= log.LvlCrit {
- verbosity = conf.Node.LogVerbosity
+ var verbosity = log.LevelInfo
+ if conf.Node.LogVerbosity <= log.LevelTrace && conf.Node.LogVerbosity >= log.LevelCrit {
+ verbosity = log.FromLegacyLevel(int(conf.Node.LogVerbosity))
}
// Reinitialize the logger
- glogger = log.NewGlogHandler(log.StreamHandler(writer, log.TerminalFormat(true)))
+ innerHandler = log.NewTerminalHandler(writer, true)
+ glogger = log.NewGlogHandler(innerHandler)
glogger.Verbosity(verbosity)
- log.Root().SetHandler(glogger)
+ log.SetDefault(log.NewLogger(glogger))
}
// execP2PNode starts a simulation node when the current binary is executed with
diff --git a/p2p/simulations/adapters/types.go b/p2p/simulations/adapters/types.go
index 3b4e05a901..fb8463d221 100644
--- a/p2p/simulations/adapters/types.go
+++ b/p2p/simulations/adapters/types.go
@@ -25,8 +25,8 @@ import (
"os"
"strconv"
- "github.com/docker/docker/pkg/reexec"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/internal/reexec"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/websocket"
+ "golang.org/x/exp/slog"
)
// Node represents a node in a simulation network which is created by a
@@ -129,7 +130,7 @@ type NodeConfig struct {
// LogVerbosity is the log verbosity of the p2p node at runtime.
//
// The default verbosity is INFO.
- LogVerbosity log.Lvl
+ LogVerbosity slog.Level
}
// nodeConfigJSON is used to encode and decode NodeConfig as JSON by encoding
@@ -197,7 +198,7 @@ func (n *NodeConfig) UnmarshalJSON(data []byte) error {
n.Port = confJSON.Port
n.EnableMsgEvents = confJSON.EnableMsgEvents
n.LogFile = confJSON.LogFile
- n.LogVerbosity = log.Lvl(confJSON.LogVerbosity)
+ n.LogVerbosity = slog.Level(confJSON.LogVerbosity)
return nil
}
diff --git a/p2p/simulations/examples/ping-pong.go b/p2p/simulations/examples/ping-pong.go
index ad14052ad3..f093c9a98b 100644
--- a/p2p/simulations/examples/ping-pong.go
+++ b/p2p/simulations/examples/ping-pong.go
@@ -42,7 +42,7 @@ func main() {
flag.Parse()
// set the log level to Trace
- log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, false)))
// register a single ping-pong service
services := map[string]adapters.LifecycleConstructor{
diff --git a/p2p/simulations/http.go b/p2p/simulations/http.go
index 7a4f70e9b0..34521b4778 100644
--- a/p2p/simulations/http.go
+++ b/p2p/simulations/http.go
@@ -479,12 +479,12 @@ func (s *Server) StreamNetworkEvents(w http.ResponseWriter, req *http.Request) {
func NewMsgFilters(filterParam string) (MsgFilters, error) {
filters := make(MsgFilters)
for _, filter := range strings.Split(filterParam, "-") {
- protoCodes := strings.SplitN(filter, ":", 2)
- if len(protoCodes) != 2 || protoCodes[0] == "" || protoCodes[1] == "" {
+ proto, codes, found := strings.Cut(filter, ":")
+ if !found || proto == "" || codes == "" {
return nil, fmt.Errorf("invalid message filter: %s", filter)
}
- proto := protoCodes[0]
- for _, code := range strings.Split(protoCodes[1], ",") {
+
+ for _, code := range strings.Split(codes, ",") {
if code == "*" || code == "-1" {
filters[MsgFilter{Proto: proto, Code: -1}] = struct{}{}
continue
diff --git a/p2p/simulations/http_test.go b/p2p/simulations/http_test.go
index 05e43238ab..c53a49797b 100644
--- a/p2p/simulations/http_test.go
+++ b/p2p/simulations/http_test.go
@@ -37,14 +37,14 @@ import (
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
"github.com/ethereum/go-ethereum/rpc"
"github.com/mattn/go-colorable"
+ "golang.org/x/exp/slog"
)
func TestMain(m *testing.M) {
loglevel := flag.Int("loglevel", 2, "verbosity of logs")
flag.Parse()
- log.PrintOrigins(true)
- log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(colorable.NewColorableStderr(), slog.Level(*loglevel), true)))
os.Exit(m.Run())
}
diff --git a/p2p/simulations/network_test.go b/p2p/simulations/network_test.go
index ab8cf19462..4ed1e4e6c3 100644
--- a/p2p/simulations/network_test.go
+++ b/p2p/simulations/network_test.go
@@ -683,7 +683,7 @@ func triggerChecks(ctx context.Context, ids []enode.ID, trigger chan enode.ID, i
}
}
-// \todo: refactor to implement shapshots
+// \todo: refactor to implement snapshots
// and connect configuration methods once these are moved from
// swarm/network/simulations/connect.go
func BenchmarkMinimalService(b *testing.B) {
diff --git a/params/bootnodes.go b/params/bootnodes.go
index 25f5ec8750..06e762450f 100644
--- a/params/bootnodes.go
+++ b/params/bootnodes.go
@@ -32,20 +32,25 @@ var MainnetBootnodes = []string{
var V5Bootnodes = []string{
// Teku team's bootnode
- "enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA",
- "enr:-KG4QDyytgmE4f7AnvW-ZaUOIi9i79qX4JwjRAiXBZCU65wOfBu-3Nb5I7b_Rmg3KCOcZM_C3y5pg7EBU5XGrcLTduQEhGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaEDKnz_-ps3UUOfHWVYaskI5kWYO_vtYMGYCQRAR3gHDouDdGNwgiMog3VkcIIjKA",
+ "enr:-KG4QMOEswP62yzDjSwWS4YEjtTZ5PO6r65CPqYBkgTTkrpaedQ8uEUo1uMALtJIvb2w_WWEVmg5yt1UAuK1ftxUU7QDhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQEnfA2iXNlY3AyNTZrMaEDfol8oLr6XJ7FsdAYE7lpJhKMls4G_v6qQOGKJUWGb_uDdGNwgiMog3VkcIIjKA", // # 4.157.240.54 | azure-us-east-virginia
+ "enr:-KG4QF4B5WrlFcRhUU6dZETwY5ZzAXnA0vGC__L1Kdw602nDZwXSTs5RFXFIFUnbQJmhNGVU6OIX7KVrCSTODsz1tK4DhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQExNYEiXNlY3AyNTZrMaECQmM9vp7KhaXhI-nqL_R0ovULLCFSFTa9CPPSdb1zPX6DdGNwgiMog3VkcIIjKA", // 4.196.214.4 | azure-au-east-sydney
// Prylab team's bootnodes
- "enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg",
- "enr:-Ku4QP2xDnEtUXIjzJ_DhlCRN9SN99RYQPJL92TMlSv7U5C1YnYLjwOQHgZIUXw6c-BvRg2Yc2QsZxxoS_pPRVe0yK8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMeFF5GrS7UZpAH2Ly84aLK-TyvH-dRo0JM1i8yygH50YN1ZHCCJxA",
- "enr:-Ku4QPp9z1W4tAO8Ber_NQierYaOStqhDqQdOPY3bB3jDgkjcbk6YrEnVYIiCBbTxuar3CzS528d2iE7TdJsrL-dEKoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMw5fqqkw2hHC4F5HZZDPsNmPdB1Gi8JPQK7pRc9XHh-oN1ZHCCKvg",
+ "enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg", // 18.223.219.100 | aws-us-east-2-ohio
+ "enr:-Ku4QP2xDnEtUXIjzJ_DhlCRN9SN99RYQPJL92TMlSv7U5C1YnYLjwOQHgZIUXw6c-BvRg2Yc2QsZxxoS_pPRVe0yK8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMeFF5GrS7UZpAH2Ly84aLK-TyvH-dRo0JM1i8yygH50YN1ZHCCJxA", // 18.223.219.100 | aws-us-east-2-ohio
+ "enr:-Ku4QPp9z1W4tAO8Ber_NQierYaOStqhDqQdOPY3bB3jDgkjcbk6YrEnVYIiCBbTxuar3CzS528d2iE7TdJsrL-dEKoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMw5fqqkw2hHC4F5HZZDPsNmPdB1Gi8JPQK7pRc9XHh-oN1ZHCCKvg", // 18.223.219.100 | aws-us-east-2-ohio
// Lighthouse team's bootnodes
- "enr:-IS4QLkKqDMy_ExrpOEWa59NiClemOnor-krjp4qoeZwIw2QduPC-q7Kz4u1IOWf3DDbdxqQIgC4fejavBOuUPy-HE4BgmlkgnY0gmlwhCLzAHqJc2VjcDI1NmsxoQLQSJfEAHZApkm5edTCZ_4qps_1k_ub2CxHFxi-gr2JMIN1ZHCCIyg",
- "enr:-IS4QDAyibHCzYZmIYZCjXwU9BqpotWmv2BsFlIq1V31BwDDMJPFEbox1ijT5c2Ou3kvieOKejxuaCqIcjxBjJ_3j_cBgmlkgnY0gmlwhAMaHiCJc2VjcDI1NmsxoQJIdpj_foZ02MXz4It8xKD7yUHTBx7lVFn3oeRP21KRV4N1ZHCCIyg",
+ "enr:-Le4QPUXJS2BTORXxyx2Ia-9ae4YqA_JWX3ssj4E_J-3z1A-HmFGrU8BpvpqhNabayXeOZ2Nq_sbeDgtzMJpLLnXFgAChGV0aDKQtTA_KgEAAAAAIgEAAAAAAIJpZIJ2NIJpcISsaa0Zg2lwNpAkAIkHAAAAAPA8kv_-awoTiXNlY3AyNTZrMaEDHAD2JKYevx89W0CcFJFiskdcEzkH_Wdv9iW42qLK79ODdWRwgiMohHVkcDaCI4I", // 172.105.173.25 | linode-au-sydney
+ "enr:-Le4QLHZDSvkLfqgEo8IWGG96h6mxwe_PsggC20CL3neLBjfXLGAQFOPSltZ7oP6ol54OvaNqO02Rnvb8YmDR274uq8ChGV0aDKQtTA_KgEAAAAAIgEAAAAAAIJpZIJ2NIJpcISLosQxg2lwNpAqAX4AAAAAAPA8kv_-ax65iXNlY3AyNTZrMaEDBJj7_dLFACaxBfaI8KZTh_SSJUjhyAyfshimvSqo22WDdWRwgiMohHVkcDaCI4I", // 139.162.196.49 | linode-uk-london
+ "enr:-Le4QH6LQrusDbAHPjU_HcKOuMeXfdEB5NJyXgHWFadfHgiySqeDyusQMvfphdYWOzuSZO9Uq2AMRJR5O4ip7OvVma8BhGV0aDKQtTA_KgEAAAAAIgEAAAAAAIJpZIJ2NIJpcISLY9ncg2lwNpAkAh8AgQIBAAAAAAAAAAmXiXNlY3AyNTZrMaECDYCZTZEksF-kmgPholqgVt8IXr-8L7Nu7YrZ7HUpgxmDdWRwgiMohHVkcDaCI4I", // 139.99.217.220 | ovh-au-sydney
+ "enr:-Le4QIqLuWybHNONr933Lk0dcMmAB5WgvGKRyDihy1wHDIVlNuuztX62W51voT4I8qD34GcTEOTmag1bcdZ_8aaT4NUBhGV0aDKQtTA_KgEAAAAAIgEAAAAAAIJpZIJ2NIJpcISLY04ng2lwNpAkAh8AgAIBAAAAAAAAAA-fiXNlY3AyNTZrMaEDscnRV6n1m-D9ID5UsURk0jsoKNXt1TIrj8uKOGW6iluDdWRwgiMohHVkcDaCI4I", // 139.99.78.39 | ovh-singapore
// EF bootnodes
- "enr:-Ku4QHqVeJ8PPICcWk1vSn_XcSkjOkNiTg6Fmii5j6vUQgvzMc9L1goFnLKgXqBJspJjIsB91LTOleFmyWWrFVATGngBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAMRHkWJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyg",
- "enr:-Ku4QG-2_Md3sZIAUebGYT6g0SMskIml77l6yR-M_JXc-UdNHCmHQeOiMLbylPejyJsdAPsTHJyjJB2sYGDLe0dn8uYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhBLY-NyJc2VjcDI1NmsxoQORcM6e19T1T9gi7jxEZjk_sjVLGFscUNqAY9obgZaxbIN1ZHCCIyg",
- "enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg",
- "enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg",
+ "enr:-Ku4QHqVeJ8PPICcWk1vSn_XcSkjOkNiTg6Fmii5j6vUQgvzMc9L1goFnLKgXqBJspJjIsB91LTOleFmyWWrFVATGngBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAMRHkWJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyg", // 3.17.30.69 | aws-us-east-2-ohio
+ "enr:-Ku4QG-2_Md3sZIAUebGYT6g0SMskIml77l6yR-M_JXc-UdNHCmHQeOiMLbylPejyJsdAPsTHJyjJB2sYGDLe0dn8uYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhBLY-NyJc2VjcDI1NmsxoQORcM6e19T1T9gi7jxEZjk_sjVLGFscUNqAY9obgZaxbIN1ZHCCIyg", // 18.216.248.220 | aws-us-east-2-ohio
+ "enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg", // 54.178.44.198 | aws-ap-northeast-1-tokyo
+ "enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg", // 54.65.172.253 | aws-ap-northeast-1-tokyo
+ // Nimbus team's bootnodes
+ "enr:-LK4QA8FfhaAjlb_BXsXxSfiysR7R52Nhi9JBt4F8SPssu8hdE1BXQQEtVDC3qStCW60LSO7hEsVHv5zm8_6Vnjhcn0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAN4aBKJc2VjcDI1NmsxoQJerDhsJ-KxZ8sHySMOCmTO6sHM3iCFQ6VMvLTe948MyYN0Y3CCI4yDdWRwgiOM", // 3.120.104.18 | aws-eu-central-1-frankfurt
+ "enr:-LK4QKWrXTpV9T78hNG6s8AM6IO4XH9kFT91uZtFg1GcsJ6dKovDOr1jtAAFPnS2lvNltkOGA9k29BUN7lFh_sjuc9QBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhANAdd-Jc2VjcDI1NmsxoQLQa6ai7y9PMN5hpLe5HmiJSlYzMuzP7ZhwRiwHvqNXdoN0Y3CCI4yDdWRwgiOM", // 3.64.117.223 | aws-eu-central-1-frankfurt}
}
const dnsPrefix = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@"
diff --git a/params/config.go b/params/config.go
index 2aad8f1d71..1e460f0745 100644
--- a/params/config.go
+++ b/params/config.go
@@ -21,6 +21,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/params/forks"
)
// Genesis hashes to enforce below configs on.
@@ -65,53 +66,54 @@ var (
ShanghaiTime: newUint64(1681338455),
Ethash: new(EthashConfig),
}
-
- // just for prysm compile pass
// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
SepoliaChainConfig = &ChainConfig{
- ChainID: big.NewInt(11155111),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: true,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- IstanbulBlock: big.NewInt(0),
- MuirGlacierBlock: big.NewInt(0),
- BerlinBlock: big.NewInt(0),
- MirrorSyncBlock: big.NewInt(0),
- BrunoBlock: big.NewInt(0),
- EulerBlock: big.NewInt(0),
- LondonBlock: big.NewInt(0),
- Ethash: new(EthashConfig),
+ ChainID: big.NewInt(11155111),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: nil,
+ GrayGlacierBlock: nil,
+ TerminalTotalDifficulty: big.NewInt(17_000_000_000_000_000),
+ TerminalTotalDifficultyPassed: true,
+ MergeNetsplitBlock: big.NewInt(1735371),
+ ShanghaiTime: newUint64(1677557088),
+ CancunTime: newUint64(1706655072),
+ Ethash: new(EthashConfig),
}
// just for prysm compile pass
// GoerliChainConfig contains the chain parameters to run a node on the Görli test network.
GoerliChainConfig = &ChainConfig{
- ChainID: big.NewInt(5),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: nil,
- DAOForkSupport: true,
- EIP150Block: big.NewInt(0),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- RamanujanBlock: big.NewInt(0),
- NielsBlock: big.NewInt(0),
- MirrorSyncBlock: big.NewInt(0),
- BrunoBlock: big.NewInt(0),
- EulerBlock: big.NewInt(0),
- IstanbulBlock: big.NewInt(1_561_651),
- MuirGlacierBlock: nil,
- BerlinBlock: big.NewInt(4_460_644),
- LondonBlock: big.NewInt(5_062_605),
- ArrowGlacierBlock: nil,
+ ChainID: big.NewInt(5),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(1_561_651),
+ MuirGlacierBlock: nil,
+ BerlinBlock: big.NewInt(4_460_644),
+ LondonBlock: big.NewInt(5_062_605),
+ ArrowGlacierBlock: nil,
+ TerminalTotalDifficulty: big.NewInt(10_790_000),
+ TerminalTotalDifficultyPassed: true,
+ ShanghaiTime: newUint64(1678832736),
+ CancunTime: newUint64(1705473120),
Clique: &CliqueConfig{
Period: 15,
Epoch: 30000,
@@ -148,6 +150,9 @@ var (
ShanghaiTime: newUint64(1705996800),
KeplerTime: newUint64(1705996800),
+ // TODO
+ FeynmanTime: nil,
+
Parlia: &ParliaConfig{
Period: 3,
Epoch: 200,
@@ -183,6 +188,7 @@ var (
// UnixTime: 1702972800 is December 19, 2023 8:00:00 AM UTC
ShanghaiTime: newUint64(1702972800),
KeplerTime: newUint64(1702972800),
+ FeynmanTime: newUint64(1710136800),
Parlia: &ParliaConfig{
Period: 3,
@@ -219,6 +225,7 @@ var (
HertzfixBlock: big.NewInt(8),
ShanghaiTime: newUint64(0),
KeplerTime: newUint64(0),
+ FeynmanTime: newUint64(0),
Parlia: &ParliaConfig{
Period: 3,
@@ -306,7 +313,6 @@ var (
ShanghaiTime: newUint64(0),
TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true,
- IsDevMode: true,
}
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
@@ -340,7 +346,7 @@ var (
}
// TestChainConfig contains every protocol change (EIPs) introduced
- // and accepted by the Ethereum core developers for testing proposes.
+ // and accepted by the Ethereum core developers for testing purposes.
TestChainConfig = &ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
@@ -369,6 +375,36 @@ var (
Clique: nil,
}
+ // MergedTestChainConfig contains every protocol change (EIPs) introduced
+ // and accepted by the Ethereum core developers for testing purposes.
+ MergedTestChainConfig = &ChainConfig{
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: big.NewInt(0),
+ GrayGlacierBlock: big.NewInt(0),
+ MergeNetsplitBlock: big.NewInt(0),
+ ShanghaiTime: newUint64(0),
+ CancunTime: newUint64(0),
+ PragueTime: nil,
+ VerkleTime: nil,
+ TerminalTotalDifficulty: big.NewInt(0),
+ TerminalTotalDifficultyPassed: true,
+ Ethash: new(EthashConfig),
+ Clique: nil,
+ }
+
// NonActivatedConfig defines the chain configuration without activating
// any protocol change (EIPs).
NonActivatedConfig = &ChainConfig{
@@ -454,11 +490,12 @@ type ChainConfig struct {
// Fork scheduling was switched from blocks to timestamps here
- ShanghaiTime *uint64 `json:"shanghaiTime,omitempty" ` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
- KeplerTime *uint64 `json:"keplerTime,omitempty"` // Kepler switch time (nil = no fork, 0 = already activated)
- CancunTime *uint64 `json:"cancunTime,omitempty" ` // Cancun switch time (nil = no fork, 0 = already on cancun)
- PragueTime *uint64 `json:"pragueTime,omitempty" ` // Prague switch time (nil = no fork, 0 = already on prague)
- VerkleTime *uint64 `json:"verkleTime,omitempty" ` // Verkle switch time (nil = no fork, 0 = already on verkle)
+ ShanghaiTime *uint64 `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
+ KeplerTime *uint64 `json:"keplerTime,omitempty"` // Kepler switch time (nil = no fork, 0 = already activated)
+ FeynmanTime *uint64 `json:"feynmanTime,omitempty"` // Feynman switch time (nil = no fork, 0 = already activated)
+ CancunTime *uint64 `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun)
+ PragueTime *uint64 `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague)
+ VerkleTime *uint64 `json:"verkleTime,omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle)
// TerminalTotalDifficulty is the amount of total difficulty reached by
// the network that triggers the consensus upgrade.
@@ -483,10 +520,9 @@ type ChainConfig struct {
HertzBlock *big.Int `json:"hertzBlock,omitempty"` // hertzBlock switch block (nil = no fork, 0 = already activated)
HertzfixBlock *big.Int `json:"hertzfixBlock,omitempty"` // hertzfixBlock switch block (nil = no fork, 0 = already activated)
// Various consensus engines
- Ethash *EthashConfig `json:"ethash,omitempty"`
- Clique *CliqueConfig `json:"clique,omitempty"`
- Parlia *ParliaConfig `json:"parlia,omitempty"`
- IsDevMode bool `json:"isDev,omitempty"`
+ Ethash *EthashConfig `json:"ethash,omitempty"`
+ Clique *CliqueConfig `json:"clique,omitempty"`
+ Parlia *ParliaConfig `json:"parlia,omitempty"`
}
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
@@ -548,7 +584,12 @@ func (c *ChainConfig) String() string {
KeplerTime = big.NewInt(0).SetUint64(*c.KeplerTime)
}
- return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Hertz: %v, Hertzfix: %v, ShanghaiTime: %v, KeplerTime: %v, Engine: %v}",
+ var FeynmanTime *big.Int
+ if c.FeynmanTime != nil {
+ FeynmanTime = big.NewInt(0).SetUint64(*c.FeynmanTime)
+ }
+
+ return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Hertz: %v, Hertzfix: %v, ShanghaiTime: %v, KeplerTime: %v, FeynmanTime: %v, Engine: %v}",
c.ChainID,
c.HomesteadBlock,
c.DAOForkBlock,
@@ -582,6 +623,7 @@ func (c *ChainConfig) String() string {
c.HertzfixBlock,
ShanghaiTime,
KeplerTime,
+ FeynmanTime,
engine,
)
}
@@ -816,6 +858,20 @@ func (c *ChainConfig) IsOnKepler(currentBlockNumber *big.Int, lastBlockTime uint
return !c.IsKepler(lastBlockNumber, lastBlockTime) && c.IsKepler(currentBlockNumber, currentBlockTime)
}
+// IsFeynman returns whether time is either equal to the Feynman fork time or greater.
+func (c *ChainConfig) IsFeynman(num *big.Int, time uint64) bool {
+ return c.IsLondon(num) && isTimestampForked(c.FeynmanTime, time)
+}
+
+// IsOnFeynman returns whether currentBlockTime is either equal to the Feynman fork time or greater firstly.
+func (c *ChainConfig) IsOnFeynman(currentBlockNumber *big.Int, lastBlockTime uint64, currentBlockTime uint64) bool {
+ lastBlockNumber := new(big.Int)
+ if currentBlockNumber.Cmp(big.NewInt(1)) >= 0 {
+ lastBlockNumber.Sub(currentBlockNumber, big.NewInt(1))
+ }
+ return !c.IsFeynman(lastBlockNumber, lastBlockTime) && c.IsFeynman(currentBlockNumber, currentBlockTime)
+}
+
// IsCancun returns whether num is either equal to the Cancun fork time or greater.
func (c *ChainConfig) IsCancun(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.CancunTime, time)
@@ -881,6 +937,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
{name: "hertzBlock", block: c.HertzBlock},
{name: "hertzfixBlock", block: c.HertzfixBlock},
{name: "keplerTime", timestamp: c.KeplerTime},
+ {name: "feynmanTime", timestamp: c.FeynmanTime},
{name: "cancunTime", timestamp: c.CancunTime, optional: true},
{name: "pragueTime", timestamp: c.PragueTime, optional: true},
{name: "verkleTime", timestamp: c.VerkleTime, optional: true},
@@ -1020,6 +1077,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int,
if isForkTimestampIncompatible(c.KeplerTime, newcfg.KeplerTime, headTimestamp) {
return newTimestampCompatError("Kepler fork timestamp", c.KeplerTime, newcfg.KeplerTime)
}
+ if isForkTimestampIncompatible(c.FeynmanTime, newcfg.FeynmanTime, headTimestamp) {
+ return newTimestampCompatError("Feynman fork timestamp", c.FeynmanTime, newcfg.FeynmanTime)
+ }
if isForkTimestampIncompatible(c.CancunTime, newcfg.CancunTime, headTimestamp) {
return newTimestampCompatError("Cancun fork timestamp", c.CancunTime, newcfg.CancunTime)
}
@@ -1042,6 +1102,24 @@ func (c *ChainConfig) ElasticityMultiplier() uint64 {
return DefaultElasticityMultiplier
}
+// LatestFork returns the latest time-based fork that would be active for the given time.
+// only include forks from ethereum
+func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
+ // Assume last non-time-based fork has passed.
+ london := c.LondonBlock
+
+ switch {
+ case c.IsPrague(london, time):
+ return forks.Prague
+ case c.IsCancun(london, time):
+ return forks.Cancun
+ case c.IsShanghai(london, time):
+ return forks.Shanghai
+ default:
+ return forks.Paris
+ }
+}
+
// isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be
// rescheduled to block s2 because head is already past the fork.
func isForkBlockIncompatible(s1, s2, head *big.Int) bool {
@@ -1181,7 +1259,7 @@ type Rules struct {
IsPlato bool
IsHertz bool
IsHertzfix bool
- IsShanghai, IsKepler, IsCancun, IsPrague bool
+ IsShanghai, IsKepler, IsFeynman, IsCancun, IsPrague bool
IsVerkle bool
}
@@ -1213,6 +1291,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsHertzfix: c.IsHertzfix(num),
IsShanghai: c.IsShanghai(num, timestamp),
IsKepler: c.IsKepler(num, timestamp),
+ IsFeynman: c.IsFeynman(num, timestamp),
IsCancun: c.IsCancun(num, timestamp),
IsPrague: c.IsPrague(num, timestamp),
IsVerkle: c.IsVerkle(num, timestamp),
diff --git a/params/forks/forks.go b/params/forks/forks.go
new file mode 100644
index 0000000000..4f50ff5aed
--- /dev/null
+++ b/params/forks/forks.go
@@ -0,0 +1,42 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package forks
+
+// Fork is a numerical identifier of specific network upgrades (forks).
+type Fork int
+
+const (
+ Frontier = iota
+ FrontierThawing
+ Homestead
+ DAO
+ TangerineWhistle
+ SpuriousDragon
+ Byzantium
+ Constantinople
+ Petersburg
+ Istanbul
+ MuirGlacier
+ Berlin
+ London
+ ArrowGlacier
+ GrayGlacier
+ Paris
+ Shanghai
+ Cancun
+ Prague
+)
diff --git a/params/protocol_params.go b/params/protocol_params.go
index 05b4ff907c..b84fa148fc 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -16,7 +16,11 @@
package params
-import "math/big"
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+)
const (
GasLimitBoundDivisor uint64 = 256 // The bound divisor of the gas limit, used in update calculations.
@@ -24,19 +28,19 @@ const (
MaxGasLimit uint64 = 0x7fffffffffffffff // Maximum the gas limit (2^63-1).
GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block.
- MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis.
- ForkIDSize uint64 = 4 // The length of fork id
- ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction.
- SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
- CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero.
- CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior.
- TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
- SystemTxsGas uint64 = 5000000 // The gas reserved for system txs; only for parlia consensus
- TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions.
- TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
- QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation.
- LogDataGas uint64 = 8 // Per byte in a LOG* operation's data.
- CallStipend uint64 = 2300 // Free gas given at beginning of call.
+ MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis.
+ ForkIDSize uint64 = 4 // The length of fork id
+ ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction.
+ SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
+ CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero.
+ CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior.
+ TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
+ SystemTxsGas uint64 = 20000000 // The gas reserved for system txs; only for parlia consensus
+ TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions.
+ TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
+ QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation.
+ LogDataGas uint64 = 8 // Per byte in a LOG* operation's data.
+ CallStipend uint64 = 2300 // Free gas given at beginning of call.
Keccak256Gas uint64 = 30 // Once per KECCAK256 operation.
Keccak256WordGas uint64 = 6 // Once per word of the KECCAK256 operation's data.
@@ -122,9 +126,10 @@ const (
// Introduced in Tangerine Whistle (Eip 150)
CreateBySelfdestructGas uint64 = 25000
- DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks.
- DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
- InitialBaseFee = 0 // Initial base fee for EIP-1559 blocks.
+ DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks.
+ DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
+ InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks.
+ InitialBaseFeeForBSC = 0 // Initial base fee for EIP-1559 blocks on bsc Mainnet
MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions
@@ -135,15 +140,16 @@ const (
IAVLMerkleProofValidateGas uint64 = 3000 // Gas for validate merkle proof
CometBFTLightBlockValidateGas uint64 = 3000 // Gas for validate cometBFT light block
- EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price
- Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation
- Sha256PerWordGas uint64 = 12 // Per-word price for a SHA256 operation
- Ripemd160BaseGas uint64 = 600 // Base price for a RIPEMD160 operation
- Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation
- IdentityBaseGas uint64 = 15 // Base price for a data copy operation
- IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation
- BlsSignatureVerifyBaseGas uint64 = 1000 // base price for a BLS signature verify operation
- BlsSignatureVerifyPerKeyGas uint64 = 3500 // Per-key price for a BLS signature verify operation
+ EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price
+ Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation
+ Sha256PerWordGas uint64 = 12 // Per-word price for a SHA256 operation
+ Ripemd160BaseGas uint64 = 600 // Base price for a RIPEMD160 operation
+ Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation
+ IdentityBaseGas uint64 = 15 // Base price for a data copy operation
+ IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation
+ BlsSignatureVerifyBaseGas uint64 = 1000 // base price for a BLS signature verify operation
+ BlsSignatureVerifyPerKeyGas uint64 = 3500 // Per-key price for a BLS signature verify operation
+ DoubleSignEvidenceVerifyGas uint64 = 10000 // Gas for verify double sign evidence
Bn256AddGasByzantium uint64 = 500 // Byzantium gas needed for an elliptic curve addition
Bn256AddGasIstanbul uint64 = 150 // Gas needed for an elliptic curve addition
@@ -170,16 +176,13 @@ const (
BlobTxBytesPerFieldElement = 32 // Size in bytes of a field element
BlobTxFieldElementsPerBlob = 4096 // Number of field elements stored in a single data blob
- BlobTxHashVersion = 0x01 // Version byte of the commitment hash
- BlobTxMaxBlobGasPerBlock = 1 << 19 // Maximum consumable blob gas for data blobs per block
- BlobTxTargetBlobGasPerBlock = 1 << 18 // Target consumable blob gas for data blobs per block (for 1559-like pricing)
BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)
BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs
- BlobTxBlobGaspriceUpdateFraction = 2225652 // Controls the maximum rate of change for blob gas price
+ BlobTxBlobGaspriceUpdateFraction = 3338477 // Controls the maximum rate of change for blob gas price
BlobTxPointEvaluationPrecompileGas = 50000 // Gas price for the point evaluation precompile.
- // used for test
- InitialBaseFeeForEthMainnet = int64(1000000000) // Initial base fee for EIP-1559 blocks on Eth hMainnet
+ BlobTxTargetBlobGasPerBlock = 3 * BlobTxBlobGasPerBlob // Target consumable blob gas for data blobs per block (for 1559-like pricing)
+ MaxBlobGasPerBlock = 6 * BlobTxBlobGasPerBlob // Maximum consumable blob gas for data blobs per block
)
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations
@@ -190,4 +193,9 @@ var (
GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
+
+ // BeaconRootsStorageAddress is the address where historical beacon roots are stored as per EIP-4788
+ BeaconRootsStorageAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
+ // SystemAddress is where the system-transaction is sent from as per EIP-4788
+ SystemAddress common.Address = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
)
diff --git a/params/version.go b/params/version.go
index 344df6518a..4907e06837 100644
--- a/params/version.go
+++ b/params/version.go
@@ -22,8 +22,8 @@ import (
const (
VersionMajor = 1 // Major version component of the current release
- VersionMinor = 3 // Minor version component of the current release
- VersionPatch = 8 // Patch version component of the current release
+ VersionMinor = 4 // Minor version component of the current release
+ VersionPatch = 0 // Patch version component of the current release
VersionMeta = "" // Version metadata to append to the version string
)
diff --git a/rlp/decode.go b/rlp/decode.go
index c9b50e8c18..9b17d2d810 100644
--- a/rlp/decode.go
+++ b/rlp/decode.go
@@ -90,7 +90,7 @@ func Decode(r io.Reader, val interface{}) error {
// DecodeBytes parses RLP data from b into val. Please see package-level documentation for
// the decoding rules. The input must contain exactly one value and no trailing data.
func DecodeBytes(b []byte, val interface{}) error {
- r := bytes.NewReader(b)
+ r := (*sliceReader)(&b)
stream := streamPool.Get().(*Stream)
defer streamPool.Put(stream)
@@ -99,7 +99,7 @@ func DecodeBytes(b []byte, val interface{}) error {
if err := stream.Decode(val); err != nil {
return err
}
- if r.Len() > 0 {
+ if len(b) > 0 {
return ErrMoreThanOneValue
}
return nil
@@ -1182,3 +1182,23 @@ func (s *Stream) listLimit() (inList bool, limit uint64) {
}
return true, s.stack[len(s.stack)-1]
}
+
+type sliceReader []byte
+
+func (sr *sliceReader) Read(b []byte) (int, error) {
+ if len(*sr) == 0 {
+ return 0, io.EOF
+ }
+ n := copy(b, *sr)
+ *sr = (*sr)[n:]
+ return n, nil
+}
+
+func (sr *sliceReader) ReadByte() (byte, error) {
+ if len(*sr) == 0 {
+ return 0, io.EOF
+ }
+ b := (*sr)[0]
+ *sr = (*sr)[1:]
+ return b, nil
+}
diff --git a/rlp/rlpgen/main.go b/rlp/rlpgen/main.go
index 25d4393cc6..b3a74b9df1 100644
--- a/rlp/rlpgen/main.go
+++ b/rlp/rlpgen/main.go
@@ -73,9 +73,8 @@ type Config struct {
func (cfg *Config) process() (code []byte, err error) {
// Load packages.
pcfg := &packages.Config{
- Mode: packages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps,
- Dir: cfg.Dir,
- BuildFlags: []string{"-tags", "norlpgen"},
+ Mode: packages.NeedName | packages.NeedTypes,
+ Dir: cfg.Dir,
}
ps, err := packages.Load(pcfg, pathOfPackageRLP, ".")
if err != nil {
@@ -117,8 +116,6 @@ func (cfg *Config) process() (code []byte, err error) {
// This is done here to avoid processing these lines with gofmt.
var header bytes.Buffer
fmt.Fprint(&header, "// Code generated by rlpgen. DO NOT EDIT.\n\n")
- fmt.Fprint(&header, "//go:build !norlpgen\n")
- fmt.Fprint(&header, "// +build !norlpgen\n\n")
return append(header.Bytes(), code...), nil
}
diff --git a/rpc/client_opt.go b/rpc/client_opt.go
index 5bef08cca8..3fa045a9b9 100644
--- a/rpc/client_opt.go
+++ b/rpc/client_opt.go
@@ -34,7 +34,8 @@ type clientConfig struct {
httpAuth HTTPAuth
// WebSocket options
- wsDialer *websocket.Dialer
+ wsDialer *websocket.Dialer
+ wsMessageSizeLimit *int64 // wsMessageSizeLimit nil = default, 0 = no limit
// RPC handler options
idgen func() ID
@@ -66,6 +67,14 @@ func WithWebsocketDialer(dialer websocket.Dialer) ClientOption {
})
}
+// WithWebsocketMessageSizeLimit configures the websocket message size limit used by the RPC
+// client. Passing a limit of 0 means no limit.
+func WithWebsocketMessageSizeLimit(messageSizeLimit int64) ClientOption {
+ return optionFunc(func(cfg *clientConfig) {
+ cfg.wsMessageSizeLimit = &messageSizeLimit
+ })
+}
+
// WithHeader configures HTTP headers set by the RPC client. Headers set using this option
// will be used for both HTTP and WebSocket connections.
func WithHeader(key, value string) ClientOption {
diff --git a/rpc/client_test.go b/rpc/client_test.go
index 7c96b2d666..ac02ad33cf 100644
--- a/rpc/client_test.go
+++ b/rpc/client_test.go
@@ -595,7 +595,7 @@ func TestClientSubscriptionChannelClose(t *testing.T) {
for i := 0; i < 100; i++ {
ch := make(chan int, 100)
- sub, err := client.Subscribe(context.Background(), "nftest", ch, "someSubscription", maxClientSubscriptionBuffer-1, 1)
+ sub, err := client.Subscribe(context.Background(), "nftest", ch, "someSubscription", 100, 1)
if err != nil {
t.Fatal(err)
}
diff --git a/rpc/ipc_windows.go b/rpc/ipc_windows.go
index adb1826f0c..efec38cf37 100644
--- a/rpc/ipc_windows.go
+++ b/rpc/ipc_windows.go
@@ -24,7 +24,7 @@ import (
"net"
"time"
- "gopkg.in/natefinch/npipe.v2"
+ "github.com/Microsoft/go-winio"
)
// This is used if the dialing context has no deadline. It is much smaller than the
@@ -33,17 +33,12 @@ const defaultPipeDialTimeout = 2 * time.Second
// ipcListen will create a named pipe on the given endpoint.
func ipcListen(endpoint string) (net.Listener, error) {
- return npipe.Listen(endpoint)
+ return winio.ListenPipe(endpoint, nil)
}
// newIPCConnection will connect to a named pipe with the given endpoint as name.
func newIPCConnection(ctx context.Context, endpoint string) (net.Conn, error) {
- timeout := defaultPipeDialTimeout
- if deadline, ok := ctx.Deadline(); ok {
- timeout = deadline.Sub(time.Now())
- if timeout < 0 {
- timeout = 0
- }
- }
- return npipe.DialTimeout(endpoint, timeout)
+ ctx, cancel := context.WithTimeout(ctx, defaultPipeDialTimeout)
+ defer cancel()
+ return winio.DialPipeContext(ctx, endpoint)
}
diff --git a/rpc/json.go b/rpc/json.go
index 8a3b162cab..5557a80760 100644
--- a/rpc/json.go
+++ b/rpc/json.go
@@ -46,6 +46,17 @@ type subscriptionResult struct {
Result json.RawMessage `json:"result,omitempty"`
}
+type subscriptionResultEnc struct {
+ ID string `json:"subscription"`
+ Result any `json:"result"`
+}
+
+type jsonrpcSubscriptionNotification struct {
+ Version string `json:"jsonrpc"`
+ Method string `json:"method"`
+ Params subscriptionResultEnc `json:"params"`
+}
+
// A value of this type can a JSON-RPC request, notification, successful response or
// error response. Which one it is depends on the fields.
type jsonrpcMessage struct {
@@ -86,8 +97,8 @@ func (msg *jsonrpcMessage) isUnsubscribe() bool {
}
func (msg *jsonrpcMessage) namespace() string {
- elem := strings.SplitN(msg.Method, serviceMethodSeparator, 2)
- return elem[0]
+ before, _, _ := strings.Cut(msg.Method, serviceMethodSeparator)
+ return before
}
func (msg *jsonrpcMessage) String() string {
diff --git a/rpc/server_test.go b/rpc/server_test.go
index 5d3929dfdc..9d1c7fb5f0 100644
--- a/rpc/server_test.go
+++ b/rpc/server_test.go
@@ -32,7 +32,8 @@ func TestServerRegisterName(t *testing.T) {
server := NewServer()
service := new(testService)
- if err := server.RegisterName("test", service); err != nil {
+ svcName := "test"
+ if err := server.RegisterName(svcName, service); err != nil {
t.Fatalf("%v", err)
}
@@ -40,12 +41,12 @@ func TestServerRegisterName(t *testing.T) {
t.Fatalf("Expected 2 service entries, got %d", len(server.services.services))
}
- svc, ok := server.services.services["test"]
+ svc, ok := server.services.services[svcName]
if !ok {
- t.Fatalf("Expected service calc to be registered")
+ t.Fatalf("Expected service %s to be registered", svcName)
}
- wantCallbacks := 13
+ wantCallbacks := 14
if len(svc.callbacks) != wantCallbacks {
t.Errorf("Expected %d callbacks for service 'service', got %d", wantCallbacks, len(svc.callbacks))
}
diff --git a/rpc/service.go b/rpc/service.go
index 8485cab3aa..a180b8db93 100644
--- a/rpc/service.go
+++ b/rpc/service.go
@@ -93,13 +93,13 @@ func (r *serviceRegistry) registerName(name string, rcvr interface{}) error {
// callback returns the callback corresponding to the given RPC method name.
func (r *serviceRegistry) callback(method string) *callback {
- elem := strings.SplitN(method, serviceMethodSeparator, 2)
- if len(elem) != 2 {
+ before, after, found := strings.Cut(method, serviceMethodSeparator)
+ if !found {
return nil
}
r.mu.Lock()
defer r.mu.Unlock()
- return r.services[elem[0]].callbacks[elem[1]]
+ return r.services[before].callbacks[after]
}
// subscription returns a subscription callback in the given service.
diff --git a/rpc/subscription.go b/rpc/subscription.go
index 3231c2ceec..9cb0727547 100644
--- a/rpc/subscription.go
+++ b/rpc/subscription.go
@@ -105,7 +105,7 @@ type Notifier struct {
mu sync.Mutex
sub *Subscription
- buffer []json.RawMessage
+ buffer []any
callReturned bool
activated bool
}
@@ -129,12 +129,7 @@ func (n *Notifier) CreateSubscription() *Subscription {
// Notify sends a notification to the client with the given data as payload.
// If an error occurs the RPC connection is closed and the error is returned.
-func (n *Notifier) Notify(id ID, data interface{}) error {
- enc, err := json.Marshal(data)
- if err != nil {
- return err
- }
-
+func (n *Notifier) Notify(id ID, data any) error {
n.mu.Lock()
defer n.mu.Unlock()
@@ -144,9 +139,9 @@ func (n *Notifier) Notify(id ID, data interface{}) error {
panic("Notify with wrong ID")
}
if n.activated {
- return n.send(n.sub, enc)
+ return n.send(n.sub, data)
}
- n.buffer = append(n.buffer, enc)
+ n.buffer = append(n.buffer, data)
return nil
}
@@ -181,16 +176,16 @@ func (n *Notifier) activate() error {
return nil
}
-func (n *Notifier) send(sub *Subscription, data json.RawMessage) error {
- params, _ := json.Marshal(&subscriptionResult{ID: string(sub.ID), Result: data})
- ctx := context.Background()
-
- msg := &jsonrpcMessage{
+func (n *Notifier) send(sub *Subscription, data any) error {
+ msg := jsonrpcSubscriptionNotification{
Version: vsn,
Method: n.namespace + notificationMethodSuffix,
- Params: params,
+ Params: subscriptionResultEnc{
+ ID: string(sub.ID),
+ Result: data,
+ },
}
- return n.h.conn.writeJSON(ctx, msg, false)
+ return n.h.conn.writeJSON(context.Background(), &msg, false)
}
// A Subscription is created by a notifier and tied to that notifier. The client can use
diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go
index b270457829..3a131c8e6b 100644
--- a/rpc/subscription_test.go
+++ b/rpc/subscription_test.go
@@ -17,12 +17,19 @@
package rpc
import (
+ "bytes"
+ "context"
"encoding/json"
"fmt"
+ "io"
+ "math/big"
"net"
"strings"
"testing"
"time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
)
func TestNewID(t *testing.T) {
@@ -218,3 +225,56 @@ func readAndValidateMessage(in *json.Decoder) (*subConfirmation, *subscriptionRe
return nil, nil, fmt.Errorf("unrecognized message: %v", msg)
}
}
+
+type mockConn struct {
+ enc *json.Encoder
+}
+
+// writeJSON writes a message to the connection.
+func (c *mockConn) writeJSON(ctx context.Context, msg interface{}, isError bool) error {
+ return c.enc.Encode(msg)
+}
+
+// Closed returns a channel which is closed when the connection is closed.
+func (c *mockConn) closed() <-chan interface{} { return nil }
+
+// RemoteAddr returns the peer address of the connection.
+func (c *mockConn) remoteAddr() string { return "" }
+
+// BenchmarkNotify benchmarks the performance of notifying a subscription.
+func BenchmarkNotify(b *testing.B) {
+ id := ID("test")
+ notifier := &Notifier{
+ h: &handler{conn: &mockConn{json.NewEncoder(io.Discard)}},
+ sub: &Subscription{ID: id},
+ activated: true,
+ }
+ msg := &types.Header{
+ ParentHash: common.HexToHash("0x01"),
+ Number: big.NewInt(100),
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ notifier.Notify(id, msg)
+ }
+}
+
+func TestNotify(t *testing.T) {
+ out := new(bytes.Buffer)
+ id := ID("test")
+ notifier := &Notifier{
+ h: &handler{conn: &mockConn{json.NewEncoder(out)}},
+ sub: &Subscription{ID: id},
+ activated: true,
+ }
+ msg := &types.Header{
+ ParentHash: common.HexToHash("0x01"),
+ Number: big.NewInt(100),
+ }
+ notifier.Notify(id, msg)
+ have := strings.TrimSpace(out.String())
+ want := `{"jsonrpc":"2.0","method":"_subscription","params":{"subscription":"test","result":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000001","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":null,"number":"0x64","gasLimit":"0x0","gasUsed":"0x0","timestamp":"0x0","extraData":"0x","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":null,"withdrawalsRoot":null,"blobGasUsed":null,"excessBlobGas":null,"parentBeaconBlockRoot":null,"hash":"0xe5fb877dde471b45b9742bb4bb4b3d74a761e2fb7cb849a3d2b687eed90fb604"}}}`
+ if have != want {
+ t.Errorf("have:\n%v\nwant:\n%v\n", have, want)
+ }
+}
diff --git a/rpc/testservice_test.go b/rpc/testservice_test.go
index eab67f1dd5..7d873af667 100644
--- a/rpc/testservice_test.go
+++ b/rpc/testservice_test.go
@@ -90,6 +90,10 @@ func (s *testService) EchoWithCtx(ctx context.Context, str string, i int, args *
return echoResult{str, i, args}
}
+func (s *testService) Repeat(msg string, i int) string {
+ return strings.Repeat(msg, i)
+}
+
func (s *testService) PeerInfo(ctx context.Context) PeerInfo {
return PeerInfoFromContext(ctx)
}
diff --git a/rpc/websocket.go b/rpc/websocket.go
index b1213fdfa6..538e53a31b 100644
--- a/rpc/websocket.go
+++ b/rpc/websocket.go
@@ -38,7 +38,7 @@ const (
wsPingInterval = 30 * time.Second
wsPingWriteTimeout = 5 * time.Second
wsPongTimeout = 30 * time.Second
- wsMessageSizeLimit = 32 * 1024 * 1024
+ wsDefaultReadLimit = 32 * 1024 * 1024
)
var wsBufferPool = new(sync.Pool)
@@ -60,7 +60,7 @@ func (s *Server) WebsocketHandler(allowedOrigins []string) http.Handler {
log.Debug("WebSocket upgrade failed", "err", err)
return
}
- codec := newWebsocketCodec(conn, r.Host, r.Header)
+ codec := newWebsocketCodec(conn, r.Host, r.Header, wsDefaultReadLimit)
s.ServeCodec(codec, 0)
})
}
@@ -251,7 +251,11 @@ func newClientTransportWS(endpoint string, cfg *clientConfig) (reconnectFunc, er
}
return nil, hErr
}
- return newWebsocketCodec(conn, dialURL, header), nil
+ messageSizeLimit := int64(wsDefaultReadLimit)
+ if cfg.wsMessageSizeLimit != nil && *cfg.wsMessageSizeLimit >= 0 {
+ messageSizeLimit = *cfg.wsMessageSizeLimit
+ }
+ return newWebsocketCodec(conn, dialURL, header, messageSizeLimit), nil
}
return connect, nil
}
@@ -278,24 +282,21 @@ type websocketCodec struct {
conn *websocket.Conn
info PeerInfo
- wg sync.WaitGroup
- pingReset chan struct{}
+ wg sync.WaitGroup
+ pingReset chan struct{}
+ pongReceived chan struct{}
}
-func newWebsocketCodec(conn *websocket.Conn, host string, req http.Header) ServerCodec {
- conn.SetReadLimit(wsMessageSizeLimit)
- conn.SetPongHandler(func(appData string) error {
- conn.SetReadDeadline(time.Time{})
- return nil
- })
-
+func newWebsocketCodec(conn *websocket.Conn, host string, req http.Header, readLimit int64) ServerCodec {
+ conn.SetReadLimit(readLimit)
encode := func(v interface{}, isErrorResponse bool) error {
return conn.WriteJSON(v)
}
wc := &websocketCodec{
- jsonCodec: NewFuncCodec(conn, encode, conn.ReadJSON).(*jsonCodec),
- conn: conn,
- pingReset: make(chan struct{}, 1),
+ jsonCodec: NewFuncCodec(conn, encode, conn.ReadJSON).(*jsonCodec),
+ conn: conn,
+ pingReset: make(chan struct{}, 1),
+ pongReceived: make(chan struct{}),
info: PeerInfo{
Transport: "ws",
RemoteAddr: conn.RemoteAddr().String(),
@@ -306,6 +307,13 @@ func newWebsocketCodec(conn *websocket.Conn, host string, req http.Header) Serve
wc.info.HTTP.Origin = req.Get("Origin")
wc.info.HTTP.UserAgent = req.Get("User-Agent")
// Start pinger.
+ conn.SetPongHandler(func(appData string) error {
+ select {
+ case wc.pongReceived <- struct{}{}:
+ case <-wc.closed():
+ }
+ return nil
+ })
wc.wg.Add(1)
go wc.pingLoop()
return wc
@@ -334,26 +342,31 @@ func (wc *websocketCodec) writeJSON(ctx context.Context, v interface{}, isError
// pingLoop sends periodic ping frames when the connection is idle.
func (wc *websocketCodec) pingLoop() {
- var timer = time.NewTimer(wsPingInterval)
+ var pingTimer = time.NewTimer(wsPingInterval)
defer wc.wg.Done()
- defer timer.Stop()
+ defer pingTimer.Stop()
for {
select {
case <-wc.closed():
return
+
case <-wc.pingReset:
- if !timer.Stop() {
- <-timer.C
+ if !pingTimer.Stop() {
+ <-pingTimer.C
}
- timer.Reset(wsPingInterval)
- case <-timer.C:
+ pingTimer.Reset(wsPingInterval)
+
+ case <-pingTimer.C:
wc.jsonCodec.encMu.Lock()
wc.conn.SetWriteDeadline(time.Now().Add(wsPingWriteTimeout))
wc.conn.WriteMessage(websocket.PingMessage, nil)
wc.conn.SetReadDeadline(time.Now().Add(wsPongTimeout))
wc.jsonCodec.encMu.Unlock()
- timer.Reset(wsPingInterval)
+ pingTimer.Reset(wsPingInterval)
+
+ case <-wc.pongReceived:
+ wc.conn.SetReadDeadline(time.Time{})
}
}
}
diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go
index fb9357605b..d3e15d94c9 100644
--- a/rpc/websocket_test.go
+++ b/rpc/websocket_test.go
@@ -113,6 +113,66 @@ func TestWebsocketLargeCall(t *testing.T) {
}
}
+// This test checks whether the wsMessageSizeLimit option is obeyed.
+func TestWebsocketLargeRead(t *testing.T) {
+ t.Parallel()
+
+ var (
+ srv = newTestServer()
+ httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"}))
+ wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
+ )
+ defer srv.Stop()
+ defer httpsrv.Close()
+
+ testLimit := func(limit *int64) {
+ opts := []ClientOption{}
+ expLimit := int64(wsDefaultReadLimit)
+ if limit != nil && *limit >= 0 {
+ opts = append(opts, WithWebsocketMessageSizeLimit(*limit))
+ if *limit > 0 {
+ expLimit = *limit // 0 means infinite
+ }
+ }
+ client, err := DialOptions(context.Background(), wsURL, opts...)
+ if err != nil {
+ t.Fatalf("can't dial: %v", err)
+ }
+ defer client.Close()
+ // Remove some bytes for json encoding overhead.
+ underLimit := int(expLimit - 128)
+ overLimit := expLimit + 1
+ if expLimit == wsDefaultReadLimit {
+ // No point trying the full 32MB in tests. Just sanity-check that
+ // it's not obviously limited.
+ underLimit = 1024
+ overLimit = -1
+ }
+ var res string
+ // Check under limit
+ if err = client.Call(&res, "test_repeat", "A", underLimit); err != nil {
+ t.Fatalf("unexpected error with limit %d: %v", expLimit, err)
+ }
+ if len(res) != underLimit || strings.Count(res, "A") != underLimit {
+ t.Fatal("incorrect data")
+ }
+ // Check over limit
+ if overLimit > 0 {
+ err = client.Call(&res, "test_repeat", "A", expLimit+1)
+ if err == nil || err != websocket.ErrReadLimit {
+ t.Fatalf("wrong error with limit %d: %v expecting %v", expLimit, err, websocket.ErrReadLimit)
+ }
+ }
+ }
+ ptr := func(v int64) *int64 { return &v }
+
+ testLimit(ptr(-1)) // Should be ignored (use default)
+ testLimit(ptr(0)) // Should be ignored (use default)
+ testLimit(nil) // Should be ignored (use default)
+ testLimit(ptr(200))
+ testLimit(ptr(wsDefaultReadLimit * 2))
+}
+
func TestWebsocketPeerInfo(t *testing.T) {
var (
s = newTestServer()
@@ -155,7 +215,7 @@ func TestClientWebsocketPing(t *testing.T) {
var (
sendPing = make(chan struct{})
server = wsPingTestServer(t, sendPing)
- ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
+ ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
)
defer cancel()
defer server.Shutdown(ctx)
@@ -206,7 +266,7 @@ func TestClientWebsocketLargeMessage(t *testing.T) {
defer srv.Stop()
defer httpsrv.Close()
- respLength := wsMessageSizeLimit - 50
+ respLength := wsDefaultReadLimit - 50
srv.RegisterName("test", largeRespService{respLength})
c, err := DialWebsocket(context.Background(), wsURL, "")
diff --git a/signer/core/api.go b/signer/core/api.go
index 43eb89ee00..ef8c136625 100644
--- a/signer/core/api.go
+++ b/signer/core/api.go
@@ -65,7 +65,7 @@ type ExternalAPI interface {
EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error)
// Version info about the APIs
Version(ctx context.Context) (string, error)
- // SignGnosisSafeTransaction signs/confirms a gnosis-safe multisig transaction
+ // SignGnosisSafeTx signs/confirms a gnosis-safe multisig transaction
SignGnosisSafeTx(ctx context.Context, signerAddress common.MixedcaseAddress, gnosisTx GnosisSafeTx, methodSelector *string) (*GnosisSafeTx, error)
}
diff --git a/signer/core/api_test.go b/signer/core/api_test.go
index 9bb55bddca..69229dadaf 100644
--- a/signer/core/api_test.go
+++ b/signer/core/api_test.go
@@ -169,6 +169,7 @@ func list(ui *headlessUi, api *core.SignerAPI, t *testing.T) ([]common.Address,
}
func TestNewAcc(t *testing.T) {
+ t.Parallel()
api, control := setup(t)
verifyNum := func(num int) {
list, err := list(control, api, t)
@@ -235,6 +236,7 @@ func mkTestTx(from common.MixedcaseAddress) apitypes.SendTxArgs {
}
func TestSignTx(t *testing.T) {
+ t.Parallel()
var (
list []common.Address
res, res2 *ethapi.SignTransactionResult
@@ -282,7 +284,7 @@ func TestSignTx(t *testing.T) {
t.Fatal(err)
}
parsedTx := &types.Transaction{}
- rlp.Decode(bytes.NewReader(res.Raw), parsedTx)
+ rlp.DecodeBytes(res.Raw, parsedTx)
//The tx should NOT be modified by the UI
if parsedTx.Value().Cmp(tx.Value.ToInt()) != 0 {
@@ -308,7 +310,7 @@ func TestSignTx(t *testing.T) {
t.Fatal(err)
}
parsedTx2 := &types.Transaction{}
- rlp.Decode(bytes.NewReader(res.Raw), parsedTx2)
+ rlp.DecodeBytes(res.Raw, parsedTx2)
//The tx should be modified by the UI
if parsedTx2.Value().Cmp(tx.Value.ToInt()) != 0 {
diff --git a/signer/core/apitypes/signed_data_internal_test.go b/signer/core/apitypes/signed_data_internal_test.go
index af7fc93ed8..8067893c21 100644
--- a/signer/core/apitypes/signed_data_internal_test.go
+++ b/signer/core/apitypes/signed_data_internal_test.go
@@ -27,6 +27,7 @@ import (
)
func TestBytesPadding(t *testing.T) {
+ t.Parallel()
tests := []struct {
Type string
Input []byte
@@ -87,6 +88,7 @@ func TestBytesPadding(t *testing.T) {
}
func TestParseAddress(t *testing.T) {
+ t.Parallel()
tests := []struct {
Input interface{}
Output []byte // nil => error
@@ -136,6 +138,7 @@ func TestParseAddress(t *testing.T) {
}
func TestParseBytes(t *testing.T) {
+ t.Parallel()
for i, tt := range []struct {
v interface{}
exp []byte
@@ -170,6 +173,7 @@ func TestParseBytes(t *testing.T) {
}
func TestParseInteger(t *testing.T) {
+ t.Parallel()
for i, tt := range []struct {
t string
v interface{}
@@ -200,6 +204,7 @@ func TestParseInteger(t *testing.T) {
}
func TestConvertStringDataToSlice(t *testing.T) {
+ t.Parallel()
slice := []string{"a", "b", "c"}
var it interface{} = slice
_, err := convertDataToSlice(it)
@@ -209,6 +214,7 @@ func TestConvertStringDataToSlice(t *testing.T) {
}
func TestConvertUint256DataToSlice(t *testing.T) {
+ t.Parallel()
slice := []*math.HexOrDecimal256{
math.NewHexOrDecimal256(1),
math.NewHexOrDecimal256(2),
@@ -222,6 +228,7 @@ func TestConvertUint256DataToSlice(t *testing.T) {
}
func TestConvertAddressDataToSlice(t *testing.T) {
+ t.Parallel()
slice := []common.Address{
common.HexToAddress("0x0000000000000000000000000000000000000001"),
common.HexToAddress("0x0000000000000000000000000000000000000002"),
diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go
index 2268923ed0..64279ce027 100644
--- a/signer/core/apitypes/types.go
+++ b/signer/core/apitypes/types.go
@@ -62,7 +62,7 @@ func (vs *ValidationMessages) Info(msg string) {
vs.Messages = append(vs.Messages, ValidationInfo{INFO, msg})
}
-// getWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
+// GetWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
func (v *ValidationMessages) GetWarnings() error {
var messages []string
for _, msg := range v.Messages {
diff --git a/signer/core/apitypes/types_test.go b/signer/core/apitypes/types_test.go
index eef3cae00c..b5aa3d1e93 100644
--- a/signer/core/apitypes/types_test.go
+++ b/signer/core/apitypes/types_test.go
@@ -19,6 +19,7 @@ package apitypes
import "testing"
func TestIsPrimitive(t *testing.T) {
+ t.Parallel()
// Expected positives
for i, tc := range []string{
"int24", "int24[]", "uint88", "uint88[]", "uint", "uint[]", "int256", "int256[]",
diff --git a/signer/core/auditlog.go b/signer/core/auditlog.go
index a0b292bf71..d2207c9eb8 100644
--- a/signer/core/auditlog.go
+++ b/signer/core/auditlog.go
@@ -19,12 +19,14 @@ package core
import (
"context"
"encoding/json"
+ "os"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
+ "golang.org/x/exp/slog"
)
type AuditLogger struct {
@@ -113,12 +115,13 @@ func (l *AuditLogger) Version(ctx context.Context) (string, error) {
}
func NewAuditLogger(path string, api ExternalAPI) (*AuditLogger, error) {
- l := log.New("api", "signer")
- handler, err := log.FileHandler(path, log.LogfmtFormat())
+ f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return nil, err
}
- l.SetHandler(handler)
+
+ handler := slog.NewTextHandler(f, nil)
+ l := log.NewLogger(handler).With("api", "signer")
l.Info("Configured", "audit log", path)
return &AuditLogger{l, api}, nil
}
diff --git a/signer/core/signed_data.go b/signer/core/signed_data.go
index e3c2afa2db..6f10da6553 100644
--- a/signer/core/signed_data.go
+++ b/signer/core/signed_data.go
@@ -262,7 +262,7 @@ func parliaHeaderHashAndRlp(header *types.Header, chainId *big.Int) (hash, rlp [
return
}
rlp = parlia.ParliaRLP(header, chainId)
- hash = parlia.SealHash(header, chainId).Bytes()
+ hash = types.SealHash(header, chainId).Bytes()
return hash, rlp, err
}
diff --git a/signer/core/signed_data_test.go b/signer/core/signed_data_test.go
index 3e3837cae2..1cf8b4bf38 100644
--- a/signer/core/signed_data_test.go
+++ b/signer/core/signed_data_test.go
@@ -183,6 +183,7 @@ var typedData = apitypes.TypedData{
}
func TestSignData(t *testing.T) {
+ t.Parallel()
api, control := setup(t)
//Create two accounts
createAccount(control, api, t)
@@ -248,6 +249,7 @@ func TestSignData(t *testing.T) {
}
func TestDomainChainId(t *testing.T) {
+ t.Parallel()
withoutChainID := apitypes.TypedData{
Types: apitypes.Types{
"EIP712Domain": []apitypes.Type{
@@ -289,6 +291,7 @@ func TestDomainChainId(t *testing.T) {
}
func TestHashStruct(t *testing.T) {
+ t.Parallel()
hash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
if err != nil {
t.Fatal(err)
@@ -309,6 +312,7 @@ func TestHashStruct(t *testing.T) {
}
func TestEncodeType(t *testing.T) {
+ t.Parallel()
domainTypeEncoding := string(typedData.EncodeType("EIP712Domain"))
if domainTypeEncoding != "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" {
t.Errorf("Expected different encodeType result (got %s)", domainTypeEncoding)
@@ -321,6 +325,7 @@ func TestEncodeType(t *testing.T) {
}
func TestTypeHash(t *testing.T) {
+ t.Parallel()
mailTypeHash := fmt.Sprintf("0x%s", common.Bytes2Hex(typedData.TypeHash(typedData.PrimaryType)))
if mailTypeHash != "0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2" {
t.Errorf("Expected different typeHash result (got %s)", mailTypeHash)
@@ -328,6 +333,7 @@ func TestTypeHash(t *testing.T) {
}
func TestEncodeData(t *testing.T) {
+ t.Parallel()
hash, err := typedData.EncodeData(typedData.PrimaryType, typedData.Message, 0)
if err != nil {
t.Fatal(err)
@@ -339,6 +345,7 @@ func TestEncodeData(t *testing.T) {
}
func TestFormatter(t *testing.T) {
+ t.Parallel()
var d apitypes.TypedData
err := json.Unmarshal([]byte(jsonTypedData), &d)
if err != nil {
@@ -368,6 +375,7 @@ func sign(typedData apitypes.TypedData) ([]byte, []byte, error) {
}
func TestJsonFiles(t *testing.T) {
+ t.Parallel()
testfiles, err := os.ReadDir("testdata/")
if err != nil {
t.Fatalf("failed reading files: %v", err)
@@ -402,6 +410,7 @@ func TestJsonFiles(t *testing.T) {
// TestFuzzerFiles tests some files that have been found by fuzzing to cause
// crashes or hangs.
func TestFuzzerFiles(t *testing.T) {
+ t.Parallel()
corpusdir := path.Join("testdata", "fuzzing")
testfiles, err := os.ReadDir(corpusdir)
if err != nil {
@@ -514,6 +523,7 @@ var gnosisTx = `
// TestGnosisTypedData tests the scenario where a user submits a full EIP-712
// struct without using the gnosis-specific endpoint
func TestGnosisTypedData(t *testing.T) {
+ t.Parallel()
var td apitypes.TypedData
err := json.Unmarshal([]byte(gnosisTypedData), &td)
if err != nil {
@@ -532,6 +542,7 @@ func TestGnosisTypedData(t *testing.T) {
// TestGnosisCustomData tests the scenario where a user submits only the gnosis-safe
// specific data, and we fill the TypedData struct on our side
func TestGnosisCustomData(t *testing.T) {
+ t.Parallel()
var tx core.GnosisSafeTx
err := json.Unmarshal([]byte(gnosisTx), &tx)
if err != nil {
@@ -644,6 +655,7 @@ var gnosisTxWithChainId = `
`
func TestGnosisTypedDataWithChainId(t *testing.T) {
+ t.Parallel()
var td apitypes.TypedData
err := json.Unmarshal([]byte(gnosisTypedDataWithChainId), &td)
if err != nil {
@@ -662,6 +674,7 @@ func TestGnosisTypedDataWithChainId(t *testing.T) {
// TestGnosisCustomData tests the scenario where a user submits only the gnosis-safe
// specific data, and we fill the TypedData struct on our side
func TestGnosisCustomDataWithChainId(t *testing.T) {
+ t.Parallel()
var tx core.GnosisSafeTx
err := json.Unmarshal([]byte(gnosisTxWithChainId), &tx)
if err != nil {
@@ -813,6 +826,7 @@ var complexTypedData = `
`
func TestComplexTypedData(t *testing.T) {
+ t.Parallel()
var td apitypes.TypedData
err := json.Unmarshal([]byte(complexTypedData), &td)
if err != nil {
@@ -829,6 +843,7 @@ func TestComplexTypedData(t *testing.T) {
}
func TestGnosisSafe(t *testing.T) {
+ t.Parallel()
// json missing chain id
js := "{\n \"safe\": \"0x899FcB1437DE65DC6315f5a69C017dd3F2837557\",\n \"to\": \"0x899FcB1437DE65DC6315f5a69C017dd3F2837557\",\n \"value\": \"0\",\n \"data\": \"0x0d582f13000000000000000000000000d3ed2b8756b942c98c851722f3bd507a17b4745f0000000000000000000000000000000000000000000000000000000000000005\",\n \"operation\": 0,\n \"gasToken\": \"0x0000000000000000000000000000000000000000\",\n \"safeTxGas\": 0,\n \"baseGas\": 0,\n \"gasPrice\": \"0\",\n \"refundReceiver\": \"0x0000000000000000000000000000000000000000\",\n \"nonce\": 0,\n \"executionDate\": null,\n \"submissionDate\": \"2022-02-23T14:09:00.018475Z\",\n \"modified\": \"2022-12-01T15:52:21.214357Z\",\n \"blockNumber\": null,\n \"transactionHash\": null,\n \"safeTxHash\": \"0x6f0f5cffee69087c9d2471e477a63cab2ae171cf433e754315d558d8836274f4\",\n \"executor\": null,\n \"isExecuted\": false,\n \"isSuccessful\": null,\n \"ethGasPrice\": null,\n \"maxFeePerGas\": null,\n \"maxPriorityFeePerGas\": null,\n \"gasUsed\": null,\n \"fee\": null,\n \"origin\": \"https://gnosis-safe.io\",\n \"dataDecoded\": {\n \"method\": \"addOwnerWithThreshold\",\n \"parameters\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"value\": \"0xD3Ed2b8756b942c98c851722F3bd507a17B4745F\"\n },\n {\n \"name\": \"_threshold\",\n \"type\": \"uint256\",\n \"value\": \"5\"\n }\n ]\n },\n \"confirmationsRequired\": 4,\n \"confirmations\": [\n {\n \"owner\": \"0x30B714E065B879F5c042A75Bb40a220A0BE27966\",\n \"submissionDate\": \"2022-03-01T14:56:22Z\",\n \"transactionHash\": \"0x6d0a9c83ac7578ef3be1f2afce089fb83b619583dfa779b82f4422fd64ff3ee9\",\n \"signature\": \"0x00000000000000000000000030b714e065b879f5c042a75bb40a220a0be27966000000000000000000000000000000000000000000000000000000000000000001\",\n \"signatureType\": \"APPROVED_HASH\"\n },\n {\n \"owner\": \"0x8300dFEa25Da0eb744fC0D98c23283F86AB8c10C\",\n \"submissionDate\": \"2022-12-01T15:52:21.214357Z\",\n \"transactionHash\": null,\n \"signature\": \"0xbce73de4cc6ee208e933a93c794dcb8ba1810f9848d1eec416b7be4dae9854c07dbf1720e60bbd310d2159197a380c941cfdb55b3ce58f9dd69efd395d7bef881b\",\n \"signatureType\": \"EOA\"\n }\n ],\n \"trusted\": true,\n \"signatures\": null\n}\n"
var gnosisTx core.GnosisSafeTx
@@ -984,6 +999,7 @@ var complexTypedDataLCRefType = `
`
func TestComplexTypedDataWithLowercaseReftype(t *testing.T) {
+ t.Parallel()
var td apitypes.TypedData
err := json.Unmarshal([]byte(complexTypedDataLCRefType), &td)
if err != nil {
diff --git a/signer/core/uiapi.go b/signer/core/uiapi.go
index 4a060147a6..b8c3acfb4d 100644
--- a/signer/core/uiapi.go
+++ b/signer/core/uiapi.go
@@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)
-// SignerUIAPI implements methods Clef provides for a UI to query, in the bidirectional communication
+// UIServerAPI implements methods Clef provides for a UI to query, in the bidirectional communication
// channel.
// This API is considered secure, since a request can only
// ever arrive from the UI -- and the UI is capable of approving any action, thus we can consider these
diff --git a/signer/core/validation_test.go b/signer/core/validation_test.go
index 6adaa21afd..7f733b0bb1 100644
--- a/signer/core/validation_test.go
+++ b/signer/core/validation_test.go
@@ -19,6 +19,7 @@ package core
import "testing"
func TestPasswordValidation(t *testing.T) {
+ t.Parallel()
testcases := []struct {
pw string
shouldFail bool
diff --git a/signer/fourbyte/abi_test.go b/signer/fourbyte/abi_test.go
index 68c027ecea..9656732dff 100644
--- a/signer/fourbyte/abi_test.go
+++ b/signer/fourbyte/abi_test.go
@@ -52,6 +52,7 @@ func verify(t *testing.T, jsondata, calldata string, exp []interface{}) {
}
func TestNewUnpacker(t *testing.T) {
+ t.Parallel()
type unpackTest struct {
jsondata string
calldata string
@@ -97,6 +98,7 @@ func TestNewUnpacker(t *testing.T) {
}
func TestCalldataDecoding(t *testing.T) {
+ t.Parallel()
// send(uint256) : a52c101e
// compareAndApprove(address,uint256,uint256) : 751e1079
// issue(address[],uint256) : 42958b54
@@ -159,6 +161,7 @@ func TestCalldataDecoding(t *testing.T) {
}
func TestMaliciousABIStrings(t *testing.T) {
+ t.Parallel()
tests := []string{
"func(uint256,uint256,[]uint256)",
"func(uint256,uint256,uint256,)",
diff --git a/signer/fourbyte/fourbyte_test.go b/signer/fourbyte/fourbyte_test.go
index 017001f97b..a3dc3b5117 100644
--- a/signer/fourbyte/fourbyte_test.go
+++ b/signer/fourbyte/fourbyte_test.go
@@ -17,8 +17,8 @@
package fourbyte
import (
+ "encoding/json"
"fmt"
- "strings"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi"
@@ -27,18 +27,19 @@ import (
// Tests that all the selectors contained in the 4byte database are valid.
func TestEmbeddedDatabase(t *testing.T) {
+ t.Parallel()
db, err := New()
if err != nil {
t.Fatal(err)
}
+ var abistruct abi.ABI
for id, selector := range db.embedded {
abistring, err := parseSelector(selector)
if err != nil {
t.Errorf("Failed to convert selector to ABI: %v", err)
continue
}
- abistruct, err := abi.JSON(strings.NewReader(string(abistring)))
- if err != nil {
+ if err := json.Unmarshal(abistring, &abistruct); err != nil {
t.Errorf("Failed to parse ABI: %v", err)
continue
}
@@ -55,6 +56,7 @@ func TestEmbeddedDatabase(t *testing.T) {
// Tests that custom 4byte datasets can be handled too.
func TestCustomDatabase(t *testing.T) {
+ t.Parallel()
// Create a new custom 4byte database with no embedded component
tmpdir := t.TempDir()
filename := fmt.Sprintf("%s/4byte_custom.json", tmpdir)
diff --git a/signer/fourbyte/validation_test.go b/signer/fourbyte/validation_test.go
index 1b0ab507a8..74fed9fe01 100644
--- a/signer/fourbyte/validation_test.go
+++ b/signer/fourbyte/validation_test.go
@@ -73,6 +73,7 @@ type txtestcase struct {
}
func TestTransactionValidation(t *testing.T) {
+ t.Parallel()
var (
// use empty db, there are other tests for the abi-specific stuff
db = newEmpty()
diff --git a/signer/rules/rules_test.go b/signer/rules/rules_test.go
index c35da8ecc1..d27de22b29 100644
--- a/signer/rules/rules_test.go
+++ b/signer/rules/rules_test.go
@@ -124,6 +124,7 @@ func initRuleEngine(js string) (*rulesetUI, error) {
}
func TestListRequest(t *testing.T) {
+ t.Parallel()
accs := make([]accounts.Account, 5)
for i := range accs {
@@ -152,6 +153,7 @@ func TestListRequest(t *testing.T) {
}
func TestSignTxRequest(t *testing.T) {
+ t.Parallel()
js := `
function ApproveTx(r){
console.log("transaction.from", r.transaction.from);
@@ -244,6 +246,7 @@ func (d *dummyUI) OnSignerStartup(info core.StartupInfo) {
// TestForwarding tests that the rule-engine correctly dispatches requests to the next caller
func TestForwarding(t *testing.T) {
+ t.Parallel()
js := ""
ui := &dummyUI{make([]string, 0)}
jsBackend := storage.NewEphemeralStorage()
@@ -271,6 +274,7 @@ func TestForwarding(t *testing.T) {
}
func TestMissingFunc(t *testing.T) {
+ t.Parallel()
r, err := initRuleEngine(JS)
if err != nil {
t.Errorf("Couldn't create evaluator %v", err)
@@ -293,6 +297,7 @@ func TestMissingFunc(t *testing.T) {
t.Logf("Err %v", err)
}
func TestStorage(t *testing.T) {
+ t.Parallel()
js := `
function testStorage(){
storage.put("mykey", "myvalue")
@@ -455,6 +460,7 @@ func dummySigned(value *big.Int) *types.Transaction {
}
func TestLimitWindow(t *testing.T) {
+ t.Parallel()
r, err := initRuleEngine(ExampleTxWindow)
if err != nil {
t.Errorf("Couldn't create evaluator %v", err)
@@ -540,6 +546,7 @@ func (d *dontCallMe) OnApprovedTx(tx ethapi.SignTransactionResult) {
// if it does, that would be bad since developers may rely on that to store data,
// instead of using the disk-based data storage
func TestContextIsCleared(t *testing.T) {
+ t.Parallel()
js := `
function ApproveTx(){
if (typeof foobar == 'undefined') {
@@ -571,6 +578,7 @@ func TestContextIsCleared(t *testing.T) {
}
func TestSignData(t *testing.T) {
+ t.Parallel()
js := `function ApproveListing(){
return "Approve"
}
diff --git a/signer/storage/aes_gcm_storage_test.go b/signer/storage/aes_gcm_storage_test.go
index e1fea59280..a223b1a6b4 100644
--- a/signer/storage/aes_gcm_storage_test.go
+++ b/signer/storage/aes_gcm_storage_test.go
@@ -26,9 +26,11 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/mattn/go-colorable"
+ "golang.org/x/exp/slog"
)
func TestEncryption(t *testing.T) {
+ t.Parallel()
// key := []byte("AES256Key-32Characters1234567890")
// plaintext := []byte(value)
key := []byte("AES256Key-32Characters1234567890")
@@ -51,6 +53,7 @@ func TestEncryption(t *testing.T) {
}
func TestFileStorage(t *testing.T) {
+ t.Parallel()
a := map[string]storedCredential{
"secret": {
Iv: common.Hex2Bytes("cdb30036279601aeee60f16b"),
@@ -89,7 +92,8 @@ func TestFileStorage(t *testing.T) {
}
}
func TestEnd2End(t *testing.T) {
- log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(3), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))
+ t.Parallel()
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(colorable.NewColorableStderr(), slog.LevelInfo, true)))
d := t.TempDir()
@@ -109,9 +113,10 @@ func TestEnd2End(t *testing.T) {
}
func TestSwappedKeys(t *testing.T) {
+ t.Parallel()
// It should not be possible to swap the keys/values, so that
// K1:V1, K2:V2 can be swapped into K1:V2, K2:V1
- log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(3), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true))))
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(colorable.NewColorableStderr(), slog.LevelInfo, true)))
d := t.TempDir()
diff --git a/tests/0001-diff-go-ethereum.patch b/tests/0001-diff-go-ethereum.patch
index 52e11752b8..32ad84b430 100644
--- a/tests/0001-diff-go-ethereum.patch
+++ b/tests/0001-diff-go-ethereum.patch
@@ -1,16 +1,5 @@
-From a1fe21e9b999b60705b7310737f2b6bbb680969d Mon Sep 17 00:00:00 2001
-From: buddh0
-Date: Mon, 8 Jan 2024 17:16:29 +0800
-Subject: [PATCH] diff go-ethereum
-
----
- core/vm/contracts.go | 3 ---
- core/vm/jump_table.go | 2 +-
- params/protocol_params.go | 8 ++++----
- 3 files changed, 5 insertions(+), 8 deletions(-)
-
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
-index 482c020a6..7d9a59a92 100644
+index 36d33e41c..adb10883e 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -78,9 +78,6 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
@@ -24,10 +13,10 @@ index 482c020a6..7d9a59a92 100644
var PrecompiledContractsNano = map[common.Address]PrecompiledContract{
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
-index 38a0a7653..702b18661 100644
+index 70c543f14..65716f944 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
-@@ -90,7 +90,7 @@ func newCancunInstructionSet() JumpTable {
+@@ -91,7 +91,7 @@ func newCancunInstructionSet() JumpTable {
}
func newShanghaiInstructionSet() JumpTable {
@@ -37,11 +26,11 @@ index 38a0a7653..702b18661 100644
enable3860(&instructionSet) // Limit and meter initcode
diff --git a/params/protocol_params.go b/params/protocol_params.go
-index 2b5cf8996..e14a2f414 100644
+index b32b4d943..8b544af08 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
-@@ -19,7 +19,7 @@ package params
- import "math/big"
+@@ -23,7 +23,7 @@ import (
+ )
const (
- GasLimitBoundDivisor uint64 = 256 // The bound divisor of the gas limit, used in update calculations.
@@ -49,19 +38,3 @@ index 2b5cf8996..e14a2f414 100644
MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be.
MaxGasLimit uint64 = 0x7fffffffffffffff // Maximum the gas limit (2^63-1).
GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block.
-@@ -122,9 +122,9 @@ const (
- // Introduced in Tangerine Whistle (Eip 150)
- CreateBySelfdestructGas uint64 = 25000
-
-- DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks.
-- DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
-- InitialBaseFee = 0 // Initial base fee for EIP-1559 blocks.
-+ DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks.
-+ DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
-+ InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks.
-
- MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
- MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions
---
-2.41.0
-
diff --git a/tests/block_test.go b/tests/block_test.go
index d9bff392c7..77681716d6 100644
--- a/tests/block_test.go
+++ b/tests/block_test.go
@@ -17,14 +17,15 @@
package tests
import (
+ "math/rand"
+ "runtime"
"testing"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
)
func TestBlockchain(t *testing.T) {
- t.Parallel()
-
bt := new(testMatcher)
// General state tests are 'exported' as blockchain tests, but we can run them natively.
// For speedier CI-runs, the line below can be uncommented, so those are skipped.
@@ -51,20 +52,43 @@ func TestBlockchain(t *testing.T) {
bt.skipLoad(`.*randomStatetest94.json.*`)
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
- if err := bt.checkFailure(t, test.Run(false, rawdb.HashScheme, nil)); err != nil {
- t.Errorf("test in hash mode without snapshotter failed: %v", err)
- }
- if err := bt.checkFailure(t, test.Run(true, rawdb.HashScheme, nil)); err != nil {
- t.Errorf("test in hash mode with snapshotter failed: %v", err)
- }
- if err := bt.checkFailure(t, test.Run(false, rawdb.PathScheme, nil)); err != nil {
- t.Errorf("test in path mode without snapshotter failed: %v", err)
- }
- if err := bt.checkFailure(t, test.Run(true, rawdb.PathScheme, nil)); err != nil {
- t.Errorf("test in path mode with snapshotter failed: %v", err)
+ if runtime.GOARCH == "386" && runtime.GOOS == "windows" && rand.Int63()%2 == 0 {
+ t.Skip("test (randomly) skipped on 32-bit windows")
}
+ execBlockTest(t, bt, test)
})
// There is also a LegacyTests folder, containing blockchain tests generated
// prior to Istanbul. However, they are all derived from GeneralStateTests,
// which run natively, so there's no reason to run them here.
}
+
+// TestExecutionSpec runs the test fixtures from execution-spec-tests.
+func TestExecutionSpec(t *testing.T) {
+ if !common.FileExist(executionSpecDir) {
+ t.Skipf("directory %s does not exist", executionSpecDir)
+ }
+ bt := new(testMatcher)
+
+ bt.walk(t, executionSpecDir, func(t *testing.T, name string, test *BlockTest) {
+ execBlockTest(t, bt, test)
+ })
+}
+
+func execBlockTest(t *testing.T, bt *testMatcher, test *BlockTest) {
+ if err := bt.checkFailure(t, test.Run(false, rawdb.HashScheme, nil, nil)); err != nil {
+ t.Errorf("test in hash mode without snapshotter failed: %v", err)
+ return
+ }
+ if err := bt.checkFailure(t, test.Run(true, rawdb.HashScheme, nil, nil)); err != nil {
+ t.Errorf("test in hash mode with snapshotter failed: %v", err)
+ return
+ }
+ if err := bt.checkFailure(t, test.Run(false, rawdb.PathScheme, nil, nil)); err != nil {
+ t.Errorf("test in path mode without snapshotter failed: %v", err)
+ return
+ }
+ if err := bt.checkFailure(t, test.Run(true, rawdb.PathScheme, nil, nil)); err != nil {
+ t.Errorf("test in path mode with snapshotter failed: %v", err)
+ return
+ }
+}
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index 24a5944b76..50adee3e0b 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
@@ -73,24 +74,27 @@ type btBlock struct {
//go:generate go run github.com/fjl/gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go
type btHeader struct {
- Bloom types.Bloom
- Coinbase common.Address
- MixHash common.Hash
- Nonce types.BlockNonce
- Number *big.Int
- Hash common.Hash
- ParentHash common.Hash
- ReceiptTrie common.Hash
- StateRoot common.Hash
- TransactionsTrie common.Hash
- UncleHash common.Hash
- ExtraData []byte
- Difficulty *big.Int
- GasLimit uint64
- GasUsed uint64
- Timestamp uint64
- BaseFeePerGas *big.Int
- WithdrawalsRoot *common.Hash
+ Bloom types.Bloom
+ Coinbase common.Address
+ MixHash common.Hash
+ Nonce types.BlockNonce
+ Number *big.Int
+ Hash common.Hash
+ ParentHash common.Hash
+ ReceiptTrie common.Hash
+ StateRoot common.Hash
+ TransactionsTrie common.Hash
+ UncleHash common.Hash
+ ExtraData []byte
+ Difficulty *big.Int
+ GasLimit uint64
+ GasUsed uint64
+ Timestamp uint64
+ BaseFeePerGas *big.Int
+ WithdrawalsRoot *common.Hash
+ BlobGasUsed *uint64
+ ExcessBlobGas *uint64
+ ParentBeaconBlockRoot *common.Hash
}
type btHeaderMarshaling struct {
@@ -101,9 +105,11 @@ type btHeaderMarshaling struct {
GasUsed math.HexOrDecimal64
Timestamp math.HexOrDecimal64
BaseFeePerGas *math.HexOrDecimal256
+ BlobGasUsed *math.HexOrDecimal64
+ ExcessBlobGas *math.HexOrDecimal64
}
-func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger) error {
+func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, postCheck func(error, *core.BlockChain)) (result error) {
config, ok := Forks[t.json.Network]
if !ok {
return UnsupportedForkError{t.json.Network}
@@ -111,7 +117,9 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger) er
// import pre accounts & construct test genesis block & state root
var (
db = rawdb.NewMemoryDatabase()
- tconf = &trie.Config{}
+ tconf = &trie.Config{
+ Preimages: true,
+ }
)
if scheme == rawdb.PathScheme {
tconf.PathDB = pathdb.Defaults
@@ -136,7 +144,7 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger) er
// Wrap the original engine within the beacon-engine
engine := beacon.New(ethash.NewFaker())
- cache := &core.CacheConfig{TrieCleanLimit: 0, TriesInMemory: 128, StateScheme: scheme}
+ cache := &core.CacheConfig{TrieCleanLimit: 0, TriesInMemory: 128, StateScheme: scheme, Preimages: true}
if snapshotter {
cache.SnapshotLimit = 1
cache.SnapshotWait = true
@@ -153,6 +161,11 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger) er
if err != nil {
return err
}
+ // Import succeeded: regardless of whether the _test_ succeeds or not, schedule
+ // the post-check to run
+ if postCheck != nil {
+ defer postCheck(result, chain)
+ }
cmlast := chain.CurrentBlock().Hash()
if common.Hash(t.json.BestBlock) != cmlast {
return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast)
@@ -175,18 +188,20 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger) er
func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
return &core.Genesis{
- Config: config,
- Nonce: t.json.Genesis.Nonce.Uint64(),
- Timestamp: t.json.Genesis.Timestamp,
- ParentHash: t.json.Genesis.ParentHash,
- ExtraData: t.json.Genesis.ExtraData,
- GasLimit: t.json.Genesis.GasLimit,
- GasUsed: t.json.Genesis.GasUsed,
- Difficulty: t.json.Genesis.Difficulty,
- Mixhash: t.json.Genesis.MixHash,
- Coinbase: t.json.Genesis.Coinbase,
- Alloc: t.json.Pre,
- BaseFee: t.json.Genesis.BaseFeePerGas,
+ Config: config,
+ Nonce: t.json.Genesis.Nonce.Uint64(),
+ Timestamp: t.json.Genesis.Timestamp,
+ ParentHash: t.json.Genesis.ParentHash,
+ ExtraData: t.json.Genesis.ExtraData,
+ GasLimit: t.json.Genesis.GasLimit,
+ GasUsed: t.json.Genesis.GasUsed,
+ Difficulty: t.json.Genesis.Difficulty,
+ Mixhash: t.json.Genesis.MixHash,
+ Coinbase: t.json.Genesis.Coinbase,
+ Alloc: t.json.Pre,
+ BaseFee: t.json.Genesis.BaseFeePerGas,
+ BlobGasUsed: t.json.Genesis.BlobGasUsed,
+ ExcessBlobGas: t.json.Genesis.ExcessBlobGas,
}
}
@@ -210,6 +225,7 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error)
cb, err := b.decode()
if err != nil {
if b.BlockHeader == nil {
+ log.Info("Block decoding failed", "index", bi, "err", err)
continue // OK - block is supposed to be invalid, continue with next block
} else {
return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err)
@@ -295,6 +311,15 @@ func validateHeader(h *btHeader, h2 *types.Header) error {
if !reflect.DeepEqual(h.WithdrawalsRoot, h2.WithdrawalsHash) {
return fmt.Errorf("withdrawalsRoot: want: %v have: %v", h.WithdrawalsRoot, h2.WithdrawalsHash)
}
+ if !reflect.DeepEqual(h.BlobGasUsed, h2.BlobGasUsed) {
+ return fmt.Errorf("blobGasUsed: want: %v have: %v", h.BlobGasUsed, h2.BlobGasUsed)
+ }
+ if !reflect.DeepEqual(h.ExcessBlobGas, h2.ExcessBlobGas) {
+ return fmt.Errorf("excessBlobGas: want: %v have: %v", h.ExcessBlobGas, h2.ExcessBlobGas)
+ }
+ if !reflect.DeepEqual(h.ParentBeaconBlockRoot, h2.ParentBeaconRoot) {
+ return fmt.Errorf("parentBeaconBlockRoot: want: %v have: %v", h.ParentBeaconBlockRoot, h2.ParentBeaconRoot)
+ }
return nil
}
@@ -303,7 +328,7 @@ func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
for addr, acct := range t.json.Post {
// address is indirectly verified by the other fields, as it's the db key
code2 := statedb.GetCode(addr)
- balance2 := statedb.GetBalance(addr)
+ balance2 := statedb.GetBalance(addr).ToBig()
nonce2 := statedb.GetNonce(addr)
if !bytes.Equal(code2, acct.Code) {
return fmt.Errorf("account code mismatch for addr: %s want: %v have: %s", addr, acct.Code, hex.EncodeToString(code2))
@@ -314,6 +339,12 @@ func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
if nonce2 != acct.Nonce {
return fmt.Errorf("account nonce mismatch for addr: %s want: %d have: %d", addr, acct.Nonce, nonce2)
}
+ for k, v := range acct.Storage {
+ v2 := statedb.GetState(addr, k)
+ if v2 != v {
+ return fmt.Errorf("account storage mismatch for addr: %s, slot: %x, want: %x, have: %x", addr, k, v, v2)
+ }
+ }
}
return nil
}
diff --git a/tests/fuzzers/abi/abifuzzer_test.go b/tests/fuzzers/abi/abifuzzer_test.go
deleted file mode 100644
index c66399e1b7..0000000000
--- a/tests/fuzzers/abi/abifuzzer_test.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package abi
-
-import (
- "testing"
-)
-
-// TestReplicate can be used to replicate crashers from the fuzzing tests.
-// Just replace testString with the data in .quoted
-func TestReplicate(t *testing.T) {
- testString := "\x20\x20\x20\x20\x20\x20\x20\x20\x80\x00\x00\x00\x20\x20\x20\x20\x00"
- data := []byte(testString)
- runFuzzer(data)
-}
-
-// TestGenerateCorpus can be used to add corpus for the fuzzer.
-// Just replace corpusHex with the hexEncoded output you want to add to the fuzzer.
-func TestGenerateCorpus(t *testing.T) {
- /*
- corpusHex := "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
- data := common.FromHex(corpusHex)
- checksum := sha1.Sum(data)
- outf := fmt.Sprintf("corpus/%x", checksum)
- if err := os.WriteFile(outf, data, 0777); err != nil {
- panic(err)
- }
- */
-}
diff --git a/tests/fuzzers/bitutil/compress_fuzz.go b/tests/fuzzers/bitutil/compress_fuzz.go
deleted file mode 100644
index 5903cf2f93..0000000000
--- a/tests/fuzzers/bitutil/compress_fuzz.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package bitutil
-
-import (
- "bytes"
-
- "github.com/ethereum/go-ethereum/common/bitutil"
-)
-
-// Fuzz implements a go-fuzz fuzzer method to test various encoding method
-// invocations.
-func Fuzz(data []byte) int {
- if len(data) == 0 {
- return 0
- }
- if data[0]%2 == 0 {
- return fuzzEncode(data[1:])
- }
- return fuzzDecode(data[1:])
-}
-
-// fuzzEncode implements a go-fuzz fuzzer method to test the bitset encoding and
-// decoding algorithm.
-func fuzzEncode(data []byte) int {
- proc, _ := bitutil.DecompressBytes(bitutil.CompressBytes(data), len(data))
- if !bytes.Equal(data, proc) {
- panic("content mismatch")
- }
- return 1
-}
-
-// fuzzDecode implements a go-fuzz fuzzer method to test the bit decoding and
-// reencoding algorithm.
-func fuzzDecode(data []byte) int {
- blob, err := bitutil.DecompressBytes(data, 1024)
- if err != nil {
- return 0
- }
- // re-compress it (it's OK if the re-compressed differs from the
- // original - the first input may not have been compressed at all)
- comp := bitutil.CompressBytes(blob)
- if len(comp) > len(blob) {
- // After compression, it must be smaller or equal
- panic("bad compression")
- }
- // But decompressing it once again should work
- decomp, err := bitutil.DecompressBytes(data, 1024)
- if err != nil {
- panic(err)
- }
- if !bytes.Equal(decomp, blob) {
- panic("content mismatch")
- }
- return 1
-}
diff --git a/tests/fuzzers/bls12381/bls12381_fuzz.go b/tests/fuzzers/bls12381/bls12381_fuzz.go
index ced87dd41a..9a5c566540 100644
--- a/tests/fuzzers/bls12381/bls12381_fuzz.go
+++ b/tests/fuzzers/bls12381/bls12381_fuzz.go
@@ -14,8 +14,8 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build gofuzz
-// +build gofuzz
+//go:build cgo
+// +build cgo
package bls
@@ -35,7 +35,7 @@ import (
blst "github.com/supranational/blst/bindings/go"
)
-func FuzzCrossPairing(data []byte) int {
+func fuzzCrossPairing(data []byte) int {
input := bytes.NewReader(data)
// get random G1 points
@@ -101,7 +101,7 @@ func massageBLST(in []byte) []byte {
return out
}
-func FuzzCrossG1Add(data []byte) int {
+func fuzzCrossG1Add(data []byte) int {
input := bytes.NewReader(data)
// get random G1 points
@@ -139,7 +139,7 @@ func FuzzCrossG1Add(data []byte) int {
return 1
}
-func FuzzCrossG2Add(data []byte) int {
+func fuzzCrossG2Add(data []byte) int {
input := bytes.NewReader(data)
// get random G2 points
@@ -177,7 +177,7 @@ func FuzzCrossG2Add(data []byte) int {
return 1
}
-func FuzzCrossG1MultiExp(data []byte) int {
+func fuzzCrossG1MultiExp(data []byte) int {
var (
input = bytes.NewReader(data)
gethScalars []*big.Int
diff --git a/tests/fuzzers/bls12381/bls12381_test.go b/tests/fuzzers/bls12381/bls12381_test.go
new file mode 100644
index 0000000000..3e88979d16
--- /dev/null
+++ b/tests/fuzzers/bls12381/bls12381_test.go
@@ -0,0 +1,100 @@
+// Copyright 2023 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 .
+
+//go:build cgo
+// +build cgo
+
+package bls
+
+import "testing"
+
+func FuzzCrossPairing(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzCrossPairing(data)
+ })
+}
+
+func FuzzCrossG1Add(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzCrossG1Add(data)
+ })
+}
+
+func FuzzCrossG2Add(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzCrossG2Add(data)
+ })
+}
+
+func FuzzCrossG1MultiExp(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzCrossG1MultiExp(data)
+ })
+}
+
+func FuzzG1Add(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsG1Add, data)
+ })
+}
+
+func FuzzG1Mul(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsG1Mul, data)
+ })
+}
+
+func FuzzG1MultiExp(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsG1MultiExp, data)
+ })
+}
+
+func FuzzG2Add(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsG2Add, data)
+ })
+}
+
+func FuzzG2Mul(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsG2Mul, data)
+ })
+}
+
+func FuzzG2MultiExp(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsG2MultiExp, data)
+ })
+}
+
+func FuzzPairing(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsPairing, data)
+ })
+}
+
+func FuzzMapG1(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsMapG1, data)
+ })
+}
+
+func FuzzMapG2(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(blsMapG2, data)
+ })
+}
diff --git a/tests/fuzzers/bls12381/precompile_fuzzer.go b/tests/fuzzers/bls12381/precompile_fuzzer.go
index cab2bcba38..763ed56e9f 100644
--- a/tests/fuzzers/bls12381/precompile_fuzzer.go
+++ b/tests/fuzzers/bls12381/precompile_fuzzer.go
@@ -36,16 +36,6 @@ const (
blsMapG2 = byte(18)
)
-func FuzzG1Add(data []byte) int { return fuzz(blsG1Add, data) }
-func FuzzG1Mul(data []byte) int { return fuzz(blsG1Mul, data) }
-func FuzzG1MultiExp(data []byte) int { return fuzz(blsG1MultiExp, data) }
-func FuzzG2Add(data []byte) int { return fuzz(blsG2Add, data) }
-func FuzzG2Mul(data []byte) int { return fuzz(blsG2Mul, data) }
-func FuzzG2MultiExp(data []byte) int { return fuzz(blsG2MultiExp, data) }
-func FuzzPairing(data []byte) int { return fuzz(blsPairing, data) }
-func FuzzMapG1(data []byte) int { return fuzz(blsMapG1, data) }
-func FuzzMapG2(data []byte) int { return fuzz(blsMapG2, data) }
-
func checkInput(id byte, inputLen int) bool {
switch id {
case blsG1Add:
diff --git a/tests/fuzzers/bn256/bn256_fuzz.go b/tests/fuzzers/bn256/bn256_fuzz.go
index abf1b88615..75f7d59dee 100644
--- a/tests/fuzzers/bn256/bn256_fuzz.go
+++ b/tests/fuzzers/bn256/bn256_fuzz.go
@@ -14,9 +14,6 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build gofuzz
-// +build gofuzz
-
package bn256
import (
@@ -64,8 +61,8 @@ func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine)
return xc, xg, xs
}
-// FuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
-func FuzzAdd(data []byte) int {
+// fuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
+func fuzzAdd(data []byte) int {
input := bytes.NewReader(data)
xc, xg, xs := getG1Points(input)
if xc == nil {
@@ -97,9 +94,9 @@ func FuzzAdd(data []byte) int {
return 1
}
-// FuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare
+// fuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare
// libraries.
-func FuzzMul(data []byte) int {
+func fuzzMul(data []byte) int {
input := bytes.NewReader(data)
pc, pg, ps := getG1Points(input)
if pc == nil {
@@ -139,7 +136,7 @@ func FuzzMul(data []byte) int {
return 1
}
-func FuzzPair(data []byte) int {
+func fuzzPair(data []byte) int {
input := bytes.NewReader(data)
pc, pg, ps := getG1Points(input)
if pc == nil {
diff --git a/internal/debug/trace_fallback.go b/tests/fuzzers/bn256/bn256_test.go
similarity index 67%
rename from internal/debug/trace_fallback.go
rename to tests/fuzzers/bn256/bn256_test.go
index ec07d991ef..8b2f962284 100644
--- a/internal/debug/trace_fallback.go
+++ b/tests/fuzzers/bn256/bn256_test.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2023 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
@@ -14,19 +14,24 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build !go1.5
-// +build !go1.5
+package bn256
-// no-op implementation of tracing methods for Go < 1.5.
+import "testing"
-package debug
-
-import "errors"
+func FuzzAdd(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzAdd(data)
+ })
+}
-func (*HandlerT) StartGoTrace(string) error {
- return errors.New("tracing is not supported on Go < 1.5")
+func FuzzMul(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzMul(data)
+ })
}
-func (*HandlerT) StopGoTrace() error {
- return errors.New("tracing is not supported on Go < 1.5")
+func FuzzPair(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzPair(data)
+ })
}
diff --git a/tests/fuzzers/difficulty/debug/main.go b/tests/fuzzers/difficulty/debug/main.go
deleted file mode 100644
index 70cf092568..0000000000
--- a/tests/fuzzers/difficulty/debug/main.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package main
-
-import (
- "fmt"
- "os"
-
- "github.com/ethereum/go-ethereum/tests/fuzzers/difficulty"
-)
-
-func main() {
- if len(os.Args) != 2 {
- fmt.Fprintf(os.Stderr, "Usage: debug ")
- os.Exit(1)
- }
- crasher := os.Args[1]
- data, err := os.ReadFile(crasher)
- if err != nil {
- fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
- os.Exit(1)
- }
- difficulty.Fuzz(data)
-}
diff --git a/tests/fuzzers/difficulty/difficulty-fuzz.go b/tests/fuzzers/difficulty/difficulty-fuzz.go
index e8753bb623..fbbd7f6876 100644
--- a/tests/fuzzers/difficulty/difficulty-fuzz.go
+++ b/tests/fuzzers/difficulty/difficulty-fuzz.go
@@ -75,7 +75,7 @@ func (f *fuzzer) readBool() bool {
// - 0 otherwise
//
// other values are reserved for future use.
-func Fuzz(data []byte) int {
+func fuzz(data []byte) int {
f := fuzzer{
input: bytes.NewReader(data),
exhausted: false,
diff --git a/internal/debug/loudpanic_fallback.go b/tests/fuzzers/difficulty/difficulty_test.go
similarity index 78%
rename from internal/debug/loudpanic_fallback.go
rename to tests/fuzzers/difficulty/difficulty_test.go
index 377490e5be..49beedb486 100644
--- a/internal/debug/loudpanic_fallback.go
+++ b/tests/fuzzers/difficulty/difficulty_test.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2023 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
@@ -14,12 +14,12 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build !go1.6
-// +build !go1.6
+package difficulty
-package debug
+import "testing"
-// LoudPanic panics in a way that gets all goroutine stacks printed on stderr.
-func LoudPanic(x interface{}) {
- panic(x)
+func Fuzz(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(data)
+ })
}
diff --git a/tests/fuzzers/keystore/corpus/0176eaf52ed014ec5c91cf4afa070dd3fd469077-1 b/tests/fuzzers/keystore/corpus/0176eaf52ed014ec5c91cf4afa070dd3fd469077-1
deleted file mode 100644
index 1c0ecf5250..0000000000
--- a/tests/fuzzers/keystore/corpus/0176eaf52ed014ec5c91cf4afa070dd3fd469077-1
+++ /dev/null
@@ -1 +0,0 @@
-ns,
\ No newline at end of file
diff --git a/tests/fuzzers/rangeproof/debug/main.go b/tests/fuzzers/rangeproof/debug/main.go
deleted file mode 100644
index d4cab8ec46..0000000000
--- a/tests/fuzzers/rangeproof/debug/main.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package main
-
-import (
- "fmt"
- "os"
-
- "github.com/ethereum/go-ethereum/tests/fuzzers/rangeproof"
-)
-
-func main() {
- if len(os.Args) != 2 {
- fmt.Fprintf(os.Stderr, "Usage: debug \n")
- fmt.Fprintf(os.Stderr, "Example\n")
- fmt.Fprintf(os.Stderr, " $ debug ../crashers/4bbef6857c733a87ecf6fd8b9e7238f65eb9862a\n")
- os.Exit(1)
- }
- crasher := os.Args[1]
- data, err := os.ReadFile(crasher)
- if err != nil {
- fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
- os.Exit(1)
- }
- rangeproof.Fuzz(data)
-}
diff --git a/tests/fuzzers/rangeproof/rangeproof-fuzzer.go b/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
index ba490b761f..6b5ca90880 100644
--- a/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
+++ b/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
@@ -128,7 +128,7 @@ func (f *fuzzer) fuzz() int {
if len(keys) == 0 {
return 0
}
- var first, last = keys[0], keys[len(keys)-1]
+ var first = keys[0]
testcase %= 6
switch testcase {
case 0:
@@ -165,7 +165,7 @@ func (f *fuzzer) fuzz() int {
}
ok = 1
//nodes, subtrie
- hasMore, err := trie.VerifyRangeProof(tr.Hash(), first, last, keys, vals, proof)
+ hasMore, err := trie.VerifyRangeProof(tr.Hash(), first, keys, vals, proof)
if err != nil {
if hasMore {
panic("err != nil && hasMore == true")
@@ -185,7 +185,7 @@ func (f *fuzzer) fuzz() int {
// - 0 otherwise
//
// other values are reserved for future use.
-func Fuzz(input []byte) int {
+func fuzz(input []byte) int {
if len(input) < 100 {
return 0
}
diff --git a/tests/fuzzers/rangeproof/rangeproof_test.go b/tests/fuzzers/rangeproof/rangeproof_test.go
new file mode 100644
index 0000000000..bc7badc5b3
--- /dev/null
+++ b/tests/fuzzers/rangeproof/rangeproof_test.go
@@ -0,0 +1,25 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package rangeproof
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(data)
+ })
+}
diff --git a/tests/fuzzers/rlp/corpus/block_with_uncle.rlp b/tests/fuzzers/rlp/corpus/block_with_uncle.rlp
deleted file mode 100644
index 1b49fe6a09..0000000000
Binary files a/tests/fuzzers/rlp/corpus/block_with_uncle.rlp and /dev/null differ
diff --git a/tests/fuzzers/rlp/corpus/r.bin b/tests/fuzzers/rlp/corpus/r.bin
deleted file mode 100644
index cb98a76a8a..0000000000
--- a/tests/fuzzers/rlp/corpus/r.bin
+++ /dev/null
@@ -1 +0,0 @@
-ˀ
\ No newline at end of file
diff --git a/tests/fuzzers/rlp/corpus/transaction.rlp b/tests/fuzzers/rlp/corpus/transaction.rlp
deleted file mode 100644
index 80eea1aec6..0000000000
--- a/tests/fuzzers/rlp/corpus/transaction.rlp
+++ /dev/null
@@ -1,2 +0,0 @@
-N
-aP?-'{ЋDYfj\E~읕F?1(ij6@vLڑ
\ No newline at end of file
diff --git a/tests/fuzzers/rlp/rlp_fuzzer.go b/tests/fuzzers/rlp/rlp_fuzzer.go
deleted file mode 100644
index 9fcdb57769..0000000000
--- a/tests/fuzzers/rlp/rlp_fuzzer.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2019 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package rlp
-
-import (
- "bytes"
- "fmt"
- "math/big"
-
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/rlp"
- "github.com/holiman/uint256"
-)
-
-func decodeEncode(input []byte, val interface{}, i int) {
- if err := rlp.DecodeBytes(input, val); err == nil {
- output, err := rlp.EncodeToBytes(val)
- if err != nil {
- panic(err)
- }
- if !bytes.Equal(input, output) {
- panic(fmt.Sprintf("case %d: encode-decode is not equal, \ninput : %x\noutput: %x", i, input, output))
- }
- }
-}
-
-func Fuzz(input []byte) int {
- if len(input) == 0 {
- return 0
- }
- if len(input) > 500*1024 {
- return 0
- }
-
- var i int
- {
- rlp.Split(input)
- }
- {
- if elems, _, err := rlp.SplitList(input); err == nil {
- rlp.CountValues(elems)
- }
- }
-
- {
- rlp.NewStream(bytes.NewReader(input), 0).Decode(new(interface{}))
- }
-
- {
- decodeEncode(input, new(interface{}), i)
- i++
- }
- {
- var v struct {
- Int uint
- String string
- Bytes []byte
- }
- decodeEncode(input, &v, i)
- i++
- }
-
- {
- type Types struct {
- Bool bool
- Raw rlp.RawValue
- Slice []*Types
- Iface []interface{}
- }
- var v Types
- decodeEncode(input, &v, i)
- i++
- }
- {
- type AllTypes struct {
- Int uint
- String string
- Bytes []byte
- Bool bool
- Raw rlp.RawValue
- Slice []*AllTypes
- Array [3]*AllTypes
- Iface []interface{}
- }
- var v AllTypes
- decodeEncode(input, &v, i)
- i++
- }
- {
- decodeEncode(input, [10]byte{}, i)
- i++
- }
- {
- var v struct {
- Byte [10]byte
- Rool [10]bool
- }
- decodeEncode(input, &v, i)
- i++
- }
- {
- var h types.Header
- decodeEncode(input, &h, i)
- i++
- var b types.Block
- decodeEncode(input, &b, i)
- i++
- var t types.Transaction
- decodeEncode(input, &t, i)
- i++
- var txs types.Transactions
- decodeEncode(input, &txs, i)
- i++
- var rs types.Receipts
- decodeEncode(input, &rs, i)
- }
- {
- i++
- var v struct {
- AnIntPtr *big.Int
- AnInt big.Int
- AnU256Ptr *uint256.Int
- AnU256 uint256.Int
- NotAnU256 [4]uint64
- }
- decodeEncode(input, &v, i)
- }
- return 1
-}
diff --git a/tests/fuzzers/secp256k1/secp_fuzzer.go b/tests/fuzzers/secp256k1/secp_fuzzer.go
deleted file mode 100644
index 47083d5fe3..0000000000
--- a/tests/fuzzers/secp256k1/secp_fuzzer.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 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 .
-
-// build +gofuzz
-
-package secp256k1
-
-import (
- "fmt"
-
- "github.com/btcsuite/btcd/btcec/v2"
- "github.com/ethereum/go-ethereum/crypto/secp256k1"
- fuzz "github.com/google/gofuzz"
-)
-
-func Fuzz(input []byte) int {
- var (
- fuzzer = fuzz.NewFromGoFuzz(input)
- curveA = secp256k1.S256()
- curveB = btcec.S256()
- dataP1 []byte
- dataP2 []byte
- )
- // first point
- fuzzer.Fuzz(&dataP1)
- x1, y1 := curveB.ScalarBaseMult(dataP1)
- // second point
- fuzzer.Fuzz(&dataP2)
- x2, y2 := curveB.ScalarBaseMult(dataP2)
- resAX, resAY := curveA.Add(x1, y1, x2, y2)
- resBX, resBY := curveB.Add(x1, y1, x2, y2)
- if resAX.Cmp(resBX) != 0 || resAY.Cmp(resBY) != 0 {
- fmt.Printf("%s %s %s %s\n", x1, y1, x2, y2)
- panic(fmt.Sprintf("Addition failed: geth: %s %s btcd: %s %s", resAX, resAY, resBX, resBY))
- }
- return 0
-}
diff --git a/tests/fuzzers/secp256k1/secp_test.go b/tests/fuzzers/secp256k1/secp_test.go
index 0ca16cb9bf..ca3039764b 100644
--- a/tests/fuzzers/secp256k1/secp_test.go
+++ b/tests/fuzzers/secp256k1/secp_test.go
@@ -16,9 +16,38 @@
package secp256k1
-import "testing"
+import (
+ "fmt"
+ "testing"
+
+ "github.com/btcsuite/btcd/btcec/v2"
+ "github.com/ethereum/go-ethereum/crypto/secp256k1"
+)
func TestFuzzer(t *testing.T) {
- test := "00000000N0000000/R00000000000000000U0000S0000000mkhP000000000000000U"
- Fuzz([]byte(test))
+ a, b := "00000000N0000000/R0000000000000000", "0U0000S0000000mkhP000000000000000U"
+ fuzz([]byte(a), []byte(b))
+}
+
+func Fuzz(f *testing.F) {
+ f.Fuzz(func(t *testing.T, a, b []byte) {
+ fuzz(a, b)
+ })
+}
+
+func fuzz(dataP1, dataP2 []byte) {
+ var (
+ curveA = secp256k1.S256()
+ curveB = btcec.S256()
+ )
+ // first point
+ x1, y1 := curveB.ScalarBaseMult(dataP1)
+ // second points
+ x2, y2 := curveB.ScalarBaseMult(dataP2)
+ resAX, resAY := curveA.Add(x1, y1, x2, y2)
+ resBX, resBY := curveB.Add(x1, y1, x2, y2)
+ if resAX.Cmp(resBX) != 0 || resAY.Cmp(resBY) != 0 {
+ fmt.Printf("%s %s %s %s\n", x1, y1, x2, y2)
+ panic(fmt.Sprintf("Addition failed: geth: %s %s btcd: %s %s", resAX, resAY, resBX, resBY))
+ }
}
diff --git a/tests/fuzzers/stacktrie/debug/main.go b/tests/fuzzers/stacktrie/debug/main.go
deleted file mode 100644
index 6b634f05c2..0000000000
--- a/tests/fuzzers/stacktrie/debug/main.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package main
-
-import (
- "fmt"
- "os"
-
- "github.com/ethereum/go-ethereum/tests/fuzzers/stacktrie"
-)
-
-func main() {
- if len(os.Args) != 2 {
- fmt.Fprintf(os.Stderr, "Usage: debug ")
- os.Exit(1)
- }
- crasher := os.Args[1]
- data, err := os.ReadFile(crasher)
- if err != nil {
- fmt.Fprintf(os.Stderr, "error loading crasher %v: %v", crasher, err)
- os.Exit(1)
- }
- stacktrie.Debug(data)
-}
diff --git a/tests/fuzzers/stacktrie/trie_fuzzer.go b/tests/fuzzers/stacktrie/trie_fuzzer.go
deleted file mode 100644
index b818f2ec3c..0000000000
--- a/tests/fuzzers/stacktrie/trie_fuzzer.go
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package stacktrie
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "hash"
- "io"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/trienode"
- "golang.org/x/crypto/sha3"
- "golang.org/x/exp/slices"
-)
-
-type fuzzer struct {
- input io.Reader
- exhausted bool
- debugging bool
-}
-
-func (f *fuzzer) read(size int) []byte {
- out := make([]byte, size)
- if _, err := f.input.Read(out); err != nil {
- f.exhausted = true
- }
- return out
-}
-
-func (f *fuzzer) readSlice(min, max int) []byte {
- var a uint16
- binary.Read(f.input, binary.LittleEndian, &a)
- size := min + int(a)%(max-min)
- out := make([]byte, size)
- if _, err := f.input.Read(out); err != nil {
- f.exhausted = true
- }
- return out
-}
-
-// spongeDb is a dummy db backend which accumulates writes in a sponge
-type spongeDb struct {
- sponge hash.Hash
- debug bool
-}
-
-func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") }
-func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, errors.New("no such elem") }
-func (s *spongeDb) Delete(key []byte) error { panic("implement me") }
-func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} }
-func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} }
-func (s *spongeDb) NewSnapshot() (ethdb.Snapshot, error) { panic("implement me") }
-func (s *spongeDb) Stat(property string) (string, error) { panic("implement me") }
-func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
-func (s *spongeDb) Close() error { return nil }
-
-func (s *spongeDb) Put(key []byte, value []byte) error {
- if s.debug {
- fmt.Printf("db.Put %x : %x\n", key, value)
- }
- s.sponge.Write(key)
- s.sponge.Write(value)
- return nil
-}
-func (s *spongeDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { panic("implement me") }
-
-// spongeBatch is a dummy batch which immediately writes to the underlying spongedb
-type spongeBatch struct {
- db *spongeDb
-}
-
-func (b *spongeBatch) Put(key, value []byte) error {
- b.db.Put(key, value)
- return nil
-}
-func (b *spongeBatch) Delete(key []byte) error { panic("implement me") }
-func (b *spongeBatch) ValueSize() int { return 100 }
-func (b *spongeBatch) Write() error { return nil }
-func (b *spongeBatch) Reset() {}
-func (b *spongeBatch) Replay(w ethdb.KeyValueWriter) error { return nil }
-
-type kv struct {
- k, v []byte
-}
-
-// Fuzz is the fuzzing entry-point.
-// The function must return
-//
-// - 1 if the fuzzer should increase priority of the
-// given input during subsequent fuzzing (for example, the input is lexically
-// correct and was parsed successfully);
-// - -1 if the input must not be added to corpus even if gives new coverage; and
-// - 0 otherwise
-//
-// other values are reserved for future use.
-func Fuzz(data []byte) int {
- f := fuzzer{
- input: bytes.NewReader(data),
- exhausted: false,
- }
- return f.fuzz()
-}
-
-func Debug(data []byte) int {
- f := fuzzer{
- input: bytes.NewReader(data),
- exhausted: false,
- debugging: true,
- }
- return f.fuzz()
-}
-
-func (f *fuzzer) fuzz() int {
- // This spongeDb is used to check the sequence of disk-db-writes
- var (
- spongeA = &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- dbA = trie.NewDatabase(rawdb.NewDatabase(spongeA), nil)
- trieA = trie.NewEmpty(dbA)
- spongeB = &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- dbB = trie.NewDatabase(rawdb.NewDatabase(spongeB), nil)
-
- options = trie.NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(spongeB, common.Hash{}, path, hash, blob, dbB.Scheme())
- })
- trieB = trie.NewStackTrie(options)
- vals []kv
- useful bool
- maxElements = 10000
- // operate on unique keys only
- keys = make(map[string]struct{})
- )
- // Fill the trie with elements
- for i := 0; !f.exhausted && i < maxElements; i++ {
- k := f.read(32)
- v := f.readSlice(1, 500)
- if f.exhausted {
- // If it was exhausted while reading, the value may be all zeroes,
- // thus 'deletion' which is not supported on stacktrie
- break
- }
- if _, present := keys[string(k)]; present {
- // This key is a duplicate, ignore it
- continue
- }
- keys[string(k)] = struct{}{}
- vals = append(vals, kv{k: k, v: v})
- trieA.MustUpdate(k, v)
- useful = true
- }
- if !useful {
- return 0
- }
- // Flush trie -> database
- rootA, nodes, err := trieA.Commit(false)
- if err != nil {
- panic(err)
- }
- if nodes != nil {
- dbA.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- }
- // Flush memdb -> disk (sponge)
- dbA.Commit(rootA, false)
-
- // Stacktrie requires sorted insertion
- slices.SortFunc(vals, func(a, b kv) int {
- return bytes.Compare(a.k, b.k)
- })
- for _, kv := range vals {
- if f.debugging {
- fmt.Printf("{\"%#x\" , \"%#x\"} // stacktrie.Update\n", kv.k, kv.v)
- }
- trieB.MustUpdate(kv.k, kv.v)
- }
- rootB := trieB.Hash()
- trieB.Commit()
- if rootA != rootB {
- panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootB))
- }
- sumA := spongeA.sponge.Sum(nil)
- sumB := spongeB.sponge.Sum(nil)
- if !bytes.Equal(sumA, sumB) {
- panic(fmt.Sprintf("sequence differ: (trie) %x != %x (stacktrie)", sumA, sumB))
- }
-
- // Ensure all the nodes are persisted correctly
- var (
- nodeset = make(map[string][]byte) // path -> blob
- optionsC = trie.NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- if crypto.Keccak256Hash(blob) != hash {
- panic("invalid node blob")
- }
- nodeset[string(path)] = common.CopyBytes(blob)
- })
- trieC = trie.NewStackTrie(optionsC)
- checked int
- )
- for _, kv := range vals {
- trieC.MustUpdate(kv.k, kv.v)
- }
- rootC := trieC.Commit()
- if rootA != rootC {
- panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootC))
- }
- trieA, _ = trie.New(trie.TrieID(rootA), dbA)
- iterA := trieA.MustNodeIterator(nil)
- for iterA.Next(true) {
- if iterA.Hash() == (common.Hash{}) {
- if _, present := nodeset[string(iterA.Path())]; present {
- panic("unexpected tiny node")
- }
- continue
- }
- nodeBlob, present := nodeset[string(iterA.Path())]
- if !present {
- panic("missing node")
- }
- if !bytes.Equal(nodeBlob, iterA.NodeBlob()) {
- panic("node blob is not matched")
- }
- checked += 1
- }
- if checked != len(nodeset) {
- panic("node number is not matched")
- }
- return 1
-}
diff --git a/tests/fuzzers/trie/corpus/data b/tests/fuzzers/trie/corpus/data
deleted file mode 100644
index c4a4839cb8..0000000000
--- a/tests/fuzzers/trie/corpus/data
+++ /dev/null
@@ -1 +0,0 @@
-asdlfkjasf23oiejfasdfadkfqlkjfasdlkfjalwk4jfalsdkfjawlefkjsadlfkjasldkfjwalefkjasdlfkjM
\ No newline at end of file
diff --git a/tests/fuzzers/trie/trie-fuzzer.go b/tests/fuzzers/trie/trie-fuzzer.go
deleted file mode 100644
index 687f5efb1c..0000000000
--- a/tests/fuzzers/trie/trie-fuzzer.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2019 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package trie
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
-
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/trienode"
-)
-
-// randTest performs random trie operations.
-// Instances of this test are created by Generate.
-type randTest []randTestStep
-
-type randTestStep struct {
- op int
- key []byte // for opUpdate, opDelete, opGet
- value []byte // for opUpdate
- err error // for debugging
-}
-
-type proofDb struct{}
-
-func (proofDb) Put(key []byte, value []byte) error {
- return nil
-}
-
-func (proofDb) Delete(key []byte) error {
- return nil
-}
-
-const (
- opUpdate = iota
- opDelete
- opGet
- opHash
- opCommit
- opItercheckhash
- opProve
- opMax // boundary value, not an actual op
-)
-
-type dataSource struct {
- input []byte
- reader *bytes.Reader
-}
-
-func newDataSource(input []byte) *dataSource {
- return &dataSource{
- input, bytes.NewReader(input),
- }
-}
-func (ds *dataSource) readByte() byte {
- if b, err := ds.reader.ReadByte(); err != nil {
- return 0
- } else {
- return b
- }
-}
-func (ds *dataSource) Read(buf []byte) (int, error) {
- return ds.reader.Read(buf)
-}
-func (ds *dataSource) Ended() bool {
- return ds.reader.Len() == 0
-}
-
-func Generate(input []byte) randTest {
- var allKeys [][]byte
- r := newDataSource(input)
- genKey := func() []byte {
- if len(allKeys) < 2 || r.readByte() < 0x0f {
- // new key
- key := make([]byte, r.readByte()%50)
- r.Read(key)
- allKeys = append(allKeys, key)
- return key
- }
- // use existing key
- return allKeys[int(r.readByte())%len(allKeys)]
- }
-
- var steps randTest
-
- for i := 0; !r.Ended(); i++ {
- step := randTestStep{op: int(r.readByte()) % opMax}
- switch step.op {
- case opUpdate:
- step.key = genKey()
- step.value = make([]byte, 8)
- binary.BigEndian.PutUint64(step.value, uint64(i))
- case opGet, opDelete, opProve:
- step.key = genKey()
- }
- steps = append(steps, step)
- if len(steps) > 500 {
- break
- }
- }
-
- return steps
-}
-
-// Fuzz is the fuzzing entry-point.
-// The function must return
-//
-// - 1 if the fuzzer should increase priority of the
-// given input during subsequent fuzzing (for example, the input is lexically
-// correct and was parsed successfully);
-// - -1 if the input must not be added to corpus even if gives new coverage; and
-// - 0 otherwise
-//
-// other values are reserved for future use.
-func Fuzz(input []byte) int {
- program := Generate(input)
- if len(program) == 0 {
- return 0
- }
- if err := runRandTest(program); err != nil {
- panic(err)
- }
- return 1
-}
-
-func runRandTest(rt randTest) error {
- var (
- triedb = trie.NewDatabase(rawdb.NewMemoryDatabase(), nil)
- tr = trie.NewEmpty(triedb)
- origin = types.EmptyRootHash
- values = make(map[string]string) // tracks content of the trie
- )
- for i, step := range rt {
- switch step.op {
- case opUpdate:
- tr.MustUpdate(step.key, step.value)
- values[string(step.key)] = string(step.value)
- case opDelete:
- tr.MustDelete(step.key)
- delete(values, string(step.key))
- case opGet:
- v := tr.MustGet(step.key)
- want := values[string(step.key)]
- if string(v) != want {
- rt[i].err = fmt.Errorf("mismatch for key %#x, got %#x want %#x", step.key, v, want)
- }
- case opHash:
- tr.Hash()
- case opCommit:
- hash, nodes, err := tr.Commit(false)
- if err != nil {
- return err
- }
- if nodes != nil {
- if err := triedb.Update(hash, origin, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
- return err
- }
- }
- newtr, err := trie.New(trie.TrieID(hash), triedb)
- if err != nil {
- return err
- }
- tr = newtr
- origin = hash
- case opItercheckhash:
- checktr := trie.NewEmpty(triedb)
- it := trie.NewIterator(tr.MustNodeIterator(nil))
- for it.Next() {
- checktr.MustUpdate(it.Key, it.Value)
- }
- if tr.Hash() != checktr.Hash() {
- return errors.New("hash mismatch in opItercheckhash")
- }
- case opProve:
- rt[i].err = tr.Prove(step.key, proofDb{})
- }
- // Abort the test on error.
- if rt[i].err != nil {
- return rt[i].err
- }
- }
- return nil
-}
diff --git a/tests/fuzzers/txfetcher/txfetcher_fuzzer.go b/tests/fuzzers/txfetcher/txfetcher_fuzzer.go
index 91ca2eefb2..57173bc80c 100644
--- a/tests/fuzzers/txfetcher/txfetcher_fuzzer.go
+++ b/tests/fuzzers/txfetcher/txfetcher_fuzzer.go
@@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock"
- "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/fetcher"
)
@@ -49,7 +48,7 @@ func init() {
}
}
-func Fuzz(input []byte) int {
+func fuzz(input []byte) int {
// Don't generate insanely large test cases, not much value in them
if len(input) > 16*1024 {
return 0
@@ -80,10 +79,11 @@ func Fuzz(input []byte) int {
f := fetcher.NewTxFetcherForTests(
func(common.Hash) bool { return false },
- func(peer string, txs []*txpool.Transaction) []error {
+ func(peer string, txs []*types.Transaction) []error {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
+ nil,
clock, rand,
)
f.Start()
@@ -117,6 +117,8 @@ func Fuzz(input []byte) int {
var (
announceIdxs = make([]int, announce)
announces = make([]common.Hash, announce)
+ types = make([]byte, announce)
+ sizes = make([]uint32, announce)
)
for i := 0; i < len(announces); i++ {
annBuf := make([]byte, 2)
@@ -125,11 +127,13 @@ func Fuzz(input []byte) int {
}
announceIdxs[i] = (int(annBuf[0])*256 + int(annBuf[1])) % len(txs)
announces[i] = txs[announceIdxs[i]].Hash()
+ types[i] = txs[announceIdxs[i]].Type()
+ sizes[i] = uint32(txs[announceIdxs[i]].Size())
}
if verbose {
fmt.Println("Notify", peer, announceIdxs)
}
- if err := f.Notify(peer, announces); err != nil {
+ if err := f.Notify(peer, types, sizes, announces); err != nil {
panic(err)
}
diff --git a/tests/fuzzers/txfetcher/txfetcher_test.go b/tests/fuzzers/txfetcher/txfetcher_test.go
new file mode 100644
index 0000000000..ac2e6b1c67
--- /dev/null
+++ b/tests/fuzzers/txfetcher/txfetcher_test.go
@@ -0,0 +1,25 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package txfetcher
+
+import "testing"
+
+func Fuzz(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(data)
+ })
+}
diff --git a/tests/gen_btheader.go b/tests/gen_btheader.go
index 985ea692d7..80ad89e03b 100644
--- a/tests/gen_btheader.go
+++ b/tests/gen_btheader.go
@@ -17,24 +17,27 @@ var _ = (*btHeaderMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (b btHeader) MarshalJSON() ([]byte, error) {
type btHeader struct {
- Bloom types.Bloom
- Coinbase common.Address
- MixHash common.Hash
- Nonce types.BlockNonce
- Number *math.HexOrDecimal256
- Hash common.Hash
- ParentHash common.Hash
- ReceiptTrie common.Hash
- StateRoot common.Hash
- TransactionsTrie common.Hash
- UncleHash common.Hash
- ExtraData hexutil.Bytes
- Difficulty *math.HexOrDecimal256
- GasLimit math.HexOrDecimal64
- GasUsed math.HexOrDecimal64
- Timestamp math.HexOrDecimal64
- BaseFeePerGas *math.HexOrDecimal256
- WithdrawalsRoot *common.Hash
+ Bloom types.Bloom
+ Coinbase common.Address
+ MixHash common.Hash
+ Nonce types.BlockNonce
+ Number *math.HexOrDecimal256
+ Hash common.Hash
+ ParentHash common.Hash
+ ReceiptTrie common.Hash
+ StateRoot common.Hash
+ TransactionsTrie common.Hash
+ UncleHash common.Hash
+ ExtraData hexutil.Bytes
+ Difficulty *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
+ GasUsed math.HexOrDecimal64
+ Timestamp math.HexOrDecimal64
+ BaseFeePerGas *math.HexOrDecimal256
+ WithdrawalsRoot *common.Hash
+ BlobGasUsed *math.HexOrDecimal64
+ ExcessBlobGas *math.HexOrDecimal64
+ ParentBeaconBlockRoot *common.Hash
}
var enc btHeader
enc.Bloom = b.Bloom
@@ -55,30 +58,36 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
enc.Timestamp = math.HexOrDecimal64(b.Timestamp)
enc.BaseFeePerGas = (*math.HexOrDecimal256)(b.BaseFeePerGas)
enc.WithdrawalsRoot = b.WithdrawalsRoot
+ enc.BlobGasUsed = (*math.HexOrDecimal64)(b.BlobGasUsed)
+ enc.ExcessBlobGas = (*math.HexOrDecimal64)(b.ExcessBlobGas)
+ enc.ParentBeaconBlockRoot = b.ParentBeaconBlockRoot
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (b *btHeader) UnmarshalJSON(input []byte) error {
type btHeader struct {
- Bloom *types.Bloom
- Coinbase *common.Address
- MixHash *common.Hash
- Nonce *types.BlockNonce
- Number *math.HexOrDecimal256
- Hash *common.Hash
- ParentHash *common.Hash
- ReceiptTrie *common.Hash
- StateRoot *common.Hash
- TransactionsTrie *common.Hash
- UncleHash *common.Hash
- ExtraData *hexutil.Bytes
- Difficulty *math.HexOrDecimal256
- GasLimit *math.HexOrDecimal64
- GasUsed *math.HexOrDecimal64
- Timestamp *math.HexOrDecimal64
- BaseFeePerGas *math.HexOrDecimal256
- WithdrawalsRoot *common.Hash
+ Bloom *types.Bloom
+ Coinbase *common.Address
+ MixHash *common.Hash
+ Nonce *types.BlockNonce
+ Number *math.HexOrDecimal256
+ Hash *common.Hash
+ ParentHash *common.Hash
+ ReceiptTrie *common.Hash
+ StateRoot *common.Hash
+ TransactionsTrie *common.Hash
+ UncleHash *common.Hash
+ ExtraData *hexutil.Bytes
+ Difficulty *math.HexOrDecimal256
+ GasLimit *math.HexOrDecimal64
+ GasUsed *math.HexOrDecimal64
+ Timestamp *math.HexOrDecimal64
+ BaseFeePerGas *math.HexOrDecimal256
+ WithdrawalsRoot *common.Hash
+ BlobGasUsed *math.HexOrDecimal64
+ ExcessBlobGas *math.HexOrDecimal64
+ ParentBeaconBlockRoot *common.Hash
}
var dec btHeader
if err := json.Unmarshal(input, &dec); err != nil {
@@ -138,5 +147,14 @@ func (b *btHeader) UnmarshalJSON(input []byte) error {
if dec.WithdrawalsRoot != nil {
b.WithdrawalsRoot = dec.WithdrawalsRoot
}
+ if dec.BlobGasUsed != nil {
+ b.BlobGasUsed = (*uint64)(dec.BlobGasUsed)
+ }
+ if dec.ExcessBlobGas != nil {
+ b.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
+ }
+ if dec.ParentBeaconBlockRoot != nil {
+ b.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
+ }
return nil
}
diff --git a/tests/gen_stenv.go b/tests/gen_stenv.go
index 71f0063178..a5bd0d5fcb 100644
--- a/tests/gen_stenv.go
+++ b/tests/gen_stenv.go
@@ -16,13 +16,14 @@ var _ = (*stEnvMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (s stEnv) MarshalJSON() ([]byte, error) {
type stEnv struct {
- Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
- Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
- GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
- Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
- Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
+ Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
+ GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
+ Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
+ Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
var enc stEnv
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
@@ -32,19 +33,21 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
enc.Number = math.HexOrDecimal64(s.Number)
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
enc.BaseFee = (*math.HexOrDecimal256)(s.BaseFee)
+ enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (s *stEnv) UnmarshalJSON(input []byte) error {
type stEnv struct {
- Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
- Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
- GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
- Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
- Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
+ Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
+ GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
+ Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
+ Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
var dec stEnv
if err := json.Unmarshal(input, &dec); err != nil {
@@ -75,5 +78,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
if dec.BaseFee != nil {
s.BaseFee = (*big.Int)(dec.BaseFee)
}
+ if dec.ExcessBlobGas != nil {
+ s.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
+ }
return nil
}
diff --git a/tests/gen_sttransaction.go b/tests/gen_sttransaction.go
index f47da494fa..9b5aecbfe6 100644
--- a/tests/gen_sttransaction.go
+++ b/tests/gen_sttransaction.go
@@ -27,6 +27,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) {
GasLimit []math.HexOrDecimal64 `json:"gasLimit"`
Value []string `json:"value"`
PrivateKey hexutil.Bytes `json:"secretKey"`
+ Sender *common.Address `json:"sender"`
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
BlobGasFeeCap *math.HexOrDecimal256 `json:"maxFeePerBlobGas,omitempty"`
}
@@ -46,6 +47,7 @@ func (s stTransaction) MarshalJSON() ([]byte, error) {
}
enc.Value = s.Value
enc.PrivateKey = s.PrivateKey
+ enc.Sender = s.Sender
enc.BlobVersionedHashes = s.BlobVersionedHashes
enc.BlobGasFeeCap = (*math.HexOrDecimal256)(s.BlobGasFeeCap)
return json.Marshal(&enc)
@@ -64,6 +66,7 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error {
GasLimit []math.HexOrDecimal64 `json:"gasLimit"`
Value []string `json:"value"`
PrivateKey *hexutil.Bytes `json:"secretKey"`
+ Sender *common.Address `json:"sender"`
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
BlobGasFeeCap *math.HexOrDecimal256 `json:"maxFeePerBlobGas,omitempty"`
}
@@ -104,6 +107,9 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error {
if dec.PrivateKey != nil {
s.PrivateKey = *dec.PrivateKey
}
+ if dec.Sender != nil {
+ s.Sender = dec.Sender
+ }
if dec.BlobVersionedHashes != nil {
s.BlobVersionedHashes = dec.BlobVersionedHashes
}
diff --git a/tests/init.go b/tests/init.go
index a04e227dc7..99b7e4d333 100644
--- a/tests/init.go
+++ b/tests/init.go
@@ -318,6 +318,25 @@ var Forks = map[string]*params.ChainConfig{
ShanghaiTime: u64(0),
CancunTime: u64(0),
},
+ "ShanghaiToCancunAtTime15k": {
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: big.NewInt(0),
+ MergeNetsplitBlock: big.NewInt(0),
+ TerminalTotalDifficulty: big.NewInt(0),
+ ShanghaiTime: u64(0),
+ CancunTime: u64(15_000),
+ },
}
// AvailableForks returns the set of defined fork names
diff --git a/tests/init_test.go b/tests/init_test.go
index 46a0a86089..25511fcc07 100644
--- a/tests/init_test.go
+++ b/tests/init_test.go
@@ -41,6 +41,7 @@ var (
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
rlpTestDir = filepath.Join(baseDir, "RLPTests")
difficultyTestDir = filepath.Join(baseDir, "BasicTests")
+ executionSpecDir = filepath.Join(".", "spec-tests", "fixtures")
benchmarksDir = filepath.Join(".", "evm-benchmarks", "benchmarks")
)
@@ -250,6 +251,10 @@ func (tm *testMatcher) runTestFile(t *testing.T, path, name string, runTest inte
if r, _ := tm.findSkip(name); r != "" {
t.Skip(r)
}
+ // TODO(Nathan): fix before enable Cancun
+ if strings.Contains(key, "Cancun") {
+ return
+ }
runTestFunc(runTest, t, name, m, key)
})
}
diff --git a/tests/state_test.go b/tests/state_test.go
index 094dafcafd..18d8a0b50e 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -21,9 +21,11 @@ import (
"bytes"
"fmt"
"math/big"
+ "math/rand"
"os"
"path/filepath"
"reflect"
+ "runtime"
"strings"
"testing"
"time"
@@ -35,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
+ "github.com/holiman/uint256"
)
func TestState(t *testing.T) {
@@ -60,14 +63,6 @@ func TestState(t *testing.T) {
// EOF is not part of cancun
st.skipLoad(`^stEOF/`)
- // EIP-4844 tests need to be regenerated due to the data-to-blob rename
- st.skipLoad(`^stEIP4844-blobtransactions/`)
-
- // Expected failures:
- // These EIP-4844 tests need to be regenerated.
- st.fails(`stEIP4844-blobtransactions/opcodeBlobhashOutOfRange.json`, "test has incorrect state root")
- st.fails(`stEIP4844-blobtransactions/opcodeBlobhBounds.json`, "test has incorrect state root")
-
// For Istanbul, older tests were moved into LegacyTests
for _, dir := range []string{
filepath.Join(baseDir, "EIPTests", "StateTests"),
@@ -76,7 +71,15 @@ func TestState(t *testing.T) {
benchmarksDir,
} {
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
+ if runtime.GOARCH == "386" && runtime.GOOS == "windows" && rand.Int63()%2 == 0 {
+ t.Skip("test (randomly) skipped on 32-bit windows")
+ return
+ }
for _, subtest := range test.Subtests() {
+ // TODO(Nathan): fix before enable Cancun
+ if subtest.Fork == "Cancun" {
+ return
+ }
subtest := subtest
key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index)
@@ -281,7 +284,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
start := time.Now()
// Execute the message.
- _, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, msg.Value)
+ _, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value))
if err != nil {
b.Error(err)
return
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index d058fbf188..7253ec540a 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
@@ -41,6 +42,7 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
@@ -83,23 +85,25 @@ type stPostState struct {
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
type stEnv struct {
- Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
- Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
- Random *big.Int `json:"currentRandom" gencodec:"optional"`
- GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
- Number uint64 `json:"currentNumber" gencodec:"required"`
- Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
+ Random *big.Int `json:"currentRandom" gencodec:"optional"`
+ GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
+ Number uint64 `json:"currentNumber" gencodec:"required"`
+ Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *uint64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
type stEnvMarshaling struct {
- Coinbase common.UnprefixedAddress
- Difficulty *math.HexOrDecimal256
- Random *math.HexOrDecimal256
- GasLimit math.HexOrDecimal64
- Number math.HexOrDecimal64
- Timestamp math.HexOrDecimal64
- BaseFee *math.HexOrDecimal256
+ Coinbase common.UnprefixedAddress
+ Difficulty *math.HexOrDecimal256
+ Random *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
+ Number math.HexOrDecimal64
+ Timestamp math.HexOrDecimal64
+ BaseFee *math.HexOrDecimal256
+ ExcessBlobGas *math.HexOrDecimal64
}
//go:generate go run github.com/fjl/gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go
@@ -115,6 +119,7 @@ type stTransaction struct {
GasLimit []uint64 `json:"gasLimit"`
Value []string `json:"value"`
PrivateKey []byte `json:"secretKey"`
+ Sender *common.Address `json:"sender"`
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
BlobGasFeeCap *big.Int `json:"maxFeePerBlobGas,omitempty"`
}
@@ -199,6 +204,9 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo
if triedb != nil {
triedb.Close()
}
+ if snaps != nil {
+ snaps.Release()
+ }
}()
checkedErr := t.checkError(subtest, err)
if checkedErr != nil {
@@ -279,8 +287,22 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
context.Random = &rnd
context.Difficulty = big.NewInt(0)
}
+ if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
+ context.BlobBaseFee = eip4844.CalcBlobFee(*t.json.Env.ExcessBlobGas)
+ }
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
+ { // Blob transactions may be present after the Cancun fork.
+ // In production,
+ // - the header is verified against the max in eip4844.go:VerifyEIP4844Header
+ // - the block body is verified against the header in block_validator.go:ValidateBody
+ // Here, we just do this shortcut smaller fix, since state tests do not
+ // utilize those codepaths
+ if len(msg.BlobHashes)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
+ return nil, nil, nil, common.Hash{}, errors.New("blob gas exceeds maximum")
+ }
+ }
+
// Execute the message.
snapshot := statedb.Snapshot()
gaspool := new(core.GasPool)
@@ -296,7 +318,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
// - the coinbase self-destructed, or
// - there are only 'bad' transactions, which aren't executed. In those cases,
// the coinbase gets no txfee, so isn't created, and thus needs to be touched
- statedb.AddBalance(block.Coinbase(), new(big.Int))
+ statedb.AddBalance(block.Coinbase(), new(uint256.Int))
// And _now_ get the state root
root := statedb.IntermediateRoot(config.IsEIP158(block.Number()))
statedb.SetExpectedStateRoot(root)
@@ -321,7 +343,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter boo
for addr, a := range accounts {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce)
- statedb.SetBalance(addr, a.Balance)
+ statedb.SetBalance(addr, uint256.MustFromBig(a.Balance))
for k, v := range a.Storage {
statedb.SetState(addr, k, v)
}
@@ -339,7 +361,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter boo
NoBuild: false,
AsyncBuild: false,
}
- snaps, _ = snapshot.New(snapconfig, db, sdb.TrieDB(), root, 128, false)
+ snaps, _ = snapshot.New(snapconfig, db, triedb, root, 128, false)
}
statedb, _ = state.New(root, sdb, snaps)
return triedb, snaps, statedb
@@ -364,9 +386,12 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
}
func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Message, error) {
- // Derive sender from private key if present.
var from common.Address
- if len(tx.PrivateKey) > 0 {
+ // If 'sender' field is present, use that
+ if tx.Sender != nil {
+ from = *tx.Sender
+ } else if len(tx.PrivateKey) > 0 {
+ // Derive sender from private key if needed.
key, err := crypto.ToECDSA(tx.PrivateKey)
if err != nil {
return nil, fmt.Errorf("invalid private key: %v", err)
diff --git a/tests/testdata b/tests/testdata
index ee3fa4c86d..fa51c5c164 160000
--- a/tests/testdata
+++ b/tests/testdata
@@ -1 +1 @@
-Subproject commit ee3fa4c86d05f99f2717f83a6ad08008490ddf07
+Subproject commit fa51c5c164f79140730ccb8fe26a46c3d3994338
diff --git a/trie/database.go b/trie/database.go
index df83dd081c..aaa20257a5 100644
--- a/trie/database.go
+++ b/trie/database.go
@@ -32,14 +32,12 @@ import (
// Config defines all necessary options for database.
type Config struct {
- NoTries bool
Preimages bool // Flag whether the preimage of node key is recorded
Cache int
+ NoTries bool
+ IsVerkle bool // Flag whether the db is holding a verkle tree
HashDB *hashdb.Config // Configs for hash-based scheme
PathDB *pathdb.Config // Configs for experimental path-based scheme
-
- // Testing hooks
- OnCommit func(states *triestate.Set) // Hook invoked when commit is performed
}
// HashDefaults represents a config for using hash-based scheme with
@@ -89,20 +87,6 @@ type Database struct {
backend backend // The backend for managing trie nodes
}
-// prepare initializes the database with provided configs, but the
-// database backend is still left as nil.
-func prepare(diskdb ethdb.Database, config *Config) *Database {
- var preimages *preimageStore
- if config != nil && config.Preimages {
- preimages = newPreimageStore(diskdb)
- }
- return &Database{
- config: config,
- diskdb: diskdb,
- preimages: preimages,
- }
-}
-
// NewDatabase initializes the trie database with default settings, note
// the legacy hash-based scheme is used by default.
func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
@@ -186,9 +170,6 @@ func (db *Database) Reader(blockRoot common.Hash) (Reader, error) {
// The passed in maps(nodes, states) will be retained to avoid copying everything.
// Therefore, these maps must not be changed afterwards.
func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error {
- if db.config != nil && db.config.OnCommit != nil {
- db.config.OnCommit(states)
- }
if db.preimages != nil {
db.preimages.commit(false)
}
@@ -205,8 +186,9 @@ func (db *Database) Commit(root common.Hash, report bool) error {
return db.backend.Commit(root, report)
}
-// Size returns the storage size of dirty trie nodes in front of the persistent
-// database and the size of cached preimages.
+// Size returns the storage size of diff layer nodes above the persistent disk
+// layer, the dirty nodes buffered within the disk layer, and the size of cached
+// preimages.
func (db *Database) Size() (common.StorageSize, common.StorageSize, common.StorageSize, common.StorageSize) {
var (
diffs, nodes, immutablenodes common.StorageSize
@@ -245,6 +227,15 @@ func (db *Database) WritePreimages() {
}
}
+// Preimage retrieves a cached trie node pre-image from memory. If it cannot be
+// found cached, the method queries the persistent database for the content.
+func (db *Database) Preimage(hash common.Hash) []byte {
+ if db.preimages == nil {
+ return nil
+ }
+ return db.preimages.preimage(hash)
+}
+
// Cap iteratively flushes old but still referenced trie nodes until the total
// memory usage goes below the given threshold. The held pre-images accumulated
// up to this point will be flushed in case the size exceeds the threshold.
@@ -286,17 +277,6 @@ func (db *Database) Dereference(root common.Hash) error {
return nil
}
-// Node retrieves the rlp-encoded node blob with provided node hash. It's
-// only supported by hash-based database and will return an error for others.
-// Note, this function should be deprecated once ETH66 is deprecated.
-func (db *Database) Node(hash common.Hash) ([]byte, error) {
- hdb, ok := db.backend.(*hashdb.Database)
- if !ok {
- return nil, errors.New("not supported")
- }
- return hdb.Node(hash)
-}
-
// Recover rollbacks the database to a specified historical point. The state is
// supported as the rollback destination only if it's canonical state and the
// corresponding trie histories are existent. It's only supported by path-based
@@ -320,15 +300,27 @@ func (db *Database) Recoverable(root common.Hash) (bool, error) {
return pdb.Recoverable(root), nil
}
-// Reset wipes all available journal from the persistent database and discard
-// all caches and diff layers. Using the given root to create a new disk layer.
+// Disable deactivates the database and invalidates all available state layers
+// as stale to prevent access to the persistent state, which is in the syncing
+// stage.
+//
// It's only supported by path-based database and will return an error for others.
-func (db *Database) Reset(root common.Hash) error {
+func (db *Database) Disable() error {
pdb, ok := db.backend.(*pathdb.Database)
if !ok {
return errors.New("not supported")
}
- return pdb.Reset(root)
+ return pdb.Disable()
+}
+
+// Enable activates database and resets the state tree with the provided persistent
+// state root once the state sync is finished.
+func (db *Database) Enable(root common.Hash) error {
+ pdb, ok := db.backend.(*pathdb.Database)
+ if !ok {
+ return errors.New("not supported")
+ }
+ return pdb.Enable(root)
}
// Journal commits an entire diff hierarchy to disk into a single journal entry.
@@ -376,3 +368,8 @@ func (db *Database) GetAllRooHash() [][]string {
}
return pdb.GetAllRooHash()
}
+
+// IsVerkle returns the indicator if the database is holding a verkle tree.
+func (db *Database) IsVerkle() bool {
+ return db.config.IsVerkle
+}
diff --git a/trie/database_test.go b/trie/database_test.go
index d675a2191b..d508c65533 100644
--- a/trie/database_test.go
+++ b/trie/database_test.go
@@ -25,11 +25,16 @@ import (
// newTestDatabase initializes the trie database with specified scheme.
func newTestDatabase(diskdb ethdb.Database, scheme string) *Database {
- db := prepare(diskdb, nil)
+ config := &Config{Preimages: false}
if scheme == rawdb.HashScheme {
- db.backend = hashdb.New(diskdb, &hashdb.Config{}, mptResolver{})
+ config.HashDB = &hashdb.Config{
+ CleanCacheSize: 0,
+ } // disable clean cache
} else {
- db.backend = pathdb.New(diskdb, &pathdb.Config{}) // disable clean/dirty cache
+ config.PathDB = &pathdb.Config{
+ CleanCacheSize: 0,
+ DirtyCacheSize: 0,
+ } // disable clean/dirty cache
}
- return db
+ return NewDatabase(diskdb, config)
}
diff --git a/trie/hasher.go b/trie/hasher.go
index e594d6d6b2..1e063d8020 100644
--- a/trie/hasher.go
+++ b/trie/hasher.go
@@ -84,20 +84,19 @@ func (h *hasher) hash(n node, force bool) (hashed node, cached node) {
}
return hashed, cached
default:
- // Value and hash nodes don't have children so they're left as were
+ // Value and hash nodes don't have children, so they're left as were
return n, n
}
}
// hashShortNodeChildren collapses the short node. The returned collapsed node
// holds a live reference to the Key, and must not be modified.
-// The cached
func (h *hasher) hashShortNodeChildren(n *shortNode) (collapsed, cached *shortNode) {
// Hash the short node's child, caching the newly hashed subtree
collapsed, cached = n.copy(), n.copy()
// Previously, we did copy this one. We don't seem to need to actually
// do that, since we don't overwrite/reuse keys
- //cached.Key = common.CopyBytes(n.Key)
+ // cached.Key = common.CopyBytes(n.Key)
collapsed.Key = hexToCompact(n.Key)
// Unless the child is a valuenode or hashnode, hash it
switch n.Val.(type) {
@@ -153,7 +152,7 @@ func (h *hasher) shortnodeToHash(n *shortNode, force bool) node {
return h.hashData(enc)
}
-// shortnodeToHash is used to creates a hashNode from a set of hashNodes, (which
+// fullnodeToHash is used to create a hashNode from a fullNode, (which
// may contain nil values)
func (h *hasher) fullnodeToHash(n *fullNode, force bool) node {
n.encode(h.encbuf)
@@ -203,7 +202,7 @@ func (h *hasher) proofHash(original node) (collapsed, hashed node) {
fn, _ := h.hashFullNodeChildren(n)
return fn, h.fullnodeToHash(fn, false)
default:
- // Value and hash nodes don't have children so they're left as were
+ // Value and hash nodes don't have children, so they're left as were
return n, n
}
}
diff --git a/trie/iterator.go b/trie/iterator.go
index 6f054a7245..83ccc0740f 100644
--- a/trie/iterator.go
+++ b/trie/iterator.go
@@ -144,7 +144,8 @@ type nodeIterator struct {
path []byte // Path to the current node
err error // Failure set in case of an internal error in the iterator
- resolver NodeResolver // optional node resolver for avoiding disk hits
+ resolver NodeResolver // optional node resolver for avoiding disk hits
+ pool []*nodeIteratorState // local pool for iteratorstates
}
// errIteratorEnd is stored in nodeIterator.err when iteration is done.
@@ -172,6 +173,24 @@ func newNodeIterator(trie *Trie, start []byte) NodeIterator {
return it
}
+func (it *nodeIterator) putInPool(item *nodeIteratorState) {
+ if len(it.pool) < 40 {
+ item.node = nil
+ it.pool = append(it.pool, item)
+ }
+}
+
+func (it *nodeIterator) getFromPool() *nodeIteratorState {
+ idx := len(it.pool) - 1
+ if idx < 0 {
+ return new(nodeIteratorState)
+ }
+ el := it.pool[idx]
+ it.pool[idx] = nil
+ it.pool = it.pool[:idx]
+ return el
+}
+
func (it *nodeIterator) AddResolver(resolver NodeResolver) {
it.resolver = resolver
}
@@ -423,8 +442,9 @@ func (st *nodeIteratorState) resolve(it *nodeIterator, path []byte) error {
return nil
}
-func findChild(n *fullNode, index int, path []byte, ancestor common.Hash) (node, *nodeIteratorState, []byte, int) {
+func (it *nodeIterator) findChild(n *fullNode, index int, ancestor common.Hash) (node, *nodeIteratorState, []byte, int) {
var (
+ path = it.path
child node
state *nodeIteratorState
childPath []byte
@@ -433,13 +453,12 @@ func findChild(n *fullNode, index int, path []byte, ancestor common.Hash) (node,
if n.Children[index] != nil {
child = n.Children[index]
hash, _ := child.cache()
- state = &nodeIteratorState{
- hash: common.BytesToHash(hash),
- node: child,
- parent: ancestor,
- index: -1,
- pathlen: len(path),
- }
+ state = it.getFromPool()
+ state.hash = common.BytesToHash(hash)
+ state.node = child
+ state.parent = ancestor
+ state.index = -1
+ state.pathlen = len(path)
childPath = append(childPath, path...)
childPath = append(childPath, byte(index))
return child, state, childPath, index
@@ -452,7 +471,7 @@ func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Has
switch node := parent.node.(type) {
case *fullNode:
// Full node, move to the first non-nil child.
- if child, state, path, index := findChild(node, parent.index+1, it.path, ancestor); child != nil {
+ if child, state, path, index := it.findChild(node, parent.index+1, ancestor); child != nil {
parent.index = index - 1
return state, path, true
}
@@ -460,13 +479,12 @@ func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Has
// Short node, return the pointer singleton child
if parent.index < 0 {
hash, _ := node.Val.cache()
- state := &nodeIteratorState{
- hash: common.BytesToHash(hash),
- node: node.Val,
- parent: ancestor,
- index: -1,
- pathlen: len(it.path),
- }
+ state := it.getFromPool()
+ state.hash = common.BytesToHash(hash)
+ state.node = node.Val
+ state.parent = ancestor
+ state.index = -1
+ state.pathlen = len(it.path)
path := append(it.path, node.Key...)
return state, path, true
}
@@ -480,7 +498,7 @@ func (it *nodeIterator) nextChildAt(parent *nodeIteratorState, ancestor common.H
switch n := parent.node.(type) {
case *fullNode:
// Full node, move to the first non-nil child before the desired key position
- child, state, path, index := findChild(n, parent.index+1, it.path, ancestor)
+ child, state, path, index := it.findChild(n, parent.index+1, ancestor)
if child == nil {
// No more children in this fullnode
return parent, it.path, false
@@ -492,7 +510,7 @@ func (it *nodeIterator) nextChildAt(parent *nodeIteratorState, ancestor common.H
}
// The child is before the seek position. Try advancing
for {
- nextChild, nextState, nextPath, nextIndex := findChild(n, index+1, it.path, ancestor)
+ nextChild, nextState, nextPath, nextIndex := it.findChild(n, index+1, ancestor)
// If we run out of children, or skipped past the target, return the
// previous one
if nextChild == nil || bytes.Compare(nextPath, key) >= 0 {
@@ -506,13 +524,12 @@ func (it *nodeIterator) nextChildAt(parent *nodeIteratorState, ancestor common.H
// Short node, return the pointer singleton child
if parent.index < 0 {
hash, _ := n.Val.cache()
- state := &nodeIteratorState{
- hash: common.BytesToHash(hash),
- node: n.Val,
- parent: ancestor,
- index: -1,
- pathlen: len(it.path),
- }
+ state := it.getFromPool()
+ state.hash = common.BytesToHash(hash)
+ state.node = n.Val
+ state.parent = ancestor
+ state.index = -1
+ state.pathlen = len(it.path)
path := append(it.path, n.Key...)
return state, path, true
}
@@ -533,6 +550,8 @@ func (it *nodeIterator) pop() {
it.path = it.path[:last.pathlen]
it.stack[len(it.stack)-1] = nil
it.stack = it.stack[:len(it.stack)-1]
+ // last is now unused
+ it.putInPool(last)
}
func compareNodes(a, b NodeIterator) int {
diff --git a/trie/iterator_test.go b/trie/iterator_test.go
index 57d1f06a16..9679b49ca7 100644
--- a/trie/iterator_test.go
+++ b/trie/iterator_test.go
@@ -616,3 +616,15 @@ func isTrieNode(scheme string, key, val []byte) (bool, []byte, common.Hash) {
}
return true, path, hash
}
+
+func BenchmarkIterator(b *testing.B) {
+ diskDb, srcDb, tr, _ := makeTestTrie(rawdb.HashScheme)
+ root := tr.Hash()
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ if err := checkTrieConsistency(diskDb, srcDb.Scheme(), root, false); err != nil {
+ b.Fatal(err)
+ }
+ }
+}
diff --git a/trie/proof.go b/trie/proof.go
index a463c80b48..a526a53402 100644
--- a/trie/proof.go
+++ b/trie/proof.go
@@ -481,7 +481,7 @@ func hasRightElement(node node, key []byte) bool {
// Note: This method does not verify that the proof is of minimal form. If the input
// proofs are 'bloated' with neighbour leaves or random data, aside from the 'useful'
// data, then the proof will still be accepted.
-func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, keys [][]byte, values [][]byte, proof ethdb.KeyValueReader) (bool, error) {
+func VerifyRangeProof(rootHash common.Hash, firstKey []byte, keys [][]byte, values [][]byte, proof ethdb.KeyValueReader) (bool, error) {
if len(keys) != len(values) {
return false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values))
}
@@ -520,6 +520,7 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, key
}
return false, nil
}
+ var lastKey = keys[len(keys)-1]
// Special case, there is only one element and two edge keys are same.
// In this case, we can't construct two edge paths. So handle it here.
if len(keys) == 1 && bytes.Equal(firstKey, lastKey) {
diff --git a/trie/proof_test.go b/trie/proof_test.go
index 21a7302f10..59ae201cea 100644
--- a/trie/proof_test.go
+++ b/trie/proof_test.go
@@ -191,7 +191,7 @@ func TestRangeProof(t *testing.T) {
keys = append(keys, entries[i].k)
vals = append(vals, entries[i].v)
}
- _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof)
+ _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, vals, proof)
if err != nil {
t.Fatalf("Case %d(%d->%d) expect no error, got %v", i, start, end-1, err)
}
@@ -221,19 +221,10 @@ func TestRangeProofWithNonExistentProof(t *testing.T) {
if bytes.Compare(first, entries[start].k) > 0 {
continue
}
- // Short circuit if the increased key is same with the next key
- last := increaseKey(common.CopyBytes(entries[end-1].k))
- if end != len(entries) && bytes.Equal(last, entries[end].k) {
- continue
- }
- // Short circuit if the increased key is overflow
- if bytes.Compare(last, entries[end-1].k) < 0 {
- continue
- }
if err := trie.Prove(first, proof); err != nil {
t.Fatalf("Failed to prove the first node %v", err)
}
- if err := trie.Prove(last, proof); err != nil {
+ if err := trie.Prove(entries[end-1].k, proof); err != nil {
t.Fatalf("Failed to prove the last node %v", err)
}
var keys [][]byte
@@ -242,36 +233,15 @@ func TestRangeProofWithNonExistentProof(t *testing.T) {
keys = append(keys, entries[i].k)
vals = append(vals, entries[i].v)
}
- _, err := VerifyRangeProof(trie.Hash(), first, last, keys, vals, proof)
+ _, err := VerifyRangeProof(trie.Hash(), first, keys, vals, proof)
if err != nil {
t.Fatalf("Case %d(%d->%d) expect no error, got %v", i, start, end-1, err)
}
}
- // Special case, two edge proofs for two edge key.
- proof := memorydb.New()
- first := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000").Bytes()
- last := common.MaxHash.Bytes()
- if err := trie.Prove(first, proof); err != nil {
- t.Fatalf("Failed to prove the first node %v", err)
- }
- if err := trie.Prove(last, proof); err != nil {
- t.Fatalf("Failed to prove the last node %v", err)
- }
- var k [][]byte
- var v [][]byte
- for i := 0; i < len(entries); i++ {
- k = append(k, entries[i].k)
- v = append(v, entries[i].v)
- }
- _, err := VerifyRangeProof(trie.Hash(), first, last, k, v, proof)
- if err != nil {
- t.Fatal("Failed to verify whole rang with non-existent edges")
- }
}
// TestRangeProofWithInvalidNonExistentProof tests such scenarios:
// - There exists a gap between the first element and the left edge proof
-// - There exists a gap between the last element and the right edge proof
func TestRangeProofWithInvalidNonExistentProof(t *testing.T) {
trie, vals := randomTrie(4096)
var entries []*kv
@@ -298,29 +268,7 @@ func TestRangeProofWithInvalidNonExistentProof(t *testing.T) {
k = append(k, entries[i].k)
v = append(v, entries[i].v)
}
- _, err := VerifyRangeProof(trie.Hash(), first, k[len(k)-1], k, v, proof)
- if err == nil {
- t.Fatalf("Expected to detect the error, got nil")
- }
-
- // Case 2
- start, end = 100, 200
- last := increaseKey(common.CopyBytes(entries[end-1].k))
- proof = memorydb.New()
- if err := trie.Prove(entries[start].k, proof); err != nil {
- t.Fatalf("Failed to prove the first node %v", err)
- }
- if err := trie.Prove(last, proof); err != nil {
- t.Fatalf("Failed to prove the last node %v", err)
- }
- end = 195 // Capped slice
- k = make([][]byte, 0)
- v = make([][]byte, 0)
- for i := start; i < end; i++ {
- k = append(k, entries[i].k)
- v = append(v, entries[i].v)
- }
- _, err = VerifyRangeProof(trie.Hash(), k[0], last, k, v, proof)
+ _, err := VerifyRangeProof(trie.Hash(), first, k, v, proof)
if err == nil {
t.Fatalf("Expected to detect the error, got nil")
}
@@ -344,7 +292,7 @@ func TestOneElementRangeProof(t *testing.T) {
if err := trie.Prove(entries[start].k, proof); err != nil {
t.Fatalf("Failed to prove the first node %v", err)
}
- _, err := VerifyRangeProof(trie.Hash(), entries[start].k, entries[start].k, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof)
+ _, err := VerifyRangeProof(trie.Hash(), entries[start].k, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -359,7 +307,7 @@ func TestOneElementRangeProof(t *testing.T) {
if err := trie.Prove(entries[start].k, proof); err != nil {
t.Fatalf("Failed to prove the last node %v", err)
}
- _, err = VerifyRangeProof(trie.Hash(), first, entries[start].k, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof)
+ _, err = VerifyRangeProof(trie.Hash(), first, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -374,7 +322,7 @@ func TestOneElementRangeProof(t *testing.T) {
if err := trie.Prove(last, proof); err != nil {
t.Fatalf("Failed to prove the last node %v", err)
}
- _, err = VerifyRangeProof(trie.Hash(), entries[start].k, last, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof)
+ _, err = VerifyRangeProof(trie.Hash(), entries[start].k, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -389,7 +337,7 @@ func TestOneElementRangeProof(t *testing.T) {
if err := trie.Prove(last, proof); err != nil {
t.Fatalf("Failed to prove the last node %v", err)
}
- _, err = VerifyRangeProof(trie.Hash(), first, last, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof)
+ _, err = VerifyRangeProof(trie.Hash(), first, [][]byte{entries[start].k}, [][]byte{entries[start].v}, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -408,7 +356,7 @@ func TestOneElementRangeProof(t *testing.T) {
if err := tinyTrie.Prove(last, proof); err != nil {
t.Fatalf("Failed to prove the last node %v", err)
}
- _, err = VerifyRangeProof(tinyTrie.Hash(), first, last, [][]byte{entry.k}, [][]byte{entry.v}, proof)
+ _, err = VerifyRangeProof(tinyTrie.Hash(), first, [][]byte{entry.k}, [][]byte{entry.v}, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -430,7 +378,7 @@ func TestAllElementsProof(t *testing.T) {
k = append(k, entries[i].k)
v = append(v, entries[i].v)
}
- _, err := VerifyRangeProof(trie.Hash(), nil, nil, k, v, nil)
+ _, err := VerifyRangeProof(trie.Hash(), nil, k, v, nil)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -443,7 +391,7 @@ func TestAllElementsProof(t *testing.T) {
if err := trie.Prove(entries[len(entries)-1].k, proof); err != nil {
t.Fatalf("Failed to prove the last node %v", err)
}
- _, err = VerifyRangeProof(trie.Hash(), k[0], k[len(k)-1], k, v, proof)
+ _, err = VerifyRangeProof(trie.Hash(), k[0], k, v, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -451,14 +399,13 @@ func TestAllElementsProof(t *testing.T) {
// Even with non-existent edge proofs, it should still work.
proof = memorydb.New()
first := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000").Bytes()
- last := common.MaxHash.Bytes()
if err := trie.Prove(first, proof); err != nil {
t.Fatalf("Failed to prove the first node %v", err)
}
- if err := trie.Prove(last, proof); err != nil {
+ if err := trie.Prove(entries[len(entries)-1].k, proof); err != nil {
t.Fatalf("Failed to prove the last node %v", err)
}
- _, err = VerifyRangeProof(trie.Hash(), first, last, k, v, proof)
+ _, err = VerifyRangeProof(trie.Hash(), first, k, v, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -491,43 +438,7 @@ func TestSingleSideRangeProof(t *testing.T) {
k = append(k, entries[i].k)
v = append(v, entries[i].v)
}
- _, err := VerifyRangeProof(trie.Hash(), common.Hash{}.Bytes(), k[len(k)-1], k, v, proof)
- if err != nil {
- t.Fatalf("Expected no error, got %v", err)
- }
- }
- }
-}
-
-// TestReverseSingleSideRangeProof tests the range ends with 0xffff...fff.
-func TestReverseSingleSideRangeProof(t *testing.T) {
- for i := 0; i < 64; i++ {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
- var entries []*kv
- for i := 0; i < 4096; i++ {
- value := &kv{randBytes(32), randBytes(20), false}
- trie.MustUpdate(value.k, value.v)
- entries = append(entries, value)
- }
- slices.SortFunc(entries, (*kv).cmp)
-
- var cases = []int{0, 1, 50, 100, 1000, 2000, len(entries) - 1}
- for _, pos := range cases {
- proof := memorydb.New()
- if err := trie.Prove(entries[pos].k, proof); err != nil {
- t.Fatalf("Failed to prove the first node %v", err)
- }
- last := common.MaxHash
- if err := trie.Prove(last.Bytes(), proof); err != nil {
- t.Fatalf("Failed to prove the last node %v", err)
- }
- k := make([][]byte, 0)
- v := make([][]byte, 0)
- for i := pos; i < len(entries); i++ {
- k = append(k, entries[i].k)
- v = append(v, entries[i].v)
- }
- _, err := VerifyRangeProof(trie.Hash(), k[0], last.Bytes(), k, v, proof)
+ _, err := VerifyRangeProof(trie.Hash(), common.Hash{}.Bytes(), k, v, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -561,7 +472,7 @@ func TestBadRangeProof(t *testing.T) {
keys = append(keys, entries[i].k)
vals = append(vals, entries[i].v)
}
- var first, last = keys[0], keys[len(keys)-1]
+ var first = keys[0]
testcase := mrand.Intn(6)
var index int
switch testcase {
@@ -576,7 +487,7 @@ func TestBadRangeProof(t *testing.T) {
case 2:
// Gapped entry slice
index = mrand.Intn(end - start)
- if (index == 0 && start < 100) || (index == end-start-1 && end <= 100) {
+ if (index == 0 && start < 100) || (index == end-start-1) {
continue
}
keys = append(keys[:index], keys[index+1:]...)
@@ -599,7 +510,7 @@ func TestBadRangeProof(t *testing.T) {
index = mrand.Intn(end - start)
vals[index] = nil
}
- _, err := VerifyRangeProof(trie.Hash(), first, last, keys, vals, proof)
+ _, err := VerifyRangeProof(trie.Hash(), first, keys, vals, proof)
if err == nil {
t.Fatalf("%d Case %d index %d range: (%d->%d) expect error, got nil", i, testcase, index, start, end-1)
}
@@ -633,7 +544,7 @@ func TestGappedRangeProof(t *testing.T) {
keys = append(keys, entries[i].k)
vals = append(vals, entries[i].v)
}
- _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof)
+ _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, vals, proof)
if err == nil {
t.Fatal("expect error, got nil")
}
@@ -649,24 +560,22 @@ func TestSameSideProofs(t *testing.T) {
slices.SortFunc(entries, (*kv).cmp)
pos := 1000
- first := decreaseKey(common.CopyBytes(entries[pos].k))
- first = decreaseKey(first)
- last := decreaseKey(common.CopyBytes(entries[pos].k))
+ first := common.CopyBytes(entries[0].k)
proof := memorydb.New()
if err := trie.Prove(first, proof); err != nil {
t.Fatalf("Failed to prove the first node %v", err)
}
- if err := trie.Prove(last, proof); err != nil {
- t.Fatalf("Failed to prove the last node %v", err)
+ if err := trie.Prove(entries[2000].k, proof); err != nil {
+ t.Fatalf("Failed to prove the first node %v", err)
}
- _, err := VerifyRangeProof(trie.Hash(), first, last, [][]byte{entries[pos].k}, [][]byte{entries[pos].v}, proof)
+ _, err := VerifyRangeProof(trie.Hash(), first, [][]byte{entries[pos].k}, [][]byte{entries[pos].v}, proof)
if err == nil {
t.Fatalf("Expected error, got nil")
}
first = increaseKey(common.CopyBytes(entries[pos].k))
- last = increaseKey(common.CopyBytes(entries[pos].k))
+ last := increaseKey(common.CopyBytes(entries[pos].k))
last = increaseKey(last)
proof = memorydb.New()
@@ -676,7 +585,7 @@ func TestSameSideProofs(t *testing.T) {
if err := trie.Prove(last, proof); err != nil {
t.Fatalf("Failed to prove the last node %v", err)
}
- _, err = VerifyRangeProof(trie.Hash(), first, last, [][]byte{entries[pos].k}, [][]byte{entries[pos].v}, proof)
+ _, err = VerifyRangeProof(trie.Hash(), first, [][]byte{entries[pos].k}, [][]byte{entries[pos].v}, proof)
if err == nil {
t.Fatalf("Expected error, got nil")
}
@@ -703,15 +612,12 @@ func TestHasRightElement(t *testing.T) {
{50, 100, true},
{50, len(entries), false}, // No more element expected
{len(entries) - 1, len(entries), false}, // Single last element with two existent proofs(point to same key)
- {len(entries) - 1, -1, false}, // Single last element with non-existent right proof
{0, len(entries), false}, // The whole set with existent left proof
{-1, len(entries), false}, // The whole set with non-existent left proof
- {-1, -1, false}, // The whole set with non-existent left/right proof
}
for _, c := range cases {
var (
firstKey []byte
- lastKey []byte
start = c.start
end = c.end
proof = memorydb.New()
@@ -727,16 +633,8 @@ func TestHasRightElement(t *testing.T) {
t.Fatalf("Failed to prove the first node %v", err)
}
}
- if c.end == -1 {
- lastKey, end = common.MaxHash.Bytes(), len(entries)
- if err := trie.Prove(lastKey, proof); err != nil {
- t.Fatalf("Failed to prove the first node %v", err)
- }
- } else {
- lastKey = entries[c.end-1].k
- if err := trie.Prove(entries[c.end-1].k, proof); err != nil {
- t.Fatalf("Failed to prove the first node %v", err)
- }
+ if err := trie.Prove(entries[c.end-1].k, proof); err != nil {
+ t.Fatalf("Failed to prove the first node %v", err)
}
k := make([][]byte, 0)
v := make([][]byte, 0)
@@ -744,7 +642,7 @@ func TestHasRightElement(t *testing.T) {
k = append(k, entries[i].k)
v = append(v, entries[i].v)
}
- hasMore, err := VerifyRangeProof(trie.Hash(), firstKey, lastKey, k, v, proof)
+ hasMore, err := VerifyRangeProof(trie.Hash(), firstKey, k, v, proof)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
@@ -777,7 +675,7 @@ func TestEmptyRangeProof(t *testing.T) {
if err := trie.Prove(first, proof); err != nil {
t.Fatalf("Failed to prove the first node %v", err)
}
- _, err := VerifyRangeProof(trie.Hash(), first, nil, nil, nil, proof)
+ _, err := VerifyRangeProof(trie.Hash(), first, nil, nil, proof)
if c.err && err == nil {
t.Fatalf("Expected error, got nil")
}
@@ -817,7 +715,7 @@ func TestBloatedProof(t *testing.T) {
trie.Prove(keys[0], want)
trie.Prove(keys[len(keys)-1], want)
- if _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof); err != nil {
+ if _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, vals, proof); err != nil {
t.Fatalf("expected bloated proof to succeed, got %v", err)
}
}
@@ -860,7 +758,7 @@ func TestEmptyValueRangeProof(t *testing.T) {
keys = append(keys, entries[i].k)
vals = append(vals, entries[i].v)
}
- _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof)
+ _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, vals, proof)
if err == nil {
t.Fatalf("Expected failure on noop entry")
}
@@ -895,7 +793,7 @@ func TestAllElementsEmptyValueRangeProof(t *testing.T) {
keys = append(keys, entries[i].k)
vals = append(vals, entries[i].v)
}
- _, err := VerifyRangeProof(trie.Hash(), nil, nil, keys, vals, nil)
+ _, err := VerifyRangeProof(trie.Hash(), nil, keys, vals, nil)
if err == nil {
t.Fatalf("Expected failure on noop entry")
}
@@ -1001,7 +899,7 @@ func benchmarkVerifyRangeProof(b *testing.B, size int) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
- _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, values, proof)
+ _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, values, proof)
if err != nil {
b.Fatalf("Case %d(%d->%d) expect no error, got %v", i, start, end-1, err)
}
@@ -1028,7 +926,7 @@ func benchmarkVerifyRangeNoProof(b *testing.B, size int) {
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
- _, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, values, nil)
+ _, err := VerifyRangeProof(trie.Hash(), keys[0], keys, values, nil)
if err != nil {
b.Fatalf("Expected no error, got %v", err)
}
@@ -1087,15 +985,14 @@ func TestRangeProofKeysWithSharedPrefix(t *testing.T) {
root := trie.Hash()
proof := memorydb.New()
start := common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")
- end := common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
if err := trie.Prove(start, proof); err != nil {
t.Fatalf("failed to prove start: %v", err)
}
- if err := trie.Prove(end, proof); err != nil {
+ if err := trie.Prove(keys[len(keys)-1], proof); err != nil {
t.Fatalf("failed to prove end: %v", err)
}
- more, err := VerifyRangeProof(root, start, end, keys, vals, proof)
+ more, err := VerifyRangeProof(root, start, keys, vals, proof)
if err != nil {
t.Fatalf("failed to verify range proof: %v", err)
}
diff --git a/trie/stacktrie.go b/trie/stacktrie.go
index 423afdec88..f2f5355c49 100644
--- a/trie/stacktrie.go
+++ b/trie/stacktrie.go
@@ -18,6 +18,7 @@ package trie
import (
"bytes"
+ "errors"
"sync"
"github.com/ethereum/go-ethereum/common"
@@ -92,12 +93,14 @@ func NewStackTrie(options *StackTrieOptions) *StackTrie {
// Update inserts a (key, value) pair into the stack trie.
func (t *StackTrie) Update(key, value []byte) error {
- k := keybytesToHex(key)
if len(value) == 0 {
- panic("deletion not supported")
+ return errors.New("trying to insert empty (deletion)")
}
+ k := keybytesToHex(key)
k = k[:len(k)-1] // chop the termination flag
-
+ if bytes.Compare(t.last, k) >= 0 {
+ return errors.New("non-ascending key order")
+ }
// track the first and last inserted entries.
if t.first == nil {
t.first = append([]byte{}, k...)
diff --git a/trie/stacktrie_fuzzer_test.go b/trie/stacktrie_fuzzer_test.go
new file mode 100644
index 0000000000..1b3f9dbe9c
--- /dev/null
+++ b/trie/stacktrie_fuzzer_test.go
@@ -0,0 +1,155 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package trie
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/trie/trienode"
+ "golang.org/x/crypto/sha3"
+ "golang.org/x/exp/slices"
+)
+
+func FuzzStackTrie(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzz(data, false)
+ })
+}
+
+func fuzz(data []byte, debugging bool) {
+ // This spongeDb is used to check the sequence of disk-db-writes
+ var (
+ input = bytes.NewReader(data)
+ spongeA = &spongeDb{sponge: sha3.NewLegacyKeccak256()}
+ dbA = NewDatabase(rawdb.NewDatabase(spongeA), nil)
+ trieA = NewEmpty(dbA)
+ spongeB = &spongeDb{sponge: sha3.NewLegacyKeccak256()}
+ dbB = NewDatabase(rawdb.NewDatabase(spongeB), nil)
+
+ options = NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ rawdb.WriteTrieNode(spongeB, common.Hash{}, path, hash, blob, dbB.Scheme())
+ })
+ trieB = NewStackTrie(options)
+ vals []*kv
+ maxElements = 10000
+ // operate on unique keys only
+ keys = make(map[string]struct{})
+ )
+ // Fill the trie with elements
+ for i := 0; input.Len() > 0 && i < maxElements; i++ {
+ k := make([]byte, 32)
+ input.Read(k)
+ var a uint16
+ binary.Read(input, binary.LittleEndian, &a)
+ a = 1 + a%100
+ v := make([]byte, a)
+ input.Read(v)
+ if input.Len() == 0 {
+ // If it was exhausted while reading, the value may be all zeroes,
+ // thus 'deletion' which is not supported on stacktrie
+ break
+ }
+ if _, present := keys[string(k)]; present {
+ // This key is a duplicate, ignore it
+ continue
+ }
+ keys[string(k)] = struct{}{}
+ vals = append(vals, &kv{k: k, v: v})
+ trieA.MustUpdate(k, v)
+ }
+ if len(vals) == 0 {
+ return
+ }
+ // Flush trie -> database
+ rootA, nodes, err := trieA.Commit(false)
+ if err != nil {
+ panic(err)
+ }
+ if nodes != nil {
+ dbA.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ }
+ // Flush memdb -> disk (sponge)
+ dbA.Commit(rootA, false)
+
+ // Stacktrie requires sorted insertion
+ slices.SortFunc(vals, (*kv).cmp)
+
+ for _, kv := range vals {
+ if debugging {
+ fmt.Printf("{\"%#x\" , \"%#x\"} // stacktrie.Update\n", kv.k, kv.v)
+ }
+ trieB.MustUpdate(kv.k, kv.v)
+ }
+ rootB := trieB.Hash()
+ trieB.Commit()
+ if rootA != rootB {
+ panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootB))
+ }
+ sumA := spongeA.sponge.Sum(nil)
+ sumB := spongeB.sponge.Sum(nil)
+ if !bytes.Equal(sumA, sumB) {
+ panic(fmt.Sprintf("sequence differ: (trie) %x != %x (stacktrie)", sumA, sumB))
+ }
+
+ // Ensure all the nodes are persisted correctly
+ var (
+ nodeset = make(map[string][]byte) // path -> blob
+ optionsC = NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ if crypto.Keccak256Hash(blob) != hash {
+ panic("invalid node blob")
+ }
+ nodeset[string(path)] = common.CopyBytes(blob)
+ })
+ trieC = NewStackTrie(optionsC)
+ checked int
+ )
+ for _, kv := range vals {
+ trieC.MustUpdate(kv.k, kv.v)
+ }
+ rootC := trieC.Commit()
+ if rootA != rootC {
+ panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootC))
+ }
+ trieA, _ = New(TrieID(rootA), dbA)
+ iterA := trieA.MustNodeIterator(nil)
+ for iterA.Next(true) {
+ if iterA.Hash() == (common.Hash{}) {
+ if _, present := nodeset[string(iterA.Path())]; present {
+ panic("unexpected tiny node")
+ }
+ continue
+ }
+ nodeBlob, present := nodeset[string(iterA.Path())]
+ if !present {
+ panic("missing node")
+ }
+ if !bytes.Equal(nodeBlob, iterA.NodeBlob()) {
+ panic("node blob is not matched")
+ }
+ checked += 1
+ }
+ if checked != len(nodeset) {
+ panic("node number is not matched")
+ }
+}
diff --git a/trie/stacktrie_test.go b/trie/stacktrie_test.go
index 802d472e36..909a77062a 100644
--- a/trie/stacktrie_test.go
+++ b/trie/stacktrie_test.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/trie/testutil"
+ "github.com/stretchr/testify/assert"
"golang.org/x/exp/slices"
)
@@ -168,6 +169,38 @@ func TestStackTrieInsertAndHash(t *testing.T) {
{"123e", "x___________________________2", "0d230561e398c579e09a9f7b69ceaf7d3970f5a436fdb28b68b7a37c5bdd6b80"},
{"13aa", "x___________________________3", "ff0dc70ce2e5db90ee42a4c2ad12139596b890e90eb4e16526ab38fa465b35cf"},
},
+ { // branch node with short values
+ {"01", "a", "b48605025f5f4b129d40a420e721aa7d504487f015fce85b96e52126365ef7dc"},
+ {"80", "b", "2dc6b680daf74db067cb7aeaad73265ded93d96fce190fcbf64f498d475672ab"},
+ {"ee", "c", "017dc705a54ac5328dd263fa1bae68d655310fb3e3f7b7bc57e9a43ddf99c4bf"},
+ {"ff", "d", "bd5a3584d271d459bd4eb95247b2fc88656b3671b60c1125ffe7bc0b689470d0"},
+ },
+ { // ext node with short branch node, then becoming long
+ {"a0", "a", "a83e028cb1e4365935661a9fd36a5c65c30b9ab416eaa877424146ca2a69d088"},
+ {"a1", "b", "f586a4639b07b01798ca65e05c253b75d51135ebfbf6f8d6e87c0435089e65f0"},
+ {"a2", "c", "63e297c295c008e09a8d531e18d57f270b6bc403e23179b915429db948cd62e3"},
+ {"a3", "d", "94a7b721535578e9381f1f4e4b6ec29f8bdc5f0458a30320684c562f5d47b4b5"},
+ {"a4", "e", "4b7e66d1c81965cdbe8fab8295ef56bc57fefdc5733d4782d2f8baf630f083c6"},
+ {"a5", "f", "2997e7b502198ce1783b5277faacf52b25844fb55a99b63e88bdbbafac573106"},
+ {"a6", "g", "bee629dd27a40772b2e1a67ec6db270d26acdf8d3b674dfae27866ad6ae1f48b"},
+ },
+ { // branch node with short values, then long ones
+ {"a001", "v1", "b9cc982d995392b51e6787f1915f0b88efd4ad8b30f138da0a3e2242f2323e35"},
+ {"b002", "v2", "a7b474bc77ef5097096fa0ee6298fdae8928c0bc3724e7311cd0fa9ed1942fc7"},
+ {"c003", "v___________________________3", "dceb5bb7c92b0e348df988a8d9fc36b101397e38ebd405df55ba6ee5f14a264a"},
+ {"d004", "v___________________________4", "36e60ecb86b9626165e1c6543c42ecbe4d83bca58e8e1124746961511fce362a"},
+ },
+ { // ext node to branch node with short values, then long ones
+ {"8002", "v1", "3258fcb3e9e7d7234ecd3b8d4743999e4ab3a21592565e0a5ca64c141e8620d9"},
+ {"8004", "v2", "b6cb95b7024a83c17624a3c9bed09b4b5e8ed426f49f54b8ad13c39028b1e75a"},
+ {"8008", "v___________________________3", "c769d82963abe6f0900bf69754738eeb2f84559777cfa87a44f54e1aab417871"},
+ {"800d", "v___________________________4", "1cad1fdaab1a6fa95d7b780fd680030e423eb76669971368ba04797a8d9cdfc9"},
+ },
+ { // ext node with a child of size 31 (Y) and branch node with a child of size 31 (X)
+ {"000001", "ZZZZZZZZZ", "cef154b87c03c563408520ff9b26923c360cbc3ddb590c079bedeeb25a8c9c77"},
+ {"000002", "Y", "2130735e600f612f6e657a32bd7be64ddcaec6512c5694844b19de713922895d"},
+ {"000003", "XXXXXXXXXXXXXXXXXXXXXXXXXXXX", "962c0fffdeef7612a4f7bff1950d67e3e81c878e48b9ae45b3b374253b050bd8"},
+ },
}
for i, test := range tests {
// The StackTrie does not allow Insert(), Hash(), Insert(), ...
@@ -431,3 +464,24 @@ func TestPartialStackTrie(t *testing.T) {
}
}
}
+
+func TestStackTrieErrors(t *testing.T) {
+ s := NewStackTrie(nil)
+ // Deletion
+ if err := s.Update(nil, nil); err == nil {
+ t.Fatal("expected error")
+ }
+ if err := s.Update(nil, []byte{}); err == nil {
+ t.Fatal("expected error")
+ }
+ if err := s.Update([]byte{0xa}, []byte{}); err == nil {
+ t.Fatal("expected error")
+ }
+ // Non-ascending keys (going backwards or repeating)
+ assert.Nil(t, s.Update([]byte{0xaa}, []byte{0xa}))
+ assert.NotNil(t, s.Update([]byte{0xaa}, []byte{0xa}), "repeat insert same key")
+ assert.NotNil(t, s.Update([]byte{0xaa}, []byte{0xb}), "repeat insert same key")
+ assert.Nil(t, s.Update([]byte{0xab}, []byte{0xa}))
+ assert.NotNil(t, s.Update([]byte{0x10}, []byte{0xb}), "out of order insert")
+ assert.NotNil(t, s.Update([]byte{0xaa}, []byte{0xb}), "repeat insert same key")
+}
diff --git a/trie/sync.go b/trie/sync.go
index e5af26ff91..589d28364b 100644
--- a/trie/sync.go
+++ b/trie/sync.go
@@ -116,10 +116,9 @@ type LeafCallback func(keys [][]byte, path []byte, leaf []byte, parent common.Ha
// nodeRequest represents a scheduled or already in-flight trie node retrieval request.
type nodeRequest struct {
- hash common.Hash // Hash of the trie node to retrieve
- path []byte // Merkle path leading to this node for prioritization
- data []byte // Data content of the node, cached until all subtrees complete
- deletes [][]byte // List of internal path segments for trie nodes to delete
+ hash common.Hash // Hash of the trie node to retrieve
+ path []byte // Merkle path leading to this node for prioritization
+ data []byte // Data content of the node, cached until all subtrees complete
parent *nodeRequest // Parent state node referencing this entry
deps int // Number of dependencies before allowed to commit this node
@@ -146,38 +145,85 @@ type CodeSyncResult struct {
Data []byte // Data content of the retrieved bytecode
}
+// nodeOp represents an operation upon the trie node. It can either represent a
+// deletion to the specific node or a node write for persisting retrieved node.
+type nodeOp struct {
+ owner common.Hash // identifier of the trie (empty for account trie)
+ path []byte // path from the root to the specified node.
+ blob []byte // the content of the node (nil for deletion)
+ hash common.Hash // hash of the node content (empty for node deletion)
+}
+
+// isDelete indicates if the operation is a database deletion.
+func (op *nodeOp) isDelete() bool {
+ return len(op.blob) == 0
+}
+
// syncMemBatch is an in-memory buffer of successfully downloaded but not yet
// persisted data items.
type syncMemBatch struct {
- nodes map[string][]byte // In-memory membatch of recently completed nodes
- hashes map[string]common.Hash // Hashes of recently completed nodes
- deletes map[string]struct{} // List of paths for trie node to delete
- codes map[common.Hash][]byte // In-memory membatch of recently completed codes
- size uint64 // Estimated batch-size of in-memory data.
+ scheme string // State scheme identifier
+ codes map[common.Hash][]byte // In-memory batch of recently completed codes
+ nodes []nodeOp // In-memory batch of recently completed/deleted nodes
+ size uint64 // Estimated batch-size of in-memory data.
}
// newSyncMemBatch allocates a new memory-buffer for not-yet persisted trie nodes.
-func newSyncMemBatch() *syncMemBatch {
+func newSyncMemBatch(scheme string) *syncMemBatch {
return &syncMemBatch{
- nodes: make(map[string][]byte),
- hashes: make(map[string]common.Hash),
- deletes: make(map[string]struct{}),
- codes: make(map[common.Hash][]byte),
+ scheme: scheme,
+ codes: make(map[common.Hash][]byte),
}
}
-// hasNode reports the trie node with specific path is already cached.
-func (batch *syncMemBatch) hasNode(path []byte) bool {
- _, ok := batch.nodes[string(path)]
- return ok
-}
-
// hasCode reports the contract code with specific hash is already cached.
func (batch *syncMemBatch) hasCode(hash common.Hash) bool {
_, ok := batch.codes[hash]
return ok
}
+// addCode caches a contract code database write operation.
+func (batch *syncMemBatch) addCode(hash common.Hash, code []byte) {
+ batch.codes[hash] = code
+ batch.size += common.HashLength + uint64(len(code))
+}
+
+// addNode caches a node database write operation.
+func (batch *syncMemBatch) addNode(owner common.Hash, path []byte, blob []byte, hash common.Hash) {
+ if batch.scheme == rawdb.PathScheme {
+ if owner == (common.Hash{}) {
+ batch.size += uint64(len(path) + len(blob))
+ } else {
+ batch.size += common.HashLength + uint64(len(path)+len(blob))
+ }
+ } else {
+ batch.size += common.HashLength + uint64(len(blob))
+ }
+ batch.nodes = append(batch.nodes, nodeOp{
+ owner: owner,
+ path: path,
+ blob: blob,
+ hash: hash,
+ })
+}
+
+// delNode caches a node database delete operation.
+func (batch *syncMemBatch) delNode(owner common.Hash, path []byte) {
+ if batch.scheme != rawdb.PathScheme {
+ log.Error("Unexpected node deletion", "owner", owner, "path", path, "scheme", batch.scheme)
+ return // deletion is not supported in hash mode.
+ }
+ if owner == (common.Hash{}) {
+ batch.size += uint64(len(path))
+ } else {
+ batch.size += common.HashLength + uint64(len(path))
+ }
+ batch.nodes = append(batch.nodes, nodeOp{
+ owner: owner,
+ path: path,
+ })
+}
+
// Sync is the main state trie synchronisation scheduler, which provides yet
// unknown trie hashes to retrieve, accepts node data associated with said hashes
// and reconstructs the trie step by step until all is done.
@@ -196,7 +242,7 @@ func NewSync(root common.Hash, database ethdb.KeyValueReader, callback LeafCallb
ts := &Sync{
scheme: scheme,
database: database,
- membatch: newSyncMemBatch(),
+ membatch: newSyncMemBatch(scheme),
nodeReqs: make(map[string]*nodeRequest),
codeReqs: make(map[common.Hash]*codeRequest),
queue: prque.New[int64, any](nil), // Ugh, can contain both string and hash, whyyy
@@ -210,16 +256,17 @@ func NewSync(root common.Hash, database ethdb.KeyValueReader, callback LeafCallb
// parent for completion tracking. The given path is a unique node path in
// hex format and contain all the parent path if it's layered trie node.
func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, parentPath []byte, callback LeafCallback) {
- // Short circuit if the trie is empty or already known
if root == types.EmptyRootHash {
return
}
- if s.membatch.hasNode(path) {
- return
- }
owner, inner := ResolvePath(path)
- if rawdb.HasTrieNode(s.database, owner, inner, root, s.scheme) {
+ exist, inconsistent := s.hasNode(owner, inner, root)
+ if exist {
+ // The entire subtrie is already present in the database.
return
+ } else if inconsistent {
+ // There is a pre-existing node with the wrong hash in DB, remove it.
+ s.membatch.delNode(owner, inner)
}
// Assemble the new sub-trie sync request
req := &nodeRequest{
@@ -314,7 +361,7 @@ func (s *Sync) Missing(max int) ([]string, []common.Hash, []common.Hash) {
}
// ProcessCode injects the received data for requested item. Note it can
-// happpen that the single response commits two pending requests(e.g.
+// happen that the single response commits two pending requests(e.g.
// there are two requests one for code and one for node but the hash
// is same). In this case the second response for the same hash will
// be treated as "non-requested" item or "already-processed" item but
@@ -371,39 +418,42 @@ func (s *Sync) ProcessNode(result NodeSyncResult) error {
}
// Commit flushes the data stored in the internal membatch out to persistent
-// storage, returning any occurred error.
+// storage, returning any occurred error. The whole data set will be flushed
+// in an atomic database batch.
func (s *Sync) Commit(dbw ethdb.Batch) error {
// Flush the pending node writes into database batch.
var (
account int
storage int
)
- for path, value := range s.membatch.nodes {
- owner, inner := ResolvePath([]byte(path))
- if owner == (common.Hash{}) {
- account += 1
+ for _, op := range s.membatch.nodes {
+ if op.isDelete() {
+ // node deletion is only supported in path mode.
+ if op.owner == (common.Hash{}) {
+ rawdb.DeleteAccountTrieNode(dbw, op.path)
+ } else {
+ rawdb.DeleteStorageTrieNode(dbw, op.owner, op.path)
+ }
+ deletionGauge.Inc(1)
} else {
- storage += 1
+ if op.owner == (common.Hash{}) {
+ account += 1
+ } else {
+ storage += 1
+ }
+ rawdb.WriteTrieNode(dbw, op.owner, op.path, op.hash, op.blob, s.scheme)
}
- rawdb.WriteTrieNode(dbw, owner, inner, s.membatch.hashes[path], value, s.scheme)
}
accountNodeSyncedGauge.Inc(int64(account))
storageNodeSyncedGauge.Inc(int64(storage))
- // Flush the pending node deletes into the database batch.
- // Please note that each written and deleted node has a
- // unique path, ensuring no duplication occurs.
- for path := range s.membatch.deletes {
- owner, inner := ResolvePath([]byte(path))
- rawdb.DeleteTrieNode(dbw, owner, inner, common.Hash{} /* unused */, s.scheme)
- }
// Flush the pending code writes into database batch.
for hash, value := range s.membatch.codes {
rawdb.WriteCode(dbw, hash, value)
}
codeSyncedGauge.Inc(int64(len(s.membatch.codes)))
- s.membatch = newSyncMemBatch() // reset the batch
+ s.membatch = newSyncMemBatch(s.scheme) // reset the batch
return nil
}
@@ -417,7 +467,7 @@ func (s *Sync) Pending() int {
return len(s.nodeReqs) + len(s.codeReqs)
}
-// schedule inserts a new state retrieval request into the fetch queue. If there
+// scheduleNodeRequest inserts a new state retrieval request into the fetch queue. If there
// is already a pending request for this node, the new request will be discarded
// and only a parent reference added to the old one.
func (s *Sync) scheduleNodeRequest(req *nodeRequest) {
@@ -432,7 +482,7 @@ func (s *Sync) scheduleNodeRequest(req *nodeRequest) {
s.queue.Push(string(req.path), prio)
}
-// schedule inserts a new state retrieval request into the fetch queue. If there
+// scheduleCodeRequest inserts a new state retrieval request into the fetch queue. If there
// is already a pending request for this node, the new request will be discarded
// and only a parent reference added to the old one.
func (s *Sync) scheduleCodeRequest(req *codeRequest) {
@@ -476,12 +526,15 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) {
// child as invalid. This is essential in the case of path mode
// scheme; otherwise, state healing might overwrite existing child
// nodes silently while leaving a dangling parent node within the
- // range of this internal path on disk. This would break the
- // guarantee for state healing.
+ // range of this internal path on disk and the persistent state
+ // ends up with a very weird situation that nodes on the same path
+ // are not inconsistent while they all present in disk. This property
+ // would break the guarantee for state healing.
//
// While it's possible for this shortNode to overwrite a previously
// existing full node, the other branches of the fullNode can be
- // retained as they remain untouched and complete.
+ // retained as they are not accessible with the new shortNode, and
+ // also the whole sub-trie is still untouched and complete.
//
// This step is only necessary for path mode, as there is no deletion
// in hash mode at all.
@@ -498,8 +551,7 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) {
exists = rawdb.ExistsStorageTrieNode(s.database, owner, append(inner, key[:i]...))
}
if exists {
- req.deletes = append(req.deletes, key[:i])
- deletionGauge.Inc(1)
+ s.membatch.delNode(owner, append(inner, key[:i]...))
log.Debug("Detected dangling node", "owner", owner, "path", append(inner, key[:i]...))
}
}
@@ -521,6 +573,7 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) {
var (
missing = make(chan *nodeRequest, len(children))
pending sync.WaitGroup
+ batchMu sync.Mutex
)
for _, child := range children {
// Notify any external watcher of a new key/value node
@@ -538,34 +591,32 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) {
}
}
}
- // If the child references another node, resolve or schedule
+ // If the child references another node, resolve or schedule.
+ // We check all children concurrently.
if node, ok := (child.node).(hashNode); ok {
- // Try to resolve the node from the local database
- if s.membatch.hasNode(child.path) {
- continue
- }
- // Check the presence of children concurrently
+ path := child.path
+ hash := common.BytesToHash(node)
pending.Add(1)
- go func(child childNode) {
+ go func() {
defer pending.Done()
-
- // If database says duplicate, then at least the trie node is present
- // and we hold the assumption that it's NOT legacy contract code.
- var (
- chash = common.BytesToHash(node)
- owner, inner = ResolvePath(child.path)
- )
- if rawdb.HasTrieNode(s.database, owner, inner, chash, s.scheme) {
+ owner, inner := ResolvePath(path)
+ exist, inconsistent := s.hasNode(owner, inner, hash)
+ if exist {
return
+ } else if inconsistent {
+ // There is a pre-existing node with the wrong hash in DB, remove it.
+ batchMu.Lock()
+ s.membatch.delNode(owner, inner)
+ batchMu.Unlock()
}
// Locally unknown node, schedule for retrieval
missing <- &nodeRequest{
- path: child.path,
- hash: chash,
+ path: path,
+ hash: hash,
parent: req,
callback: req.callback,
}
- }(child)
+ }()
}
}
pending.Wait()
@@ -582,26 +633,15 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) {
return requests, nil
}
-// commit finalizes a retrieval request and stores it into the membatch. If any
+// commitNodeRequest finalizes a retrieval request and stores it into the membatch. If any
// of the referencing parent requests complete due to this commit, they are also
// committed themselves.
func (s *Sync) commitNodeRequest(req *nodeRequest) error {
// Write the node content to the membatch
- s.membatch.nodes[string(req.path)] = req.data
- s.membatch.hashes[string(req.path)] = req.hash
+ owner, path := ResolvePath(req.path)
+ s.membatch.addNode(owner, path, req.data, req.hash)
- // The size tracking refers to the db-batch, not the in-memory data.
- if s.scheme == rawdb.PathScheme {
- s.membatch.size += uint64(len(req.path) + len(req.data))
- } else {
- s.membatch.size += common.HashLength + uint64(len(req.data))
- }
- // Delete the internal nodes which are marked as invalid
- for _, segment := range req.deletes {
- path := append(req.path, segment...)
- s.membatch.deletes[string(path)] = struct{}{}
- s.membatch.size += uint64(len(path))
- }
+ // Removed the completed node request
delete(s.nodeReqs, string(req.path))
s.fetches[len(req.path)]--
@@ -617,13 +657,14 @@ func (s *Sync) commitNodeRequest(req *nodeRequest) error {
return nil
}
-// commit finalizes a retrieval request and stores it into the membatch. If any
+// commitCodeRequest finalizes a retrieval request and stores it into the membatch. If any
// of the referencing parent requests complete due to this commit, they are also
// committed themselves.
func (s *Sync) commitCodeRequest(req *codeRequest) error {
// Write the node content to the membatch
- s.membatch.codes[req.hash] = req.data
- s.membatch.size += common.HashLength + uint64(len(req.data))
+ s.membatch.addCode(req.hash, req.data)
+
+ // Removed the completed code request
delete(s.codeReqs, req.hash)
s.fetches[len(req.path)]--
@@ -639,6 +680,28 @@ func (s *Sync) commitCodeRequest(req *codeRequest) error {
return nil
}
+// hasNode reports whether the specified trie node is present in the database.
+// 'exists' is true when the node exists in the database and matches the given root
+// hash. The 'inconsistent' return value is true when the node exists but does not
+// match the expected hash.
+func (s *Sync) hasNode(owner common.Hash, path []byte, hash common.Hash) (exists bool, inconsistent bool) {
+ // If node is running with hash scheme, check the presence with node hash.
+ if s.scheme == rawdb.HashScheme {
+ return rawdb.HasLegacyTrieNode(s.database, hash), false
+ }
+ // If node is running with path scheme, check the presence with node path.
+ var blob []byte
+ var dbHash common.Hash
+ if owner == (common.Hash{}) {
+ blob, dbHash = rawdb.ReadAccountTrieNode(s.database, path)
+ } else {
+ blob, dbHash = rawdb.ReadStorageTrieNode(s.database, owner, path)
+ }
+ exists = hash == dbHash
+ inconsistent = !exists && len(blob) != 0
+ return exists, inconsistent
+}
+
// ResolvePath resolves the provided composite node path by separating the
// path in account trie if it's existent.
func ResolvePath(path []byte) (common.Hash, []byte) {
diff --git a/trie/sync_test.go b/trie/sync_test.go
index 3b7986ef67..585181b48c 100644
--- a/trie/sync_test.go
+++ b/trie/sync_test.go
@@ -19,6 +19,7 @@ package trie
import (
"bytes"
"fmt"
+ "math/rand"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -571,7 +572,7 @@ func testIncompleteSync(t *testing.T, scheme string) {
hash := crypto.Keccak256Hash(result.Data)
if hash != root {
addedKeys = append(addedKeys, result.Path)
- addedHashes = append(addedHashes, crypto.Keccak256Hash(result.Data))
+ addedHashes = append(addedHashes, hash)
}
}
// Fetch the next batch to retrieve
@@ -587,6 +588,10 @@ func testIncompleteSync(t *testing.T, scheme string) {
}
// Sanity check that removing any node from the database is detected
for i, path := range addedKeys {
+ if rand.Int31n(100) > 5 {
+ // Only check 5 percent of added keys as a sanity check
+ continue
+ }
owner, inner := ResolvePath([]byte(path))
nodeHash := addedHashes[i]
value := rawdb.ReadTrieNode(diskdb, owner, inner, nodeHash, scheme)
@@ -679,8 +684,11 @@ func testSyncOrdering(t *testing.T, scheme string) {
}
}
}
-
func syncWith(t *testing.T, root common.Hash, db ethdb.Database, srcDb *Database) {
+ syncWithHookWriter(t, root, db, srcDb, nil)
+}
+
+func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb *Database, hookWriter ethdb.KeyValueWriter) {
// Create a destination trie and sync with the scheduler
sched := NewSync(root, db, nil, srcDb.Scheme())
@@ -718,8 +726,11 @@ func syncWith(t *testing.T, root common.Hash, db ethdb.Database, srcDb *Database
if err := sched.Commit(batch); err != nil {
t.Fatalf("failed to commit data: %v", err)
}
- batch.Write()
-
+ if hookWriter != nil {
+ batch.Replay(hookWriter)
+ } else {
+ batch.Write()
+ }
paths, nodes, _ = sched.Missing(0)
elements = elements[:0]
for i := 0; i < len(paths); i++ {
@@ -889,3 +900,116 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
syncWith(t, rootC, destDisk, srcTrieDB)
checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateC, true)
}
+
+func TestSyncAbort(t *testing.T) {
+ testSyncAbort(t, rawdb.PathScheme)
+ testSyncAbort(t, rawdb.HashScheme)
+}
+
+type hookWriter struct {
+ db ethdb.KeyValueStore
+ filter func(key []byte, value []byte) bool
+}
+
+// Put inserts the given value into the key-value data store.
+func (w *hookWriter) Put(key []byte, value []byte) error {
+ if w.filter != nil && w.filter(key, value) {
+ return nil
+ }
+ return w.db.Put(key, value)
+}
+
+// Delete removes the key from the key-value data store.
+func (w *hookWriter) Delete(key []byte) error {
+ return w.db.Delete(key)
+}
+
+func testSyncAbort(t *testing.T, scheme string) {
+ var (
+ srcDisk = rawdb.NewMemoryDatabase()
+ srcTrieDB = newTestDatabase(srcDisk, scheme)
+ srcTrie, _ = New(TrieID(types.EmptyRootHash), srcTrieDB)
+
+ deleteFn = func(key []byte, tr *Trie, states map[string][]byte) {
+ tr.Delete(key)
+ delete(states, string(key))
+ }
+ writeFn = func(key []byte, val []byte, tr *Trie, states map[string][]byte) {
+ if val == nil {
+ val = randBytes(32)
+ }
+ tr.Update(key, val)
+ states[string(key)] = common.CopyBytes(val)
+ }
+ copyStates = func(states map[string][]byte) map[string][]byte {
+ cpy := make(map[string][]byte)
+ for k, v := range states {
+ cpy[k] = v
+ }
+ return cpy
+ }
+ )
+ var (
+ stateA = make(map[string][]byte)
+ key = randBytes(32)
+ val = randBytes(32)
+ )
+ for i := 0; i < 256; i++ {
+ writeFn(randBytes(32), nil, srcTrie, stateA)
+ }
+ writeFn(key, val, srcTrie, stateA)
+
+ rootA, nodesA, _ := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil); err != nil {
+ panic(err)
+ }
+ if err := srcTrieDB.Commit(rootA, false); err != nil {
+ panic(err)
+ }
+ // Create a destination trie and sync with the scheduler
+ destDisk := rawdb.NewMemoryDatabase()
+ syncWith(t, rootA, destDisk, srcTrieDB)
+ checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateA, true)
+
+ // Delete the element from the trie
+ stateB := copyStates(stateA)
+ srcTrie, _ = New(TrieID(rootA), srcTrieDB)
+ deleteFn(key, srcTrie, stateB)
+
+ rootB, nodesB, _ := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootB, rootA, 0, trienode.NewWithNodeSet(nodesB), nil); err != nil {
+ panic(err)
+ }
+ if err := srcTrieDB.Commit(rootB, false); err != nil {
+ panic(err)
+ }
+
+ // Sync the new state, but never persist the new root node. Before the
+ // fix #28595, the original old root node will still be left in database
+ // which breaks the next healing cycle.
+ syncWithHookWriter(t, rootB, destDisk, srcTrieDB, &hookWriter{db: destDisk, filter: func(key []byte, value []byte) bool {
+ if scheme == rawdb.HashScheme {
+ return false
+ }
+ if len(value) == 0 {
+ return false
+ }
+ ok, path := rawdb.ResolveAccountTrieNodeKey(key)
+ return ok && len(path) == 0
+ }})
+
+ // Add elements to expand trie
+ stateC := copyStates(stateB)
+ srcTrie, _ = New(TrieID(rootB), srcTrieDB)
+
+ writeFn(key, val, srcTrie, stateC)
+ rootC, nodesC, _ := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootC, rootB, 0, trienode.NewWithNodeSet(nodesC), nil); err != nil {
+ panic(err)
+ }
+ if err := srcTrieDB.Commit(rootC, false); err != nil {
+ panic(err)
+ }
+ syncWith(t, rootC, destDisk, srcTrieDB)
+ checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateC, true)
+}
diff --git a/trie/trie_test.go b/trie/trie_test.go
index e805a6e4c9..fcbd552e22 100644
--- a/trie/trie_test.go
+++ b/trie/trie_test.go
@@ -22,7 +22,7 @@ import (
"errors"
"fmt"
"hash"
- "math/big"
+ "io"
"math/rand"
"reflect"
"testing"
@@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
@@ -362,13 +363,18 @@ func TestRandomCases(t *testing.T) {
{op: 1, key: common.Hex2Bytes("980c393656413a15c8da01978ed9f89feb80b502f58f2d640e3a2f5f7a99a7018f1b573befd92053ac6f78fca4a87268"), value: common.Hex2Bytes("")}, // step 24
{op: 1, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 25
}
- runRandTest(rt)
+ if err := runRandTest(rt); err != nil {
+ t.Fatal(err)
+ }
}
// randTest performs random trie operations.
// Instances of this test are created by Generate.
type randTest []randTestStep
+// compile-time interface check
+var _ quick.Generator = (randTest)(nil)
+
type randTestStep struct {
op int
key []byte // for opUpdate, opDelete, opGet
@@ -389,33 +395,45 @@ const (
)
func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
+ var finishedFn = func() bool {
+ size--
+ return size == 0
+ }
+ return reflect.ValueOf(generateSteps(finishedFn, r))
+}
+
+func generateSteps(finished func() bool, r io.Reader) randTest {
var allKeys [][]byte
+ var one = []byte{0}
genKey := func() []byte {
- if len(allKeys) < 2 || r.Intn(100) < 10 {
+ r.Read(one)
+ if len(allKeys) < 2 || one[0]%100 > 90 {
// new key
- key := make([]byte, r.Intn(50))
+ size := one[0] % 50
+ key := make([]byte, size)
r.Read(key)
allKeys = append(allKeys, key)
return key
}
// use existing key
- return allKeys[r.Intn(len(allKeys))]
+ idx := int(one[0]) % len(allKeys)
+ return allKeys[idx]
}
-
var steps randTest
- for i := 0; i < size; i++ {
- step := randTestStep{op: r.Intn(opMax)}
+ for !finished() {
+ r.Read(one)
+ step := randTestStep{op: int(one[0]) % opMax}
switch step.op {
case opUpdate:
step.key = genKey()
step.value = make([]byte, 8)
- binary.BigEndian.PutUint64(step.value, uint64(i))
+ binary.BigEndian.PutUint64(step.value, uint64(len(steps)))
case opGet, opDelete, opProve:
step.key = genKey()
}
steps = append(steps, step)
}
- return reflect.ValueOf(steps)
+ return steps
}
func verifyAccessList(old *Trie, new *Trie, set *trienode.NodeSet) error {
@@ -460,7 +478,12 @@ func verifyAccessList(old *Trie, new *Trie, set *trienode.NodeSet) error {
return nil
}
-func runRandTest(rt randTest) bool {
+// runRandTestBool coerces error to boolean, for use in quick.Check
+func runRandTestBool(rt randTest) bool {
+ return runRandTest(rt) == nil
+}
+
+func runRandTest(rt randTest) error {
var scheme = rawdb.HashScheme
if rand.Intn(2) == 0 {
scheme = rawdb.PathScheme
@@ -513,12 +536,12 @@ func runRandTest(rt randTest) bool {
newtr, err := New(TrieID(root), triedb)
if err != nil {
rt[i].err = err
- return false
+ return err
}
if nodes != nil {
if err := verifyAccessList(origTrie, newtr, nodes); err != nil {
rt[i].err = err
- return false
+ return err
}
}
tr = newtr
@@ -587,14 +610,14 @@ func runRandTest(rt randTest) bool {
}
// Abort the test on error.
if rt[i].err != nil {
- return false
+ return rt[i].err
}
}
- return true
+ return nil
}
func TestRandom(t *testing.T) {
- if err := quick.Check(runRandTest, nil); err != nil {
+ if err := quick.Check(runRandTestBool, nil); err != nil {
if cerr, ok := err.(*quick.CheckError); ok {
t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
}
@@ -614,7 +637,9 @@ func benchGet(b *testing.B) {
k := make([]byte, 32)
for i := 0; i < benchElemCount; i++ {
binary.LittleEndian.PutUint64(k, uint64(i))
- trie.MustUpdate(k, k)
+ v := make([]byte, 32)
+ binary.LittleEndian.PutUint64(v, uint64(i))
+ trie.MustUpdate(k, v)
}
binary.LittleEndian.PutUint64(k, benchElemCount/2)
@@ -630,8 +655,10 @@ func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
k := make([]byte, 32)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
+ v := make([]byte, 32)
e.PutUint64(k, uint64(i))
- trie.MustUpdate(k, k)
+ e.PutUint64(v, uint64(i))
+ trie.MustUpdate(k, v)
}
return trie
}
@@ -769,7 +796,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
numBytes := random.Uint32() % 33 // [0, 32] bytes
balanceBytes := make([]byte, numBytes)
random.Read(balanceBytes)
- balance := new(big.Int).SetBytes(balanceBytes)
+ balance := new(uint256.Int).SetBytes(balanceBytes)
data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, CodeHash: code})
accounts[i] = data
}
@@ -1181,3 +1208,17 @@ func TestDecodeNode(t *testing.T) {
decodeNode(hash, elems)
}
}
+
+func FuzzTrie(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ var steps = 500
+ var input = bytes.NewReader(data)
+ var finishedFn = func() bool {
+ steps--
+ return steps < 0 || input.Len() == 0
+ }
+ if err := runRandTest(generateSteps(finishedFn, input)); err != nil {
+ t.Fatal(err)
+ }
+ })
+}
diff --git a/trie/triedb/hashdb/database.go b/trie/triedb/hashdb/database.go
index caf79ef936..7fd9b06c19 100644
--- a/trie/triedb/hashdb/database.go
+++ b/trie/triedb/hashdb/database.go
@@ -82,11 +82,6 @@ var Defaults = &Config{
// Database is an intermediate write layer between the trie data structures and
// the disk database. The aim is to accumulate trie writes in-memory and only
// periodically flush a couple tries to disk, garbage collecting the remainder.
-//
-// Note, the trie Database is **not** thread safe in its mutations, but it **is**
-// thread safe in providing individual, independent node access. The rationale
-// behind this split design is to provide read access to RPC handlers and sync
-// servers even while the trie is executing expensive garbage collection.
type Database struct {
diskdb ethdb.Database // Persistent storage for matured trie nodes
resolver ChildResolver // The handler to resolve children of nodes
@@ -113,7 +108,7 @@ type Database struct {
// cachedNode is all the information we know about a single cached trie node
// in the memory database write layer.
type cachedNode struct {
- node []byte // Encoded node blob
+ node []byte // Encoded node blob, immutable
parents uint32 // Number of live nodes referencing this one
external map[common.Hash]struct{} // The set of external children
flushPrev common.Hash // Previous node in the flush-list
@@ -152,9 +147,9 @@ func New(diskdb ethdb.Database, config *Config, resolver ChildResolver) *Databas
}
}
-// insert inserts a simplified trie node into the memory database.
-// All nodes inserted by this function will be reference tracked
-// and in theory should only used for **trie nodes** insertion.
+// insert inserts a trie node into the memory database. All nodes inserted by
+// this function will be reference tracked. This function assumes the lock is
+// already held.
func (db *Database) insert(hash common.Hash, node []byte) {
// If the node's already cached, skip
if _, ok := db.dirties[hash]; ok {
@@ -183,9 +178,9 @@ func (db *Database) insert(hash common.Hash, node []byte) {
db.dirtiesSize += common.StorageSize(common.HashLength + len(node))
}
-// Node retrieves an encoded cached trie node from memory. If it cannot be found
+// node retrieves an encoded cached trie node from memory. If it cannot be found
// cached, the method queries the persistent database for the content.
-func (db *Database) Node(hash common.Hash) ([]byte, error) {
+func (db *Database) node(hash common.Hash) ([]byte, error) {
// It doesn't make sense to retrieve the metaroot
if hash == (common.Hash{}) {
return nil, errors.New("not found")
@@ -198,11 +193,14 @@ func (db *Database) Node(hash common.Hash) ([]byte, error) {
return enc, nil
}
}
- // Retrieve the node from the dirty cache if available
+ // Retrieve the node from the dirty cache if available.
db.lock.RLock()
dirty := db.dirties[hash]
db.lock.RUnlock()
+ // Return the cached node if it's found in the dirty set.
+ // The dirty.node field is immutable and safe to read it
+ // even without lock guard.
if dirty != nil {
memcacheDirtyHitMeter.Mark(1)
memcacheDirtyReadMeter.Mark(int64(len(dirty.node)))
@@ -223,20 +221,6 @@ func (db *Database) Node(hash common.Hash) ([]byte, error) {
return nil, errors.New("not found")
}
-// Nodes retrieves the hashes of all the nodes cached within the memory database.
-// This method is extremely expensive and should only be used to validate internal
-// states in test code.
-func (db *Database) Nodes() []common.Hash {
- db.lock.RLock()
- defer db.lock.RUnlock()
-
- var hashes = make([]common.Hash, 0, len(db.dirties))
- for hash := range db.dirties {
- hashes = append(hashes, hash)
- }
- return hashes
-}
-
// Reference adds a new reference from a parent node to a child node.
// This function is used to add reference between internal trie node
// and external node(e.g. storage trie root), all internal trie nodes
@@ -344,30 +328,26 @@ func (db *Database) dereference(hash common.Hash) {
// Cap iteratively flushes old but still referenced trie nodes until the total
// memory usage goes below the given threshold.
-//
-// Note, this method is a non-synchronized mutator. It is unsafe to call this
-// concurrently with other mutators.
func (db *Database) Cap(limit common.StorageSize) error {
+ db.lock.Lock()
+ defer db.lock.Unlock()
+
// Create a database batch to flush persistent data out. It is important that
// outside code doesn't see an inconsistent state (referenced data removed from
// memory cache during commit but not yet in persistent storage). This is ensured
// by only uncaching existing data when the database write finalizes.
- db.lock.RLock()
+ batch := db.diskdb.NewBatch()
nodes, storage, start := len(db.dirties), db.dirtiesSize, time.Now()
+
// db.dirtiesSize only contains the useful data in the cache, but when reporting
// the total memory consumption, the maintenance metadata is also needed to be
// counted.
size := db.dirtiesSize + common.StorageSize(len(db.dirties)*cachedNodeSize)
size += db.childrenSize
- db.lock.RUnlock()
-
- batch := db.diskdb.NewBatch()
// Keep committing nodes from the flush-list until we're below allowance
oldest := db.oldest
err := func() error {
- db.lock.RLock()
- defer db.lock.RUnlock()
for size > limit && oldest != (common.Hash{}) {
// Fetch the oldest referenced node and push into the batch
node := db.dirties[oldest]
@@ -401,9 +381,6 @@ func (db *Database) Cap(limit common.StorageSize) error {
return err
}
// Write successful, clear out the flushed data
- db.lock.Lock()
- defer db.lock.Unlock()
-
for db.oldest != oldest {
node := db.dirties[db.oldest]
delete(db.dirties, db.oldest)
@@ -434,10 +411,10 @@ func (db *Database) Cap(limit common.StorageSize) error {
// Commit iterates over all the children of a particular node, writes them out
// to disk, forcefully tearing down all references in both directions. As a side
// effect, all pre-images accumulated up to this point are also written.
-//
-// Note, this method is a non-synchronized mutator. It is unsafe to call this
-// concurrently with other mutators.
func (db *Database) Commit(node common.Hash, report bool) error {
+ db.lock.Lock()
+ defer db.lock.Unlock()
+
// Create a database batch to flush persistent data out. It is important that
// outside code doesn't see an inconsistent state (referenced data removed from
// memory cache during commit but not yet in persistent storage). This is ensured
@@ -446,10 +423,8 @@ func (db *Database) Commit(node common.Hash, report bool) error {
batch := db.diskdb.NewBatch()
// Move all of the accumulated preimages into a write batch
- db.lock.RLock()
// Move the trie itself into the batch, flushing if enough data is accumulated
nodes, storage := len(db.dirties), db.dirtiesSize
- db.lock.RUnlock()
uncacher := &cleaner{db}
if err := db.commit(node, batch, uncacher); err != nil {
@@ -462,8 +437,6 @@ func (db *Database) Commit(node common.Hash, report bool) error {
return err
}
// Uncache any leftovers in the last batch
- db.lock.Lock()
- defer db.lock.Unlock()
if err := batch.Replay(uncacher); err != nil {
return err
}
@@ -491,13 +464,10 @@ func (db *Database) Commit(node common.Hash, report bool) error {
// commit is the private locked version of Commit.
func (db *Database) commit(hash common.Hash, batch ethdb.Batch, uncacher *cleaner) error {
// If the node does not exist, it's a previously committed node
- db.lock.RLock()
node, ok := db.dirties[hash]
if !ok {
- db.lock.RUnlock()
return nil
}
- db.lock.RUnlock()
var err error
@@ -516,13 +486,11 @@ func (db *Database) commit(hash common.Hash, batch ethdb.Batch, uncacher *cleane
if err := batch.Write(); err != nil {
return err
}
- db.lock.Lock()
err := batch.Replay(uncacher)
- batch.Reset()
- db.lock.Unlock()
if err != nil {
return err
}
+ batch.Reset()
}
return nil
}
@@ -591,7 +559,7 @@ func (db *Database) Initialized(genesisRoot common.Hash) bool {
func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *triestate.Set) error {
// Ensure the parent state is present and signal a warning if not.
if parent != types.EmptyRootHash {
- if blob, _ := db.Node(parent); len(blob) == 0 {
+ if blob, _ := db.node(parent); len(blob) == 0 {
log.Error("parent state is not present")
}
}
@@ -641,6 +609,9 @@ func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, n
// Size returns the current storage size of the memory cache in front of the
// persistent database layer.
+//
+// The first return will always be 0, representing the memory stored in unbounded
+// diff layers above the dirty cache. This is only available in pathdb.
func (db *Database) Size() (common.StorageSize, common.StorageSize, common.StorageSize) {
db.lock.RLock()
defer db.lock.RUnlock()
@@ -669,7 +640,7 @@ func (db *Database) Scheme() string {
// Reader retrieves a node reader belonging to the given state root.
// An error will be returned if the requested state is not available.
func (db *Database) Reader(root common.Hash) (*reader, error) {
- if _, err := db.Node(root); err != nil {
+ if _, err := db.node(root); err != nil {
return nil, fmt.Errorf("state %#x is not available, %v", root, err)
}
return &reader{db: db}, nil
@@ -680,9 +651,9 @@ type reader struct {
db *Database
}
-// Node retrieves the trie node with the given node hash.
-// No error will be returned if the node is not found.
+// Node retrieves the trie node with the given node hash. No error will be
+// returned if the node is not found.
func (reader *reader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
- blob, _ := reader.db.Node(hash)
+ blob, _ := reader.db.node(hash)
return blob, nil
}
diff --git a/trie/triedb/pathdb/database.go b/trie/triedb/pathdb/database.go
index aacd6b9323..e9edf0dcfa 100644
--- a/trie/triedb/pathdb/database.go
+++ b/trie/triedb/pathdb/database.go
@@ -139,7 +139,8 @@ type Database struct {
// readOnly is the flag whether the mutation is allowed to be applied.
// It will be set automatically when the database is journaled during
// the shutdown to reject all following unexpected mutations.
- readOnly bool // Indicator if database is opened in read only mode
+ readOnly bool // Flag if database is opened in read only mode
+ waitSync bool // Flag if database is deactivated due to initial state sync
bufferSize int // Memory allowance (in bytes) for caching dirty nodes
config *Config // Configuration for database
diskdb ethdb.Database // Persistent storage for matured trie nodes
@@ -181,14 +182,37 @@ func New(diskdb ethdb.Database, config *Config) *Database {
}
db.freezer = freezer
- // Truncate the extra state histories above in freezer in case
- // it's not aligned with the disk layer.
- pruned, err := truncateFromHead(db.diskdb, freezer, db.tree.bottom().stateID())
- if err != nil {
- log.Crit("Failed to truncate extra state histories", "err", err)
+ diskLayerID := db.tree.bottom().stateID()
+ if diskLayerID == 0 {
+ // Reset the entire state histories in case the trie database is
+ // not initialized yet, as these state histories are not expected.
+ frozen, err := db.freezer.Ancients()
+ if err != nil {
+ log.Crit("Failed to retrieve head of state history", "err", err)
+ }
+ if frozen != 0 {
+ err := db.freezer.Reset()
+ if err != nil {
+ log.Crit("Failed to reset state histories", "err", err)
+ }
+ log.Info("Truncated extraneous state history")
+ }
+ } else {
+ // Truncate the extra state histories above in freezer in case
+ // it's not aligned with the disk layer.
+ pruned, err := truncateFromHead(db.diskdb, freezer, diskLayerID)
+ if err != nil {
+ log.Crit("Failed to truncate extra state histories", "err", err)
+ }
+ if pruned != 0 {
+ log.Warn("Truncated extra state histories", "number", pruned)
+ }
}
- if pruned != 0 {
- log.Warn("Truncated extra state histories", "number", pruned)
+ }
+ // Disable database in case node is still in the initial state sync stage.
+ if rawdb.ReadSnapSyncStatusFlag(diskdb) == rawdb.StateSyncRunning && !db.readOnly {
+ if err := db.Disable(); err != nil {
+ log.Crit("Failed to disable database", "err", err) // impossible to happen
}
}
log.Warn("Path-based state scheme is an experimental feature", "sync", db.config.SyncFlush)
@@ -216,9 +240,9 @@ func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint6
db.lock.Lock()
defer db.lock.Unlock()
- // Short circuit if the database is in read only mode.
- if db.readOnly {
- return errSnapshotReadOnly
+ // Short circuit if the mutation is not allowed.
+ if err := db.modifyAllowed(); err != nil {
+ return err
}
if err := db.tree.add(root, parentRoot, block, nodes, states); err != nil {
return err
@@ -239,45 +263,59 @@ func (db *Database) Commit(root common.Hash, report bool) error {
db.lock.Lock()
defer db.lock.Unlock()
- // Short circuit if the database is in read only mode.
- if db.readOnly {
- return errSnapshotReadOnly
+ // Short circuit if the mutation is not allowed.
+ if err := db.modifyAllowed(); err != nil {
+ return err
}
return db.tree.cap(root, 0)
}
-// Reset rebuilds the database with the specified state as the base.
-//
-// - if target state is empty, clear the stored state and all layers on top
-// - if target state is non-empty, ensure the stored state matches with it
-// and clear all other layers on top.
-func (db *Database) Reset(root common.Hash) error {
+// Disable deactivates the database and invalidates all available state layers
+// as stale to prevent access to the persistent state, which is in the syncing
+// stage.
+func (db *Database) Disable() error {
db.lock.Lock()
defer db.lock.Unlock()
// Short circuit if the database is in read only mode.
if db.readOnly {
- return errSnapshotReadOnly
+ return errDatabaseReadOnly
}
- batch := db.diskdb.NewBatch()
- root = types.TrieRootHash(root)
- if root == types.EmptyRootHash {
- // Empty state is requested as the target, nuke out
- // the root node and leave all others as dangling.
- rawdb.DeleteAccountTrieNode(batch, nil)
- } else {
- // Ensure the requested state is existent before any
- // action is applied.
- _, hash := rawdb.ReadAccountTrieNode(db.diskdb, nil)
- if hash != root {
- return fmt.Errorf("state is mismatched, local: %x, target: %x", hash, root)
- }
+ // Prevent duplicated disable operation.
+ if db.waitSync {
+ log.Error("Reject duplicated disable operation")
+ return nil
}
- // Mark the disk layer as stale before applying any mutation.
+ db.waitSync = true
+
+ // Mark the disk layer as stale to prevent access to persistent state.
db.tree.bottom().markStale()
+ // Write the initial sync flag to persist it across restarts.
+ rawdb.WriteSnapSyncStatusFlag(db.diskdb, rawdb.StateSyncRunning)
+ log.Info("Disabled trie database due to state sync")
+ return nil
+}
+
+// Enable activates database and resets the state tree with the provided persistent
+// state root once the state sync is finished.
+func (db *Database) Enable(root common.Hash) error {
+ db.lock.Lock()
+ defer db.lock.Unlock()
+
+ // Short circuit if the database is in read only mode.
+ if db.readOnly {
+ return errDatabaseReadOnly
+ }
+ // Ensure the provided state root matches the stored one.
+ root = types.TrieRootHash(root)
+ _, stored := rawdb.ReadAccountTrieNode(db.diskdb, nil)
+ if stored != root {
+ return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root)
+ }
// Drop the stale state journal in persistent database and
// reset the persistent state id back to zero.
+ batch := db.diskdb.NewBatch()
rawdb.DeleteTrieJournal(batch)
rawdb.WritePersistentStateID(batch, 0)
if err := batch.Write(); err != nil {
@@ -296,6 +334,10 @@ func (db *Database) Reset(root common.Hash) error {
// with **empty clean cache and node buffer**.
dl := newDiskLayer(root, 0, db, nil, NewTrieNodeBuffer(db.config.SyncFlush, db.bufferSize, nil, 0))
db.tree.reset(dl)
+
+ // Re-enable the database as the final step.
+ db.waitSync = false
+ rawdb.WriteSnapSyncStatusFlag(db.diskdb, rawdb.StateSyncFinished)
log.Info("Rebuilt trie database", "root", root)
return nil
}
@@ -308,7 +350,10 @@ func (db *Database) Recover(root common.Hash, loader triestate.TrieLoader) error
defer db.lock.Unlock()
// Short circuit if rollback operation is not supported.
- if db.readOnly || db.freezer == nil {
+ if err := db.modifyAllowed(); err != nil {
+ return err
+ }
+ if db.freezer == nil {
return errors.New("state rollback is non-supported")
}
// Short circuit if the target state is not recoverable.
@@ -416,6 +461,9 @@ func (db *Database) Initialized(genesisRoot common.Hash) bool {
inited = true
}
})
+ if !inited {
+ inited = rawdb.ReadSnapSyncStatusFlag(db.diskdb) != rawdb.StateSyncUnknown
+ }
return inited
}
@@ -444,6 +492,18 @@ func (db *Database) Head() common.Hash {
return db.tree.front()
}
+// modifyAllowed returns the indicator if mutation is allowed. This function
+// assumes the db.lock is already held.
+func (db *Database) modifyAllowed() error {
+ if db.readOnly {
+ return errDatabaseReadOnly
+ }
+ if db.waitSync {
+ return errDatabaseWaitSync
+ }
+ return nil
+}
+
// GetAllRooHash returns all diffLayer and diskLayer root hash
func (db *Database) GetAllRooHash() [][]string {
db.lock.Lock()
diff --git a/trie/triedb/pathdb/database_test.go b/trie/triedb/pathdb/database_test.go
index 42bb014e73..6fcb160bdd 100644
--- a/trie/triedb/pathdb/database_test.go
+++ b/trie/triedb/pathdb/database_test.go
@@ -20,7 +20,6 @@ import (
"bytes"
"errors"
"fmt"
- "math/big"
"math/rand"
"testing"
@@ -32,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/trie/testutil"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/holiman/uint256"
)
func updateTrie(addrHash common.Hash, root common.Hash, dirties, cleans map[common.Hash][]byte) (common.Hash, *trienode.NodeSet) {
@@ -53,7 +53,7 @@ func updateTrie(addrHash common.Hash, root common.Hash, dirties, cleans map[comm
func generateAccount(storageRoot common.Hash) types.StateAccount {
return types.StateAccount{
Nonce: uint64(rand.Intn(100)),
- Balance: big.NewInt(rand.Int63()),
+ Balance: uint256.NewInt(rand.Uint64()),
CodeHash: testutil.RandBytes(32),
Root: storageRoot,
}
@@ -443,38 +443,39 @@ func TestDatabaseRecoverable(t *testing.T) {
}
}
-func TestReset(t *testing.T) {
- var (
- tester = newTester(t, 0)
- index = tester.bottomIndex()
- )
+func TestDisable(t *testing.T) {
+ tester := newTester(t, 0)
defer tester.release()
- // Reset database to unknown target, should reject it
- if err := tester.db.Reset(testutil.RandomHash()); err == nil {
- t.Fatal("Failed to reject invalid reset")
+ _, stored := rawdb.ReadAccountTrieNode(tester.db.diskdb, nil)
+ if err := tester.db.Disable(); err != nil {
+ t.Fatal("Failed to deactivate database")
}
- // Reset database to state persisted in the disk
- if err := tester.db.Reset(types.EmptyRootHash); err != nil {
- t.Fatalf("Failed to reset database %v", err)
+ if err := tester.db.Enable(types.EmptyRootHash); err == nil {
+ t.Fatalf("Invalid activation should be rejected")
}
+ if err := tester.db.Enable(stored); err != nil {
+ t.Fatal("Failed to activate database")
+ }
+
// Ensure journal is deleted from disk
if blob := rawdb.ReadTrieJournal(tester.db.diskdb); len(blob) != 0 {
t.Fatal("Failed to clean journal")
}
// Ensure all trie histories are removed
- for i := 0; i <= index; i++ {
- _, err := readHistory(tester.db.freezer, uint64(i+1))
- if err == nil {
- t.Fatalf("Failed to clean state history, index %d", i+1)
- }
+ n, err := tester.db.freezer.Ancients()
+ if err != nil {
+ t.Fatal("Failed to clean state history")
+ }
+ if n != 0 {
+ t.Fatal("Failed to clean state history")
}
// Verify layer tree structure, single disk layer is expected
if tester.db.tree.len() != 1 {
t.Fatalf("Extra layer kept %d", tester.db.tree.len())
}
- if tester.db.tree.bottom().rootHash() != types.EmptyRootHash {
- t.Fatalf("Root hash is not matched exp %x got %x", types.EmptyRootHash, tester.db.tree.bottom().rootHash())
+ if tester.db.tree.bottom().rootHash() != stored {
+ t.Fatalf("Root hash is not matched exp %x got %x", stored, tester.db.tree.bottom().rootHash())
}
}
diff --git a/trie/triedb/pathdb/errors.go b/trie/triedb/pathdb/errors.go
index 03114f9d65..46b986f884 100644
--- a/trie/triedb/pathdb/errors.go
+++ b/trie/triedb/pathdb/errors.go
@@ -25,9 +25,13 @@ import (
)
var (
- // errSnapshotReadOnly is returned if the database is opened in read only mode
- // and mutation is requested.
- errSnapshotReadOnly = errors.New("read only")
+ // errDatabaseReadOnly is returned if the database is opened in read only mode
+ // to prevent any mutation.
+ errDatabaseReadOnly = errors.New("read only")
+
+ // errDatabaseWaitSync is returned if the initial state sync is not completed
+ // yet and database is disabled to prevent accessing state.
+ errDatabaseWaitSync = errors.New("waiting for sync")
// errSnapshotStale is returned from data accessors if the underlying layer
// layer had been invalidated due to the chain progressing forward far enough
diff --git a/trie/triedb/pathdb/journal.go b/trie/triedb/pathdb/journal.go
index bb4594747b..1100e03ba3 100644
--- a/trie/triedb/pathdb/journal.go
+++ b/trie/triedb/pathdb/journal.go
@@ -359,7 +359,7 @@ func (db *Database) Journal(root common.Hash) error {
disk.buffer.waitAndStopFlushing()
// Short circuit if the database is in read only mode.
if db.readOnly {
- return errSnapshotReadOnly
+ return errDatabaseReadOnly
}
// Firstly write out the metadata of journal
journal := new(bytes.Buffer)
diff --git a/trie/trienode/node.go b/trie/trienode/node.go
index 98d5588b6d..95315c2e9a 100644
--- a/trie/trienode/node.go
+++ b/trie/trienode/node.go
@@ -39,7 +39,7 @@ func (n *Node) Size() int {
// IsDeleted returns the indicator if the node is marked as deleted.
func (n *Node) IsDeleted() bool {
- return n.Hash == (common.Hash{})
+ return len(n.Blob) == 0
}
// New constructs a node with provided node information.
diff --git a/trie/utils/verkle.go b/trie/utils/verkle.go
new file mode 100644
index 0000000000..ce059edc64
--- /dev/null
+++ b/trie/utils/verkle.go
@@ -0,0 +1,342 @@
+// Copyright 2023 go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package utils
+
+import (
+ "encoding/binary"
+ "sync"
+
+ "github.com/crate-crypto/go-ipa/bandersnatch/fr"
+ "github.com/ethereum/go-ethereum/common/lru"
+ "github.com/ethereum/go-ethereum/metrics"
+ "github.com/gballet/go-verkle"
+ "github.com/holiman/uint256"
+)
+
+const (
+ // The spec of verkle key encoding can be found here.
+ // https://notes.ethereum.org/@vbuterin/verkle_tree_eip#Tree-embedding
+ VersionLeafKey = 0
+ BalanceLeafKey = 1
+ NonceLeafKey = 2
+ CodeKeccakLeafKey = 3
+ CodeSizeLeafKey = 4
+)
+
+var (
+ zero = uint256.NewInt(0)
+ verkleNodeWidthLog2 = 8
+ headerStorageOffset = uint256.NewInt(64)
+ mainStorageOffsetLshVerkleNodeWidth = new(uint256.Int).Lsh(uint256.NewInt(256), 31-uint(verkleNodeWidthLog2))
+ codeOffset = uint256.NewInt(128)
+ verkleNodeWidth = uint256.NewInt(256)
+ codeStorageDelta = uint256.NewInt(0).Sub(codeOffset, headerStorageOffset)
+
+ index0Point *verkle.Point // pre-computed commitment of polynomial [2+256*64]
+
+ // cacheHitGauge is the metric to track how many cache hit occurred.
+ cacheHitGauge = metrics.NewRegisteredGauge("trie/verkle/cache/hit", nil)
+
+ // cacheMissGauge is the metric to track how many cache miss occurred.
+ cacheMissGauge = metrics.NewRegisteredGauge("trie/verkle/cache/miss", nil)
+)
+
+func init() {
+ // The byte array is the Marshalled output of the point computed as such:
+ //
+ // var (
+ // config = verkle.GetConfig()
+ // fr verkle.Fr
+ // )
+ // verkle.FromLEBytes(&fr, []byte{2, 64})
+ // point := config.CommitToPoly([]verkle.Fr{fr}, 1)
+ index0Point = new(verkle.Point)
+ err := index0Point.SetBytes([]byte{34, 25, 109, 242, 193, 5, 144, 224, 76, 52, 189, 92, 197, 126, 9, 145, 27, 152, 199, 130, 165, 3, 210, 27, 193, 131, 142, 28, 110, 26, 16, 191})
+ if err != nil {
+ panic(err)
+ }
+}
+
+// PointCache is the LRU cache for storing evaluated address commitment.
+type PointCache struct {
+ lru lru.BasicLRU[string, *verkle.Point]
+ lock sync.RWMutex
+}
+
+// NewPointCache returns the cache with specified size.
+func NewPointCache(maxItems int) *PointCache {
+ return &PointCache{
+ lru: lru.NewBasicLRU[string, *verkle.Point](maxItems),
+ }
+}
+
+// Get returns the cached commitment for the specified address, or computing
+// it on the flight.
+func (c *PointCache) Get(addr []byte) *verkle.Point {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ p, ok := c.lru.Get(string(addr))
+ if ok {
+ cacheHitGauge.Inc(1)
+ return p
+ }
+ cacheMissGauge.Inc(1)
+ p = evaluateAddressPoint(addr)
+ c.lru.Add(string(addr), p)
+ return p
+}
+
+// GetStem returns the first 31 bytes of the tree key as the tree stem. It only
+// works for the account metadata whose treeIndex is 0.
+func (c *PointCache) GetStem(addr []byte) []byte {
+ p := c.Get(addr)
+ return pointToHash(p, 0)[:31]
+}
+
+// GetTreeKey performs both the work of the spec's get_tree_key function, and that
+// of pedersen_hash: it builds the polynomial in pedersen_hash without having to
+// create a mostly zero-filled buffer and "type cast" it to a 128-long 16-byte
+// array. Since at most the first 5 coefficients of the polynomial will be non-zero,
+// these 5 coefficients are created directly.
+func GetTreeKey(address []byte, treeIndex *uint256.Int, subIndex byte) []byte {
+ if len(address) < 32 {
+ var aligned [32]byte
+ address = append(aligned[:32-len(address)], address...)
+ }
+ // poly = [2+256*64, address_le_low, address_le_high, tree_index_le_low, tree_index_le_high]
+ var poly [5]fr.Element
+
+ // 32-byte address, interpreted as two little endian
+ // 16-byte numbers.
+ verkle.FromLEBytes(&poly[1], address[:16])
+ verkle.FromLEBytes(&poly[2], address[16:])
+
+ // treeIndex must be interpreted as a 32-byte aligned little-endian integer.
+ // e.g: if treeIndex is 0xAABBCC, we need the byte representation to be 0xCCBBAA00...00.
+ // poly[3] = LE({CC,BB,AA,00...0}) (16 bytes), poly[4]=LE({00,00,...}) (16 bytes).
+ //
+ // To avoid unnecessary endianness conversions for go-ipa, we do some trick:
+ // - poly[3]'s byte representation is the same as the *top* 16 bytes (trieIndexBytes[16:]) of
+ // 32-byte aligned big-endian representation (BE({00,...,AA,BB,CC})).
+ // - poly[4]'s byte representation is the same as the *low* 16 bytes (trieIndexBytes[:16]) of
+ // the 32-byte aligned big-endian representation (BE({00,00,...}).
+ trieIndexBytes := treeIndex.Bytes32()
+ verkle.FromBytes(&poly[3], trieIndexBytes[16:])
+ verkle.FromBytes(&poly[4], trieIndexBytes[:16])
+
+ cfg := verkle.GetConfig()
+ ret := cfg.CommitToPoly(poly[:], 0)
+
+ // add a constant point corresponding to poly[0]=[2+256*64].
+ ret.Add(ret, index0Point)
+
+ return pointToHash(ret, subIndex)
+}
+
+// GetTreeKeyWithEvaluatedAddress is basically identical to GetTreeKey, the only
+// difference is a part of polynomial is already evaluated.
+//
+// Specifically, poly = [2+256*64, address_le_low, address_le_high] is already
+// evaluated.
+func GetTreeKeyWithEvaluatedAddress(evaluated *verkle.Point, treeIndex *uint256.Int, subIndex byte) []byte {
+ var poly [5]fr.Element
+
+ poly[0].SetZero()
+ poly[1].SetZero()
+ poly[2].SetZero()
+
+ // little-endian, 32-byte aligned treeIndex
+ var index [32]byte
+ for i := 0; i < len(treeIndex); i++ {
+ binary.LittleEndian.PutUint64(index[i*8:(i+1)*8], treeIndex[i])
+ }
+ verkle.FromLEBytes(&poly[3], index[:16])
+ verkle.FromLEBytes(&poly[4], index[16:])
+
+ cfg := verkle.GetConfig()
+ ret := cfg.CommitToPoly(poly[:], 0)
+
+ // add the pre-evaluated address
+ ret.Add(ret, evaluated)
+
+ return pointToHash(ret, subIndex)
+}
+
+// VersionKey returns the verkle tree key of the version field for the specified account.
+func VersionKey(address []byte) []byte {
+ return GetTreeKey(address, zero, VersionLeafKey)
+}
+
+// BalanceKey returns the verkle tree key of the balance field for the specified account.
+func BalanceKey(address []byte) []byte {
+ return GetTreeKey(address, zero, BalanceLeafKey)
+}
+
+// NonceKey returns the verkle tree key of the nonce field for the specified account.
+func NonceKey(address []byte) []byte {
+ return GetTreeKey(address, zero, NonceLeafKey)
+}
+
+// CodeKeccakKey returns the verkle tree key of the code keccak field for
+// the specified account.
+func CodeKeccakKey(address []byte) []byte {
+ return GetTreeKey(address, zero, CodeKeccakLeafKey)
+}
+
+// CodeSizeKey returns the verkle tree key of the code size field for the
+// specified account.
+func CodeSizeKey(address []byte) []byte {
+ return GetTreeKey(address, zero, CodeSizeLeafKey)
+}
+
+func codeChunkIndex(chunk *uint256.Int) (*uint256.Int, byte) {
+ var (
+ chunkOffset = new(uint256.Int).Add(codeOffset, chunk)
+ treeIndex = new(uint256.Int).Div(chunkOffset, verkleNodeWidth)
+ subIndexMod = new(uint256.Int).Mod(chunkOffset, verkleNodeWidth)
+ )
+ var subIndex byte
+ if len(subIndexMod) != 0 {
+ subIndex = byte(subIndexMod[0])
+ }
+ return treeIndex, subIndex
+}
+
+// CodeChunkKey returns the verkle tree key of the code chunk for the
+// specified account.
+func CodeChunkKey(address []byte, chunk *uint256.Int) []byte {
+ treeIndex, subIndex := codeChunkIndex(chunk)
+ return GetTreeKey(address, treeIndex, subIndex)
+}
+
+func storageIndex(bytes []byte) (*uint256.Int, byte) {
+ // If the storage slot is in the header, we need to add the header offset.
+ var key uint256.Int
+ key.SetBytes(bytes)
+ if key.Cmp(codeStorageDelta) < 0 {
+ // This addition is always safe; it can't ever overflow since pos
+
+package utils
+
+import (
+ "bytes"
+ "testing"
+
+ "github.com/gballet/go-verkle"
+ "github.com/holiman/uint256"
+)
+
+func TestTreeKey(t *testing.T) {
+ var (
+ address = []byte{0x01}
+ addressEval = evaluateAddressPoint(address)
+ smallIndex = uint256.NewInt(1)
+ largeIndex = uint256.NewInt(10000)
+ smallStorage = []byte{0x1}
+ largeStorage = bytes.Repeat([]byte{0xff}, 16)
+ )
+ if !bytes.Equal(VersionKey(address), VersionKeyWithEvaluatedAddress(addressEval)) {
+ t.Fatal("Unmatched version key")
+ }
+ if !bytes.Equal(BalanceKey(address), BalanceKeyWithEvaluatedAddress(addressEval)) {
+ t.Fatal("Unmatched balance key")
+ }
+ if !bytes.Equal(NonceKey(address), NonceKeyWithEvaluatedAddress(addressEval)) {
+ t.Fatal("Unmatched nonce key")
+ }
+ if !bytes.Equal(CodeKeccakKey(address), CodeKeccakKeyWithEvaluatedAddress(addressEval)) {
+ t.Fatal("Unmatched code keccak key")
+ }
+ if !bytes.Equal(CodeSizeKey(address), CodeSizeKeyWithEvaluatedAddress(addressEval)) {
+ t.Fatal("Unmatched code size key")
+ }
+ if !bytes.Equal(CodeChunkKey(address, smallIndex), CodeChunkKeyWithEvaluatedAddress(addressEval, smallIndex)) {
+ t.Fatal("Unmatched code chunk key")
+ }
+ if !bytes.Equal(CodeChunkKey(address, largeIndex), CodeChunkKeyWithEvaluatedAddress(addressEval, largeIndex)) {
+ t.Fatal("Unmatched code chunk key")
+ }
+ if !bytes.Equal(StorageSlotKey(address, smallStorage), StorageSlotKeyWithEvaluatedAddress(addressEval, smallStorage)) {
+ t.Fatal("Unmatched storage slot key")
+ }
+ if !bytes.Equal(StorageSlotKey(address, largeStorage), StorageSlotKeyWithEvaluatedAddress(addressEval, largeStorage)) {
+ t.Fatal("Unmatched storage slot key")
+ }
+}
+
+// goos: darwin
+// goarch: amd64
+// pkg: github.com/ethereum/go-ethereum/trie/utils
+// cpu: VirtualApple @ 2.50GHz
+// BenchmarkTreeKey
+// BenchmarkTreeKey-8 398731 2961 ns/op 32 B/op 1 allocs/op
+func BenchmarkTreeKey(b *testing.B) {
+ // Initialize the IPA settings which can be pretty expensive.
+ verkle.GetConfig()
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ BalanceKey([]byte{0x01})
+ }
+}
+
+// goos: darwin
+// goarch: amd64
+// pkg: github.com/ethereum/go-ethereum/trie/utils
+// cpu: VirtualApple @ 2.50GHz
+// BenchmarkTreeKeyWithEvaluation
+// BenchmarkTreeKeyWithEvaluation-8 513855 2324 ns/op 32 B/op 1 allocs/op
+func BenchmarkTreeKeyWithEvaluation(b *testing.B) {
+ // Initialize the IPA settings which can be pretty expensive.
+ verkle.GetConfig()
+
+ addr := []byte{0x01}
+ eval := evaluateAddressPoint(addr)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ BalanceKeyWithEvaluatedAddress(eval)
+ }
+}
+
+// goos: darwin
+// goarch: amd64
+// pkg: github.com/ethereum/go-ethereum/trie/utils
+// cpu: VirtualApple @ 2.50GHz
+// BenchmarkStorageKey
+// BenchmarkStorageKey-8 230516 4584 ns/op 96 B/op 3 allocs/op
+func BenchmarkStorageKey(b *testing.B) {
+ // Initialize the IPA settings which can be pretty expensive.
+ verkle.GetConfig()
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ StorageSlotKey([]byte{0x01}, bytes.Repeat([]byte{0xff}, 32))
+ }
+}
+
+// goos: darwin
+// goarch: amd64
+// pkg: github.com/ethereum/go-ethereum/trie/utils
+// cpu: VirtualApple @ 2.50GHz
+// BenchmarkStorageKeyWithEvaluation
+// BenchmarkStorageKeyWithEvaluation-8 320125 3753 ns/op 96 B/op 3 allocs/op
+func BenchmarkStorageKeyWithEvaluation(b *testing.B) {
+ // Initialize the IPA settings which can be pretty expensive.
+ verkle.GetConfig()
+
+ addr := []byte{0x01}
+ eval := evaluateAddressPoint(addr)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ StorageSlotKeyWithEvaluatedAddress(eval, bytes.Repeat([]byte{0xff}, 32))
+ }
+}
diff --git a/trie/verkle.go b/trie/verkle.go
new file mode 100644
index 0000000000..c21a796a0f
--- /dev/null
+++ b/trie/verkle.go
@@ -0,0 +1,374 @@
+// Copyright 2023 go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package trie
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/trie/utils"
+ "github.com/gballet/go-verkle"
+ "github.com/holiman/uint256"
+)
+
+var (
+ zero [32]byte
+ errInvalidRootType = errors.New("invalid node type for root")
+)
+
+// VerkleTrie is a wrapper around VerkleNode that implements the trie.Trie
+// interface so that Verkle trees can be reused verbatim.
+type VerkleTrie struct {
+ root verkle.VerkleNode
+ db *Database
+ cache *utils.PointCache
+ reader *trieReader
+}
+
+// NewVerkleTrie constructs a verkle tree based on the specified root hash.
+func NewVerkleTrie(root common.Hash, db *Database, cache *utils.PointCache) (*VerkleTrie, error) {
+ reader, err := newTrieReader(root, common.Hash{}, db)
+ if err != nil {
+ return nil, err
+ }
+ // Parse the root verkle node if it's not empty.
+ node := verkle.New()
+ if root != types.EmptyVerkleHash && root != types.EmptyRootHash {
+ blob, err := reader.node(nil, common.Hash{})
+ if err != nil {
+ return nil, err
+ }
+ node, err = verkle.ParseNode(blob, 0)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &VerkleTrie{
+ root: node,
+ db: db,
+ cache: cache,
+ reader: reader,
+ }, nil
+}
+
+// GetKey returns the sha3 preimage of a hashed key that was previously used
+// to store a value.
+func (t *VerkleTrie) GetKey(key []byte) []byte {
+ return key
+}
+
+// GetAccount implements state.Trie, retrieving the account with the specified
+// account address. If the specified account is not in the verkle tree, nil will
+// be returned. If the tree is corrupted, an error will be returned.
+func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error) {
+ var (
+ acc = &types.StateAccount{}
+ values [][]byte
+ err error
+ )
+ switch n := t.root.(type) {
+ case *verkle.InternalNode:
+ values, err = n.GetValuesAtStem(t.cache.GetStem(addr[:]), t.nodeResolver)
+ if err != nil {
+ return nil, fmt.Errorf("GetAccount (%x) error: %v", addr, err)
+ }
+ default:
+ return nil, errInvalidRootType
+ }
+ if values == nil {
+ return nil, nil
+ }
+ // Decode nonce in little-endian
+ if len(values[utils.NonceLeafKey]) > 0 {
+ acc.Nonce = binary.LittleEndian.Uint64(values[utils.NonceLeafKey])
+ }
+ // Decode balance in little-endian
+ var balance [32]byte
+ copy(balance[:], values[utils.BalanceLeafKey])
+ for i := 0; i < len(balance)/2; i++ {
+ balance[len(balance)-i-1], balance[i] = balance[i], balance[len(balance)-i-1]
+ }
+ acc.Balance = new(uint256.Int).SetBytes32(balance[:])
+
+ // Decode codehash
+ acc.CodeHash = values[utils.CodeKeccakLeafKey]
+
+ // TODO account.Root is leave as empty. How should we handle the legacy account?
+ return acc, nil
+}
+
+// GetStorage implements state.Trie, retrieving the storage slot with the specified
+// account address and storage key. If the specified slot is not in the verkle tree,
+// nil will be returned. If the tree is corrupted, an error will be returned.
+func (t *VerkleTrie) GetStorage(addr common.Address, key []byte) ([]byte, error) {
+ k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), key)
+ val, err := t.root.Get(k, t.nodeResolver)
+ if err != nil {
+ return nil, err
+ }
+ return common.TrimLeftZeroes(val), nil
+}
+
+// UpdateAccount implements state.Trie, writing the provided account into the tree.
+// If the tree is corrupted, an error will be returned.
+func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount) error {
+ var (
+ err error
+ nonce, balance [32]byte
+ values = make([][]byte, verkle.NodeWidth)
+ )
+ values[utils.VersionLeafKey] = zero[:]
+ values[utils.CodeKeccakLeafKey] = acc.CodeHash[:]
+
+ // Encode nonce in little-endian
+ binary.LittleEndian.PutUint64(nonce[:], acc.Nonce)
+ values[utils.NonceLeafKey] = nonce[:]
+
+ // Encode balance in little-endian
+ bytes := acc.Balance.Bytes()
+ if len(bytes) > 0 {
+ for i, b := range bytes {
+ balance[len(bytes)-i-1] = b
+ }
+ }
+ values[utils.BalanceLeafKey] = balance[:]
+
+ switch n := t.root.(type) {
+ case *verkle.InternalNode:
+ err = n.InsertValuesAtStem(t.cache.GetStem(addr[:]), values, t.nodeResolver)
+ if err != nil {
+ return fmt.Errorf("UpdateAccount (%x) error: %v", addr, err)
+ }
+ default:
+ return errInvalidRootType
+ }
+ // TODO figure out if the code size needs to be updated, too
+ return nil
+}
+
+// UpdateStorage implements state.Trie, writing the provided storage slot into
+// the tree. If the tree is corrupted, an error will be returned.
+func (t *VerkleTrie) UpdateStorage(address common.Address, key, value []byte) error {
+ // Left padding the slot value to 32 bytes.
+ var v [32]byte
+ if len(value) >= 32 {
+ copy(v[:], value[:32])
+ } else {
+ copy(v[32-len(value):], value[:])
+ }
+ k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(address.Bytes()), key)
+ return t.root.Insert(k, v[:], t.nodeResolver)
+}
+
+// DeleteAccount implements state.Trie, deleting the specified account from the
+// trie. If the account was not existent in the trie, no error will be returned.
+// If the trie is corrupted, an error will be returned.
+func (t *VerkleTrie) DeleteAccount(addr common.Address) error {
+ var (
+ err error
+ values = make([][]byte, verkle.NodeWidth)
+ )
+ for i := 0; i < verkle.NodeWidth; i++ {
+ values[i] = zero[:]
+ }
+ switch n := t.root.(type) {
+ case *verkle.InternalNode:
+ err = n.InsertValuesAtStem(t.cache.GetStem(addr.Bytes()), values, t.nodeResolver)
+ if err != nil {
+ return fmt.Errorf("DeleteAccount (%x) error: %v", addr, err)
+ }
+ default:
+ return errInvalidRootType
+ }
+ return nil
+}
+
+// DeleteStorage implements state.Trie, deleting the specified storage slot from
+// the trie. If the storage slot was not existent in the trie, no error will be
+// returned. If the trie is corrupted, an error will be returned.
+func (t *VerkleTrie) DeleteStorage(addr common.Address, key []byte) error {
+ var zero [32]byte
+ k := utils.StorageSlotKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), key)
+ return t.root.Insert(k, zero[:], t.nodeResolver)
+}
+
+// Hash returns the root hash of the tree. It does not write to the database and
+// can be used even if the tree doesn't have one.
+func (t *VerkleTrie) Hash() common.Hash {
+ return t.root.Commit().Bytes()
+}
+
+// Commit writes all nodes to the tree's memory database.
+func (t *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) {
+ root, ok := t.root.(*verkle.InternalNode)
+ if !ok {
+ return common.Hash{}, nil, errors.New("unexpected root node type")
+ }
+ nodes, err := root.BatchSerialize()
+ if err != nil {
+ return common.Hash{}, nil, fmt.Errorf("serializing tree nodes: %s", err)
+ }
+ nodeset := trienode.NewNodeSet(common.Hash{})
+ for _, node := range nodes {
+ // hash parameter is not used in pathdb
+ nodeset.AddNode(node.Path, trienode.New(common.Hash{}, node.SerializedBytes))
+ }
+ // Serialize root commitment form
+ return t.Hash(), nodeset, nil
+}
+
+// NodeIterator implements state.Trie, returning an iterator that returns
+// nodes of the trie. Iteration starts at the key after the given start key.
+//
+// TODO(gballet, rjl493456442) implement it.
+func (t *VerkleTrie) NodeIterator(startKey []byte) (NodeIterator, error) {
+ panic("not implemented")
+}
+
+// Prove implements state.Trie, constructing a Merkle proof for key. The result
+// contains all encoded nodes on the path to the value at key. The value itself
+// is also included in the last node and can be retrieved by verifying the proof.
+//
+// If the trie does not contain a value for key, the returned proof contains all
+// nodes of the longest existing prefix of the key (at least the root), ending
+// with the node that proves the absence of the key.
+//
+// TODO(gballet, rjl493456442) implement it.
+func (t *VerkleTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
+ panic("not implemented")
+}
+
+// Copy returns a deep-copied verkle tree.
+func (t *VerkleTrie) Copy() *VerkleTrie {
+ return &VerkleTrie{
+ root: t.root.Copy(),
+ db: t.db,
+ cache: t.cache,
+ reader: t.reader,
+ }
+}
+
+// IsVerkle indicates if the trie is a Verkle trie.
+func (t *VerkleTrie) IsVerkle() bool {
+ return true
+}
+
+// ChunkedCode represents a sequence of 32-bytes chunks of code (31 bytes of which
+// are actual code, and 1 byte is the pushdata offset).
+type ChunkedCode []byte
+
+// Copy the values here so as to avoid an import cycle
+const (
+ PUSH1 = byte(0x60)
+ PUSH32 = byte(0x7f)
+)
+
+// ChunkifyCode generates the chunked version of an array representing EVM bytecode
+func ChunkifyCode(code []byte) ChunkedCode {
+ var (
+ chunkOffset = 0 // offset in the chunk
+ chunkCount = len(code) / 31
+ codeOffset = 0 // offset in the code
+ )
+ if len(code)%31 != 0 {
+ chunkCount++
+ }
+ chunks := make([]byte, chunkCount*32)
+ for i := 0; i < chunkCount; i++ {
+ // number of bytes to copy, 31 unless the end of the code has been reached.
+ end := 31 * (i + 1)
+ if len(code) < end {
+ end = len(code)
+ }
+ copy(chunks[i*32+1:], code[31*i:end]) // copy the code itself
+
+ // chunk offset = taken from the last chunk.
+ if chunkOffset > 31 {
+ // skip offset calculation if push data covers the whole chunk
+ chunks[i*32] = 31
+ chunkOffset = 1
+ continue
+ }
+ chunks[32*i] = byte(chunkOffset)
+ chunkOffset = 0
+
+ // Check each instruction and update the offset it should be 0 unless
+ // a PUSH-N overflows.
+ for ; codeOffset < end; codeOffset++ {
+ if code[codeOffset] >= PUSH1 && code[codeOffset] <= PUSH32 {
+ codeOffset += int(code[codeOffset] - PUSH1 + 1)
+ if codeOffset+1 >= 31*(i+1) {
+ codeOffset++
+ chunkOffset = codeOffset - 31*(i+1)
+ break
+ }
+ }
+ }
+ }
+ return chunks
+}
+
+// UpdateContractCode implements state.Trie, writing the provided contract code
+// into the trie.
+func (t *VerkleTrie) UpdateContractCode(addr common.Address, codeHash common.Hash, code []byte) error {
+ var (
+ chunks = ChunkifyCode(code)
+ values [][]byte
+ key []byte
+ err error
+ )
+ for i, chunknr := 0, uint64(0); i < len(chunks); i, chunknr = i+32, chunknr+1 {
+ groupOffset := (chunknr + 128) % 256
+ if groupOffset == 0 /* start of new group */ || chunknr == 0 /* first chunk in header group */ {
+ values = make([][]byte, verkle.NodeWidth)
+ key = utils.CodeChunkKeyWithEvaluatedAddress(t.cache.Get(addr.Bytes()), uint256.NewInt(chunknr))
+ }
+ values[groupOffset] = chunks[i : i+32]
+
+ // Reuse the calculated key to also update the code size.
+ if i == 0 {
+ cs := make([]byte, 32)
+ binary.LittleEndian.PutUint64(cs, uint64(len(code)))
+ values[utils.CodeSizeLeafKey] = cs
+ }
+ if groupOffset == 255 || len(chunks)-i <= 32 {
+ switch root := t.root.(type) {
+ case *verkle.InternalNode:
+ err = root.InsertValuesAtStem(key[:31], values, t.nodeResolver)
+ if err != nil {
+ return fmt.Errorf("UpdateContractCode (addr=%x) error: %w", addr[:], err)
+ }
+ default:
+ return errInvalidRootType
+ }
+ }
+ }
+ return nil
+}
+
+func (t *VerkleTrie) ToDot() string {
+ return verkle.ToDot(t.root)
+}
+
+func (t *VerkleTrie) nodeResolver(path []byte) ([]byte, error) {
+ return t.reader.node(path, common.Hash{})
+}
diff --git a/trie/verkle_test.go b/trie/verkle_test.go
new file mode 100644
index 0000000000..1c65b673aa
--- /dev/null
+++ b/trie/verkle_test.go
@@ -0,0 +1,97 @@
+// Copyright 2023 go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package trie
+
+import (
+ "bytes"
+ "reflect"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/trie/utils"
+ "github.com/holiman/uint256"
+)
+
+var (
+ accounts = map[common.Address]*types.StateAccount{
+ {1}: {
+ Nonce: 100,
+ Balance: uint256.NewInt(100),
+ CodeHash: common.Hash{0x1}.Bytes(),
+ },
+ {2}: {
+ Nonce: 200,
+ Balance: uint256.NewInt(200),
+ CodeHash: common.Hash{0x2}.Bytes(),
+ },
+ }
+ storages = map[common.Address]map[common.Hash][]byte{
+ {1}: {
+ common.Hash{10}: []byte{10},
+ common.Hash{11}: []byte{11},
+ common.MaxHash: []byte{0xff},
+ },
+ {2}: {
+ common.Hash{20}: []byte{20},
+ common.Hash{21}: []byte{21},
+ common.MaxHash: []byte{0xff},
+ },
+ }
+)
+
+func TestVerkleTreeReadWrite(t *testing.T) {
+ db := NewDatabase(rawdb.NewMemoryDatabase(), &Config{
+ IsVerkle: true,
+ PathDB: pathdb.Defaults,
+ })
+ defer db.Close()
+
+ tr, _ := NewVerkleTrie(types.EmptyVerkleHash, db, utils.NewPointCache(100))
+
+ for addr, acct := range accounts {
+ if err := tr.UpdateAccount(addr, acct); err != nil {
+ t.Fatalf("Failed to update account, %v", err)
+ }
+ for key, val := range storages[addr] {
+ if err := tr.UpdateStorage(addr, key.Bytes(), val); err != nil {
+ t.Fatalf("Failed to update account, %v", err)
+ }
+ }
+ }
+
+ for addr, acct := range accounts {
+ stored, err := tr.GetAccount(addr)
+ if err != nil {
+ t.Fatalf("Failed to get account, %v", err)
+ }
+ if !reflect.DeepEqual(stored, acct) {
+ t.Fatal("account is not matched")
+ }
+ for key, val := range storages[addr] {
+ stored, err := tr.GetStorage(addr, key.Bytes())
+ if err != nil {
+ t.Fatalf("Failed to get storage, %v", err)
+ }
+ if !bytes.Equal(stored, val) {
+ t.Fatal("storage is not matched")
+ }
+ }
+ }
+}