diff --git a/.gitea/workflows/release-azure-cleanup.yml b/.gitea/workflows/release-azure-cleanup.yml index 311b2196bb44..0b04581e9b95 100644 --- a/.gitea/workflows/release-azure-cleanup.yml +++ b/.gitea/workflows/release-azure-cleanup.yml @@ -1,8 +1,13 @@ on: - schedule: - - cron: '0 14 * * *' workflow_dispatch: + ### Note we cannot use cron-triggered builds right now, Gitea seems to have + ### a few bugs in that area. So this workflow is scheduled using an external + ### triggering mechanism and workflow_dispatch. + # + # schedule: + # - cron: '0 15 * * *' + jobs: azure-cleanup: runs-on: ubuntu-latest diff --git a/.gitea/workflows/release-ppa.yml b/.gitea/workflows/release-ppa.yml index 6c0631dc990e..129badac16f9 100644 --- a/.gitea/workflows/release-ppa.yml +++ b/.gitea/workflows/release-ppa.yml @@ -1,11 +1,17 @@ on: - schedule: - - cron: '0 15 * * *' push: - branches: - - "release/*" + tags: + - "v*" workflow_dispatch: + ### Note we cannot use cron-triggered builds right now, Gitea seems to have + ### a few bugs in that area. So this workflow is scheduled using an external + ### triggering mechanism and workflow_dispatch. + # + # schedule: + # - cron: '0 16 * * *' + + jobs: ppa: name: PPA Upload @@ -13,6 +19,10 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Show environment + run: | + env + - name: Set up Go uses: actions/setup-go@v5 with: diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 04e724ccf454..f2dcc3ae96a8 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -4,6 +4,7 @@ on: - "master" tags: - "v*" + workflow_dispatch: jobs: linux-intel: @@ -25,7 +26,7 @@ jobs: - name: Build (amd64) run: | - go run build/ci.go install -arch amd64 -dlgo + go run build/ci.go install -static -arch amd64 -dlgo - name: Create/upload archive (amd64) run: | @@ -37,7 +38,7 @@ jobs: - name: Build (386) run: | - go run build/ci.go install -arch 386 -dlgo + go run build/ci.go install -static -arch 386 -dlgo - name: Create/upload archive (386) run: | @@ -67,7 +68,7 @@ jobs: - name: Build (arm64) run: | - go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc + go run build/ci.go install -static -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc - name: Create/upload archive (arm64) run: | @@ -79,7 +80,7 @@ jobs: - name: Run build (arm5) run: | - go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc + go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc env: GOARM: "5" @@ -93,7 +94,7 @@ jobs: - name: Run build (arm6) run: | - go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc + go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc env: GOARM: "6" @@ -108,7 +109,7 @@ jobs: - name: Run build (arm7) run: | - go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc + go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc env: GOARM: "7" @@ -121,6 +122,37 @@ jobs: LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }} AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }} + windows: + name: Windows Build + runs-on: "win-11" + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.24 + cache: false + + # Note: gcc.exe only works properly if the corresponding bin/ directory is + # contained in PATH. + + - name: "Build (amd64)" + shell: cmd + run: | + set PATH=%GETH_MINGW%\bin;%PATH% + go run build/ci.go install -dlgo -arch amd64 -cc %GETH_MINGW%\bin\gcc.exe + env: + GETH_MINGW: 'C:\msys64\mingw64' + + - name: "Build (386)" + shell: cmd + run: | + set PATH=%GETH_MINGW%\bin;%PATH% + go run build/ci.go install -dlgo -arch 386 -cc %GETH_MINGW%\bin\gcc.exe + env: + GETH_MINGW: 'C:\msys64\mingw32' + docker: name: Docker Image runs-on: ubuntu-latest diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 78410aab10fd..13f97898bbc0 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,18 +1,20 @@ -name: i386 linux tests - on: push: - branches: [ master ] + branches: + - master pull_request: - branches: [ master ] + branches: + - master workflow_dispatch: jobs: lint: name: Lint - runs-on: self-hosted + runs-on: self-hosted-ghr steps: - uses: actions/checkout@v4 + with: + submodules: false # Cache build tools to avoid downloading them each time - uses: actions/cache@v4 @@ -23,7 +25,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.23.0 + go-version: 1.24 cache: false - name: Run linters @@ -32,17 +34,25 @@ jobs: go run build/ci.go check_generate go run build/ci.go check_baddeps - build: - runs-on: self-hosted + test: + name: Test + needs: lint + runs-on: self-hosted-ghr + strategy: + matrix: + go: + - '1.24' + - '1.23' steps: - uses: actions/checkout@v4 + with: + submodules: true + - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.24.0 + go-version: ${{ matrix.go }} cache: false + - name: Run tests - run: go test -short ./... - env: - GOOS: linux - GOARCH: 386 + run: go test ./... diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 28d934c65560..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,86 +0,0 @@ -language: go -go_import_path: github.com/ethereum/go-ethereum -sudo: false -jobs: - include: - # This builder create and push the Docker images for all architectures - - stage: build - if: type = push && tag ~= /^v[0-9]/ - os: linux - arch: amd64 - dist: focal - go: 1.24.x - env: - - docker - services: - - docker - git: - submodules: false # avoid cloning ethereum/tests - before_install: - - export DOCKER_CLI_EXPERIMENTAL=enabled - script: - - go run build/ci.go dockerx -platform "linux/amd64,linux/arm64,linux/riscv64" -hub ethereum/client-go -upload - - # This builder does the Ubuntu PPA nightly uploads - - stage: build - if: type = push && tag ~= /^v[0-9]/ - os: linux - dist: focal - go: 1.24.x - env: - - ubuntu-ppa - git: - submodules: false # avoid cloning ethereum/tests - before_install: - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot - script: - - echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts - - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " - - # This builder does the Linux Azure uploads - - stage: build - if: type = push && tag ~= /^v[0-9]/ - os: linux - dist: focal - sudo: required - go: 1.24.x - env: - - azure-linux - git: - submodules: false # avoid cloning ethereum/tests - script: - # build amd64 - - go run build/ci.go install -dlgo - - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - # build 386 - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib - - git status --porcelain - - go run build/ci.go install -dlgo -arch 386 - - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - # Switch over GCC to cross compilation (breaks 386, hence why do it here only) - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross - - sudo ln -s /usr/include/asm-generic /usr/include/asm - - - GOARM=5 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - GOARM=6 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - GOARM=7 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabihf-gcc - - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc - - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - # This builder does the Azure archive purges to avoid accumulating junk - - stage: build - if: type = cron - os: linux - dist: focal - go: 1.24.x - env: - - azure-purge - git: - submodules: false # avoid cloning ethereum/tests - script: - - go run build/ci.go purge -store gethstore/builds -days 14 diff --git a/Makefile b/Makefile index f4932165a482..f3d7f48f2f66 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # with Go source code. If you know what GOPATH is then you probably # don't need to bother with make. -.PHONY: geth all test lint fmt clean devtools help +.PHONY: geth evm all test lint fmt clean devtools help GOBIN = ./build/bin GO ?= latest @@ -14,6 +14,12 @@ geth: @echo "Done building." @echo "Run \"$(GOBIN)/geth\" to launch geth." +#? evm: Build evm. +evm: + $(GORUN) build/ci.go install ./cmd/evm + @echo "Done building." + @echo "Run \"$(GOBIN)/evm\" to launch evm." + #? all: Build all packages and executables. all: $(GORUN) build/ci.go install diff --git a/accounts/abi/abigen/bindv2_test.go b/accounts/abi/abigen/bindv2_test.go index 2756ba0835e2..ee943f1c3f37 100644 --- a/accounts/abi/abigen/bindv2_test.go +++ b/accounts/abi/abigen/bindv2_test.go @@ -281,7 +281,7 @@ func TestBindingV2ConvertedV1Tests(t *testing.T) { } // Set this environment variable to regenerate the test outputs. if os.Getenv("WRITE_TEST_FILES") != "" { - if err := os.WriteFile((fname), []byte(have), 0666); err != nil { + if err := os.WriteFile(fname, []byte(have), 0666); err != nil { t.Fatalf("err writing expected output to file: %v\n", err) } } diff --git a/accounts/abi/abigen/source2.go.tpl b/accounts/abi/abigen/source2.go.tpl index 8f9d4d4103eb..8ef906b8d6a4 100644 --- a/accounts/abi/abigen/source2.go.tpl +++ b/accounts/abi/abigen/source2.go.tpl @@ -90,7 +90,8 @@ var ( {{range .Calls}} // Pack{{.Normalized.Name}} is the Go binding used to pack the parameters required for calling - // the contract method with ID 0x{{printf "%x" .Original.ID}}. + // the contract method with ID 0x{{printf "%x" .Original.ID}}. This method will panic if any + // invalid/nil inputs are passed. // // Solidity: {{.Original.String}} func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Pack{{.Normalized.Name}}({{range .Normalized.Inputs}} {{.Name}} {{bindtype .Type $structs}}, {{end}}) []byte { @@ -101,6 +102,15 @@ var ( return enc } + // TryPack{{.Normalized.Name}} is the Go binding used to pack the parameters required for calling + // the contract method with ID 0x{{printf "%x" .Original.ID}}. This method will return an error + // if any inputs are invalid/nil. + // + // Solidity: {{.Original.String}} + func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) TryPack{{.Normalized.Name}}({{range .Normalized.Inputs}} {{.Name}} {{bindtype .Type $structs}}, {{end}}) ([]byte, error) { + return {{ decapitalise $contract.Type}}.abi.Pack("{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}}) + } + {{/* Unpack method is needed only when there are return args */}} {{if .Normalized.Outputs }} {{ if .Structured }} @@ -133,8 +143,7 @@ var ( outstruct.{{capitalise .Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}) {{- end }} {{- end }} - return *outstruct, err - {{else}} + return *outstruct, nil{{else}} if err != nil { return {{range $i, $_ := .Normalized.Outputs}}{{if ispointertype .Type}}new({{underlyingbindtype .Type }}), {{else}}*new({{bindtype .Type $structs}}), {{end}}{{end}} err } @@ -145,8 +154,8 @@ var ( out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}) {{- end }} {{- end}} - return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err - {{- end}} + return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} nil + {{- end}} } {{end}} {{end}} diff --git a/accounts/abi/abigen/testdata/v2/callbackparam.go.txt b/accounts/abi/abigen/testdata/v2/callbackparam.go.txt index e3205bde0dc7..d22b9784863c 100644 --- a/accounts/abi/abigen/testdata/v2/callbackparam.go.txt +++ b/accounts/abi/abigen/testdata/v2/callbackparam.go.txt @@ -52,7 +52,8 @@ func (c *CallbackParam) Instance(backend bind.ContractBackend, addr common.Addre } // PackTest is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xd7a5aba2. +// the contract method with ID 0xd7a5aba2. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function test(function callback) returns() func (callbackParam *CallbackParam) PackTest(callback [24]byte) []byte { @@ -62,3 +63,12 @@ func (callbackParam *CallbackParam) PackTest(callback [24]byte) []byte { } return enc } + +// TryPackTest is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xd7a5aba2. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function test(function callback) returns() +func (callbackParam *CallbackParam) TryPackTest(callback [24]byte) ([]byte, error) { + return callbackParam.abi.Pack("test", callback) +} diff --git a/accounts/abi/abigen/testdata/v2/crowdsale.go.txt b/accounts/abi/abigen/testdata/v2/crowdsale.go.txt index 60d8b4ec11bd..b2183c91ea59 100644 --- a/accounts/abi/abigen/testdata/v2/crowdsale.go.txt +++ b/accounts/abi/abigen/testdata/v2/crowdsale.go.txt @@ -64,7 +64,8 @@ func (crowdsale *Crowdsale) PackConstructor(ifSuccessfulSendTo common.Address, f } // PackAmountRaised is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x7b3e5e7b. +// the contract method with ID 0x7b3e5e7b. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function amountRaised() returns(uint256) func (crowdsale *Crowdsale) PackAmountRaised() []byte { @@ -75,6 +76,15 @@ func (crowdsale *Crowdsale) PackAmountRaised() []byte { return enc } +// TryPackAmountRaised is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x7b3e5e7b. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function amountRaised() returns(uint256) +func (crowdsale *Crowdsale) TryPackAmountRaised() ([]byte, error) { + return crowdsale.abi.Pack("amountRaised") +} + // UnpackAmountRaised is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x7b3e5e7b. // @@ -85,11 +95,12 @@ func (crowdsale *Crowdsale) UnpackAmountRaised(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackBeneficiary is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x38af3eed. +// the contract method with ID 0x38af3eed. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function beneficiary() returns(address) func (crowdsale *Crowdsale) PackBeneficiary() []byte { @@ -100,6 +111,15 @@ func (crowdsale *Crowdsale) PackBeneficiary() []byte { return enc } +// TryPackBeneficiary is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x38af3eed. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function beneficiary() returns(address) +func (crowdsale *Crowdsale) TryPackBeneficiary() ([]byte, error) { + return crowdsale.abi.Pack("beneficiary") +} + // UnpackBeneficiary is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x38af3eed. // @@ -110,11 +130,12 @@ func (crowdsale *Crowdsale) UnpackBeneficiary(data []byte) (common.Address, erro return *new(common.Address), err } out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - return out0, err + return out0, nil } // PackCheckGoalReached is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x01cb3b20. +// the contract method with ID 0x01cb3b20. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function checkGoalReached() returns() func (crowdsale *Crowdsale) PackCheckGoalReached() []byte { @@ -125,8 +146,18 @@ func (crowdsale *Crowdsale) PackCheckGoalReached() []byte { return enc } +// TryPackCheckGoalReached is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x01cb3b20. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function checkGoalReached() returns() +func (crowdsale *Crowdsale) TryPackCheckGoalReached() ([]byte, error) { + return crowdsale.abi.Pack("checkGoalReached") +} + // PackDeadline is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x29dcb0cf. +// the contract method with ID 0x29dcb0cf. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function deadline() returns(uint256) func (crowdsale *Crowdsale) PackDeadline() []byte { @@ -137,6 +168,15 @@ func (crowdsale *Crowdsale) PackDeadline() []byte { return enc } +// TryPackDeadline is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x29dcb0cf. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function deadline() returns(uint256) +func (crowdsale *Crowdsale) TryPackDeadline() ([]byte, error) { + return crowdsale.abi.Pack("deadline") +} + // UnpackDeadline is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x29dcb0cf. // @@ -147,11 +187,12 @@ func (crowdsale *Crowdsale) UnpackDeadline(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackFunders is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xdc0d3dff. +// the contract method with ID 0xdc0d3dff. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function funders(uint256 ) returns(address addr, uint256 amount) func (crowdsale *Crowdsale) PackFunders(arg0 *big.Int) []byte { @@ -162,6 +203,15 @@ func (crowdsale *Crowdsale) PackFunders(arg0 *big.Int) []byte { return enc } +// TryPackFunders is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xdc0d3dff. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function funders(uint256 ) returns(address addr, uint256 amount) +func (crowdsale *Crowdsale) TryPackFunders(arg0 *big.Int) ([]byte, error) { + return crowdsale.abi.Pack("funders", arg0) +} + // FundersOutput serves as a container for the return parameters of contract // method Funders. type FundersOutput struct { @@ -181,12 +231,12 @@ func (crowdsale *Crowdsale) UnpackFunders(data []byte) (FundersOutput, error) { } outstruct.Addr = *abi.ConvertType(out[0], new(common.Address)).(*common.Address) outstruct.Amount = abi.ConvertType(out[1], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackFundingGoal is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x7a3a0e84. +// the contract method with ID 0x7a3a0e84. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function fundingGoal() returns(uint256) func (crowdsale *Crowdsale) PackFundingGoal() []byte { @@ -197,6 +247,15 @@ func (crowdsale *Crowdsale) PackFundingGoal() []byte { return enc } +// TryPackFundingGoal is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x7a3a0e84. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function fundingGoal() returns(uint256) +func (crowdsale *Crowdsale) TryPackFundingGoal() ([]byte, error) { + return crowdsale.abi.Pack("fundingGoal") +} + // UnpackFundingGoal is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x7a3a0e84. // @@ -207,11 +266,12 @@ func (crowdsale *Crowdsale) UnpackFundingGoal(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackPrice is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xa035b1fe. +// the contract method with ID 0xa035b1fe. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function price() returns(uint256) func (crowdsale *Crowdsale) PackPrice() []byte { @@ -222,6 +282,15 @@ func (crowdsale *Crowdsale) PackPrice() []byte { return enc } +// TryPackPrice is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xa035b1fe. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function price() returns(uint256) +func (crowdsale *Crowdsale) TryPackPrice() ([]byte, error) { + return crowdsale.abi.Pack("price") +} + // UnpackPrice is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xa035b1fe. // @@ -232,11 +301,12 @@ func (crowdsale *Crowdsale) UnpackPrice(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackTokenReward is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x6e66f6e9. +// the contract method with ID 0x6e66f6e9. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function tokenReward() returns(address) func (crowdsale *Crowdsale) PackTokenReward() []byte { @@ -247,6 +317,15 @@ func (crowdsale *Crowdsale) PackTokenReward() []byte { return enc } +// TryPackTokenReward is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x6e66f6e9. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function tokenReward() returns(address) +func (crowdsale *Crowdsale) TryPackTokenReward() ([]byte, error) { + return crowdsale.abi.Pack("tokenReward") +} + // UnpackTokenReward is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x6e66f6e9. // @@ -257,7 +336,7 @@ func (crowdsale *Crowdsale) UnpackTokenReward(data []byte) (common.Address, erro return *new(common.Address), err } out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - return out0, err + return out0, nil } // CrowdsaleFundTransfer represents a FundTransfer event raised by the Crowdsale contract. diff --git a/accounts/abi/abigen/testdata/v2/dao.go.txt b/accounts/abi/abigen/testdata/v2/dao.go.txt index 72a80949f6c5..75fa95df9107 100644 --- a/accounts/abi/abigen/testdata/v2/dao.go.txt +++ b/accounts/abi/abigen/testdata/v2/dao.go.txt @@ -64,7 +64,8 @@ func (dAO *DAO) PackConstructor(minimumQuorumForProposals *big.Int, minutesForDe } // PackChangeMembership is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x9644fcbd. +// the contract method with ID 0x9644fcbd. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function changeMembership(address targetMember, bool canVote, string memberName) returns() func (dAO *DAO) PackChangeMembership(targetMember common.Address, canVote bool, memberName string) []byte { @@ -75,8 +76,18 @@ func (dAO *DAO) PackChangeMembership(targetMember common.Address, canVote bool, return enc } +// TryPackChangeMembership is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x9644fcbd. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function changeMembership(address targetMember, bool canVote, string memberName) returns() +func (dAO *DAO) TryPackChangeMembership(targetMember common.Address, canVote bool, memberName string) ([]byte, error) { + return dAO.abi.Pack("changeMembership", targetMember, canVote, memberName) +} + // PackChangeVotingRules is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xbcca1fd3. +// the contract method with ID 0xbcca1fd3. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function changeVotingRules(uint256 minimumQuorumForProposals, uint256 minutesForDebate, int256 marginOfVotesForMajority) returns() func (dAO *DAO) PackChangeVotingRules(minimumQuorumForProposals *big.Int, minutesForDebate *big.Int, marginOfVotesForMajority *big.Int) []byte { @@ -87,8 +98,18 @@ func (dAO *DAO) PackChangeVotingRules(minimumQuorumForProposals *big.Int, minute return enc } +// TryPackChangeVotingRules is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xbcca1fd3. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function changeVotingRules(uint256 minimumQuorumForProposals, uint256 minutesForDebate, int256 marginOfVotesForMajority) returns() +func (dAO *DAO) TryPackChangeVotingRules(minimumQuorumForProposals *big.Int, minutesForDebate *big.Int, marginOfVotesForMajority *big.Int) ([]byte, error) { + return dAO.abi.Pack("changeVotingRules", minimumQuorumForProposals, minutesForDebate, marginOfVotesForMajority) +} + // PackCheckProposalCode is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xeceb2945. +// the contract method with ID 0xeceb2945. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function checkProposalCode(uint256 proposalNumber, address beneficiary, uint256 etherAmount, bytes transactionBytecode) returns(bool codeChecksOut) func (dAO *DAO) PackCheckProposalCode(proposalNumber *big.Int, beneficiary common.Address, etherAmount *big.Int, transactionBytecode []byte) []byte { @@ -99,6 +120,15 @@ func (dAO *DAO) PackCheckProposalCode(proposalNumber *big.Int, beneficiary commo return enc } +// TryPackCheckProposalCode is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xeceb2945. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function checkProposalCode(uint256 proposalNumber, address beneficiary, uint256 etherAmount, bytes transactionBytecode) returns(bool codeChecksOut) +func (dAO *DAO) TryPackCheckProposalCode(proposalNumber *big.Int, beneficiary common.Address, etherAmount *big.Int, transactionBytecode []byte) ([]byte, error) { + return dAO.abi.Pack("checkProposalCode", proposalNumber, beneficiary, etherAmount, transactionBytecode) +} + // UnpackCheckProposalCode is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xeceb2945. // @@ -109,11 +139,12 @@ func (dAO *DAO) UnpackCheckProposalCode(data []byte) (bool, error) { return *new(bool), err } out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - return out0, err + return out0, nil } // PackDebatingPeriodInMinutes is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x69bd3436. +// the contract method with ID 0x69bd3436. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function debatingPeriodInMinutes() returns(uint256) func (dAO *DAO) PackDebatingPeriodInMinutes() []byte { @@ -124,6 +155,15 @@ func (dAO *DAO) PackDebatingPeriodInMinutes() []byte { return enc } +// TryPackDebatingPeriodInMinutes is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x69bd3436. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function debatingPeriodInMinutes() returns(uint256) +func (dAO *DAO) TryPackDebatingPeriodInMinutes() ([]byte, error) { + return dAO.abi.Pack("debatingPeriodInMinutes") +} + // UnpackDebatingPeriodInMinutes is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x69bd3436. // @@ -134,11 +174,12 @@ func (dAO *DAO) UnpackDebatingPeriodInMinutes(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackExecuteProposal is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x237e9492. +// the contract method with ID 0x237e9492. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function executeProposal(uint256 proposalNumber, bytes transactionBytecode) returns(int256 result) func (dAO *DAO) PackExecuteProposal(proposalNumber *big.Int, transactionBytecode []byte) []byte { @@ -149,6 +190,15 @@ func (dAO *DAO) PackExecuteProposal(proposalNumber *big.Int, transactionBytecode return enc } +// TryPackExecuteProposal is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x237e9492. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function executeProposal(uint256 proposalNumber, bytes transactionBytecode) returns(int256 result) +func (dAO *DAO) TryPackExecuteProposal(proposalNumber *big.Int, transactionBytecode []byte) ([]byte, error) { + return dAO.abi.Pack("executeProposal", proposalNumber, transactionBytecode) +} + // UnpackExecuteProposal is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x237e9492. // @@ -159,11 +209,12 @@ func (dAO *DAO) UnpackExecuteProposal(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackMajorityMargin is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xaa02a90f. +// the contract method with ID 0xaa02a90f. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function majorityMargin() returns(int256) func (dAO *DAO) PackMajorityMargin() []byte { @@ -174,6 +225,15 @@ func (dAO *DAO) PackMajorityMargin() []byte { return enc } +// TryPackMajorityMargin is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xaa02a90f. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function majorityMargin() returns(int256) +func (dAO *DAO) TryPackMajorityMargin() ([]byte, error) { + return dAO.abi.Pack("majorityMargin") +} + // UnpackMajorityMargin is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xaa02a90f. // @@ -184,11 +244,12 @@ func (dAO *DAO) UnpackMajorityMargin(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackMemberId is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x39106821. +// the contract method with ID 0x39106821. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function memberId(address ) returns(uint256) func (dAO *DAO) PackMemberId(arg0 common.Address) []byte { @@ -199,6 +260,15 @@ func (dAO *DAO) PackMemberId(arg0 common.Address) []byte { return enc } +// TryPackMemberId is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x39106821. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function memberId(address ) returns(uint256) +func (dAO *DAO) TryPackMemberId(arg0 common.Address) ([]byte, error) { + return dAO.abi.Pack("memberId", arg0) +} + // UnpackMemberId is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x39106821. // @@ -209,11 +279,12 @@ func (dAO *DAO) UnpackMemberId(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackMembers is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x5daf08ca. +// the contract method with ID 0x5daf08ca. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function members(uint256 ) returns(address member, bool canVote, string name, uint256 memberSince) func (dAO *DAO) PackMembers(arg0 *big.Int) []byte { @@ -224,6 +295,15 @@ func (dAO *DAO) PackMembers(arg0 *big.Int) []byte { return enc } +// TryPackMembers is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x5daf08ca. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function members(uint256 ) returns(address member, bool canVote, string name, uint256 memberSince) +func (dAO *DAO) TryPackMembers(arg0 *big.Int) ([]byte, error) { + return dAO.abi.Pack("members", arg0) +} + // MembersOutput serves as a container for the return parameters of contract // method Members. type MembersOutput struct { @@ -247,12 +327,12 @@ func (dAO *DAO) UnpackMembers(data []byte) (MembersOutput, error) { outstruct.CanVote = *abi.ConvertType(out[1], new(bool)).(*bool) outstruct.Name = *abi.ConvertType(out[2], new(string)).(*string) outstruct.MemberSince = abi.ConvertType(out[3], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackMinimumQuorum is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x8160f0b5. +// the contract method with ID 0x8160f0b5. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function minimumQuorum() returns(uint256) func (dAO *DAO) PackMinimumQuorum() []byte { @@ -263,6 +343,15 @@ func (dAO *DAO) PackMinimumQuorum() []byte { return enc } +// TryPackMinimumQuorum is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x8160f0b5. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function minimumQuorum() returns(uint256) +func (dAO *DAO) TryPackMinimumQuorum() ([]byte, error) { + return dAO.abi.Pack("minimumQuorum") +} + // UnpackMinimumQuorum is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x8160f0b5. // @@ -273,11 +362,12 @@ func (dAO *DAO) UnpackMinimumQuorum(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackNewProposal is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xb1050da5. +// the contract method with ID 0xb1050da5. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function newProposal(address beneficiary, uint256 etherAmount, string JobDescription, bytes transactionBytecode) returns(uint256 proposalID) func (dAO *DAO) PackNewProposal(beneficiary common.Address, etherAmount *big.Int, jobDescription string, transactionBytecode []byte) []byte { @@ -288,6 +378,15 @@ func (dAO *DAO) PackNewProposal(beneficiary common.Address, etherAmount *big.Int return enc } +// TryPackNewProposal is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xb1050da5. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function newProposal(address beneficiary, uint256 etherAmount, string JobDescription, bytes transactionBytecode) returns(uint256 proposalID) +func (dAO *DAO) TryPackNewProposal(beneficiary common.Address, etherAmount *big.Int, jobDescription string, transactionBytecode []byte) ([]byte, error) { + return dAO.abi.Pack("newProposal", beneficiary, etherAmount, jobDescription, transactionBytecode) +} + // UnpackNewProposal is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xb1050da5. // @@ -298,11 +397,12 @@ func (dAO *DAO) UnpackNewProposal(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackNumProposals is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x400e3949. +// the contract method with ID 0x400e3949. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function numProposals() returns(uint256) func (dAO *DAO) PackNumProposals() []byte { @@ -313,6 +413,15 @@ func (dAO *DAO) PackNumProposals() []byte { return enc } +// TryPackNumProposals is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x400e3949. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function numProposals() returns(uint256) +func (dAO *DAO) TryPackNumProposals() ([]byte, error) { + return dAO.abi.Pack("numProposals") +} + // UnpackNumProposals is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x400e3949. // @@ -323,11 +432,12 @@ func (dAO *DAO) UnpackNumProposals(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackOwner is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x8da5cb5b. +// the contract method with ID 0x8da5cb5b. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function owner() returns(address) func (dAO *DAO) PackOwner() []byte { @@ -338,6 +448,15 @@ func (dAO *DAO) PackOwner() []byte { return enc } +// TryPackOwner is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x8da5cb5b. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function owner() returns(address) +func (dAO *DAO) TryPackOwner() ([]byte, error) { + return dAO.abi.Pack("owner") +} + // UnpackOwner is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x8da5cb5b. // @@ -348,11 +467,12 @@ func (dAO *DAO) UnpackOwner(data []byte) (common.Address, error) { return *new(common.Address), err } out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - return out0, err + return out0, nil } // PackProposals is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x013cf08b. +// the contract method with ID 0x013cf08b. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function proposals(uint256 ) returns(address recipient, uint256 amount, string description, uint256 votingDeadline, bool executed, bool proposalPassed, uint256 numberOfVotes, int256 currentResult, bytes32 proposalHash) func (dAO *DAO) PackProposals(arg0 *big.Int) []byte { @@ -363,6 +483,15 @@ func (dAO *DAO) PackProposals(arg0 *big.Int) []byte { return enc } +// TryPackProposals is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x013cf08b. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function proposals(uint256 ) returns(address recipient, uint256 amount, string description, uint256 votingDeadline, bool executed, bool proposalPassed, uint256 numberOfVotes, int256 currentResult, bytes32 proposalHash) +func (dAO *DAO) TryPackProposals(arg0 *big.Int) ([]byte, error) { + return dAO.abi.Pack("proposals", arg0) +} + // ProposalsOutput serves as a container for the return parameters of contract // method Proposals. type ProposalsOutput struct { @@ -396,12 +525,12 @@ func (dAO *DAO) UnpackProposals(data []byte) (ProposalsOutput, error) { outstruct.NumberOfVotes = abi.ConvertType(out[6], new(big.Int)).(*big.Int) outstruct.CurrentResult = abi.ConvertType(out[7], new(big.Int)).(*big.Int) outstruct.ProposalHash = *abi.ConvertType(out[8], new([32]byte)).(*[32]byte) - return *outstruct, err - + return *outstruct, nil } // PackTransferOwnership is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xf2fde38b. +// the contract method with ID 0xf2fde38b. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function transferOwnership(address newOwner) returns() func (dAO *DAO) PackTransferOwnership(newOwner common.Address) []byte { @@ -412,8 +541,18 @@ func (dAO *DAO) PackTransferOwnership(newOwner common.Address) []byte { return enc } +// TryPackTransferOwnership is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xf2fde38b. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (dAO *DAO) TryPackTransferOwnership(newOwner common.Address) ([]byte, error) { + return dAO.abi.Pack("transferOwnership", newOwner) +} + // PackVote is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xd3c0715b. +// the contract method with ID 0xd3c0715b. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function vote(uint256 proposalNumber, bool supportsProposal, string justificationText) returns(uint256 voteID) func (dAO *DAO) PackVote(proposalNumber *big.Int, supportsProposal bool, justificationText string) []byte { @@ -424,6 +563,15 @@ func (dAO *DAO) PackVote(proposalNumber *big.Int, supportsProposal bool, justifi return enc } +// TryPackVote is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xd3c0715b. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function vote(uint256 proposalNumber, bool supportsProposal, string justificationText) returns(uint256 voteID) +func (dAO *DAO) TryPackVote(proposalNumber *big.Int, supportsProposal bool, justificationText string) ([]byte, error) { + return dAO.abi.Pack("vote", proposalNumber, supportsProposal, justificationText) +} + // UnpackVote is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xd3c0715b. // @@ -434,7 +582,7 @@ func (dAO *DAO) UnpackVote(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // DAOChangeOfRules represents a ChangeOfRules event raised by the DAO contract. diff --git a/accounts/abi/abigen/testdata/v2/deeplynestedarray.go.txt b/accounts/abi/abigen/testdata/v2/deeplynestedarray.go.txt index 00f717d020ce..302f1d736fcc 100644 --- a/accounts/abi/abigen/testdata/v2/deeplynestedarray.go.txt +++ b/accounts/abi/abigen/testdata/v2/deeplynestedarray.go.txt @@ -52,7 +52,8 @@ func (c *DeeplyNestedArray) Instance(backend bind.ContractBackend, addr common.A } // PackDeepUint64Array is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x98ed1856. +// the contract method with ID 0x98ed1856. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function deepUint64Array(uint256 , uint256 , uint256 ) view returns(uint64) func (deeplyNestedArray *DeeplyNestedArray) PackDeepUint64Array(arg0 *big.Int, arg1 *big.Int, arg2 *big.Int) []byte { @@ -63,6 +64,15 @@ func (deeplyNestedArray *DeeplyNestedArray) PackDeepUint64Array(arg0 *big.Int, a return enc } +// TryPackDeepUint64Array is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x98ed1856. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function deepUint64Array(uint256 , uint256 , uint256 ) view returns(uint64) +func (deeplyNestedArray *DeeplyNestedArray) TryPackDeepUint64Array(arg0 *big.Int, arg1 *big.Int, arg2 *big.Int) ([]byte, error) { + return deeplyNestedArray.abi.Pack("deepUint64Array", arg0, arg1, arg2) +} + // UnpackDeepUint64Array is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x98ed1856. // @@ -73,11 +83,12 @@ func (deeplyNestedArray *DeeplyNestedArray) UnpackDeepUint64Array(data []byte) ( return *new(uint64), err } out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - return out0, err + return out0, nil } // PackRetrieveDeepArray is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x8ed4573a. +// the contract method with ID 0x8ed4573a. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function retrieveDeepArray() view returns(uint64[3][4][5]) func (deeplyNestedArray *DeeplyNestedArray) PackRetrieveDeepArray() []byte { @@ -88,6 +99,15 @@ func (deeplyNestedArray *DeeplyNestedArray) PackRetrieveDeepArray() []byte { return enc } +// TryPackRetrieveDeepArray is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x8ed4573a. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function retrieveDeepArray() view returns(uint64[3][4][5]) +func (deeplyNestedArray *DeeplyNestedArray) TryPackRetrieveDeepArray() ([]byte, error) { + return deeplyNestedArray.abi.Pack("retrieveDeepArray") +} + // UnpackRetrieveDeepArray is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x8ed4573a. // @@ -98,11 +118,12 @@ func (deeplyNestedArray *DeeplyNestedArray) UnpackRetrieveDeepArray(data []byte) return *new([5][4][3]uint64), err } out0 := *abi.ConvertType(out[0], new([5][4][3]uint64)).(*[5][4][3]uint64) - return out0, err + return out0, nil } // PackStoreDeepUintArray is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x34424855. +// the contract method with ID 0x34424855. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function storeDeepUintArray(uint64[3][4][5] arr) returns() func (deeplyNestedArray *DeeplyNestedArray) PackStoreDeepUintArray(arr [5][4][3]uint64) []byte { @@ -112,3 +133,12 @@ func (deeplyNestedArray *DeeplyNestedArray) PackStoreDeepUintArray(arr [5][4][3] } return enc } + +// TryPackStoreDeepUintArray is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x34424855. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function storeDeepUintArray(uint64[3][4][5] arr) returns() +func (deeplyNestedArray *DeeplyNestedArray) TryPackStoreDeepUintArray(arr [5][4][3]uint64) ([]byte, error) { + return deeplyNestedArray.abi.Pack("storeDeepUintArray", arr) +} diff --git a/accounts/abi/abigen/testdata/v2/getter.go.txt b/accounts/abi/abigen/testdata/v2/getter.go.txt index 8e6e7debbfae..69a4fb54c822 100644 --- a/accounts/abi/abigen/testdata/v2/getter.go.txt +++ b/accounts/abi/abigen/testdata/v2/getter.go.txt @@ -52,7 +52,8 @@ func (c *Getter) Instance(backend bind.ContractBackend, addr common.Address) *bi } // PackGetter is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x993a04b7. +// the contract method with ID 0x993a04b7. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function getter() returns(string, int256, bytes32) func (getter *Getter) PackGetter() []byte { @@ -63,6 +64,15 @@ func (getter *Getter) PackGetter() []byte { return enc } +// TryPackGetter is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x993a04b7. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function getter() returns(string, int256, bytes32) +func (getter *Getter) TryPackGetter() ([]byte, error) { + return getter.abi.Pack("getter") +} + // GetterOutput serves as a container for the return parameters of contract // method Getter. type GetterOutput struct { @@ -84,6 +94,5 @@ func (getter *Getter) UnpackGetter(data []byte) (GetterOutput, error) { outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int) outstruct.Arg2 = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) - return *outstruct, err - + return *outstruct, nil } diff --git a/accounts/abi/abigen/testdata/v2/identifiercollision.go.txt b/accounts/abi/abigen/testdata/v2/identifiercollision.go.txt index 60554aac132d..e7301521f4d0 100644 --- a/accounts/abi/abigen/testdata/v2/identifiercollision.go.txt +++ b/accounts/abi/abigen/testdata/v2/identifiercollision.go.txt @@ -52,7 +52,8 @@ func (c *IdentifierCollision) Instance(backend bind.ContractBackend, addr common } // PackMyVar is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x4ef1f0ad. +// the contract method with ID 0x4ef1f0ad. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function MyVar() view returns(uint256) func (identifierCollision *IdentifierCollision) PackMyVar() []byte { @@ -63,6 +64,15 @@ func (identifierCollision *IdentifierCollision) PackMyVar() []byte { return enc } +// TryPackMyVar is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x4ef1f0ad. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function MyVar() view returns(uint256) +func (identifierCollision *IdentifierCollision) TryPackMyVar() ([]byte, error) { + return identifierCollision.abi.Pack("MyVar") +} + // UnpackMyVar is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x4ef1f0ad. // @@ -73,11 +83,12 @@ func (identifierCollision *IdentifierCollision) UnpackMyVar(data []byte) (*big.I return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackPubVar is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x01ad4d87. +// the contract method with ID 0x01ad4d87. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function _myVar() view returns(uint256) func (identifierCollision *IdentifierCollision) PackPubVar() []byte { @@ -88,6 +99,15 @@ func (identifierCollision *IdentifierCollision) PackPubVar() []byte { return enc } +// TryPackPubVar is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x01ad4d87. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function _myVar() view returns(uint256) +func (identifierCollision *IdentifierCollision) TryPackPubVar() ([]byte, error) { + return identifierCollision.abi.Pack("_myVar") +} + // UnpackPubVar is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x01ad4d87. // @@ -98,5 +118,5 @@ func (identifierCollision *IdentifierCollision) UnpackPubVar(data []byte) (*big. return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } diff --git a/accounts/abi/abigen/testdata/v2/inputchecker.go.txt b/accounts/abi/abigen/testdata/v2/inputchecker.go.txt index 7b226aa90bd8..1743f336db0c 100644 --- a/accounts/abi/abigen/testdata/v2/inputchecker.go.txt +++ b/accounts/abi/abigen/testdata/v2/inputchecker.go.txt @@ -51,7 +51,8 @@ func (c *InputChecker) Instance(backend bind.ContractBackend, addr common.Addres } // PackAnonInput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x3e708e82. +// the contract method with ID 0x3e708e82. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function anonInput(string ) returns() func (inputChecker *InputChecker) PackAnonInput(arg0 string) []byte { @@ -62,8 +63,18 @@ func (inputChecker *InputChecker) PackAnonInput(arg0 string) []byte { return enc } +// TryPackAnonInput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x3e708e82. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function anonInput(string ) returns() +func (inputChecker *InputChecker) TryPackAnonInput(arg0 string) ([]byte, error) { + return inputChecker.abi.Pack("anonInput", arg0) +} + // PackAnonInputs is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x28160527. +// the contract method with ID 0x28160527. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function anonInputs(string , string ) returns() func (inputChecker *InputChecker) PackAnonInputs(arg0 string, arg1 string) []byte { @@ -74,8 +85,18 @@ func (inputChecker *InputChecker) PackAnonInputs(arg0 string, arg1 string) []byt return enc } +// TryPackAnonInputs is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x28160527. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function anonInputs(string , string ) returns() +func (inputChecker *InputChecker) TryPackAnonInputs(arg0 string, arg1 string) ([]byte, error) { + return inputChecker.abi.Pack("anonInputs", arg0, arg1) +} + // PackMixedInputs is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xc689ebdc. +// the contract method with ID 0xc689ebdc. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function mixedInputs(string , string str) returns() func (inputChecker *InputChecker) PackMixedInputs(arg0 string, str string) []byte { @@ -86,8 +107,18 @@ func (inputChecker *InputChecker) PackMixedInputs(arg0 string, str string) []byt return enc } +// TryPackMixedInputs is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xc689ebdc. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function mixedInputs(string , string str) returns() +func (inputChecker *InputChecker) TryPackMixedInputs(arg0 string, str string) ([]byte, error) { + return inputChecker.abi.Pack("mixedInputs", arg0, str) +} + // PackNamedInput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x0d402005. +// the contract method with ID 0x0d402005. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function namedInput(string str) returns() func (inputChecker *InputChecker) PackNamedInput(str string) []byte { @@ -98,8 +129,18 @@ func (inputChecker *InputChecker) PackNamedInput(str string) []byte { return enc } +// TryPackNamedInput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x0d402005. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function namedInput(string str) returns() +func (inputChecker *InputChecker) TryPackNamedInput(str string) ([]byte, error) { + return inputChecker.abi.Pack("namedInput", str) +} + // PackNamedInputs is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x63c796ed. +// the contract method with ID 0x63c796ed. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function namedInputs(string str1, string str2) returns() func (inputChecker *InputChecker) PackNamedInputs(str1 string, str2 string) []byte { @@ -110,8 +151,18 @@ func (inputChecker *InputChecker) PackNamedInputs(str1 string, str2 string) []by return enc } +// TryPackNamedInputs is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x63c796ed. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function namedInputs(string str1, string str2) returns() +func (inputChecker *InputChecker) TryPackNamedInputs(str1 string, str2 string) ([]byte, error) { + return inputChecker.abi.Pack("namedInputs", str1, str2) +} + // PackNoInput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x53539029. +// the contract method with ID 0x53539029. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function noInput() returns() func (inputChecker *InputChecker) PackNoInput() []byte { @@ -121,3 +172,12 @@ func (inputChecker *InputChecker) PackNoInput() []byte { } return enc } + +// TryPackNoInput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x53539029. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function noInput() returns() +func (inputChecker *InputChecker) TryPackNoInput() ([]byte, error) { + return inputChecker.abi.Pack("noInput") +} diff --git a/accounts/abi/abigen/testdata/v2/interactor.go.txt b/accounts/abi/abigen/testdata/v2/interactor.go.txt index cc0900856ec8..f33c95b63926 100644 --- a/accounts/abi/abigen/testdata/v2/interactor.go.txt +++ b/accounts/abi/abigen/testdata/v2/interactor.go.txt @@ -64,7 +64,8 @@ func (interactor *Interactor) PackConstructor(str string) []byte { } // PackDeployString is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x6874e809. +// the contract method with ID 0x6874e809. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function deployString() returns(string) func (interactor *Interactor) PackDeployString() []byte { @@ -75,6 +76,15 @@ func (interactor *Interactor) PackDeployString() []byte { return enc } +// TryPackDeployString is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x6874e809. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function deployString() returns(string) +func (interactor *Interactor) TryPackDeployString() ([]byte, error) { + return interactor.abi.Pack("deployString") +} + // UnpackDeployString is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x6874e809. // @@ -85,11 +95,12 @@ func (interactor *Interactor) UnpackDeployString(data []byte) (string, error) { return *new(string), err } out0 := *abi.ConvertType(out[0], new(string)).(*string) - return out0, err + return out0, nil } // PackTransact is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xd736c513. +// the contract method with ID 0xd736c513. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function transact(string str) returns() func (interactor *Interactor) PackTransact(str string) []byte { @@ -100,8 +111,18 @@ func (interactor *Interactor) PackTransact(str string) []byte { return enc } +// TryPackTransact is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xd736c513. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function transact(string str) returns() +func (interactor *Interactor) TryPackTransact(str string) ([]byte, error) { + return interactor.abi.Pack("transact", str) +} + // PackTransactString is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x0d86a0e1. +// the contract method with ID 0x0d86a0e1. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function transactString() returns(string) func (interactor *Interactor) PackTransactString() []byte { @@ -112,6 +133,15 @@ func (interactor *Interactor) PackTransactString() []byte { return enc } +// TryPackTransactString is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x0d86a0e1. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function transactString() returns(string) +func (interactor *Interactor) TryPackTransactString() ([]byte, error) { + return interactor.abi.Pack("transactString") +} + // UnpackTransactString is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x0d86a0e1. // @@ -122,5 +152,5 @@ func (interactor *Interactor) UnpackTransactString(data []byte) (string, error) return *new(string), err } out0 := *abi.ConvertType(out[0], new(string)).(*string) - return out0, err + return out0, nil } diff --git a/accounts/abi/abigen/testdata/v2/nameconflict.go.txt b/accounts/abi/abigen/testdata/v2/nameconflict.go.txt index 6228bf7cc73c..fbc61a5c6c93 100644 --- a/accounts/abi/abigen/testdata/v2/nameconflict.go.txt +++ b/accounts/abi/abigen/testdata/v2/nameconflict.go.txt @@ -58,7 +58,8 @@ func (c *NameConflict) Instance(backend bind.ContractBackend, addr common.Addres } // PackAddRequest is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xcce7b048. +// the contract method with ID 0xcce7b048. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function addRequest((bytes,bytes) req) pure returns() func (nameConflict *NameConflict) PackAddRequest(req Oraclerequest) []byte { @@ -69,8 +70,18 @@ func (nameConflict *NameConflict) PackAddRequest(req Oraclerequest) []byte { return enc } +// TryPackAddRequest is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xcce7b048. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function addRequest((bytes,bytes) req) pure returns() +func (nameConflict *NameConflict) TryPackAddRequest(req Oraclerequest) ([]byte, error) { + return nameConflict.abi.Pack("addRequest", req) +} + // PackGetRequest is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xc2bb515f. +// the contract method with ID 0xc2bb515f. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function getRequest() pure returns((bytes,bytes)) func (nameConflict *NameConflict) PackGetRequest() []byte { @@ -81,6 +92,15 @@ func (nameConflict *NameConflict) PackGetRequest() []byte { return enc } +// TryPackGetRequest is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xc2bb515f. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function getRequest() pure returns((bytes,bytes)) +func (nameConflict *NameConflict) TryPackGetRequest() ([]byte, error) { + return nameConflict.abi.Pack("getRequest") +} + // UnpackGetRequest is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xc2bb515f. // @@ -91,7 +111,7 @@ func (nameConflict *NameConflict) UnpackGetRequest(data []byte) (Oraclerequest, return *new(Oraclerequest), err } out0 := *abi.ConvertType(out[0], new(Oraclerequest)).(*Oraclerequest) - return out0, err + return out0, nil } // NameConflictLog represents a log event raised by the NameConflict contract. diff --git a/accounts/abi/abigen/testdata/v2/numericmethodname.go.txt b/accounts/abi/abigen/testdata/v2/numericmethodname.go.txt index 5a2208e0d42e..9d698a2657fc 100644 --- a/accounts/abi/abigen/testdata/v2/numericmethodname.go.txt +++ b/accounts/abi/abigen/testdata/v2/numericmethodname.go.txt @@ -52,7 +52,8 @@ func (c *NumericMethodName) Instance(backend bind.ContractBackend, addr common.A } // PackE1test is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xffa02795. +// the contract method with ID 0xffa02795. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function _1test() pure returns() func (numericMethodName *NumericMethodName) PackE1test() []byte { @@ -63,8 +64,18 @@ func (numericMethodName *NumericMethodName) PackE1test() []byte { return enc } +// TryPackE1test is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xffa02795. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function _1test() pure returns() +func (numericMethodName *NumericMethodName) TryPackE1test() ([]byte, error) { + return numericMethodName.abi.Pack("_1test") +} + // PackE1test0 is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xd02767c7. +// the contract method with ID 0xd02767c7. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function __1test() pure returns() func (numericMethodName *NumericMethodName) PackE1test0() []byte { @@ -75,8 +86,18 @@ func (numericMethodName *NumericMethodName) PackE1test0() []byte { return enc } +// TryPackE1test0 is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xd02767c7. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function __1test() pure returns() +func (numericMethodName *NumericMethodName) TryPackE1test0() ([]byte, error) { + return numericMethodName.abi.Pack("__1test") +} + // PackE2test is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x9d993132. +// the contract method with ID 0x9d993132. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function __2test() pure returns() func (numericMethodName *NumericMethodName) PackE2test() []byte { @@ -87,6 +108,15 @@ func (numericMethodName *NumericMethodName) PackE2test() []byte { return enc } +// TryPackE2test is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x9d993132. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function __2test() pure returns() +func (numericMethodName *NumericMethodName) TryPackE2test() ([]byte, error) { + return numericMethodName.abi.Pack("__2test") +} + // NumericMethodNameE1TestEvent represents a _1TestEvent event raised by the NumericMethodName contract. type NumericMethodNameE1TestEvent struct { Param common.Address diff --git a/accounts/abi/abigen/testdata/v2/outputchecker.go.txt b/accounts/abi/abigen/testdata/v2/outputchecker.go.txt index 6f1f8e67957b..f1c98f536e80 100644 --- a/accounts/abi/abigen/testdata/v2/outputchecker.go.txt +++ b/accounts/abi/abigen/testdata/v2/outputchecker.go.txt @@ -51,7 +51,8 @@ func (c *OutputChecker) Instance(backend bind.ContractBackend, addr common.Addre } // PackAnonOutput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x008bda05. +// the contract method with ID 0x008bda05. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function anonOutput() returns(string) func (outputChecker *OutputChecker) PackAnonOutput() []byte { @@ -62,6 +63,15 @@ func (outputChecker *OutputChecker) PackAnonOutput() []byte { return enc } +// TryPackAnonOutput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x008bda05. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function anonOutput() returns(string) +func (outputChecker *OutputChecker) TryPackAnonOutput() ([]byte, error) { + return outputChecker.abi.Pack("anonOutput") +} + // UnpackAnonOutput is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x008bda05. // @@ -72,11 +82,12 @@ func (outputChecker *OutputChecker) UnpackAnonOutput(data []byte) (string, error return *new(string), err } out0 := *abi.ConvertType(out[0], new(string)).(*string) - return out0, err + return out0, nil } // PackAnonOutputs is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x3c401115. +// the contract method with ID 0x3c401115. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function anonOutputs() returns(string, string) func (outputChecker *OutputChecker) PackAnonOutputs() []byte { @@ -87,6 +98,15 @@ func (outputChecker *OutputChecker) PackAnonOutputs() []byte { return enc } +// TryPackAnonOutputs is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x3c401115. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function anonOutputs() returns(string, string) +func (outputChecker *OutputChecker) TryPackAnonOutputs() ([]byte, error) { + return outputChecker.abi.Pack("anonOutputs") +} + // AnonOutputsOutput serves as a container for the return parameters of contract // method AnonOutputs. type AnonOutputsOutput struct { @@ -106,12 +126,12 @@ func (outputChecker *OutputChecker) UnpackAnonOutputs(data []byte) (AnonOutputsO } outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Arg1 = *abi.ConvertType(out[1], new(string)).(*string) - return *outstruct, err - + return *outstruct, nil } // PackCollidingOutputs is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xeccbc1ee. +// the contract method with ID 0xeccbc1ee. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function collidingOutputs() returns(string str, string Str) func (outputChecker *OutputChecker) PackCollidingOutputs() []byte { @@ -122,6 +142,15 @@ func (outputChecker *OutputChecker) PackCollidingOutputs() []byte { return enc } +// TryPackCollidingOutputs is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xeccbc1ee. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function collidingOutputs() returns(string str, string Str) +func (outputChecker *OutputChecker) TryPackCollidingOutputs() ([]byte, error) { + return outputChecker.abi.Pack("collidingOutputs") +} + // CollidingOutputsOutput serves as a container for the return parameters of contract // method CollidingOutputs. type CollidingOutputsOutput struct { @@ -141,12 +170,12 @@ func (outputChecker *OutputChecker) UnpackCollidingOutputs(data []byte) (Collidi } outstruct.Str = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Str0 = *abi.ConvertType(out[1], new(string)).(*string) - return *outstruct, err - + return *outstruct, nil } // PackMixedOutputs is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x21b77b44. +// the contract method with ID 0x21b77b44. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function mixedOutputs() returns(string, string str) func (outputChecker *OutputChecker) PackMixedOutputs() []byte { @@ -157,6 +186,15 @@ func (outputChecker *OutputChecker) PackMixedOutputs() []byte { return enc } +// TryPackMixedOutputs is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x21b77b44. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function mixedOutputs() returns(string, string str) +func (outputChecker *OutputChecker) TryPackMixedOutputs() ([]byte, error) { + return outputChecker.abi.Pack("mixedOutputs") +} + // MixedOutputsOutput serves as a container for the return parameters of contract // method MixedOutputs. type MixedOutputsOutput struct { @@ -176,12 +214,12 @@ func (outputChecker *OutputChecker) UnpackMixedOutputs(data []byte) (MixedOutput } outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Str = *abi.ConvertType(out[1], new(string)).(*string) - return *outstruct, err - + return *outstruct, nil } // PackNamedOutput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x5e632bd5. +// the contract method with ID 0x5e632bd5. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function namedOutput() returns(string str) func (outputChecker *OutputChecker) PackNamedOutput() []byte { @@ -192,6 +230,15 @@ func (outputChecker *OutputChecker) PackNamedOutput() []byte { return enc } +// TryPackNamedOutput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x5e632bd5. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function namedOutput() returns(string str) +func (outputChecker *OutputChecker) TryPackNamedOutput() ([]byte, error) { + return outputChecker.abi.Pack("namedOutput") +} + // UnpackNamedOutput is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x5e632bd5. // @@ -202,11 +249,12 @@ func (outputChecker *OutputChecker) UnpackNamedOutput(data []byte) (string, erro return *new(string), err } out0 := *abi.ConvertType(out[0], new(string)).(*string) - return out0, err + return out0, nil } // PackNamedOutputs is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x7970a189. +// the contract method with ID 0x7970a189. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function namedOutputs() returns(string str1, string str2) func (outputChecker *OutputChecker) PackNamedOutputs() []byte { @@ -217,6 +265,15 @@ func (outputChecker *OutputChecker) PackNamedOutputs() []byte { return enc } +// TryPackNamedOutputs is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x7970a189. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function namedOutputs() returns(string str1, string str2) +func (outputChecker *OutputChecker) TryPackNamedOutputs() ([]byte, error) { + return outputChecker.abi.Pack("namedOutputs") +} + // NamedOutputsOutput serves as a container for the return parameters of contract // method NamedOutputs. type NamedOutputsOutput struct { @@ -236,12 +293,12 @@ func (outputChecker *OutputChecker) UnpackNamedOutputs(data []byte) (NamedOutput } outstruct.Str1 = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Str2 = *abi.ConvertType(out[1], new(string)).(*string) - return *outstruct, err - + return *outstruct, nil } // PackNoOutput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x625f0306. +// the contract method with ID 0x625f0306. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function noOutput() returns() func (outputChecker *OutputChecker) PackNoOutput() []byte { @@ -251,3 +308,12 @@ func (outputChecker *OutputChecker) PackNoOutput() []byte { } return enc } + +// TryPackNoOutput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x625f0306. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function noOutput() returns() +func (outputChecker *OutputChecker) TryPackNoOutput() ([]byte, error) { + return outputChecker.abi.Pack("noOutput") +} diff --git a/accounts/abi/abigen/testdata/v2/overload.go.txt b/accounts/abi/abigen/testdata/v2/overload.go.txt index ed7c0b543ce2..3b9a95a125b3 100644 --- a/accounts/abi/abigen/testdata/v2/overload.go.txt +++ b/accounts/abi/abigen/testdata/v2/overload.go.txt @@ -52,7 +52,8 @@ func (c *Overload) Instance(backend bind.ContractBackend, addr common.Address) * } // PackFoo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x04bc52f8. +// the contract method with ID 0x04bc52f8. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function foo(uint256 i, uint256 j) returns() func (overload *Overload) PackFoo(i *big.Int, j *big.Int) []byte { @@ -63,8 +64,18 @@ func (overload *Overload) PackFoo(i *big.Int, j *big.Int) []byte { return enc } +// TryPackFoo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x04bc52f8. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function foo(uint256 i, uint256 j) returns() +func (overload *Overload) TryPackFoo(i *big.Int, j *big.Int) ([]byte, error) { + return overload.abi.Pack("foo", i, j) +} + // PackFoo0 is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2fbebd38. +// the contract method with ID 0x2fbebd38. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function foo(uint256 i) returns() func (overload *Overload) PackFoo0(i *big.Int) []byte { @@ -75,6 +86,15 @@ func (overload *Overload) PackFoo0(i *big.Int) []byte { return enc } +// TryPackFoo0 is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2fbebd38. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function foo(uint256 i) returns() +func (overload *Overload) TryPackFoo0(i *big.Int) ([]byte, error) { + return overload.abi.Pack("foo0", i) +} + // OverloadBar represents a bar event raised by the Overload contract. type OverloadBar struct { I *big.Int diff --git a/accounts/abi/abigen/testdata/v2/rangekeyword.go.txt b/accounts/abi/abigen/testdata/v2/rangekeyword.go.txt index c7f142539589..296de1fccc71 100644 --- a/accounts/abi/abigen/testdata/v2/rangekeyword.go.txt +++ b/accounts/abi/abigen/testdata/v2/rangekeyword.go.txt @@ -52,7 +52,8 @@ func (c *RangeKeyword) Instance(backend bind.ContractBackend, addr common.Addres } // PackFunctionWithKeywordParameter is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x527a119f. +// the contract method with ID 0x527a119f. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function functionWithKeywordParameter(uint256 range) pure returns() func (rangeKeyword *RangeKeyword) PackFunctionWithKeywordParameter(arg0 *big.Int) []byte { @@ -62,3 +63,12 @@ func (rangeKeyword *RangeKeyword) PackFunctionWithKeywordParameter(arg0 *big.Int } return enc } + +// TryPackFunctionWithKeywordParameter is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x527a119f. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function functionWithKeywordParameter(uint256 range) pure returns() +func (rangeKeyword *RangeKeyword) TryPackFunctionWithKeywordParameter(arg0 *big.Int) ([]byte, error) { + return rangeKeyword.abi.Pack("functionWithKeywordParameter", arg0) +} diff --git a/accounts/abi/abigen/testdata/v2/slicer.go.txt b/accounts/abi/abigen/testdata/v2/slicer.go.txt index b66c05cf0ff3..379f136453e0 100644 --- a/accounts/abi/abigen/testdata/v2/slicer.go.txt +++ b/accounts/abi/abigen/testdata/v2/slicer.go.txt @@ -52,7 +52,8 @@ func (c *Slicer) Instance(backend bind.ContractBackend, addr common.Address) *bi } // PackEchoAddresses is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xbe1127a3. +// the contract method with ID 0xbe1127a3. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function echoAddresses(address[] input) returns(address[] output) func (slicer *Slicer) PackEchoAddresses(input []common.Address) []byte { @@ -63,6 +64,15 @@ func (slicer *Slicer) PackEchoAddresses(input []common.Address) []byte { return enc } +// TryPackEchoAddresses is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xbe1127a3. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function echoAddresses(address[] input) returns(address[] output) +func (slicer *Slicer) TryPackEchoAddresses(input []common.Address) ([]byte, error) { + return slicer.abi.Pack("echoAddresses", input) +} + // UnpackEchoAddresses is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xbe1127a3. // @@ -73,11 +83,12 @@ func (slicer *Slicer) UnpackEchoAddresses(data []byte) ([]common.Address, error) return *new([]common.Address), err } out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - return out0, err + return out0, nil } // PackEchoBools is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xf637e589. +// the contract method with ID 0xf637e589. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function echoBools(bool[] input) returns(bool[] output) func (slicer *Slicer) PackEchoBools(input []bool) []byte { @@ -88,6 +99,15 @@ func (slicer *Slicer) PackEchoBools(input []bool) []byte { return enc } +// TryPackEchoBools is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xf637e589. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function echoBools(bool[] input) returns(bool[] output) +func (slicer *Slicer) TryPackEchoBools(input []bool) ([]byte, error) { + return slicer.abi.Pack("echoBools", input) +} + // UnpackEchoBools is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xf637e589. // @@ -98,11 +118,12 @@ func (slicer *Slicer) UnpackEchoBools(data []byte) ([]bool, error) { return *new([]bool), err } out0 := *abi.ConvertType(out[0], new([]bool)).(*[]bool) - return out0, err + return out0, nil } // PackEchoFancyInts is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xd88becc0. +// the contract method with ID 0xd88becc0. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function echoFancyInts(uint24[23] input) returns(uint24[23] output) func (slicer *Slicer) PackEchoFancyInts(input [23]*big.Int) []byte { @@ -113,6 +134,15 @@ func (slicer *Slicer) PackEchoFancyInts(input [23]*big.Int) []byte { return enc } +// TryPackEchoFancyInts is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xd88becc0. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function echoFancyInts(uint24[23] input) returns(uint24[23] output) +func (slicer *Slicer) TryPackEchoFancyInts(input [23]*big.Int) ([]byte, error) { + return slicer.abi.Pack("echoFancyInts", input) +} + // UnpackEchoFancyInts is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xd88becc0. // @@ -123,11 +153,12 @@ func (slicer *Slicer) UnpackEchoFancyInts(data []byte) ([23]*big.Int, error) { return *new([23]*big.Int), err } out0 := *abi.ConvertType(out[0], new([23]*big.Int)).(*[23]*big.Int) - return out0, err + return out0, nil } // PackEchoInts is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xe15a3db7. +// the contract method with ID 0xe15a3db7. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function echoInts(int256[] input) returns(int256[] output) func (slicer *Slicer) PackEchoInts(input []*big.Int) []byte { @@ -138,6 +169,15 @@ func (slicer *Slicer) PackEchoInts(input []*big.Int) []byte { return enc } +// TryPackEchoInts is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xe15a3db7. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function echoInts(int256[] input) returns(int256[] output) +func (slicer *Slicer) TryPackEchoInts(input []*big.Int) ([]byte, error) { + return slicer.abi.Pack("echoInts", input) +} + // UnpackEchoInts is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xe15a3db7. // @@ -148,5 +188,5 @@ func (slicer *Slicer) UnpackEchoInts(data []byte) ([]*big.Int, error) { return *new([]*big.Int), err } out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) - return out0, err + return out0, nil } diff --git a/accounts/abi/abigen/testdata/v2/structs.go.txt b/accounts/abi/abigen/testdata/v2/structs.go.txt index 7fe59c5616c3..4d8864cf6ea3 100644 --- a/accounts/abi/abigen/testdata/v2/structs.go.txt +++ b/accounts/abi/abigen/testdata/v2/structs.go.txt @@ -57,7 +57,8 @@ func (c *Structs) Instance(backend bind.ContractBackend, addr common.Address) *b } // PackF is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x28811f59. +// the contract method with ID 0x28811f59. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d) func (structs *Structs) PackF() []byte { @@ -68,6 +69,15 @@ func (structs *Structs) PackF() []byte { return enc } +// TryPackF is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x28811f59. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d) +func (structs *Structs) TryPackF() ([]byte, error) { + return structs.abi.Pack("F") +} + // FOutput serves as a container for the return parameters of contract // method F. type FOutput struct { @@ -89,12 +99,12 @@ func (structs *Structs) UnpackF(data []byte) (FOutput, error) { outstruct.A = *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0) outstruct.C = *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int) outstruct.D = *abi.ConvertType(out[2], new([]bool)).(*[]bool) - return *outstruct, err - + return *outstruct, nil } // PackG is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x6fecb623. +// the contract method with ID 0x6fecb623. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function G() view returns((bytes32)[] a) func (structs *Structs) PackG() []byte { @@ -105,6 +115,15 @@ func (structs *Structs) PackG() []byte { return enc } +// TryPackG is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x6fecb623. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function G() view returns((bytes32)[] a) +func (structs *Structs) TryPackG() ([]byte, error) { + return structs.abi.Pack("G") +} + // UnpackG is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x6fecb623. // @@ -115,5 +134,5 @@ func (structs *Structs) UnpackG(data []byte) ([]Struct0, error) { return *new([]Struct0), err } out0 := *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0) - return out0, err + return out0, nil } diff --git a/accounts/abi/abigen/testdata/v2/token.go.txt b/accounts/abi/abigen/testdata/v2/token.go.txt index aca18cb227cf..69294f375a15 100644 --- a/accounts/abi/abigen/testdata/v2/token.go.txt +++ b/accounts/abi/abigen/testdata/v2/token.go.txt @@ -64,7 +64,8 @@ func (token *Token) PackConstructor(initialSupply *big.Int, tokenName string, de } // PackAllowance is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xdd62ed3e. +// the contract method with ID 0xdd62ed3e. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function allowance(address , address ) returns(uint256) func (token *Token) PackAllowance(arg0 common.Address, arg1 common.Address) []byte { @@ -75,6 +76,15 @@ func (token *Token) PackAllowance(arg0 common.Address, arg1 common.Address) []by return enc } +// TryPackAllowance is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xdd62ed3e. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function allowance(address , address ) returns(uint256) +func (token *Token) TryPackAllowance(arg0 common.Address, arg1 common.Address) ([]byte, error) { + return token.abi.Pack("allowance", arg0, arg1) +} + // UnpackAllowance is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xdd62ed3e. // @@ -85,11 +95,12 @@ func (token *Token) UnpackAllowance(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackApproveAndCall is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xcae9ca51. +// the contract method with ID 0xcae9ca51. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns(bool success) func (token *Token) PackApproveAndCall(spender common.Address, value *big.Int, extraData []byte) []byte { @@ -100,6 +111,15 @@ func (token *Token) PackApproveAndCall(spender common.Address, value *big.Int, e return enc } +// TryPackApproveAndCall is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xcae9ca51. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns(bool success) +func (token *Token) TryPackApproveAndCall(spender common.Address, value *big.Int, extraData []byte) ([]byte, error) { + return token.abi.Pack("approveAndCall", spender, value, extraData) +} + // UnpackApproveAndCall is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xcae9ca51. // @@ -110,11 +130,12 @@ func (token *Token) UnpackApproveAndCall(data []byte) (bool, error) { return *new(bool), err } out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - return out0, err + return out0, nil } // PackBalanceOf is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x70a08231. +// the contract method with ID 0x70a08231. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function balanceOf(address ) returns(uint256) func (token *Token) PackBalanceOf(arg0 common.Address) []byte { @@ -125,6 +146,15 @@ func (token *Token) PackBalanceOf(arg0 common.Address) []byte { return enc } +// TryPackBalanceOf is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x70a08231. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function balanceOf(address ) returns(uint256) +func (token *Token) TryPackBalanceOf(arg0 common.Address) ([]byte, error) { + return token.abi.Pack("balanceOf", arg0) +} + // UnpackBalanceOf is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x70a08231. // @@ -135,11 +165,12 @@ func (token *Token) UnpackBalanceOf(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackDecimals is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x313ce567. +// the contract method with ID 0x313ce567. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function decimals() returns(uint8) func (token *Token) PackDecimals() []byte { @@ -150,6 +181,15 @@ func (token *Token) PackDecimals() []byte { return enc } +// TryPackDecimals is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x313ce567. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function decimals() returns(uint8) +func (token *Token) TryPackDecimals() ([]byte, error) { + return token.abi.Pack("decimals") +} + // UnpackDecimals is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x313ce567. // @@ -160,11 +200,12 @@ func (token *Token) UnpackDecimals(data []byte) (uint8, error) { return *new(uint8), err } out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - return out0, err + return out0, nil } // PackName is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x06fdde03. +// the contract method with ID 0x06fdde03. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function name() returns(string) func (token *Token) PackName() []byte { @@ -175,6 +216,15 @@ func (token *Token) PackName() []byte { return enc } +// TryPackName is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x06fdde03. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function name() returns(string) +func (token *Token) TryPackName() ([]byte, error) { + return token.abi.Pack("name") +} + // UnpackName is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x06fdde03. // @@ -185,11 +235,12 @@ func (token *Token) UnpackName(data []byte) (string, error) { return *new(string), err } out0 := *abi.ConvertType(out[0], new(string)).(*string) - return out0, err + return out0, nil } // PackSpentAllowance is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xdc3080f2. +// the contract method with ID 0xdc3080f2. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function spentAllowance(address , address ) returns(uint256) func (token *Token) PackSpentAllowance(arg0 common.Address, arg1 common.Address) []byte { @@ -200,6 +251,15 @@ func (token *Token) PackSpentAllowance(arg0 common.Address, arg1 common.Address) return enc } +// TryPackSpentAllowance is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xdc3080f2. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function spentAllowance(address , address ) returns(uint256) +func (token *Token) TryPackSpentAllowance(arg0 common.Address, arg1 common.Address) ([]byte, error) { + return token.abi.Pack("spentAllowance", arg0, arg1) +} + // UnpackSpentAllowance is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xdc3080f2. // @@ -210,11 +270,12 @@ func (token *Token) UnpackSpentAllowance(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackSymbol is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x95d89b41. +// the contract method with ID 0x95d89b41. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function symbol() returns(string) func (token *Token) PackSymbol() []byte { @@ -225,6 +286,15 @@ func (token *Token) PackSymbol() []byte { return enc } +// TryPackSymbol is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x95d89b41. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function symbol() returns(string) +func (token *Token) TryPackSymbol() ([]byte, error) { + return token.abi.Pack("symbol") +} + // UnpackSymbol is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x95d89b41. // @@ -235,11 +305,12 @@ func (token *Token) UnpackSymbol(data []byte) (string, error) { return *new(string), err } out0 := *abi.ConvertType(out[0], new(string)).(*string) - return out0, err + return out0, nil } // PackTransfer is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xa9059cbb. +// the contract method with ID 0xa9059cbb. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function transfer(address _to, uint256 _value) returns() func (token *Token) PackTransfer(to common.Address, value *big.Int) []byte { @@ -250,8 +321,18 @@ func (token *Token) PackTransfer(to common.Address, value *big.Int) []byte { return enc } +// TryPackTransfer is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xa9059cbb. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function transfer(address _to, uint256 _value) returns() +func (token *Token) TryPackTransfer(to common.Address, value *big.Int) ([]byte, error) { + return token.abi.Pack("transfer", to, value) +} + // PackTransferFrom is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x23b872dd. +// the contract method with ID 0x23b872dd. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function transferFrom(address _from, address _to, uint256 _value) returns(bool success) func (token *Token) PackTransferFrom(from common.Address, to common.Address, value *big.Int) []byte { @@ -262,6 +343,15 @@ func (token *Token) PackTransferFrom(from common.Address, to common.Address, val return enc } +// TryPackTransferFrom is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x23b872dd. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function transferFrom(address _from, address _to, uint256 _value) returns(bool success) +func (token *Token) TryPackTransferFrom(from common.Address, to common.Address, value *big.Int) ([]byte, error) { + return token.abi.Pack("transferFrom", from, to, value) +} + // UnpackTransferFrom is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x23b872dd. // @@ -272,7 +362,7 @@ func (token *Token) UnpackTransferFrom(data []byte) (bool, error) { return *new(bool), err } out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - return out0, err + return out0, nil } // TokenTransfer represents a Transfer event raised by the Token contract. diff --git a/accounts/abi/abigen/testdata/v2/tuple.go.txt b/accounts/abi/abigen/testdata/v2/tuple.go.txt index 65af7654635f..76a1f58d52f9 100644 --- a/accounts/abi/abigen/testdata/v2/tuple.go.txt +++ b/accounts/abi/abigen/testdata/v2/tuple.go.txt @@ -77,7 +77,8 @@ func (c *Tuple) Instance(backend bind.ContractBackend, addr common.Address) *bin } // PackFunc1 is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x443c79b4. +// the contract method with ID 0x443c79b4. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function func1((uint256,uint256[],(uint256,uint256)[]) a, (uint256,uint256)[2][] b, (uint256,uint256)[][2] c, (uint256,uint256[],(uint256,uint256)[])[] d, uint256[] e) pure returns((uint256,uint256[],(uint256,uint256)[]), (uint256,uint256)[2][], (uint256,uint256)[][2], (uint256,uint256[],(uint256,uint256)[])[], uint256[]) func (tuple *Tuple) PackFunc1(a TupleS, b [][2]TupleT, c [2][]TupleT, d []TupleS, e []*big.Int) []byte { @@ -88,6 +89,15 @@ func (tuple *Tuple) PackFunc1(a TupleS, b [][2]TupleT, c [2][]TupleT, d []TupleS return enc } +// TryPackFunc1 is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x443c79b4. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function func1((uint256,uint256[],(uint256,uint256)[]) a, (uint256,uint256)[2][] b, (uint256,uint256)[][2] c, (uint256,uint256[],(uint256,uint256)[])[] d, uint256[] e) pure returns((uint256,uint256[],(uint256,uint256)[]), (uint256,uint256)[2][], (uint256,uint256)[][2], (uint256,uint256[],(uint256,uint256)[])[], uint256[]) +func (tuple *Tuple) TryPackFunc1(a TupleS, b [][2]TupleT, c [2][]TupleT, d []TupleS, e []*big.Int) ([]byte, error) { + return tuple.abi.Pack("func1", a, b, c, d, e) +} + // Func1Output serves as a container for the return parameters of contract // method Func1. type Func1Output struct { @@ -113,12 +123,12 @@ func (tuple *Tuple) UnpackFunc1(data []byte) (Func1Output, error) { outstruct.Arg2 = *abi.ConvertType(out[2], new([2][]TupleT)).(*[2][]TupleT) outstruct.Arg3 = *abi.ConvertType(out[3], new([]TupleS)).(*[]TupleS) outstruct.Arg4 = *abi.ConvertType(out[4], new([]*big.Int)).(*[]*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackFunc2 is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xd0062cdd. +// the contract method with ID 0xd0062cdd. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function func2((uint256,uint256[],(uint256,uint256)[]) a, (uint256,uint256)[2][] b, (uint256,uint256)[][2] c, (uint256,uint256[],(uint256,uint256)[])[] d, uint256[] e) returns() func (tuple *Tuple) PackFunc2(a TupleS, b [][2]TupleT, c [2][]TupleT, d []TupleS, e []*big.Int) []byte { @@ -129,8 +139,18 @@ func (tuple *Tuple) PackFunc2(a TupleS, b [][2]TupleT, c [2][]TupleT, d []TupleS return enc } +// TryPackFunc2 is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xd0062cdd. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function func2((uint256,uint256[],(uint256,uint256)[]) a, (uint256,uint256)[2][] b, (uint256,uint256)[][2] c, (uint256,uint256[],(uint256,uint256)[])[] d, uint256[] e) returns() +func (tuple *Tuple) TryPackFunc2(a TupleS, b [][2]TupleT, c [2][]TupleT, d []TupleS, e []*big.Int) ([]byte, error) { + return tuple.abi.Pack("func2", a, b, c, d, e) +} + // PackFunc3 is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xe4d9a43b. +// the contract method with ID 0xe4d9a43b. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function func3((uint16,uint16)[] ) pure returns() func (tuple *Tuple) PackFunc3(arg0 []TupleQ) []byte { @@ -141,6 +161,15 @@ func (tuple *Tuple) PackFunc3(arg0 []TupleQ) []byte { return enc } +// TryPackFunc3 is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xe4d9a43b. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function func3((uint16,uint16)[] ) pure returns() +func (tuple *Tuple) TryPackFunc3(arg0 []TupleQ) ([]byte, error) { + return tuple.abi.Pack("func3", arg0) +} + // TupleTupleEvent represents a TupleEvent event raised by the Tuple contract. type TupleTupleEvent struct { A TupleS diff --git a/accounts/abi/abigen/testdata/v2/tupler.go.txt b/accounts/abi/abigen/testdata/v2/tupler.go.txt index caa692dadec7..8643487042c8 100644 --- a/accounts/abi/abigen/testdata/v2/tupler.go.txt +++ b/accounts/abi/abigen/testdata/v2/tupler.go.txt @@ -52,7 +52,8 @@ func (c *Tupler) Instance(backend bind.ContractBackend, addr common.Address) *bi } // PackTuple is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x3175aae2. +// the contract method with ID 0x3175aae2. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function tuple() returns(string a, int256 b, bytes32 c) func (tupler *Tupler) PackTuple() []byte { @@ -63,6 +64,15 @@ func (tupler *Tupler) PackTuple() []byte { return enc } +// TryPackTuple is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x3175aae2. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function tuple() returns(string a, int256 b, bytes32 c) +func (tupler *Tupler) TryPackTuple() ([]byte, error) { + return tupler.abi.Pack("tuple") +} + // TupleOutput serves as a container for the return parameters of contract // method Tuple. type TupleOutput struct { @@ -84,6 +94,5 @@ func (tupler *Tupler) UnpackTuple(data []byte) (TupleOutput, error) { outstruct.A = *abi.ConvertType(out[0], new(string)).(*string) outstruct.B = abi.ConvertType(out[1], new(big.Int)).(*big.Int) outstruct.C = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) - return *outstruct, err - + return *outstruct, nil } diff --git a/accounts/abi/abigen/testdata/v2/underscorer.go.txt b/accounts/abi/abigen/testdata/v2/underscorer.go.txt index ef9eb864fa49..13ec9685086a 100644 --- a/accounts/abi/abigen/testdata/v2/underscorer.go.txt +++ b/accounts/abi/abigen/testdata/v2/underscorer.go.txt @@ -52,7 +52,8 @@ func (c *Underscorer) Instance(backend bind.ContractBackend, addr common.Address } // PackAllPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xb564b34d. +// the contract method with ID 0xb564b34d. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function AllPurelyUnderscoredOutput() view returns(int256 _, int256 __) func (underscorer *Underscorer) PackAllPurelyUnderscoredOutput() []byte { @@ -63,6 +64,15 @@ func (underscorer *Underscorer) PackAllPurelyUnderscoredOutput() []byte { return enc } +// TryPackAllPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xb564b34d. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function AllPurelyUnderscoredOutput() view returns(int256 _, int256 __) +func (underscorer *Underscorer) TryPackAllPurelyUnderscoredOutput() ([]byte, error) { + return underscorer.abi.Pack("AllPurelyUnderscoredOutput") +} + // AllPurelyUnderscoredOutputOutput serves as a container for the return parameters of contract // method AllPurelyUnderscoredOutput. type AllPurelyUnderscoredOutputOutput struct { @@ -82,12 +92,12 @@ func (underscorer *Underscorer) UnpackAllPurelyUnderscoredOutput(data []byte) (A } outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackLowerLowerCollision is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xe409ca45. +// the contract method with ID 0xe409ca45. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function LowerLowerCollision() view returns(int256 _res, int256 res) func (underscorer *Underscorer) PackLowerLowerCollision() []byte { @@ -98,6 +108,15 @@ func (underscorer *Underscorer) PackLowerLowerCollision() []byte { return enc } +// TryPackLowerLowerCollision is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xe409ca45. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function LowerLowerCollision() view returns(int256 _res, int256 res) +func (underscorer *Underscorer) TryPackLowerLowerCollision() ([]byte, error) { + return underscorer.abi.Pack("LowerLowerCollision") +} + // LowerLowerCollisionOutput serves as a container for the return parameters of contract // method LowerLowerCollision. type LowerLowerCollisionOutput struct { @@ -117,12 +136,12 @@ func (underscorer *Underscorer) UnpackLowerLowerCollision(data []byte) (LowerLow } outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackLowerUpperCollision is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x03a59213. +// the contract method with ID 0x03a59213. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function LowerUpperCollision() view returns(int256 _res, int256 Res) func (underscorer *Underscorer) PackLowerUpperCollision() []byte { @@ -133,6 +152,15 @@ func (underscorer *Underscorer) PackLowerUpperCollision() []byte { return enc } +// TryPackLowerUpperCollision is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x03a59213. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function LowerUpperCollision() view returns(int256 _res, int256 Res) +func (underscorer *Underscorer) TryPackLowerUpperCollision() ([]byte, error) { + return underscorer.abi.Pack("LowerUpperCollision") +} + // LowerUpperCollisionOutput serves as a container for the return parameters of contract // method LowerUpperCollision. type LowerUpperCollisionOutput struct { @@ -152,12 +180,12 @@ func (underscorer *Underscorer) UnpackLowerUpperCollision(data []byte) (LowerUpp } outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x9df48485. +// the contract method with ID 0x9df48485. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function PurelyUnderscoredOutput() view returns(int256 _, int256 res) func (underscorer *Underscorer) PackPurelyUnderscoredOutput() []byte { @@ -168,6 +196,15 @@ func (underscorer *Underscorer) PackPurelyUnderscoredOutput() []byte { return enc } +// TryPackPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x9df48485. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function PurelyUnderscoredOutput() view returns(int256 _, int256 res) +func (underscorer *Underscorer) TryPackPurelyUnderscoredOutput() ([]byte, error) { + return underscorer.abi.Pack("PurelyUnderscoredOutput") +} + // PurelyUnderscoredOutputOutput serves as a container for the return parameters of contract // method PurelyUnderscoredOutput. type PurelyUnderscoredOutputOutput struct { @@ -187,12 +224,12 @@ func (underscorer *Underscorer) UnpackPurelyUnderscoredOutput(data []byte) (Pure } outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.Res = abi.ConvertType(out[1], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackUnderscoredOutput is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x67e6633d. +// the contract method with ID 0x67e6633d. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function UnderscoredOutput() view returns(int256 _int, string _string) func (underscorer *Underscorer) PackUnderscoredOutput() []byte { @@ -203,6 +240,15 @@ func (underscorer *Underscorer) PackUnderscoredOutput() []byte { return enc } +// TryPackUnderscoredOutput is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x67e6633d. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function UnderscoredOutput() view returns(int256 _int, string _string) +func (underscorer *Underscorer) TryPackUnderscoredOutput() ([]byte, error) { + return underscorer.abi.Pack("UnderscoredOutput") +} + // UnderscoredOutputOutput serves as a container for the return parameters of contract // method UnderscoredOutput. type UnderscoredOutputOutput struct { @@ -222,12 +268,12 @@ func (underscorer *Underscorer) UnpackUnderscoredOutput(data []byte) (Underscore } outstruct.Int = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.String = *abi.ConvertType(out[1], new(string)).(*string) - return *outstruct, err - + return *outstruct, nil } // PackUpperLowerCollision is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xaf7486ab. +// the contract method with ID 0xaf7486ab. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function UpperLowerCollision() view returns(int256 _Res, int256 res) func (underscorer *Underscorer) PackUpperLowerCollision() []byte { @@ -238,6 +284,15 @@ func (underscorer *Underscorer) PackUpperLowerCollision() []byte { return enc } +// TryPackUpperLowerCollision is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xaf7486ab. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function UpperLowerCollision() view returns(int256 _Res, int256 res) +func (underscorer *Underscorer) TryPackUpperLowerCollision() ([]byte, error) { + return underscorer.abi.Pack("UpperLowerCollision") +} + // UpperLowerCollisionOutput serves as a container for the return parameters of contract // method UpperLowerCollision. type UpperLowerCollisionOutput struct { @@ -257,12 +312,12 @@ func (underscorer *Underscorer) UnpackUpperLowerCollision(data []byte) (UpperLow } outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackUpperUpperCollision is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xe02ab24d. +// the contract method with ID 0xe02ab24d. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function UpperUpperCollision() view returns(int256 _Res, int256 Res) func (underscorer *Underscorer) PackUpperUpperCollision() []byte { @@ -273,6 +328,15 @@ func (underscorer *Underscorer) PackUpperUpperCollision() []byte { return enc } +// TryPackUpperUpperCollision is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xe02ab24d. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function UpperUpperCollision() view returns(int256 _Res, int256 Res) +func (underscorer *Underscorer) TryPackUpperUpperCollision() ([]byte, error) { + return underscorer.abi.Pack("UpperUpperCollision") +} + // UpperUpperCollisionOutput serves as a container for the return parameters of contract // method UpperUpperCollision. type UpperUpperCollisionOutput struct { @@ -292,12 +356,12 @@ func (underscorer *Underscorer) UnpackUpperUpperCollision(data []byte) (UpperUpp } outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackUnderScoredFunc is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x46546dbe. +// the contract method with ID 0x46546dbe. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function _under_scored_func() view returns(int256 _int) func (underscorer *Underscorer) PackUnderScoredFunc() []byte { @@ -308,6 +372,15 @@ func (underscorer *Underscorer) PackUnderScoredFunc() []byte { return enc } +// TryPackUnderScoredFunc is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x46546dbe. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function _under_scored_func() view returns(int256 _int) +func (underscorer *Underscorer) TryPackUnderScoredFunc() ([]byte, error) { + return underscorer.abi.Pack("_under_scored_func") +} + // UnpackUnderScoredFunc is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x46546dbe. // @@ -318,5 +391,5 @@ func (underscorer *Underscorer) UnpackUnderScoredFunc(data []byte) (*big.Int, er return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } diff --git a/accounts/abi/bind/v2/internal/contracts/db/bindings.go b/accounts/abi/bind/v2/internal/contracts/db/bindings.go index 6291160fe966..fc00a555b5cc 100644 --- a/accounts/abi/bind/v2/internal/contracts/db/bindings.go +++ b/accounts/abi/bind/v2/internal/contracts/db/bindings.go @@ -59,7 +59,8 @@ func (c *DB) Instance(backend bind.ContractBackend, addr common.Address) *bind.B } // PackGet is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x9507d39a. +// the contract method with ID 0x9507d39a. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function get(uint256 k) returns(uint256) func (dB *DB) PackGet(k *big.Int) []byte { @@ -70,6 +71,15 @@ func (dB *DB) PackGet(k *big.Int) []byte { return enc } +// TryPackGet is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x9507d39a. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function get(uint256 k) returns(uint256) +func (dB *DB) TryPackGet(k *big.Int) ([]byte, error) { + return dB.abi.Pack("get", k) +} + // UnpackGet is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x9507d39a. // @@ -80,11 +90,12 @@ func (dB *DB) UnpackGet(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // PackGetNamedStatParams is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xe369ba3b. +// the contract method with ID 0xe369ba3b. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function getNamedStatParams() view returns(uint256 gets, uint256 inserts, uint256 mods) func (dB *DB) PackGetNamedStatParams() []byte { @@ -95,6 +106,15 @@ func (dB *DB) PackGetNamedStatParams() []byte { return enc } +// TryPackGetNamedStatParams is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xe369ba3b. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function getNamedStatParams() view returns(uint256 gets, uint256 inserts, uint256 mods) +func (dB *DB) TryPackGetNamedStatParams() ([]byte, error) { + return dB.abi.Pack("getNamedStatParams") +} + // GetNamedStatParamsOutput serves as a container for the return parameters of contract // method GetNamedStatParams. type GetNamedStatParamsOutput struct { @@ -116,12 +136,12 @@ func (dB *DB) UnpackGetNamedStatParams(data []byte) (GetNamedStatParamsOutput, e outstruct.Gets = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.Inserts = abi.ConvertType(out[1], new(big.Int)).(*big.Int) outstruct.Mods = abi.ConvertType(out[2], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackGetStatParams is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x6fcb9c70. +// the contract method with ID 0x6fcb9c70. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function getStatParams() view returns(uint256, uint256, uint256) func (dB *DB) PackGetStatParams() []byte { @@ -132,6 +152,15 @@ func (dB *DB) PackGetStatParams() []byte { return enc } +// TryPackGetStatParams is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x6fcb9c70. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function getStatParams() view returns(uint256, uint256, uint256) +func (dB *DB) TryPackGetStatParams() ([]byte, error) { + return dB.abi.Pack("getStatParams") +} + // GetStatParamsOutput serves as a container for the return parameters of contract // method GetStatParams. type GetStatParamsOutput struct { @@ -153,12 +182,12 @@ func (dB *DB) UnpackGetStatParams(data []byte) (GetStatParamsOutput, error) { outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int) outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int) outstruct.Arg2 = abi.ConvertType(out[2], new(big.Int)).(*big.Int) - return *outstruct, err - + return *outstruct, nil } // PackGetStatsStruct is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xee8161e0. +// the contract method with ID 0xee8161e0. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function getStatsStruct() view returns((uint256,uint256,uint256)) func (dB *DB) PackGetStatsStruct() []byte { @@ -169,6 +198,15 @@ func (dB *DB) PackGetStatsStruct() []byte { return enc } +// TryPackGetStatsStruct is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xee8161e0. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function getStatsStruct() view returns((uint256,uint256,uint256)) +func (dB *DB) TryPackGetStatsStruct() ([]byte, error) { + return dB.abi.Pack("getStatsStruct") +} + // UnpackGetStatsStruct is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xee8161e0. // @@ -179,11 +217,12 @@ func (dB *DB) UnpackGetStatsStruct(data []byte) (DBStats, error) { return *new(DBStats), err } out0 := *abi.ConvertType(out[0], new(DBStats)).(*DBStats) - return out0, err + return out0, nil } // PackInsert is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x1d834a1b. +// the contract method with ID 0x1d834a1b. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function insert(uint256 k, uint256 v) returns(uint256) func (dB *DB) PackInsert(k *big.Int, v *big.Int) []byte { @@ -194,6 +233,15 @@ func (dB *DB) PackInsert(k *big.Int, v *big.Int) []byte { return enc } +// TryPackInsert is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x1d834a1b. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function insert(uint256 k, uint256 v) returns(uint256) +func (dB *DB) TryPackInsert(k *big.Int, v *big.Int) ([]byte, error) { + return dB.abi.Pack("insert", k, v) +} + // UnpackInsert is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x1d834a1b. // @@ -204,7 +252,7 @@ func (dB *DB) UnpackInsert(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // DBInsert represents a Insert event raised by the DB contract. diff --git a/accounts/abi/bind/v2/internal/contracts/events/bindings.go b/accounts/abi/bind/v2/internal/contracts/events/bindings.go index 580bffa23eb8..ba4fdc71e3f1 100644 --- a/accounts/abi/bind/v2/internal/contracts/events/bindings.go +++ b/accounts/abi/bind/v2/internal/contracts/events/bindings.go @@ -52,7 +52,8 @@ func (c *C) Instance(backend bind.ContractBackend, addr common.Address) *bind.Bo } // PackEmitMulti is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xcb493749. +// the contract method with ID 0xcb493749. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function EmitMulti() returns() func (c *C) PackEmitMulti() []byte { @@ -63,8 +64,18 @@ func (c *C) PackEmitMulti() []byte { return enc } +// TryPackEmitMulti is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xcb493749. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function EmitMulti() returns() +func (c *C) TryPackEmitMulti() ([]byte, error) { + return c.abi.Pack("EmitMulti") +} + // PackEmitOne is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xe8e49a71. +// the contract method with ID 0xe8e49a71. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function EmitOne() returns() func (c *C) PackEmitOne() []byte { @@ -75,6 +86,15 @@ func (c *C) PackEmitOne() []byte { return enc } +// TryPackEmitOne is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xe8e49a71. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function EmitOne() returns() +func (c *C) TryPackEmitOne() ([]byte, error) { + return c.abi.Pack("EmitOne") +} + // CBasic1 represents a basic1 event raised by the C contract. type CBasic1 struct { Id *big.Int diff --git a/accounts/abi/bind/v2/internal/contracts/nested_libraries/bindings.go b/accounts/abi/bind/v2/internal/contracts/nested_libraries/bindings.go index 6fd6a1b2859a..d1cb08116b0c 100644 --- a/accounts/abi/bind/v2/internal/contracts/nested_libraries/bindings.go +++ b/accounts/abi/bind/v2/internal/contracts/nested_libraries/bindings.go @@ -68,7 +68,8 @@ func (c1 *C1) PackConstructor(v1 *big.Int, v2 *big.Int) []byte { } // PackDo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2ad11272. +// the contract method with ID 0x2ad11272. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Do(uint256 val) pure returns(uint256 res) func (c1 *C1) PackDo(val *big.Int) []byte { @@ -79,6 +80,15 @@ func (c1 *C1) PackDo(val *big.Int) []byte { return enc } +// TryPackDo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2ad11272. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Do(uint256 val) pure returns(uint256 res) +func (c1 *C1) TryPackDo(val *big.Int) ([]byte, error) { + return c1.abi.Pack("Do", val) +} + // UnpackDo is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x2ad11272. // @@ -89,7 +99,7 @@ func (c1 *C1) UnpackDo(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // C2MetaData contains all meta data concerning the C2 contract. @@ -136,7 +146,8 @@ func (c2 *C2) PackConstructor(v1 *big.Int, v2 *big.Int) []byte { } // PackDo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2ad11272. +// the contract method with ID 0x2ad11272. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Do(uint256 val) pure returns(uint256 res) func (c2 *C2) PackDo(val *big.Int) []byte { @@ -147,6 +158,15 @@ func (c2 *C2) PackDo(val *big.Int) []byte { return enc } +// TryPackDo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2ad11272. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Do(uint256 val) pure returns(uint256 res) +func (c2 *C2) TryPackDo(val *big.Int) ([]byte, error) { + return c2.abi.Pack("Do", val) +} + // UnpackDo is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x2ad11272. // @@ -157,7 +177,7 @@ func (c2 *C2) UnpackDo(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // L1MetaData contains all meta data concerning the L1 contract. @@ -188,7 +208,8 @@ func (c *L1) Instance(backend bind.ContractBackend, addr common.Address) *bind.B } // PackDo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2ad11272. +// the contract method with ID 0x2ad11272. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Do(uint256 val) pure returns(uint256) func (l1 *L1) PackDo(val *big.Int) []byte { @@ -199,6 +220,15 @@ func (l1 *L1) PackDo(val *big.Int) []byte { return enc } +// TryPackDo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2ad11272. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Do(uint256 val) pure returns(uint256) +func (l1 *L1) TryPackDo(val *big.Int) ([]byte, error) { + return l1.abi.Pack("Do", val) +} + // UnpackDo is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x2ad11272. // @@ -209,7 +239,7 @@ func (l1 *L1) UnpackDo(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // L2MetaData contains all meta data concerning the L2 contract. @@ -243,7 +273,8 @@ func (c *L2) Instance(backend bind.ContractBackend, addr common.Address) *bind.B } // PackDo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2ad11272. +// the contract method with ID 0x2ad11272. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Do(uint256 val) pure returns(uint256) func (l2 *L2) PackDo(val *big.Int) []byte { @@ -254,6 +285,15 @@ func (l2 *L2) PackDo(val *big.Int) []byte { return enc } +// TryPackDo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2ad11272. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Do(uint256 val) pure returns(uint256) +func (l2 *L2) TryPackDo(val *big.Int) ([]byte, error) { + return l2.abi.Pack("Do", val) +} + // UnpackDo is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x2ad11272. // @@ -264,7 +304,7 @@ func (l2 *L2) UnpackDo(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // L2bMetaData contains all meta data concerning the L2b contract. @@ -298,7 +338,8 @@ func (c *L2b) Instance(backend bind.ContractBackend, addr common.Address) *bind. } // PackDo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2ad11272. +// the contract method with ID 0x2ad11272. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Do(uint256 val) pure returns(uint256) func (l2b *L2b) PackDo(val *big.Int) []byte { @@ -309,6 +350,15 @@ func (l2b *L2b) PackDo(val *big.Int) []byte { return enc } +// TryPackDo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2ad11272. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Do(uint256 val) pure returns(uint256) +func (l2b *L2b) TryPackDo(val *big.Int) ([]byte, error) { + return l2b.abi.Pack("Do", val) +} + // UnpackDo is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x2ad11272. // @@ -319,7 +369,7 @@ func (l2b *L2b) UnpackDo(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // L3MetaData contains all meta data concerning the L3 contract. @@ -350,7 +400,8 @@ func (c *L3) Instance(backend bind.ContractBackend, addr common.Address) *bind.B } // PackDo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2ad11272. +// the contract method with ID 0x2ad11272. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Do(uint256 val) pure returns(uint256) func (l3 *L3) PackDo(val *big.Int) []byte { @@ -361,6 +412,15 @@ func (l3 *L3) PackDo(val *big.Int) []byte { return enc } +// TryPackDo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2ad11272. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Do(uint256 val) pure returns(uint256) +func (l3 *L3) TryPackDo(val *big.Int) ([]byte, error) { + return l3.abi.Pack("Do", val) +} + // UnpackDo is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x2ad11272. // @@ -371,7 +431,7 @@ func (l3 *L3) UnpackDo(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // L4MetaData contains all meta data concerning the L4 contract. @@ -406,7 +466,8 @@ func (c *L4) Instance(backend bind.ContractBackend, addr common.Address) *bind.B } // PackDo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2ad11272. +// the contract method with ID 0x2ad11272. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Do(uint256 val) pure returns(uint256) func (l4 *L4) PackDo(val *big.Int) []byte { @@ -417,6 +478,15 @@ func (l4 *L4) PackDo(val *big.Int) []byte { return enc } +// TryPackDo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2ad11272. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Do(uint256 val) pure returns(uint256) +func (l4 *L4) TryPackDo(val *big.Int) ([]byte, error) { + return l4.abi.Pack("Do", val) +} + // UnpackDo is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x2ad11272. // @@ -427,7 +497,7 @@ func (l4 *L4) UnpackDo(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } // L4bMetaData contains all meta data concerning the L4b contract. @@ -461,7 +531,8 @@ func (c *L4b) Instance(backend bind.ContractBackend, addr common.Address) *bind. } // PackDo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0x2ad11272. +// the contract method with ID 0x2ad11272. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Do(uint256 val) pure returns(uint256) func (l4b *L4b) PackDo(val *big.Int) []byte { @@ -472,6 +543,15 @@ func (l4b *L4b) PackDo(val *big.Int) []byte { return enc } +// TryPackDo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0x2ad11272. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Do(uint256 val) pure returns(uint256) +func (l4b *L4b) TryPackDo(val *big.Int) ([]byte, error) { + return l4b.abi.Pack("Do", val) +} + // UnpackDo is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0x2ad11272. // @@ -482,5 +562,5 @@ func (l4b *L4b) UnpackDo(data []byte) (*big.Int, error) { return new(big.Int), err } out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) - return out0, err + return out0, nil } diff --git a/accounts/abi/bind/v2/internal/contracts/solc_errors/bindings.go b/accounts/abi/bind/v2/internal/contracts/solc_errors/bindings.go index 067fb2b0e118..627b86f1b99a 100644 --- a/accounts/abi/bind/v2/internal/contracts/solc_errors/bindings.go +++ b/accounts/abi/bind/v2/internal/contracts/solc_errors/bindings.go @@ -52,7 +52,8 @@ func (c *C) Instance(backend bind.ContractBackend, addr common.Address) *bind.Bo } // PackBar is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xb0a378b0. +// the contract method with ID 0xb0a378b0. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Bar() pure returns() func (c *C) PackBar() []byte { @@ -63,8 +64,18 @@ func (c *C) PackBar() []byte { return enc } +// TryPackBar is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xb0a378b0. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Bar() pure returns() +func (c *C) TryPackBar() ([]byte, error) { + return c.abi.Pack("Bar") +} + // PackFoo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xbfb4ebcf. +// the contract method with ID 0xbfb4ebcf. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Foo() pure returns() func (c *C) PackFoo() []byte { @@ -75,6 +86,15 @@ func (c *C) PackFoo() []byte { return enc } +// TryPackFoo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xbfb4ebcf. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Foo() pure returns() +func (c *C) TryPackFoo() ([]byte, error) { + return c.abi.Pack("Foo") +} + // UnpackError attempts to decode the provided error data using user-defined // error definitions. func (c *C) UnpackError(raw []byte) (any, error) { @@ -169,7 +189,8 @@ func (c *C2) Instance(backend bind.ContractBackend, addr common.Address) *bind.B } // PackFoo is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xbfb4ebcf. +// the contract method with ID 0xbfb4ebcf. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function Foo() pure returns() func (c2 *C2) PackFoo() []byte { @@ -180,6 +201,15 @@ func (c2 *C2) PackFoo() []byte { return enc } +// TryPackFoo is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xbfb4ebcf. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function Foo() pure returns() +func (c2 *C2) TryPackFoo() ([]byte, error) { + return c2.abi.Pack("Foo") +} + // UnpackError attempts to decode the provided error data using user-defined // error definitions. func (c2 *C2) UnpackError(raw []byte) (any, error) { diff --git a/accounts/abi/bind/v2/internal/contracts/uint256arrayreturn/bindings.go b/accounts/abi/bind/v2/internal/contracts/uint256arrayreturn/bindings.go index 4999cc75d9ef..19d09bdd6a41 100644 --- a/accounts/abi/bind/v2/internal/contracts/uint256arrayreturn/bindings.go +++ b/accounts/abi/bind/v2/internal/contracts/uint256arrayreturn/bindings.go @@ -52,7 +52,8 @@ func (c *MyContract) Instance(backend bind.ContractBackend, addr common.Address) } // PackGetNums is the Go binding used to pack the parameters required for calling -// the contract method with ID 0xbd6d1007. +// the contract method with ID 0xbd6d1007. This method will panic if any +// invalid/nil inputs are passed. // // Solidity: function GetNums() pure returns(uint256[5]) func (myContract *MyContract) PackGetNums() []byte { @@ -63,6 +64,15 @@ func (myContract *MyContract) PackGetNums() []byte { return enc } +// TryPackGetNums is the Go binding used to pack the parameters required for calling +// the contract method with ID 0xbd6d1007. This method will return an error +// if any inputs are invalid/nil. +// +// Solidity: function GetNums() pure returns(uint256[5]) +func (myContract *MyContract) TryPackGetNums() ([]byte, error) { + return myContract.abi.Pack("GetNums") +} + // UnpackGetNums is the Go binding that unpacks the parameters returned // from invoking the contract method with ID 0xbd6d1007. // @@ -73,5 +83,5 @@ func (myContract *MyContract) UnpackGetNums(data []byte) ([5]*big.Int, error) { return *new([5]*big.Int), err } out0 := *abi.ConvertType(out[0], new([5]*big.Int)).(*[5]*big.Int) - return out0, err + return out0, nil } diff --git a/accounts/manager.go b/accounts/manager.go index ac21ecd9853f..a2218e54dd91 100644 --- a/accounts/manager.go +++ b/accounts/manager.go @@ -93,9 +93,6 @@ 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 @@ -149,6 +146,10 @@ func (am *Manager) update() { am.lock.Unlock() close(event.processed) case errc := <-am.quit: + // Close all owned wallets + for _, w := range am.wallets { + w.Close() + } // Manager terminating, return errc <- nil // Signals event emitters the loop is not receiving values diff --git a/beacon/engine/types.go b/beacon/engine/types.go index 3e52933a900d..76bfd22a2367 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -123,6 +123,11 @@ type BlobAndProofV1 struct { Proof hexutil.Bytes `json:"proof"` } +type BlobAndProofV2 struct { + Blob hexutil.Bytes `json:"blob"` + CellProofs []hexutil.Bytes `json:"proofs"` +} + // JSON type overrides for ExecutionPayloadEnvelope. type executionPayloadEnvelopeMarshaling struct { BlockValue *hexutil.Big @@ -331,7 +336,9 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types. 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][:])) + } + for _, proof := range sidecar.Proofs { + bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(proof[:])) } } diff --git a/beacon/engine/types_test.go b/beacon/engine/types_test.go new file mode 100644 index 000000000000..ff376dfd2e7d --- /dev/null +++ b/beacon/engine/types_test.go @@ -0,0 +1,56 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package engine + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto/kzg4844" +) + +func TestBlobs(t *testing.T) { + var ( + emptyBlob = new(kzg4844.Blob) + emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) + emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) + emptyCellProof, _ = kzg4844.ComputeCellProofs(emptyBlob) + ) + header := types.Header{} + block := types.NewBlock(&header, &types.Body{}, nil, nil) + + sidecarWithoutCellProofs := &types.BlobTxSidecar{ + Blobs: []kzg4844.Blob{*emptyBlob}, + Commitments: []kzg4844.Commitment{emptyBlobCommit}, + Proofs: []kzg4844.Proof{emptyBlobProof}, + } + env := BlockToExecutableData(block, common.Big0, []*types.BlobTxSidecar{sidecarWithoutCellProofs}, nil) + if len(env.BlobsBundle.Proofs) != 1 { + t.Fatalf("Expect 1 proof in blobs bundle, got %v", len(env.BlobsBundle.Proofs)) + } + + sidecarWithCellProofs := &types.BlobTxSidecar{ + Blobs: []kzg4844.Blob{*emptyBlob}, + Commitments: []kzg4844.Commitment{emptyBlobCommit}, + Proofs: emptyCellProof, + } + env = BlockToExecutableData(block, common.Big0, []*types.BlobTxSidecar{sidecarWithCellProofs}, nil) + if len(env.BlobsBundle.Proofs) != 128 { + t.Fatalf("Expect 128 proofs in blobs bundle, got %v", len(env.BlobsBundle.Proofs)) + } +} diff --git a/build/checksums.txt b/build/checksums.txt index cf52172c2ec6..663bf9ed639a 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -5,54 +5,54 @@ # https://github.com/ethereum/execution-spec-tests/releases/download/v4.5.0/ 58afb92a0075a2cb7c4dec1281f7cb88b21b02afbedad096b580f3f8cc14c54c fixtures_develop.tar.gz -# version:golang 1.24.3 +# version:golang 1.24.4 # https://go.dev/dl/ -229c08b600b1446798109fae1f569228102c8473caba8104b6418cb5bc032878 go1.24.3.src.tar.gz -6f6901497547db3b77c14f7f953fbcef9fa5fb84199ee2ee14a5686e66bed5a6 go1.24.3.aix-ppc64.tar.gz -a05fa7e4043a4fec66897135219e3b8ab2202b5ef351c60c2fbb531dfb8f2900 go1.24.3.darwin-amd64.pkg -13e6fe3fcf65689d77d40e633de1e31c6febbdbcb846eb05fc2434ed2213e92b go1.24.3.darwin-amd64.tar.gz -97055ff4214043b39dc32e043fdd5c565df7c0a4e2fc0174e779a134c347ae0e go1.24.3.darwin-arm64.pkg -64a3fa22142f627e78fac3018ce3d4aeace68b743eff0afda8aae0411df5e4fb go1.24.3.darwin-arm64.tar.gz -32de3fd44d5055973978436a7f1f0ffbaae85c1b603ec6105e5c38d8a674c721 go1.24.3.dragonfly-amd64.tar.gz -9fe6101b3797919bd7337ee5ce591954f85d59db7ae88983904db29fd64c3dd1 go1.24.3.freebsd-386.tar.gz -6ccf4cca287e90cc28cd7954b6172f5d177a17e20b072b65f7f39636c325e2fb go1.24.3.freebsd-amd64.tar.gz -ce45ebf389066f82a7b056b66dd650efb51fde6f8bf92a2a3ab6990f02788ebf go1.24.3.freebsd-arm.tar.gz -8f6494a12a874d0ea57c67987829359e016960ce3ba0673273609d6ac2af589a go1.24.3.freebsd-arm64.tar.gz -f9db392560cf0851f0bc8f2190e1978e01b4603038c27fecfc8658a695b71616 go1.24.3.freebsd-riscv64.tar.gz -01717fff64c5d98457272002fa825d0a15e307bf6e189f2b0c23817fa033b61c go1.24.3.illumos-amd64.tar.gz -41b1051063e68cbd2b919bf12326764fe33937cf1d32b5c529dd1a4f43dce578 go1.24.3.linux-386.tar.gz -3333f6ea53afa971e9078895eaa4ac7204a8c6b5c68c10e6bc9a33e8e391bdd8 go1.24.3.linux-amd64.tar.gz -a463cb59382bd7ae7d8f4c68846e73c4d589f223c589ac76871b66811ded7836 go1.24.3.linux-arm64.tar.gz -17a392d7e826625dd12a32099df0b00b85c32d8132ed86fe917183ee5c3f88ed go1.24.3.linux-armv6l.tar.gz -e4b003c04c902edc140153d279b42167f1ad7c229f48f1f729bbef5e65e88d1f go1.24.3.linux-loong64.tar.gz -1c79d89edf835edf9d4336ccea7cb89bc5c0ca82b12b36b218d599a5400d60fe go1.24.3.linux-mips.tar.gz -0b64fe147d69f4d681d8e8a035c760477531432f83d831f18d37cb9bf3652488 go1.24.3.linux-mips64.tar.gz -396b784c255b64512dc00c302c053e43a3cbfc77518664c6ac5569aafad4d1e6 go1.24.3.linux-mips64le.tar.gz -93898313887f14e8efbe9d7386d5da4792b2d6c492bee562993fd4c9daa75c6d go1.24.3.linux-mipsle.tar.gz -873ae3a6a6655a7b6f820e095d9965507e8dfd3cf76bc92d75c564ecbca385f6 go1.24.3.linux-ppc64.tar.gz -341a749d168f47b1d4dad25e32cae70849b7ceed7c290823b853c9e6b0df0856 go1.24.3.linux-ppc64le.tar.gz -fa482f53ccb4ba280316b8c5751ea67291507280d9166f2a38fe4d9b5d5fb64b go1.24.3.linux-riscv64.tar.gz -a87b0c2a079a0bece1620fb29a00e02b4dba17507850f837e754af7d57cda282 go1.24.3.linux-s390x.tar.gz -63155382308db1306200aff7821aa26bf2a2dda23537dd637a9704b485b6ddf0 go1.24.3.netbsd-386.tar.gz -fe2c5c79482958b867c08a4fc2a10a998de9c0206b08d5b3ebcb2232e8d2777c go1.24.3.netbsd-amd64.tar.gz -e8ff77aef21521b5dd94e44282a3243309b80717414cf12f72835a45886a049f go1.24.3.netbsd-arm.tar.gz -b337fbaf82822685940ffaa76fbcf4be5d2f0258bc819cd80bc408b491f45c04 go1.24.3.netbsd-arm64.tar.gz -c1bb9dd8418480aa7f65452b08de3759da3bf89702be71b5a9fc084836b24ad5 go1.24.3.openbsd-386.tar.gz -531218de748b0caaf6d1ad18921206fc12baaa89bf483a0a5e60a571c206fe6f go1.24.3.openbsd-amd64.tar.gz -bcd0dc959986fc346969b5d4111c3c8031882d8bf8d87a2c2ecf1328962a91f2 go1.24.3.openbsd-arm.tar.gz -00ee6f8f1c41fd2e28ad386bd7e39acce7cab84af6de835855b29d1c597335c4 go1.24.3.openbsd-arm64.tar.gz -9f4ec0a9203ed3c54ce1a2a390ad3d45838cdb7efd85baeff857e37dfde04edd go1.24.3.openbsd-ppc64.tar.gz -da4d6f80e2373250d8c31c32dcd1e08775c327c0d610923604660cc0e07e8cba go1.24.3.openbsd-riscv64.tar.gz -f5d02149132eedda6c2d46b360d7da462b8a5f9e3f8567db100c2d7bff0ddcd7 go1.24.3.plan9-386.tar.gz -175f3d79f4762a3c545d2c6393bf6b8bac24e838026869dafab06b930735c94f go1.24.3.plan9-amd64.tar.gz -d1e4ac15095da1611659261c2228c2058756cf87d61d9fad262f76755ef26849 go1.24.3.plan9-arm.tar.gz -e644220a6ced3c07a7acc1364193cb709a97737dd8b6792a07a8ec6d9996713e go1.24.3.solaris-amd64.tar.gz -0d7e7dc0a31ba0cdd487415709d03b02fc9490ef111e8dfd22788a6d63316f37 go1.24.3.windows-386.msi -c27c463a61ab849266baa0c17a6c5c4256a574ab642f609ba25c96ec965dc184 go1.24.3.windows-386.zip -d5b7637e7e138be877d96a4501709d480e050d86a8f402bc950e72112b5aedc5 go1.24.3.windows-amd64.msi -be9787cb08998b1860fe3513e48a5fe5b96302d358a321b58e651184fa9638b3 go1.24.3.windows-amd64.zip -7efde2e5e8468e9caf2c7fc94f4da78a726a5031a1ed63acff7899527cdddff6 go1.24.3.windows-arm64.msi -eec9fa736056b54dd88ecb669db2bfad39b0c48f6f9080f036dfa1ca42dc4bb5 go1.24.3.windows-arm64.zip +5a86a83a31f9fa81490b8c5420ac384fd3d95a3e71fba665c7b3f95d1dfef2b4 go1.24.4.src.tar.gz +0d2af78e3b6e08f8013dbbdb26ae33052697b6b72e03ec17d496739c2a1aed68 go1.24.4.aix-ppc64.tar.gz +69bef555e114b4a2252452b6e7049afc31fbdf2d39790b669165e89525cd3f5c go1.24.4.darwin-amd64.tar.gz +c4d74453a26f488bdb4b0294da4840d9020806de4661785334eb6d1803ee5c27 go1.24.4.darwin-amd64.pkg +27973684b515eaf461065054e6b572d9390c05e69ba4a423076c160165336470 go1.24.4.darwin-arm64.tar.gz +2fe1f8746745c4bfebd494583aaef24cad42594f6d25ed67856879d567ee66e7 go1.24.4.darwin-arm64.pkg +70b2de9c1cafe5af7be3eb8f80753cce0501ef300db3f3bd59be7ccc464234e1 go1.24.4.dragonfly-amd64.tar.gz +8d529839db29ee171505b89dc9c3de76003a4ab56202d84bddbbecacbfb6d7c9 go1.24.4.freebsd-386.tar.gz +6cbc3ad6cc21bdcc7283824d3ac0e85512c02022f6a35eb2e844882ea6e8448c go1.24.4.freebsd-amd64.tar.gz +d49ae050c20aff646a7641dd903f03eb674570790b90ffb298076c4d41e36655 go1.24.4.freebsd-arm.tar.gz +e31924abef2a28456b7103c0a5d333dcc11ecf19e76d5de1a383ad5fe0b42457 go1.24.4.freebsd-arm64.tar.gz +b5bca135eae8ebddf22972611ac1c58ae9fbb5979fd953cc5245c5b1b2517546 go1.24.4.freebsd-riscv64.tar.gz +7d5efda511ff7e3114b130acee5d0bffbb078fedbfa9b2c1b6a807107e1ca23a go1.24.4.illumos-amd64.tar.gz +130c9b061082eca15513e595e9952a2ded32e737e609dd0e49f7dfa74eba026d go1.24.4.linux-386.tar.gz +77e5da33bb72aeaef1ba4418b6fe511bc4d041873cbf82e5aa6318740df98717 go1.24.4.linux-amd64.tar.gz +d5501ee5aca0f258d5fe9bfaed401958445014495dc115f202d43d5210b45241 go1.24.4.linux-arm64.tar.gz +6a554e32301cecae3162677e66d4264b81b3b1a89592dd1b7b5c552c7a49fe37 go1.24.4.linux-armv6l.tar.gz +b208eb25fe244408cbe269ed426454bc46e59d0e0a749b6240d39e884e969875 go1.24.4.linux-loong64.tar.gz +fddfcb28fd36fe63d2ae181026798f86f3bbd3a7bb0f1e1f617dd3d604bf3fe4 go1.24.4.linux-mips.tar.gz +7934b924d5ab8c8ae3134a09a6ae74d3c39f63f6c4322ec289364dbbf0bac3ca go1.24.4.linux-mips64.tar.gz +fa763d8673f94d6e534bb72c3cf675d4c2b8da4a6da42a89f08c5586106db39c go1.24.4.linux-mips64le.tar.gz +84363dbfe49b41d43df84420a09bd53a4770053d63bfa509868c46a5f8eb3ff7 go1.24.4.linux-mipsle.tar.gz +28fcbd5d3b56493606873c33f2b4bdd84ba93c633f37313613b5a1e6495c6fe5 go1.24.4.linux-ppc64.tar.gz +9ca4afef813a2578c23843b640ae0290aa54b2e3c950a6cc4c99e16a57dec2ec go1.24.4.linux-ppc64le.tar.gz +1d7034f98662d8f2c8abd7c700ada4093acb4f9c00e0e51a30344821d0785c77 go1.24.4.linux-riscv64.tar.gz +0449f3203c39703ab27684be763e9bb78ca9a051e0e4176727aead9461b6deb5 go1.24.4.linux-s390x.tar.gz +954b49ccc2cfcf4b5f7cd33ff662295e0d3b74e7590c8e25fc2abb30bce120ba go1.24.4.netbsd-386.tar.gz +370fabcdfee7c18857c96fdd5b706e025d4fb86a208da88ba56b1493b35498e9 go1.24.4.netbsd-amd64.tar.gz +7935ef95d4d1acc48587b1eb4acab98b0a7d9569736a32398b9c1d2e89026865 go1.24.4.netbsd-arm.tar.gz +ead78fd0fa29fbb176cc83f1caa54032e1a44f842affa56a682c647e0759f237 go1.24.4.netbsd-arm64.tar.gz +913e217394b851a636b99de175f0c2f9ab9938b41c557f047168f77ee485d776 go1.24.4.openbsd-386.tar.gz +24568da3dcbcdb24ec18b631f072faf0f3763e3d04f79032dc56ad9ec35379c4 go1.24.4.openbsd-amd64.tar.gz +45abf523f870632417ab007de3841f64dd906bde546ffc8c6380ccbe91c7fb73 go1.24.4.openbsd-arm.tar.gz +7c57c69b5dd1e946b28a3034c285240a48e2861bdcb50b7d9c0ed61bcf89c879 go1.24.4.openbsd-arm64.tar.gz +91ed711f704829372d6931e1897631ef40288b8f9e3cd6ef4a24df7126d1066a go1.24.4.openbsd-ppc64.tar.gz +de5e270d971c8790e8880168d56a2ea103979927c10ded136d792bbdf9bce3d3 go1.24.4.openbsd-riscv64.tar.gz +ff429d03f00bcd32a50f445320b8329d0fadb2a2fff899c11e95e0922a82c543 go1.24.4.plan9-386.tar.gz +39d6363a43fd16b60ae9ad7346a264e982e4fa653dee3b45f83e03cd2f7a6647 go1.24.4.plan9-amd64.tar.gz +1964ae2571259de77b930e97f2891aa92706ff81aac9909d45bb107b0fab16c8 go1.24.4.plan9-arm.tar.gz +a7f9af424e8fb87886664754badca459513f64f6a321d17f1d219b8edf519821 go1.24.4.solaris-amd64.tar.gz +d454d3cb144432f1726bf00e28c6017e78ccb256a8d01b8e3fb1b2e6b5650f28 go1.24.4.windows-386.zip +966ecace1cdbb3497a2b930bdb0f90c3ad32922fa1a7c655b2d4bbeb7e4ac308 go1.24.4.windows-386.msi +b751a1136cb9d8a2e7ebb22c538c4f02c09b98138c7c8bfb78a54a4566c013b1 go1.24.4.windows-amd64.zip +0cbb6e83865747dbe69b3d4155f92e88fcf336ff5d70182dba145e9d7bd3d8f6 go1.24.4.windows-amd64.msi +d17da51bc85bd010754a4063215d15d2c033cc289d67ca9201a03c9041b2969d go1.24.4.windows-arm64.zip +47dbe734b6a829de45654648a7abcf05bdceef5c80e03ea0b208eeebef75a852 go1.24.4.windows-arm64.msi # version:golangci 2.0.2 # https://github.com/golangci/golangci-lint/releases/ diff --git a/cmd/clef/README.md b/cmd/clef/README.md index d23e70a3d470..a92dcb1d77d7 100644 --- a/cmd/clef/README.md +++ b/cmd/clef/README.md @@ -150,7 +150,7 @@ All hex encoded values must be prefixed with `0x`. #### Create new password protected account -The signer will generate a new private key, encrypt it according to [web3 keystore spec](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) and store it in the keystore directory. +The signer will generate a new private key, encrypt it according to [web3 keystore spec](https://ethereum.org/en/developers/docs/data-structures-and-encoding/web3-secret-storage/) and store it in the keystore directory. The client is responsible for creating a backup of the keystore. If the keystore is lost there is no method of retrieving lost accounts. #### Arguments diff --git a/cmd/clef/extapi_changelog.md b/cmd/clef/extapi_changelog.md index 31554f079020..be84e88c521a 100644 --- a/cmd/clef/extapi_changelog.md +++ b/cmd/clef/extapi_changelog.md @@ -65,7 +65,7 @@ The API-method `account_signGnosisSafeTx` was added. This method takes two param ``` Not all fields are required, though. This method is really just a UX helper, which massages the -input to conform to the `EIP-712` [specification](https://docs.gnosis.io/safe/docs/contracts_tx_execution/#transaction-hash) +input to conform to the `EIP-712` [specification](https://docs.safe.global/core-api/transaction-service-reference/gnosis) for the Gnosis Safe, and making the output be directly importable to by a relay service. diff --git a/cmd/evm/eofparse.go b/cmd/evm/eofparse.go deleted file mode 100644 index 97107355768f..000000000000 --- a/cmd/evm/eofparse.go +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2024 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see . - -package main - -import ( - "bufio" - "encoding/hex" - "encoding/json" - "fmt" - "io/fs" - "os" - "path/filepath" - "strings" - - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli/v2" -) - -var jt vm.JumpTable - -const initcode = "INITCODE" - -func init() { - jt = vm.NewEOFInstructionSetForTesting() -} - -var ( - hexFlag = &cli.StringFlag{ - Name: "hex", - Usage: "Single container data parse and validation", - } - refTestFlag = &cli.StringFlag{ - Name: "test", - Usage: "Path to EOF validation reference test.", - } - eofParseCommand = &cli.Command{ - Name: "eofparse", - Aliases: []string{"eof"}, - Usage: "Parses hex eof container and returns validation errors (if any)", - Action: eofParseAction, - Flags: []cli.Flag{ - hexFlag, - refTestFlag, - }, - } - eofDumpCommand = &cli.Command{ - Name: "eofdump", - Usage: "Parses hex eof container and prints out human-readable representation of the container.", - Action: eofDumpAction, - Flags: []cli.Flag{ - hexFlag, - }, - } -) - -func eofParseAction(ctx *cli.Context) error { - // If `--test` is set, parse and validate the reference test at the provided path. - if ctx.IsSet(refTestFlag.Name) { - var ( - file = ctx.String(refTestFlag.Name) - executedTests int - passedTests int - ) - err := filepath.Walk(file, func(path string, info fs.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - log.Debug("Executing test", "name", info.Name()) - passed, tot, err := executeTest(path) - passedTests += passed - executedTests += tot - return err - }) - if err != nil { - return err - } - log.Info("Executed tests", "passed", passedTests, "total executed", executedTests) - return nil - } - // If `--hex` is set, parse and validate the hex string argument. - if ctx.IsSet(hexFlag.Name) { - if _, err := parseAndValidate(ctx.String(hexFlag.Name), false); err != nil { - return fmt.Errorf("err: %w", err) - } - fmt.Println("OK") - return nil - } - // If neither are passed in, read input from stdin. - scanner := bufio.NewScanner(os.Stdin) - scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024) - for scanner.Scan() { - l := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(l, "#") || l == "" { - continue - } - if _, err := parseAndValidate(l, false); err != nil { - fmt.Printf("err: %v\n", err) - } else { - fmt.Println("OK") - } - } - if err := scanner.Err(); err != nil { - fmt.Println(err.Error()) - } - return nil -} - -type refTests struct { - Vectors map[string]eOFTest `json:"vectors"` -} - -type eOFTest struct { - Code string `json:"code"` - Results map[string]etResult `json:"results"` - ContainerKind string `json:"containerKind"` -} - -type etResult struct { - Result bool `json:"result"` - Exception string `json:"exception,omitempty"` -} - -func executeTest(path string) (int, int, error) { - src, err := os.ReadFile(path) - if err != nil { - return 0, 0, err - } - var testsByName map[string]refTests - if err := json.Unmarshal(src, &testsByName); err != nil { - return 0, 0, err - } - passed, total := 0, 0 - for testsName, tests := range testsByName { - for name, tt := range tests.Vectors { - for fork, r := range tt.Results { - total++ - _, err := parseAndValidate(tt.Code, tt.ContainerKind == initcode) - if r.Result && err != nil { - log.Error("Test failure, expected validation success", "name", testsName, "idx", name, "fork", fork, "err", err) - continue - } - if !r.Result && err == nil { - log.Error("Test failure, expected validation error", "name", testsName, "idx", name, "fork", fork, "have err", r.Exception, "err", err) - continue - } - passed++ - } - } - } - return passed, total, nil -} - -func parseAndValidate(s string, isInitCode bool) (*vm.Container, error) { - if len(s) >= 2 && strings.HasPrefix(s, "0x") { - s = s[2:] - } - b, err := hex.DecodeString(s) - if err != nil { - return nil, fmt.Errorf("unable to decode data: %w", err) - } - return parse(b, isInitCode) -} - -func parse(b []byte, isInitCode bool) (*vm.Container, error) { - var c vm.Container - if err := c.UnmarshalBinary(b, isInitCode); err != nil { - return nil, err - } - if err := c.ValidateCode(&jt, isInitCode); err != nil { - return nil, err - } - return &c, nil -} - -func eofDumpAction(ctx *cli.Context) error { - // If `--hex` is set, parse and validate the hex string argument. - if ctx.IsSet(hexFlag.Name) { - return eofDump(ctx.String(hexFlag.Name)) - } - // Otherwise read from stdin - scanner := bufio.NewScanner(os.Stdin) - scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024) - for scanner.Scan() { - l := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(l, "#") || l == "" { - continue - } - if err := eofDump(l); err != nil { - return err - } - fmt.Println("") - } - return scanner.Err() -} - -func eofDump(hexdata string) error { - if len(hexdata) >= 2 && strings.HasPrefix(hexdata, "0x") { - hexdata = hexdata[2:] - } - b, err := hex.DecodeString(hexdata) - if err != nil { - return fmt.Errorf("unable to decode data: %w", err) - } - var c vm.Container - if err := c.UnmarshalBinary(b, false); err != nil { - return err - } - fmt.Println(c.String()) - return nil -} diff --git a/cmd/evm/eofparse_test.go b/cmd/evm/eofparse_test.go deleted file mode 100644 index a9119916a5fb..000000000000 --- a/cmd/evm/eofparse_test.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2024 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see . - -package main - -import ( - "bufio" - "bytes" - "encoding/hex" - "fmt" - "os" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" -) - -func FuzzEofParsing(f *testing.F) { - // Seed with corpus from execution-spec-tests - for i := 0; ; i++ { - fname := fmt.Sprintf("testdata/eof/eof_corpus_%d.txt", i) - corpus, err := os.Open(fname) - if err != nil { - break - } - f.Logf("Reading seed data from %v", fname) - scanner := bufio.NewScanner(corpus) - scanner.Buffer(make([]byte, 1024), 10*1024*1024) - for scanner.Scan() { - s := scanner.Text() - if len(s) >= 2 && strings.HasPrefix(s, "0x") { - s = s[2:] - } - b, err := hex.DecodeString(s) - if err != nil { - panic(err) // rotten corpus - } - f.Add(b) - } - corpus.Close() - if err := scanner.Err(); err != nil { - panic(err) // rotten corpus - } - } - // And do the fuzzing - f.Fuzz(func(t *testing.T, data []byte) { - var ( - jt = vm.NewEOFInstructionSetForTesting() - c vm.Container - ) - cpy := common.CopyBytes(data) - if err := c.UnmarshalBinary(data, true); err == nil { - c.ValidateCode(&jt, true) - if have := c.MarshalBinary(); !bytes.Equal(have, data) { - t.Fatal("Unmarshal-> Marshal failure!") - } - } - if err := c.UnmarshalBinary(data, false); err == nil { - c.ValidateCode(&jt, false) - if have := c.MarshalBinary(); !bytes.Equal(have, data) { - t.Fatal("Unmarshal-> Marshal failure!") - } - } - if !bytes.Equal(cpy, data) { - panic("data modified during unmarshalling") - } - }) -} - -func TestEofParseInitcode(t *testing.T) { - testEofParse(t, true, "testdata/eof/results.initcode.txt") -} - -func TestEofParseRegular(t *testing.T) { - testEofParse(t, false, "testdata/eof/results.regular.txt") -} - -func testEofParse(t *testing.T, isInitCode bool, wantFile string) { - var wantFn func() string - var wantLoc = 0 - { // Configure the want-reader - wants, err := os.Open(wantFile) - if err != nil { - t.Fatal(err) - } - scanner := bufio.NewScanner(wants) - scanner.Buffer(make([]byte, 1024), 10*1024*1024) - wantFn = func() string { - if scanner.Scan() { - wantLoc++ - return scanner.Text() - } - return "end of file reached" - } - } - - for i := 0; ; i++ { - fname := fmt.Sprintf("testdata/eof/eof_corpus_%d.txt", i) - corpus, err := os.Open(fname) - if err != nil { - break - } - t.Logf("# Reading seed data from %v", fname) - scanner := bufio.NewScanner(corpus) - scanner.Buffer(make([]byte, 1024), 10*1024*1024) - line := 1 - for scanner.Scan() { - s := scanner.Text() - if len(s) >= 2 && strings.HasPrefix(s, "0x") { - s = s[2:] - } - b, err := hex.DecodeString(s) - if err != nil { - panic(err) // rotten corpus - } - have := "OK" - if _, err := parse(b, isInitCode); err != nil { - have = fmt.Sprintf("ERR: %v", err) - } - if false { // Change this to generate the want-output - fmt.Printf("%v\n", have) - } else { - want := wantFn() - if have != want { - if len(want) > 100 { - want = want[:100] - } - if len(b) > 100 { - b = b[:100] - } - t.Errorf("%v:%d\n%v\ninput %x\nisInit: %v\nhave: %q\nwant: %q\n", - fname, line, fmt.Sprintf("%v:%d", wantFile, wantLoc), b, isInitCode, have, want) - } - } - line++ - } - corpus.Close() - } -} - -func BenchmarkEofParse(b *testing.B) { - corpus, err := os.Open("testdata/eof/eof_benches.txt") - if err != nil { - b.Fatal(err) - } - defer corpus.Close() - scanner := bufio.NewScanner(corpus) - scanner.Buffer(make([]byte, 1024), 10*1024*1024) - line := 1 - for scanner.Scan() { - s := scanner.Text() - if len(s) >= 2 && strings.HasPrefix(s, "0x") { - s = s[2:] - } - data, err := hex.DecodeString(s) - if err != nil { - b.Fatal(err) // rotten corpus - } - b.Run(fmt.Sprintf("test-%d", line), func(b *testing.B) { - b.ReportAllocs() - b.SetBytes(int64(len(data))) - for i := 0; i < b.N; i++ { - _, _ = parse(data, false) - } - }) - line++ - } -} diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index b2e5f7071454..da1fb3701f90 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -303,7 +303,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, } // Set the receipt logs and create the bloom filter. - receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash) + receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash, vmContext.Time) receipt.Bloom = types.CreateBloom(receipt) // These three are non-consensus fields: diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 2bc4f73b606b..0f39df0753a9 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -183,6 +183,9 @@ func Transaction(ctx *cli.Context) error { if chainConfig.IsShanghai(new(big.Int), 0) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { r.Error = errors.New("max initcode size exceeded") } + if chainConfig.IsOsaka(new(big.Int), 0) && tx.Gas() > params.MaxTxGas { + r.Error = errors.New("gas limit exceeds maximum") + } results = append(results, r) } out, err := json.MarshalIndent(results, "", " ") diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 61e46aa50e1e..bf5be9a35924 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -210,8 +210,6 @@ func init() { stateTransitionCommand, transactionCommand, blockBuilderCommand, - eofParseCommand, - eofDumpCommand, } app.Before = func(ctx *cli.Context) error { flags.MigrateGlobalFlags(ctx) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index e0606f0d0bc9..acd7b5c23000 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -58,7 +58,7 @@ var ( ArgsUsage: "", Flags: slices.Concat([]cli.Flag{ utils.CachePreimagesFlag, - utils.OverridePrague, + utils.OverrideOsaka, utils.OverrideVerkle, }, utils.DatabaseFlags), Description: ` @@ -269,9 +269,9 @@ func initGenesis(ctx *cli.Context) error { defer stack.Close() var overrides core.ChainOverrides - if ctx.IsSet(utils.OverridePrague.Name) { - v := ctx.Uint64(utils.OverridePrague.Name) - overrides.OverridePrague = &v + if ctx.IsSet(utils.OverrideOsaka.Name) { + v := ctx.Uint64(utils.OverrideOsaka.Name) + overrides.OverrideOsaka = &v } if ctx.IsSet(utils.OverrideVerkle.Name) { v := ctx.Uint64(utils.OverrideVerkle.Name) @@ -765,15 +765,8 @@ func downloadEra(ctx *cli.Context) error { } func parseRange(s string) (start uint64, end uint64, ok bool) { - if m, _ := regexp.MatchString("[0-9]+", s); m { - start, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return 0, 0, false - } - end = start - return start, end, true - } - if m, _ := regexp.MatchString("[0-9]+-[0-9]+", s); m { + log.Info("Parsing block range", "input", s) + if m, _ := regexp.MatchString("^[0-9]+-[0-9]+$", s); m { s1, s2, _ := strings.Cut(s, "-") start, err := strconv.ParseUint(s1, 10, 64) if err != nil { @@ -783,6 +776,19 @@ func parseRange(s string) (start uint64, end uint64, ok bool) { if err != nil { return 0, 0, false } + if start > end { + return 0, 0, false + } + log.Info("Parsing block range", "start", start, "end", end) + return start, end, true + } + if m, _ := regexp.MatchString("^[0-9]+$", s); m { + start, err := strconv.ParseUint(s, 10, 64) + if err != nil { + return 0, 0, false + } + end = start + log.Info("Parsing single block range", "block", start) return start, end, true } return 0, 0, false diff --git a/cmd/geth/chaincmd_test.go b/cmd/geth/chaincmd_test.go new file mode 100644 index 000000000000..131f5c45017b --- /dev/null +++ b/cmd/geth/chaincmd_test.go @@ -0,0 +1,98 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . + +package main + +import "testing" + +func TestParseRange(t *testing.T) { + var cases = []struct { + input string + valid bool + expStart uint64 + expEnd uint64 + }{ + { + input: "0", + valid: true, + expStart: 0, + expEnd: 0, + }, + { + input: "500", + valid: true, + expStart: 500, + expEnd: 500, + }, + { + input: "-1", + valid: false, + expStart: 0, + expEnd: 0, + }, + { + input: "1-1", + valid: true, + expStart: 1, + expEnd: 1, + }, + { + input: "0-1", + valid: true, + expStart: 0, + expEnd: 1, + }, + { + input: "1-0", + valid: false, + expStart: 0, + expEnd: 0, + }, + { + input: "1-1000", + valid: true, + expStart: 1, + expEnd: 1000, + }, + { + input: "1-1-", + valid: false, + expStart: 0, + expEnd: 0, + }, + { + input: "-1-1", + valid: false, + expStart: 0, + expEnd: 0, + }, + } + for _, c := range cases { + start, end, valid := parseRange(c.input) + if valid != c.valid { + t.Errorf("Unexpected result, want: %t, got: %t", c.valid, valid) + continue + } + if valid { + if c.expStart != start { + t.Errorf("Unexpected start, want: %d, got: %d", c.expStart, start) + } + if c.expEnd != end { + t.Errorf("Unexpected end, want: %d, got: %d", c.expEnd, end) + } + } + } +} diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 3eb2b6dd37fe..d7c354ff9f23 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -223,9 +223,9 @@ func constructDevModeBanner(ctx *cli.Context, cfg gethConfig) string { // makeFullNode loads geth configuration and creates the Ethereum backend. func makeFullNode(ctx *cli.Context) *node.Node { stack, cfg := makeConfigNode(ctx) - if ctx.IsSet(utils.OverridePrague.Name) { - v := ctx.Uint64(utils.OverridePrague.Name) - cfg.Eth.OverridePrague = &v + if ctx.IsSet(utils.OverrideOsaka.Name) { + v := ctx.Uint64(utils.OverrideOsaka.Name) + cfg.Eth.OverrideOsaka = &v } if ctx.IsSet(utils.OverrideVerkle.Name) { v := ctx.Uint64(utils.OverrideVerkle.Name) @@ -268,7 +268,7 @@ func makeFullNode(ctx *cli.Context) *node.Node { if len(hex) != common.HashLength { utils.Fatalf("invalid sync target length: have %d, want %d", len(hex), common.HashLength) } - utils.RegisterFullSyncTester(stack, eth, common.BytesToHash(hex)) + utils.RegisterFullSyncTester(stack, eth, common.BytesToHash(hex), ctx.Bool(utils.ExitWhenSyncedFlag.Name)) } if ctx.IsSet(utils.DeveloperFlag.Name) { diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 289af9082836..2da5c4321613 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -62,7 +62,7 @@ var ( utils.NoUSBFlag, // deprecated utils.USBFlag, utils.SmartCardDaemonPathFlag, - utils.OverridePrague, + utils.OverrideOsaka, utils.OverrideVerkle, utils.EnablePersonal, // deprecated utils.TxPoolLocalsFlag, diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index f0be52a0dffb..aa9ae7087f8c 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -220,22 +220,10 @@ func verifyState(ctx *cli.Context) error { triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) defer triedb.Close() - snapConfig := snapshot.Config{ - CacheSize: 256, - Recovery: false, - NoBuild: true, - AsyncBuild: false, - } - snaptree, err := snapshot.New(snapConfig, chaindb, triedb, headBlock.Root()) - if err != nil { - log.Error("Failed to open snapshot tree", "err", err) - return err - } - if ctx.NArg() > 1 { - log.Error("Too many arguments given") - return errors.New("too many arguments") - } - var root = headBlock.Root() + var ( + err error + root = headBlock.Root() + ) if ctx.NArg() == 1 { root, err = parseRoot(ctx.Args().First()) if err != nil { @@ -243,12 +231,34 @@ func verifyState(ctx *cli.Context) error { return err } } - if err := snaptree.Verify(root); err != nil { - log.Error("Failed to verify state", "root", root, "err", err) - return err + if triedb.Scheme() == rawdb.PathScheme { + if err := triedb.VerifyState(root); err != nil { + log.Error("Failed to verify state", "root", root, "err", err) + return err + } + log.Info("Verified the state", "root", root) + + // TODO(rjl493456442) implement dangling checks in pathdb. + return nil + } else { + snapConfig := snapshot.Config{ + CacheSize: 256, + Recovery: false, + NoBuild: true, + AsyncBuild: false, + } + snaptree, err := snapshot.New(snapConfig, chaindb, triedb, headBlock.Root()) + if err != nil { + log.Error("Failed to open snapshot tree", "err", err) + return err + } + if err := snaptree.Verify(root); err != nil { + log.Error("Failed to verify state", "root", root, "err", err) + return err + } + log.Info("Verified the state", "root", root) + return snapshot.CheckDanglingStorage(chaindb) } - log.Info("Verified the state", "root", root) - return snapshot.CheckDanglingStorage(chaindb) } // checkDanglingStorage iterates the snap storage data, and verifies that all diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index eadc6e8b2d31..d3e842149aa7 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -243,9 +243,9 @@ var ( Value: 2048, Category: flags.EthCategory, } - OverridePrague = &cli.Uint64Flag{ - Name: "override.prague", - Usage: "Manually specify the Prague fork timestamp, overriding the bundled setting", + OverrideOsaka = &cli.Uint64Flag{ + Name: "override.osaka", + Usage: "Manually specify the Osaka fork timestamp, overriding the bundled setting", Category: flags.EthCategory, } OverrideVerkle = &cli.Uint64Flag{ @@ -261,7 +261,7 @@ var ( } GCModeFlag = &cli.StringFlag{ Name: "gcmode", - Usage: `Blockchain garbage collection mode, only relevant in state.scheme=hash ("full", "archive")`, + Usage: `Blockchain garbage collection mode ("full", "archive")`, Value: "full", Category: flags.StateCategory, } @@ -1379,13 +1379,13 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name) } if ctx.IsSet(NoUSBFlag.Name) || cfg.NoUSB { - log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable") + log.Warn("Option --nousb is deprecated and USB is deactivated by default. Use --usb to enable") } if ctx.IsSet(USBFlag.Name) { cfg.USB = ctx.Bool(USBFlag.Name) } if ctx.IsSet(InsecureUnlockAllowedFlag.Name) { - log.Warn(fmt.Sprintf("Option %q is deprecated and has no effect", InsecureUnlockAllowedFlag.Name)) + log.Warn(fmt.Sprintf("Option --%s is deprecated and has no effect", InsecureUnlockAllowedFlag.Name)) } if ctx.IsSet(DBEngineFlag.Name) { dbEngine := ctx.String(DBEngineFlag.Name) @@ -1397,10 +1397,10 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { } // 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") + log.Warn("Option --log.backtrace flag is deprecated") } if ctx.IsSet(LogDebugFlag.Name) { - log.Warn("log.debug flag is deprecated") + log.Warn("Option --log.debug flag is deprecated") } } @@ -1661,11 +1661,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { cfg.TransactionHistory = 0 log.Warn("Disabled transaction unindexing for archive node") } - - if cfg.StateScheme != rawdb.HashScheme { - cfg.StateScheme = rawdb.HashScheme - log.Warn("Forcing hash state-scheme for archive mode") - } } if ctx.IsSet(LogHistoryFlag.Name) { cfg.LogHistory = ctx.Uint64(LogHistoryFlag.Name) @@ -1864,7 +1859,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig { var config bparams.ClientConfig customConfig := ctx.IsSet(BeaconConfigFlag.Name) - flags.CheckExclusive(ctx, MainnetFlag, SepoliaFlag, HoleskyFlag, BeaconConfigFlag) + flags.CheckExclusive(ctx, MainnetFlag, SepoliaFlag, HoleskyFlag, HoodiFlag, BeaconConfigFlag) switch { case ctx.Bool(MainnetFlag.Name): config.ChainConfig = *bparams.MainnetLightConfig @@ -1896,11 +1891,11 @@ func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig { if c, err := hexutil.Decode(ctx.String(BeaconGenesisRootFlag.Name)); err == nil && len(c) <= 32 { copy(config.GenesisValidatorsRoot[:len(c)], c) } else { - Fatalf("Invalid hex string", "beacon.genesis.gvroot", ctx.String(BeaconGenesisRootFlag.Name), "error", err) + Fatalf("Could not parse --%s: %v", BeaconGenesisRootFlag.Name, err) } configFile := ctx.String(BeaconConfigFlag.Name) if err := config.ChainConfig.LoadForks(configFile); err != nil { - Fatalf("Could not load beacon chain config", "file", configFile, "error", err) + Fatalf("Could not load beacon chain config '%s': %v", configFile, err) } log.Info("Using custom beacon chain config", "file", configFile) } else { @@ -1917,17 +1912,17 @@ func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig { // are saved to the specified file. if ctx.IsSet(BeaconCheckpointFileFlag.Name) { if _, err := config.SetCheckpointFile(ctx.String(BeaconCheckpointFileFlag.Name)); err != nil { - Fatalf("Could not load beacon checkpoint file", "beacon.checkpoint.file", ctx.String(BeaconCheckpointFileFlag.Name), "error", err) + Fatalf("Could not load beacon checkpoint file '%s': %v", ctx.String(BeaconCheckpointFileFlag.Name), err) } } if ctx.IsSet(BeaconCheckpointFlag.Name) { hex := ctx.String(BeaconCheckpointFlag.Name) c, err := hexutil.Decode(hex) if err != nil { - Fatalf("Invalid hex string", "beacon.checkpoint", hex, "error", err) + Fatalf("Could not parse --%s: %v", BeaconCheckpointFlag.Name, err) } if len(c) != 32 { - Fatalf("Invalid hex string length", "beacon.checkpoint", hex, "length", len(c)) + Fatalf("Could not parse --%s: invalid length %d, want 32", BeaconCheckpointFlag.Name, len(c)) } copy(config.Checkpoint[:len(c)], c) } @@ -2003,9 +1998,9 @@ func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconf } // RegisterFullSyncTester adds the full-sync tester service into node. -func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, target common.Hash) { - catalyst.RegisterFullSyncTester(stack, eth, target) - log.Info("Registered full-sync tester", "hash", target) +func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, target common.Hash, exitWhenSynced bool) { + catalyst.RegisterFullSyncTester(stack, eth, target, exitWhenSynced) + log.Info("Registered full-sync tester", "hash", target, "exitWhenSynced", exitWhenSynced) } // SetupMetrics configures the metrics system. @@ -2191,36 +2186,38 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh if err != nil { Fatalf("%v", err) } - cache := &core.CacheConfig{ - TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, - TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), - TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, - TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive", - TrieTimeLimit: ethconfig.Defaults.TrieTimeout, - SnapshotLimit: ethconfig.Defaults.SnapshotCache, - Preimages: ctx.Bool(CachePreimagesFlag.Name), - StateScheme: scheme, - StateHistory: ctx.Uint64(StateHistoryFlag.Name), - } - if cache.TrieDirtyDisabled && !cache.Preimages { - cache.Preimages = true + options := &core.BlockChainConfig{ + TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, + NoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), + TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, + ArchiveMode: ctx.String(GCModeFlag.Name) == "archive", + TrieTimeLimit: ethconfig.Defaults.TrieTimeout, + SnapshotLimit: ethconfig.Defaults.SnapshotCache, + Preimages: ctx.Bool(CachePreimagesFlag.Name), + StateScheme: scheme, + StateHistory: ctx.Uint64(StateHistoryFlag.Name), + // Disable transaction indexing/unindexing. + TxLookupLimit: -1, + } + if options.ArchiveMode && !options.Preimages { + options.Preimages = true log.Info("Enabling recording of key preimages since archive mode is used") } if !ctx.Bool(SnapshotFlag.Name) { - cache.SnapshotLimit = 0 // Disabled + options.SnapshotLimit = 0 // Disabled } else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) { - cache.SnapshotLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100 + options.SnapshotLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100 } // If we're in readonly, do not bother generating snapshot data. if readonly { - cache.SnapshotNoBuild = true + options.SnapshotNoBuild = true } if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { - cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 + options.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 } if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { - cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 + options.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 } vmcfg := vm.Config{ EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name), @@ -2235,8 +2232,9 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh vmcfg.Tracer = t } } - // Disable transaction indexing/unindexing by default. - chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil) + options.VmConfig = vmcfg + + chain, err := core.NewBlockChain(chainDb, gspec, engine, options) if err != nil { Fatalf("Can't create BlockChain: %v", err) } diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go index dc41a75d1191..239be03ad607 100644 --- a/cmd/utils/flags_legacy.go +++ b/cmd/utils/flags_legacy.go @@ -44,40 +44,50 @@ var DeprecatedFlags = []cli.Flag{ MinerNewPayloadTimeoutFlag, MinerEtherbaseFlag, MiningEnabledFlag, + MetricsEnabledExpensiveFlag, + EnablePersonal, + UnlockedAccountFlag, + InsecureUnlockAllowedFlag, } var ( // Deprecated May 2020, shown in aliased flags section NoUSBFlag = &cli.BoolFlag{ Name: "nousb", + Hidden: true, Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)", Category: flags.DeprecatedCategory, } // Deprecated March 2022 LegacyWhitelistFlag = &cli.StringFlag{ Name: "whitelist", + Hidden: true, Usage: "Comma separated block number-to-hash mappings to enforce (=) (deprecated in favor of --eth.requiredblocks)", Category: flags.DeprecatedCategory, } // Deprecated July 2023 CacheTrieJournalFlag = &cli.StringFlag{ Name: "cache.trie.journal", + Hidden: true, Usage: "Disk journal directory for trie cache to survive node restarts", Category: flags.DeprecatedCategory, } CacheTrieRejournalFlag = &cli.DurationFlag{ Name: "cache.trie.rejournal", + Hidden: true, Usage: "Time interval to regenerate the trie cache journal", Category: flags.DeprecatedCategory, } LegacyDiscoveryV5Flag = &cli.BoolFlag{ Name: "v5disc", + Hidden: true, Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism (deprecated, use --discv5 instead)", Category: flags.DeprecatedCategory, } // Deprecated August 2023 TxLookupLimitFlag = &cli.Uint64Flag{ Name: "txlookuplimit", + Hidden: true, Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain) (deprecated, use history.transactions instead)", Value: ethconfig.Defaults.TransactionHistory, Category: flags.DeprecatedCategory, @@ -85,51 +95,60 @@ var ( // Deprecated November 2023 LogBacktraceAtFlag = &cli.StringFlag{ Name: "log.backtrace", + Hidden: true, Usage: "Request a stack trace at a specific logging statement (deprecated)", Value: "", Category: flags.DeprecatedCategory, } LogDebugFlag = &cli.BoolFlag{ Name: "log.debug", + Hidden: true, Usage: "Prepends log messages with call-site location (deprecated)", Category: flags.DeprecatedCategory, } // Deprecated February 2024 MinerNewPayloadTimeoutFlag = &cli.DurationFlag{ Name: "miner.newpayload-timeout", + Hidden: true, Usage: "Specify the maximum time allowance for creating a new payload (deprecated)", Value: ethconfig.Defaults.Miner.Recommit, Category: flags.DeprecatedCategory, } MinerEtherbaseFlag = &cli.StringFlag{ Name: "miner.etherbase", + Hidden: true, Usage: "0x prefixed public address for block mining rewards (deprecated)", Category: flags.DeprecatedCategory, } MiningEnabledFlag = &cli.BoolFlag{ Name: "mine", + Hidden: true, Usage: "Enable mining (deprecated)", Category: flags.DeprecatedCategory, } MetricsEnabledExpensiveFlag = &cli.BoolFlag{ Name: "metrics.expensive", + Hidden: true, Usage: "Enable expensive metrics collection and reporting (deprecated)", Category: flags.DeprecatedCategory, } // Deprecated Oct 2024 EnablePersonal = &cli.BoolFlag{ Name: "rpc.enabledeprecatedpersonal", + Hidden: true, Usage: "This used to enable the 'personal' namespace.", Category: flags.DeprecatedCategory, } UnlockedAccountFlag = &cli.StringFlag{ Name: "unlock", + Hidden: true, Usage: "Comma separated list of accounts to unlock (deprecated)", Value: "", Category: flags.DeprecatedCategory, } InsecureUnlockAllowedFlag = &cli.BoolFlag{ Name: "allow-insecure-unlock", + Hidden: true, Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http (deprecated)", Category: flags.DeprecatedCategory, } diff --git a/cmd/utils/history_test.go b/cmd/utils/history_test.go index be51803f8c1f..994756eda5f9 100644 --- a/cmd/utils/history_test.go +++ b/cmd/utils/history_test.go @@ -31,7 +31,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/internal/era" "github.com/ethereum/go-ethereum/params" @@ -78,7 +77,7 @@ func TestHistoryImportAndExport(t *testing.T) { }) // Initialize BlockChain. - chain, err := core.NewBlockChain(db, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil) + chain, err := core.NewBlockChain(db, genesis, ethash.NewFaker(), nil) if err != nil { t.Fatalf("unable to initialize chain: %v", err) } @@ -167,7 +166,7 @@ func TestHistoryImportAndExport(t *testing.T) { }) genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults)) - imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil) + imported, err := core.NewBlockChain(db2, genesis, ethash.NewFaker(), nil) if err != nil { t.Fatalf("unable to initialize chain: %v", err) } diff --git a/cmd/workload/README.md b/cmd/workload/README.md index c85e58a0410c..1b84dd05db94 100644 --- a/cmd/workload/README.md +++ b/cmd/workload/README.md @@ -17,6 +17,13 @@ and `eth_getBlockByNumber`, use this command: > ./workload test --sepolia --run History/getBlockBy http://host:8545 ``` +Notably, trace tests require archive which keeps all the historical states for tracing. +The additional flag is required to activate the trace tests. + +``` +> ./workload test --sepolia --archive --run Trace/Block http://host:8545 +``` + ### Regenerating tests There is a facility for updating the tests from the chain. This can also be used to @@ -26,4 +33,5 @@ the following commands (in this directory) against a synced mainnet node: ```shell > go run . filtergen --queries queries/filter_queries_mainnet.json http://host:8545 > go run . historygen --history-tests queries/history_mainnet.json http://host:8545 +> go run . tracegen --trace-tests queries/trace_mainnet.json --trace-start 4000000 --trace-end 4000100 http://host:8545 ``` diff --git a/cmd/workload/client.go b/cmd/workload/client.go new file mode 100644 index 000000000000..5a6a005ced0b --- /dev/null +++ b/cmd/workload/client.go @@ -0,0 +1,104 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . + +package main + +import ( + "context" + "fmt" + + "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/ethclient" + "github.com/ethereum/go-ethereum/ethclient/gethclient" + "github.com/ethereum/go-ethereum/rpc" + "github.com/urfave/cli/v2" +) + +type client struct { + Eth *ethclient.Client + Geth *gethclient.Client + RPC *rpc.Client +} + +func makeClient(ctx *cli.Context) *client { + if ctx.NArg() < 1 { + exit("missing RPC endpoint URL as command-line argument") + } + url := ctx.Args().First() + cl, err := rpc.Dial(url) + if err != nil { + exit(fmt.Errorf("could not create RPC client at %s: %v", url, err)) + } + return &client{ + RPC: cl, + Eth: ethclient.NewClient(cl), + Geth: gethclient.New(cl), + } +} + +type simpleBlock struct { + Number hexutil.Uint64 `json:"number"` + Hash common.Hash `json:"hash"` +} + +type simpleTransaction struct { + Hash common.Hash `json:"hash"` + TransactionIndex hexutil.Uint64 `json:"transactionIndex"` +} + +func (c *client) getBlockByHash(ctx context.Context, arg common.Hash, fullTx bool) (*simpleBlock, error) { + var r *simpleBlock + err := c.RPC.CallContext(ctx, &r, "eth_getBlockByHash", arg, fullTx) + return r, err +} + +func (c *client) getBlockByNumber(ctx context.Context, arg uint64, fullTx bool) (*simpleBlock, error) { + var r *simpleBlock + err := c.RPC.CallContext(ctx, &r, "eth_getBlockByNumber", hexutil.Uint64(arg), fullTx) + return r, err +} + +func (c *client) getTransactionByBlockHashAndIndex(ctx context.Context, block common.Hash, index uint64) (*simpleTransaction, error) { + var r *simpleTransaction + err := c.RPC.CallContext(ctx, &r, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)) + return r, err +} + +func (c *client) getTransactionByBlockNumberAndIndex(ctx context.Context, block uint64, index uint64) (*simpleTransaction, error) { + var r *simpleTransaction + err := c.RPC.CallContext(ctx, &r, "eth_getTransactionByBlockNumberAndIndex", hexutil.Uint64(block), hexutil.Uint64(index)) + return r, err +} + +func (c *client) getBlockTransactionCountByHash(ctx context.Context, block common.Hash) (uint64, error) { + var r hexutil.Uint64 + err := c.RPC.CallContext(ctx, &r, "eth_getBlockTransactionCountByHash", block) + return uint64(r), err +} + +func (c *client) getBlockTransactionCountByNumber(ctx context.Context, block uint64) (uint64, error) { + var r hexutil.Uint64 + err := c.RPC.CallContext(ctx, &r, "eth_getBlockTransactionCountByNumber", hexutil.Uint64(block)) + return uint64(r), err +} + +func (c *client) getBlockReceipts(ctx context.Context, arg any) ([]*types.Receipt, error) { + var result []*types.Receipt + err := c.RPC.CallContext(ctx, &result, "eth_getBlockReceipts", arg) + return result, err +} diff --git a/cmd/workload/filtertest.go b/cmd/workload/filtertest.go index 52dd6e41ad34..11062122b899 100644 --- a/cmd/workload/filtertest.go +++ b/cmd/workload/filtertest.go @@ -21,6 +21,7 @@ import ( "encoding/json" "fmt" "math/big" + "os" "time" "github.com/ethereum/go-ethereum" @@ -45,11 +46,11 @@ func newFilterTestSuite(cfg testConfig) *filterTestSuite { return s } -func (s *filterTestSuite) allTests() []utesting.Test { - return []utesting.Test{ - {Name: "Filter/ShortRange", Fn: s.filterShortRange}, - {Name: "Filter/LongRange", Fn: s.filterLongRange, Slow: true}, - {Name: "Filter/FullRange", Fn: s.filterFullRange, Slow: true}, +func (s *filterTestSuite) allTests() []workloadTest { + return []workloadTest{ + newWorkLoadTest("Filter/ShortRange", s.filterShortRange), + newSlowWorkloadTest("Filter/LongRange", s.filterLongRange), + newSlowWorkloadTest("Filter/FullRange", s.filterFullRange), } } @@ -153,7 +154,14 @@ func (s *filterTestSuite) fullRangeQueryAndCheck(t *utesting.T, query *filterQue func (s *filterTestSuite) loadQueries() error { file, err := s.cfg.fsys.Open(s.cfg.filterQueryFile) if err != nil { - return fmt.Errorf("can't open filterQueryFile: %v", err) + // If not found in embedded FS, try to load it from disk + if !os.IsNotExist(err) { + return err + } + file, err = os.OpenFile(s.cfg.filterQueryFile, os.O_RDONLY, 0666) + if err != nil { + return fmt.Errorf("can't open filterQueryFile: %v", err) + } } defer file.Close() diff --git a/cmd/workload/historytest.go b/cmd/workload/historytest.go index 29fe3f5098ad..5d6115c0bbde 100644 --- a/cmd/workload/historytest.go +++ b/cmd/workload/historytest.go @@ -20,10 +20,10 @@ import ( "context" "encoding/json" "fmt" + "os" "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/internal/utesting" ) @@ -53,7 +53,14 @@ func newHistoryTestSuite(cfg testConfig) *historyTestSuite { func (s *historyTestSuite) loadTests() error { file, err := s.cfg.fsys.Open(s.cfg.historyTestFile) if err != nil { - return fmt.Errorf("can't open historyTestFile: %v", err) + // If not found in embedded FS, try to load it from disk + if !os.IsNotExist(err) { + return err + } + file, err = os.OpenFile(s.cfg.historyTestFile, os.O_RDONLY, 0666) + if err != nil { + return fmt.Errorf("can't open historyTestFile: %v", err) + } } defer file.Close() if err := json.NewDecoder(file).Decode(&s.tests); err != nil { @@ -65,40 +72,16 @@ func (s *historyTestSuite) loadTests() error { return nil } -func (s *historyTestSuite) allTests() []utesting.Test { - return []utesting.Test{ - { - Name: "History/getBlockByHash", - Fn: s.testGetBlockByHash, - }, - { - Name: "History/getBlockByNumber", - Fn: s.testGetBlockByNumber, - }, - { - Name: "History/getBlockReceiptsByHash", - Fn: s.testGetBlockReceiptsByHash, - }, - { - Name: "History/getBlockReceiptsByNumber", - Fn: s.testGetBlockReceiptsByNumber, - }, - { - Name: "History/getBlockTransactionCountByHash", - Fn: s.testGetBlockTransactionCountByHash, - }, - { - Name: "History/getBlockTransactionCountByNumber", - Fn: s.testGetBlockTransactionCountByNumber, - }, - { - Name: "History/getTransactionByBlockHashAndIndex", - Fn: s.testGetTransactionByBlockHashAndIndex, - }, - { - Name: "History/getTransactionByBlockNumberAndIndex", - Fn: s.testGetTransactionByBlockNumberAndIndex, - }, +func (s *historyTestSuite) allTests() []workloadTest { + return []workloadTest{ + newWorkLoadTest("History/getBlockByHash", s.testGetBlockByHash), + newWorkLoadTest("History/getBlockByNumber", s.testGetBlockByNumber), + newWorkLoadTest("History/getBlockReceiptsByHash", s.testGetBlockReceiptsByHash), + newWorkLoadTest("History/getBlockReceiptsByNumber", s.testGetBlockReceiptsByNumber), + newWorkLoadTest("History/getBlockTransactionCountByHash", s.testGetBlockTransactionCountByHash), + newWorkLoadTest("History/getBlockTransactionCountByNumber", s.testGetBlockTransactionCountByNumber), + newWorkLoadTest("History/getTransactionByBlockHashAndIndex", s.testGetTransactionByBlockHashAndIndex), + newWorkLoadTest("History/getTransactionByBlockNumberAndIndex", s.testGetTransactionByBlockNumberAndIndex), } } @@ -279,55 +262,3 @@ func (s *historyTestSuite) testGetTransactionByBlockNumberAndIndex(t *utesting.T } } } - -type simpleBlock struct { - Number hexutil.Uint64 `json:"number"` - Hash common.Hash `json:"hash"` -} - -type simpleTransaction struct { - Hash common.Hash `json:"hash"` - TransactionIndex hexutil.Uint64 `json:"transactionIndex"` -} - -func (c *client) getBlockByHash(ctx context.Context, arg common.Hash, fullTx bool) (*simpleBlock, error) { - var r *simpleBlock - err := c.RPC.CallContext(ctx, &r, "eth_getBlockByHash", arg, fullTx) - return r, err -} - -func (c *client) getBlockByNumber(ctx context.Context, arg uint64, fullTx bool) (*simpleBlock, error) { - var r *simpleBlock - err := c.RPC.CallContext(ctx, &r, "eth_getBlockByNumber", hexutil.Uint64(arg), fullTx) - return r, err -} - -func (c *client) getTransactionByBlockHashAndIndex(ctx context.Context, block common.Hash, index uint64) (*simpleTransaction, error) { - var r *simpleTransaction - err := c.RPC.CallContext(ctx, &r, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)) - return r, err -} - -func (c *client) getTransactionByBlockNumberAndIndex(ctx context.Context, block uint64, index uint64) (*simpleTransaction, error) { - var r *simpleTransaction - err := c.RPC.CallContext(ctx, &r, "eth_getTransactionByBlockNumberAndIndex", hexutil.Uint64(block), hexutil.Uint64(index)) - return r, err -} - -func (c *client) getBlockTransactionCountByHash(ctx context.Context, block common.Hash) (uint64, error) { - var r hexutil.Uint64 - err := c.RPC.CallContext(ctx, &r, "eth_getBlockTransactionCountByHash", block) - return uint64(r), err -} - -func (c *client) getBlockTransactionCountByNumber(ctx context.Context, block uint64) (uint64, error) { - var r hexutil.Uint64 - err := c.RPC.CallContext(ctx, &r, "eth_getBlockTransactionCountByNumber", hexutil.Uint64(block)) - return uint64(r), err -} - -func (c *client) getBlockReceipts(ctx context.Context, arg any) ([]*types.Receipt, error) { - var result []*types.Receipt - err := c.RPC.CallContext(ctx, &result, "eth_getBlockReceipts", arg) - return result, err -} diff --git a/cmd/workload/historytestgen.go b/cmd/workload/historytestgen.go index 9d98bb28e6a9..b88c8208dada 100644 --- a/cmd/workload/historytestgen.go +++ b/cmd/workload/historytestgen.go @@ -22,6 +22,7 @@ import ( "fmt" "math/big" "os" + "path/filepath" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -51,7 +52,7 @@ var ( } historyTestEarliestFlag = &cli.IntFlag{ Name: "earliest", - Usage: "JSON file containing filter test queries", + Usage: "The earliest block to test queries", Value: 0, Category: flags.TestingCategory, } @@ -137,11 +138,17 @@ func calcReceiptsHash(rcpt []*types.Receipt) common.Hash { } func writeJSON(fileName string, value any) { + // Ensure the directory exists + dir := filepath.Dir(fileName) + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + exit(fmt.Errorf("failed to create directories: %w", err)) + } file, err := os.Create(fileName) if err != nil { - exit(fmt.Errorf("Error creating %s: %v", fileName, err)) + exit(fmt.Errorf("error creating %s: %v", fileName, err)) return } defer file.Close() + json.NewEncoder(file).Encode(value) } diff --git a/cmd/workload/main.go b/cmd/workload/main.go index 6ade426c1687..32618d6a79b5 100644 --- a/cmd/workload/main.go +++ b/cmd/workload/main.go @@ -20,10 +20,8 @@ import ( "fmt" "os" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/rpc" "github.com/urfave/cli/v2" ) @@ -49,6 +47,7 @@ func init() { runTestCommand, historyGenerateCommand, filterGenerateCommand, + traceGenerateCommand, filterPerfCommand, } } @@ -57,26 +56,6 @@ func main() { exit(app.Run(os.Args)) } -type client struct { - Eth *ethclient.Client - RPC *rpc.Client -} - -func makeClient(ctx *cli.Context) *client { - if ctx.NArg() < 1 { - exit("missing RPC endpoint URL as command-line argument") - } - url := ctx.Args().First() - cl, err := rpc.Dial(url) - if err != nil { - exit(fmt.Errorf("Could not create RPC client at %s: %v", url, err)) - } - return &client{ - RPC: cl, - Eth: ethclient.NewClient(cl), - } -} - func exit(err any) { if err == nil { os.Exit(0) diff --git a/cmd/workload/queries/trace_mainnet.json b/cmd/workload/queries/trace_mainnet.json new file mode 100644 index 000000000000..311a8a15ffea --- /dev/null +++ b/cmd/workload/queries/trace_mainnet.json @@ -0,0 +1 @@ +{"blockHashes":["0x95b198e154acbfc64109dfd22d8224fe927fd8dfdedfae01587674482ba4baf3","0xd5ca78be6c6b42cf929074f502cef676372c26f8d0ba389b6f9b5d612d70f815","0x5b94c39ad7eecbf043f62a4a76c5abee87195207df98ae16eb3f289b2267f141","0x90c06a9fad66de217ce5862a92a2d45a8f42f9abf8ec17d5bfb85ffdc7836ca4","0x7f7889c3686d7f560dd690aeb2a10b49e3a76844543cf78cc0dfe4687e2985d2","0x127c6b9794874d7011770b3aa2a0a640e1db201c2d677d01b2b3b19e7ad427c7","0xed05b59286d4f2db801e78a23ce4584d869d857b70b2758822844427caa55a85","0xdb63e26b655ad31d60b2173c02127180ed46b28506f785a2682e058ca61afdc1","0x33d8cbded33460024677e0c705f1e5e592e888e3a0db0f7b448cf1912c679f07","0x605636224c419d83051f8102ff0429cae8d3fe856f10b34920683bf899cc2123","0x15ae8914a9ec9c329284c82684be629d4d669122d87d5d9a7a022590c2747f0a","0xfc68a1e1b6d65e32c650a8bc1c141e54a7f06f52e5b783e630d22d58abd6170f","0xebe8c4b87953fc41d70339a75739b06eb302b0f4dfd9b7afdc99d9a8b4f95e3b","0xf68f282d1fc1e116c64443efd6ef0a0e1048bf21017d443db4dd8f67ae14f575","0xed20c5a28fcabfab249d9b9b81e25cf23c35cbeec83eca95ce873f081db4b723","0x943f087b63585553db2d5a45f7550e41557405aa9ab475e29a2fdd0b008d001a","0x818da0ff8a7bed13ecbf5f8b9b6acfc671a690a5da98ccb9cea74748283e0d35","0x3015b821ec7ef1dbf4661cfeb0197b092bdaa091555953779cda5ec5edbfce0e","0xbbd1d746ae0e8b92cf375fc2089d003d228e1de8d627769be29c476b62982403","0x38252223b341f7aeaf13135d89878bb7d3f985e7d0d64217727b5b3d29c9d875","0xa5fab243e0a098c1cbe501bfc8f5b5cf623d0535e3957d78b07ace411a51a718","0x4fc45774e4a804483c14840513296f6e7a416b6adf9f451f8dfa6abc1760b45d","0xda430492add67114aed10ea6099bf766b5ca33724bab1d85cc1f3b5104bfec11","0xea6641676dfadaeedad95f821588067cb9bcf88bfa39deb9e41767ac1562ce9e","0x7e4e8579e6044d3d5843a9056a002bf795e0539115d3b737d5f5815412ae974d","0x9e82a185058efe4b0170b619228e1cc5d60dbaa87446ef68285ed848f37a836a","0xd26004408af3f29b9369015fcb2a63d40fae55a88fc53d4635bc319a05b34ad1","0xf5dda9ce831a5ff354db9a5435d17b1c966dab6e4118f4270ab91f5a7acd21fb","0x182d0a1138f6ba41f5ff72826d0afde26a3b5a7769b88bbda4f46cab69d78857","0x6ac7fe3575dfb18c5dc8b746acd0d472e78230a30ea1c67d1c6354b963d4f33b","0x2dbbc8eff60fcd4972f1148182e80c64a1ef0eaebd6e6068337b96562b83c817","0x7e1dabcde7950f21ee505dc6d8afb9be5e90e4082537b1e6ddc42c1bd26dac72","0x71ed471996c09b4e7167186f25bd7ae6eee5ff6688a1d4bfda7b5b6dc53a5bb0","0x0304c77dfd4b2ca9da6a15f2e6ffbaec258e9c6934e41a58be1a7c9a378c535a","0x686d3a5b8cea0cda3504fc995ada97ca8cd28d475a578ba034f205b3125b68e8","0x93c34dca30e23a96b756637f09356c180b6a612af95f7f9d547b71701eea4948","0xb632884440f056c907506d5ac83a6ee6882e299518519b1760f709d6d97a5f0f","0x0e6c70ac2eede00a4ed3fd9b7b6587b0fab30583d16f9882b2a8d0830485cfe7","0xe4ad7c08e013c29860653e2eadabfcd60d2eed5f9a6201ee2292fd160ea45997","0xef1038f461bde1cbe92509b2a1afc594d77f1dc42912a067e81dbf6a6d283c5a","0x6482da3c6866f077af65226e64d12404bdd8e76f912588a085816d8a13ba843e","0xbda885f11f4d15e72bd5b919f85a8fbfa27d173a158b5ece2c99b25a57f973e6","0x753e6966e1c458a359ecf097862df3ad70af307c057590e09a03cd873a7ade74","0xbde18bdef36166637234a4d17d5bd06fec2d1345e823a744c57a988d23eadf3b","0x3255c075bb1841988b0b78a2407074ff8835e339c2bc947e014056da6e7fd640","0xf3bd0abaf17f942d986672e281b557f038b2e0046bbd34bad966c3579c15a58b","0x5baadcc926e0453ec23e2978f99abcad9550b3793b0b10f31e14342bc7245c85","0x1f5a2e0deedcb06bde06c54b4b3c246cc7d5958bc8abadf63190d08cddaf0573","0x11b63dcb4a963bd443d18679e890966f28f6d42279746aead2af27fee8b7d117","0xec2429b5a1ca4c6b876117f4c89ae4fc8f10e46017c6e7843d191eda56e6826f","0xc6d2ec912590123f1dbcdf59d0a8931ae77e64818fd1584807a3d16f9c4c571e","0x3a410e839b6f1b24b1d97afbdebe0dcab39f3eac0ee431d6f4aa7df1f5508188","0xfc6e1fdfb94b2b9cc68ff60d42e1b5ff026c6063785ab0eb2342ecf2690739f7","0xa953644af839382de5ed47860033a9a0b257a5cd77faebb25507bf54efca5a1e","0xd6e3cb368aba94e2b8715b48be3c2a0569b831be1d34a572f69991a293067080","0x0609c2300622192d3b740110d003d7c948c1d85067e9d551756294671ed7ed02","0xbd51727d598f366a4a705985d584f01fbd39340dd9e0e4accaec48a43eef2f6c","0xa238c846d60eca792f56fc54f74ee3e3a65208f5a6c6bc303629554e6c708e5d","0x8259c9a3c858e2621674b8249785a984e1e8d87350d91084588e9c140c2cb23b","0x850fbfe21c65f6bb6b54f324d6b6cd0b67b98dd9e38e25befa84f9e69bef1709","0xb9f1a8023b3e2e81e65b56ce66f8a3a30b263c481d29c7c9a04b53e0f02085f0","0xca318959861224d93fa77ac1fd28933c08e9b9e49ddc234dc7259326ec5ea218","0x7f962949b8482f735faad0ad2798a3896567141c2f8729ecd12cd6c87cd26f82","0x961f5fca795aadeea317645039efdb6c41a3e4eb8a9e6729ab9ba2567ca91f13","0x5edbe0c65d943741b283ff442c814fa606af221870af04668451bd8b7a9788da","0xbd4f083f7252f72ec0f84887d42e855f235585dc7d64d28b4166bae38ac7f1c0","0xd94ce7cf1c32bcaad9d04f2c78e08554846014dd5e4e4b12b951fb1772b86b2e","0x0e32306ad7702727f05f17c1384f44d06d1ab79638024af8a6268533f7154acf","0xe822b5916d71cc14900c6838ddc60e219df533bcc8962913ad73df4edd5f285f","0x6e5195edc5b4cff579ab9b2508162c7698eabaca8ca788819ede7540fdefdd5e","0x1a0a5e8f28c5bf036c9c3142a09d660976a50d7f17380d1a40c98097af627a81","0xf7a263f83ef235b2027ca554f3475bbd76d335ad7ff0db8f1010e118c3269d29","0xc7656c3cfaa84457ac669303736880eefeb0aee1bd1789f6c5e75749079681e7","0x4a5e6e196f1ea75024386e7ddfeda8712d825373040e46cb48e5792f678d136a","0x5f230eb89480c899e2fd16a19d9cf39cd3577227b68ba5cf267d1b8215830ed8","0x5b7957207934e0926f5edeac11719e72f1cb8d7895ead21cb8e364b3bdc90b4c","0xfb301b27ff6ee407bc42f2f5e1839a55cbcaedcef21887f00625eb9af674226c","0x5427a4a53afeb85bd3316121ab0f4e0bd61c73fae7785a1591700d4f031ec82a","0x4a66ca885e1051331cbdda18a4fa6381f5e1f641b237fab616718aeae8d95622","0x6c3492f0b478c1ca519e4b7c2e81bf71081c2b6528baf70dec643f0ce15fc496","0x3c48723f514d9f663ab011cee184e4feb2b4d81827449e90098e1dc282d7dfdc","0x1ef22fff4f017bf66a2f1d48cfcf3d3ab614eb4ce43928bf0a3dc26f59ffc3b8","0x0c217925d9b5871a198dcac1243eee33346bb7bdec4ebf1e90d9205514e2b61d","0x25af3b8c8e7f9500f95adbe9d49a8ecaffb33f9a33c6da6d1d9e56e66093b96d","0x5b803a6cc13b91f540ad8354c64d5296141b8eac82bc04956dbed0010a0bf48f","0xb65c26b3c2aa485c5cfea879010d2aa477d1ab8334b11b789a3f6f86bbf3c741","0xbaa365dcb89de8afb7212c12d3da1beea54ea138b1852a1ff471c82ae8c03d61","0xff7eef1bddfc49b254ba37be219d650cbdff5142cbbf21a3aee9efb32bbd5008","0x637911b739aa0f2fe25e5128e8109f86ab754365db4c9d89c5a92faecf9b1806","0xfbd637ca042e8e6dc45887357b8a9ea4431b4853683d206aa2268c693bb4c3c7","0xd9463a5d29f85abd7bc8730ce91c0b67449104739a0f7d620c2500592c85fed6","0x63a33be571765f3e5c67ec033a4407862f247616adab7b4ef8aa54ff419aa3e8","0x1628a4a4631c8739a4fafd40aac77f8e321bdc1b813876f8aa7168912d2f3b66","0xc67c0296c83da67d1cd587ae4a627ff77047d5134a4ba9ef3130ae576b8ffb56","0xcdca66833f7a3998a8fef9f2da8cad8b4df6a5162e3e2743722bd7980d785368","0xdcf7993ecbdffeeb644149e6c0b4d23811a34ec8e5507f28d50ae87870e769f7","0x1bf10b6cf39ed297e4a225ff806655629bc4eaf3fcd982f3c6335638d802a9e2","0xed21faecef2352139c804d10e7989fcb0505030bafb147350519ba7c006ff8f8","0x589e73c56a4a66246668d34a68f0d1ed727bf1fd90ff3a8bca87059f06f41023","0x6465b61ca3573982c1ab3d33b9422c5ce34f5f61b551a8e7b684203e0ec3be60"],"traceConfigs":[{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null}],"resultHashes":["0xa494b5732ca4b77797b5211a63a25c5a5dd0377fb5ea8a9757ee7eb0f826ea71","0xa4a37cf4121c0c62bcba127c6c4eab1976041bcf6322009bf2609529d745598c","0xf427b2b1424d62bc5be274288022b87777b73cf1953bab94699cdc66c04abc1a","0x1965aa4219cffb70f5fea4a257c9a984f23c684b319d726e1c852ce748721115","0x8f36a171e32bd7179bed35de5d14dbe714d994a1763d13909ec61102499cef43","0xa01e16c49bc8b68442e5e9d938adcbe06869a8fb14ff9323126c28ebcbab5de1","0x07fcd5e7d0fc6b021d14879e61674b54998fc7df9d461d21adf335cd1ff0af7c","0x1cb61eb224250902e709e852048e3973ba3dccb54cae255850850047829da451","0x91e21e5d81693d627947a5446e365bd07e7b0e478dab81c87f5240cc6510d4c3","0xea41f336eb63c8596bdb01b32e3df181db5c41ff09ae539aaeb13673d9cef22e","0xc17247b6a334b46606dcb1903f7e3f0edd90630143bdfbbac3e2135f3bfe0889","0x146ba21457cca9418f242b2e54f7ba3afc6a848508eb752d9672c79a47ee4118","0x89faba44be9e8b3e8254ff3add5523b0e76ca612d345891d486fbce538c6aaf8","0x213c49d161e4a1c0787ee7523c812ebc4bb5940706e0ab06d9de1837cf788653","0xe1f75f8f293829e51cd7a091613cf0023ea45dd68adb63a125fcc768bdb2f0be","0x87c791c8f92874d99962c4fa40cc395901d0d2d156c2daa57697b9127d7f87c3","0x0508b29e6c9ef838006434ad9dd0249bdc7a77bd1704dce81452453a278235a5","0xe60b2420ece3436fe541e05f137d0a1c1d49e8d0c3c6bc75ea781474232213f8","0x7702f1c4996dad10e5ac301bea7884af867015e193ab9b8aa3fddf938777a1d1","0x3e0e777a9ded06636b80fb4a746748abef4d1d3ba15c020a230d9997d5b983d8","0x7b2ed914a0be7c0c66f2eca87309373df01069e1b49e1266781720ab9012a7d4","0x26e3bc840a639894a1779313b7d07f637e0d3b95a121e44f4f9ce88fc2cf88d8","0xb87e25aa2a53bdf581b569d625ee7fe0aa6d5ae0a814e1572939b86f1d2a10e2","0x71c9a1e069f0aa92e718b88f2b36aff97a07544a8289d9d4274f41d67d0def76","0x57b2afe10fd8da828fa88e34819ba4bfcbf472fb1edcfcc9edc8882fbb5ebe03","0x968375643f9659456fbb0d7323b94f65e29d9c858631486e8bc60b8f68ba62a5","0x248523c28e1c5f285ae954cc11a03622fc020e25e18650759e3d5966dbbd0c1f","0xe7ab2c9be797195145a92cb7d5bfa71d8f3f369a736a07b161a21b6a21db93f5","0xfa1e59166e25c89c6f501211e5eaa20044ce06ac489bc26a17974a31d24b99dc","0xfacdc823bf4fb79380ec8bb606e0a9c041d9ac4b47589435bc670703f950e201","0xa2732d0fbd70be98a6d42f283887ba71ebfb0e8117d43c74a908ad6c9296f7de","0x5d210d483de3b1eb832222b1f8899cac504fa9c0440ffd68d6b006d0e2977a10","0x27f0c34ed4ac7c2499e6a1c4477eb354a6999cb3252359c5588286eb86c19c94","0x2ba485c99b2292c760c42237f1753f2f5d8167d0766f7ccab77efcd33398659c","0xe5df8e86c9f87326753e710562a6ee438affa113641755ee5c1a5b114c1526ef","0x4b7ca36bf25e3e7fcdd8a486014296e57907c148cd24e2772a5499142d0252be","0x99931cd5aa23e55f5ad9bb0d2690ec78e92a59ae960404d52c45fa5a13db41d3","0x457c82fd9a151f6a1cecb052b87a9dbdad4e249a6819e4094eb815884f943fa8","0x7574896ddeecb6c692db1c91a4841f352a125b61c2f3f2bf02ab3b7239af2c81","0x492126c282230c84161d46b0266e38dc608a5ba90a10a95a1836f5d43f042ba3","0x51bdabbcfae72410a850b581169bc46503add0694f606c4df996de71121d2328","0x9de2b0cc3b87c02f0758feb53084fdac09d48c30db8c6ca170c1e054833ff56d","0x7cf6594ecf72b6540ba34b46a900378ed7f93c36bd9a366669c4ad7a4716ad56","0x2c0dc2461cbbee75f483667e9f6f7a674377ff642d17793485f0a8c738199d22","0x97748da286f37c1b981f42823574ae1d1a6d59508840f14696133d472c8c790b","0x9e4fa1ce0759054e622862b06f5983ef7a86703cb79977756846a4ed6aed3e28","0x45664dc704909326b0ce324e2894092955834092cd2d85e9398eb49edacb12e8","0xa05ddcab28b8ddb5bab409986623115b669ce57c6f964ae7308b80b214b9c22d","0xac0137dbb079de37704fe927566d3322f9d56659634e40ff6838ac0c19dabbb6","0xf3215632d2f643373cd773e6aac4812761edf362e4ca79a25dd568192ac37f14","0xb046d9c5b79ddeed29d7e884cc2cead92409eeb7556c98800a517ccd81799031","0x30c9239b10196bc694a253bb1685502759b136548e76619f7b09be05e1abd688","0xe6cbb88e3005f8867bbade495d3cab9a8f8f5637f9a895aad7e907ea7a21625d","0xa685e18bb46bf7a3eebce9513c2f16424021251cc4f8c6813ea5e33686e6a74a","0x87d835507a4e7d7c7a642bee0eb7949b97df0104d954b3473a317bd680e4ef20","0x53ac282c5bdd30b9ff0a1b0f2de1e1f3f96626762cf7a37799963f6dc2273da1","0x584d86b42620716ab262425f2bead2e53beae9636ccd5ee0cc5cc669578e2aa3","0x93d6cacf032ea3c3b0df94a7ce0ddf80a9b566251ad28ed6192617a340208276","0xfe2be73afbea3f2d42053680f1279641580fc6c93a77007a50c60bac4282e382","0xde42282c6929e9def487abfe3932378a37052892e82901de573fb10ea985d453","0x6a3e87a5c30555fe63b3a791162755b53c911dd2e2865dbf2af4dab9d28211e9","0x97f3dd511ab194a3088724484e897b4bfdffd5de5b120b11f4cf3eef2c5565ff","0x7dfb20d2212387e31047bcaf704ea13760b8ab9a215a47e47166b4dc74635784","0x4fcd5cb98429db628a0e7801d5e3b682b7b556d02e0600aae9b8567163a28246","0xe382026428a5c05fa1c13862c25b0a156b5d44ab6d44f162a322cf26ea53e71a","0x06ec53a5de3c5281a76e5b33f696cda68cef9e3f965f7a4bdd03274ca91ed77f","0x5fd73a3ed55a4b82aac95b5e8c953b3695ee8c7f0bd3cc44301d10193b9830f9","0xecc55218d90e26c273d4a93a16d54417207035bc659be5c95a4160e98dd302c1","0x8659defdffb93c5490fd7ada555b47745c49ee99470457dd99518ed6c25a73f5","0x2ae088838a2f8a3aa9b15a9bce798e61a48abc80d08346afc9721240cfd9fd1c","0xad1e1f722dbba03553e9f38f6f79aa583c92a449e2d31fbcd55528a2e3f31cec","0xe239b052ad7b05423c702d4297310af665ad42a0eb40048559cdb4de794ba3af","0x5ebde2c353c3fd557f8aa31381b1482a3ed9e6f8123f456eeb9bd3624a228566","0xfc5687ca05b915bef5186143a31cfcd079b0ab53ccf1e932cca00db59971e505","0xca06b6304ef0c27e7de3e1bc298e12853c79b8f7bdd5ed4efc2f152d82e63ced","0x627d701abb02e2430caabb77a9d036d625e516a3831dba271a1f3cb245f1a784","0x23d62e2882681f97d401d231a616a877af935626904d2b91c13181b39c699b7a","0x87a0ae83d5bf905c94e095065a6cb9ba2683d5633fbdc505feb27606d59a71c9","0x0cab8976fee8929e249343fbbf9671d00459b17e95094ca7c0f9fabf050645b8","0xebcfddc2191030dd81e7eac743e4b0a05fc6f496489c9927c599fdb3f183f4dc","0x7bc7df87a60deda25f3cfdee3f44692b471cbd2e93cab3148157938488f66ace","0x6a263476a98b7df67a7e634258b44fc8850a4dda2654d545c16816ad4a076b58","0xba9c1c8edcb7aa4ab563ce31b0ffadaa7eead7d907ef48b0fa4d33f4e6669125","0x336d6d8383964098d87dcfe8d1f345ee096cecd90e4cde0ad769d753998a1147","0x6e6493632bb4d4e0e3469bbffe08f10b903125c784c686186e3e7f54c5b9a17d","0x89261adacab107ac84f8fcf9f8edcb515f47ff6b149ca6bf82ab9740fde625a1","0x4a2a23f54ec91f4ca0eb136d232d918279df947a89e8b0e3fe9618418d00ab41","0x5079eeea6c75094903b9bc46298b491569258f8cdf0795a00df562a135ada94f","0xadf791a27c8a9189e859afcfe6c57790d8b31aababd8fca062493e02f74949a3","0x4c6097692141ac9629895561dd3a09230c0de66df72cd7b4bc2367bd89c1a2b1","0xecef37f66a1646a9521e55b0a7bb30186e5a339d0c9152a2e5ccd7a5f086f9d5","0xaf254d942ae13e429637e985e005c9c650482f25676979f882276c8f5ad9dc50","0x0b5cd79348a06f42b12902247153d2877ce4fcf97f22ce763d08d6e83ab1b416","0xf7b60dcb1f730b617082a02f9e5585fc956f3456ce96f558fd2f28d94aa4dd02","0x849593ca60a7ccf6c6d67f6ac43d9f47e30f4b7d1909278f868245ce4f4250a5","0x0d7424149860063803b980a60001be3ac690f8756df01b5af195b98d9f2c4f24","0xe1f8e0ffe179b7333a0515b00e9585f3c8970dc8d8d6a672c5f9ec3f37fa21d9","0x418b06d6e71c7e6c075dbc31670d777d8fb0c5a3324deb3ad2c3fd5f4b949a85","0xc9b705bae187acf89afe2fec62d90d0f80f33c10437d353f5b5bca09decb8ec4","0xa7d5f76edc277593a936bb83567b808b6f8cef4e36b172a8fd20016ac0743e48"]} diff --git a/cmd/workload/queries/trace_sepolia.json b/cmd/workload/queries/trace_sepolia.json new file mode 100644 index 000000000000..f1cad144cd11 --- /dev/null +++ b/cmd/workload/queries/trace_sepolia.json @@ -0,0 +1 @@ +{"blockHashes":["0x72247ea9191db039158939f7ba958e638a32df4f61a43edcae60cb7a686a2d55","0xc9ce6049b108527ad96110010c450a9998e9630ee66914277da8324f0c399995","0xfb09616b322925c339a15a4a6d1f1c1d56aa0f0d6742c03fd132cd56c38176e1","0xbf8c154fbdba2702c0b5327f0e1cf8e1b926157ca92520ac4837eac7580c480b","0x428a2f23efebbe81495163123c03655d534711c6602d389e81be080ffc0f78e6","0x4ba87a5f1b5999754bdd89239e8f4e55813db0b87603994a4c1d5440604ae9d0","0x8d5698457c298c85e3671992b20974282f94dd122f65843a2102117fa30471b9","0x6a312fbbd75e9b2ebeff4a1ea7a5d0b6be159b6f976b8bd13f9ccfd80651cf04","0x2f30342df905802a22f0a34663783252edf1d396784730673bd1c268fade2d1c","0xe44dc0d17a5a33be73bb93bfa4b24775c06dee29e0954a4ebf7f56fe6113314a","0x4ccc697441607d26c4bb2a43498add9dd5127e4f14552ec6d182af1c90627aa1","0x642f164e7adee7558f1174fdd853487830702c2cf18b0addcbf98ade8fef0a38","0xb2132465728cc2b0375c7580cdc5043b1615f13934eb6e764b808b6d6de83b22","0x863716a9d9741497fdbf73f8d52dc07f7647c3b47965e83e66509c0ac710e021","0x130a8582658947ab8359eae6064626c409db759ccbe661e79f3ff2cc73802bc7","0x168bbc5602d0b0e3d89054c4237db04bba12b917163d2bc974c2d409e997470e","0x092ce07c147ebb50eb50f165c82fdc365d3e2070095f5746b75a6158da6c0c4b","0x3995a409a8473212fbdbdfa5c7b1ce3dee5e001a9ebc6f9a02be35ccfc442237","0xc310d797239cce41107fcd5b1b21f2d03e79268f5c569094b1a6681135564ee6","0xd66b0753db0866a8e5274f2952cc86dfbdef641a3e4b7bd0dc4004d4aa58ebfb","0x48faee82713d0eecfb554354d693464d04fb6dfa6cefc80b3376d37d37f087c6","0x0f593c61cbf5c5b3bd951a77cb5a3b0696f8ad50e95f264e2e178b8fe7e8ff84","0x06665f0ec4ae78ab7e7e7daa83c0abfa0a6ed9241ae9567394390eeeeb0a0746","0x8045a3a9f3bd69b16f79e6ba00d184a3ee1bfac42ddb254ae661f0d8b45b7b35","0x323e5a7936b35c9431a9c1d4bdef4f5788364888c27412c06ab278ba04a707be","0x823a2db35ed72995e11a1c1d2f19f342562d1f7cdb4270818cb110cb8a50cc27","0x96c39cec55954ff62541b2f459dfaa8e9d55d814944019f6abb01fcc92733d75","0x37a1f7f8f43d75ea9f9a09ccee078c8b700929609be74da244993637fdfbe709","0x8f269d0be7f6b25deddd0a9067cb83bdb0c81ae5a24c07731becebfdaf7fc395","0x3ac93bf1c8273827eaf813046f7c7b02f6a35046efa6d026308db2436beaee14","0xdf1bfca6f599217a0e0af09d4d6bcfc94f9cb6a79d8c8bec3638a3c310d77b4e","0xd6ecc81a0025f771ba987fe80205eb6e5101c57b3d9438e716f14d22282a4a05","0x953a3ee3a533a4ab9467548a7dea336ca1c2eb3172a6aa65c5a8a82bfc4ee3b9","0x81b7137d1c5d210ce14b0711b2b4047846765bb61901a76f26aa4d496c0697b5","0x4828e86cee752aea4a72b0054b2ee1a8191151e17a6ab9911b28ef7131829c86","0xf3faee462f352bdc7866d930d661614c672e956083ed5bd5a5a3608e24749a1d","0x7c33d4d434ef27578a1309ad7b82ae84b68e6ae65ded9341d2c5806f6fe5e2d2","0x2aeb3d660959933dea25ccf112576f208edce9718d314b5844cd6546d2ef97a1","0x940d63435d9b3a636348af9d6cf3319c4558e587d705d3f1a1cd9e84e311b901","0x687e7faa271f9ec690cd08abda6f11063c3d9801dd9aeb69741add2fc00608c7","0x3086ed61095969dcebe06d12841a8bd5bbb2bb2decf33e39e083ce80548b7f0c","0x3d1b9168a9aa8f1126dd4b4aeda2fdbff775a0769d67f2452a83555eb23719d8","0xd97cde90f16eddc462438472877b726d041b4fb9407cbf38a7d7bb223937f290","0x50a238256bfc6e885061947e23e0a712b343436164f805dc0e5c5fe6be98c3a1","0xe94835526d18786ddc2d49ab93b80e6f304aac3267515f055b795c8beb333a67","0xa41a8e9cda350619b3aa2c7facc6008468547af9385a7a5c955092c307c46c79","0x2e7a698c7ccfbfd2003e86832bb7dfa6874eccdaf0215a2af1ce17f9d853ea2e","0x4b7ea427b979da4784e53b211f6a0b874c5d1af9a6d8334bac4c6ec18b8d2670","0xee27ee7c687d63a0c0720449d685f7b93d631ee9306b2ada1d655b940835287b","0x3ebb92a64dcc007b738a1e683fc128ee26d7a0ffeb9b559e2c7b9ca1e649f71b","0x1f82a8998613f15dc9d0a37a58e8176ac8fbe80ccdfd90520b6629de79cc37eb","0x1fb9b8b8ffb27f0a75c056f0ed221d3a409345d38429d3a0c02fde99e4ea588e","0x18fb16e15e2b75971acb78788ae442c1d3526ce31f4203011a677a437cda297c","0xd9530b906cd1806fb72610a9ed9dbb41e1d0273af009bccb5ae4b3040a2191b6","0xbe6ffe1c6238e1af551c456dc1f022c709ccad34b610a1ce8205ef3390f0a293","0x9b0e6503f150f80ba954b599d2e2336c5d565294119d1c9bcc5b2d42590d5c9a","0x42b544ba1064c1ab579d5f503d46d9ce5358e5b94b84e39e19bec2c9a5383f30","0x9e6a1e6ce2c05f5d0806c64cbcf46900c2b5781e1b39f31dabd87076cec7b9f6","0x0a7780eea2fc17e3704590f46202a04cfecd92762f3834c9f0532700f358daf1","0x15a0b03489f73343ab4850b3f318ce48c9071d5e138bea73b8fef94f59e92971","0xd6f4c83dddf203773f4fd8f7405404fec842ffdf7a5881273a9d3016e2b24e02","0x32d325519cb6954edb2d506b842b320105d21bd416ee41fa018b21cf1d5be689","0xc4a12c1e1070eafe39b140cd691b91f3f7b3c31c45559c09d3d8a4eab5f6cd96","0xa9b749fc01ea78065929e40275521fd3fd9187921fc6443f68b65833b4552a0b","0x8a03e62ab00a5160c04d26a87852f4057c909a1ef68c776dfc30342ed3c9637b","0x2a071bf4e4bb34fee5f797db14292e011140f7c1acc9dce460db3e4a5410654c","0x6efad056ab5e87d2bbad278954134882db0b3bdb0b1421b687110a86f91cf59f","0xfb749416bc1ae673255e1d931add699f30999fc27d6fd7484b2674ce995de6c4","0xb4fde5127a8e5e93d2b5766afd3a78ff981c528e8bb3c6a62e63aaa31ddda0a2","0x8a67f5a59526f88819fc5d78d489f1159c0801010b2c5efe70b48d0a294d9213","0x2be76e53d7474ed4e56bcec2fb7898d5aae60a64cd2b03bba05170e5ce6ca637","0x0036845250c01045d67da37a80e2ab6202c591ba59b48f57c157896db81e1f48","0x39d464e4eea5789ccdc9aa26b8016f216a73f5967e6faa5b502d1c3ef326d66a","0xbaeb0186a592d7cd481c7f7c114247f26f8ec971617731b52a7c01cf6ccc5ec8","0x882d6b0c7903e541af564db1887bfaccc9a43ff8fb36b1ee34076812ef12bcea","0x5c808907405528b388e0d5d8410fe2d25c3f96076ec28aad8b1b27617facdd8c","0x62ca1414ccb1ea1e32ac32089487846b83c1fa2b124e67215095cc017a7f4c19","0xa028cfb350b86c12da2a7694f68b4c9c74df9feaac0a7fc8c12894e235222c94","0x2ade89f9e38fcb72902091f27ed443634ac2efcfdaf54c6bfb9d2b918630a547","0xfb453b30e07331c6b30a5e90ea57e6466a51658e7a35d886fc365de36e5f6ead","0x2aee6691dd590d47d8d481e975c641cfdcc80fcdb62018ea16b55ece14162b2d","0xa141d5cc8043d9028c6a9940c62930e5ca1671631cf8e48f07d341dad3daa798","0x38681eb908b37c492a913b63d97ad57fe7921e52b326c68f8dcdcfde31558d12","0xaf7aa1d663ca600cf8f029373beedc5a00420cc90e99a692d995a5c7c6ca9c02","0x7cfc3ad67f2fc9354d351c63dc693b504999e8979013238384fee3d646b5257b","0x2a3aa1e949cce5c95d9c36a6ff5b05226af40e4dc78dcc65f557f67068510e3f","0x17a0ce9080b0cb3d44286414adb81878fde5d82909bbad26bb031f03ccdcda91","0x5fb8489db8e35296247f240572b97fe33ce16aa4cf1a169508d435b4128be42b","0xfc384276da73f89c0469b6663bb1c8de7ed2834b35829d0c13c92adf58947548","0xc6d027df664c0e01742073d9b16174500d203d69b4779e6a817e1cb255bfae56","0xa8891e1a8eb24f8d2e456ab77b03613ac0ef0dd89eab9e9827a90c3616f9db3d","0xa5c1ef6ddb9d9cc59e845bca997fa196a8e21d75c44ef37a3458126616c3f7b0","0xafb61af94846f1c4cafee57fca4aaf24e65c1554fbe0234728129b44c0631b17","0xcf0114ed1f5812301bd5625c7a3cbdd0cda6dd778ab0063aca3d8632990c36cb","0x16203af2ebd70011927e2c8828eb57537e80862fa6953e0986a2d942fcb3a480","0x925efd1a5a7213f635c3d77616f5aad3d6596869df5fe41f223eeb94f079fa20","0x036560d4e1071ded4a7477593e0155d3d033409c8c737824d67491099f4b43aa","0x28600a9b241ef968625a5b0688d2d9a204a15b23c3a1adb79912196ba3f22d7d","0x7610ef696e4441291e50633943a58355d1d5975435c25b78ae57416845b32939","0x637804d9acac635988d9254e0517fbbc710879d2e71b943fadc6e5d2044462e2"],"traceConfigs":[{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"prestateTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"muxTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"noopTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":false,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"callTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"EnableMemory":false,"DisableStack":true,"DisableStorage":false,"EnableReturnData":false,"Limit":0,"Tracer":null,"Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"4byteTracer","Timeout":null,"Reexec":null,"TracerConfig":null},{"Tracer":"flatCallTracer","Timeout":null,"Reexec":null,"TracerConfig":null}],"resultHashes":["0xae143a4c152a5fd7c9ab30b3592845f62cab5a06b33833b8b5ef0835ba7c8b90","0x098e56f6f77c9b1d704c00bb7fd0617af420f52d7c66e44181bb800f1f960b17","0xdb9f3f2533d5f8adcca5d5544afd7d049c774406776606e8714fa25412ae27bc","0xed74e9092469476b7c1bf17ba593ecd2a932e388ced7ae75b8e175aae851cafd","0x0f6be47ec6fcd7ea1879ddf12437ddb56cf5e90d013cd76852553754b7910707","0xa53cc737d6dc52d4b0d3cc08e35160274ed08f69de8c5d0daff9bb38442dfd78","0x9e72cbc5a10e03e604afb647391a051f9b54ed4c1341f12b8de8703add7af693","0xdd52ed69fe0ca17ca6f96710edaf59cecd1c571865095c002d38a1f1d8707513","0x6400efef1767d17e78bc5c457362868c97674ae85660fb61e09ff28b92eeb6a0","0xfa83c0b2e83af884142f37144502eb6af7f58fc363bab94f44c02142c7837faa","0x3764e1b8c50f3175a416b85dd376be22b36ec0c10416922412758375cbe55f97","0x898826a5e064a8d4b70c907036d9239a221718d621d586fa52784787fbb23e66","0x935d6d52270f81158af486f9143d64ddac7f059ff295cf64b921f38b6730886c","0x9e40e6d5593a8ebb0f938c166cd4ab474938a18933d62905739668e932b59154","0x1d61971f8e9c432ef6a6644b3e55b7dbeb470dfb75e9ac5e37403788284d2f41","0x759bebc64b3042eb084b59befff0c6fa1d98332d014ae4d9a2d0d327ad73b4b2","0x55391083ba8508864793d622b0e5208a986a2611feb329668cf1ab5a95355acf","0x551c8af6d71cfb8b1406aa3ac6b8d405599c95ad4f0c67cf6039b127d2265bb0","0x6045cd37216cb8b2700f35603b33429f32b1a380b8b06d5faff33cd1d216f9a3","0xf00540c8777135081e30c5a317e4bcc99a754940b5044cd690bf395ccb781b7a","0x57a2cafa820c9142db8022cff0a9937f52b1b9da07732e94e7482242a8562d70","0x55044f7ae037a8f839e4ac4859365c224b10ca0940a1fa8b9d2dedd89d3868d3","0x26994f90664200f462d37ad97638256790f6d211108d0aa004bd7d3c38d86c23","0x60e92afba594269fe59c3d5a7f99849948a9258d0080dadd35c88881b3fbd9f7","0x5c484fc65dbc1664937e162b541492f7aaa95e345bb686df0a13cf1531bb74df","0xd35020254ddef46293b2601c2ad93c001f3f4a060db4b3d24eb68034ef2f0fe0","0x78745a342992e6d22c0c6b0d199a55073b2e4604dbe4ff87088a1e29f36644bf","0x359d7fee0fc9c1c028f197efd00b969142f6f08ad83b30d5b746edc5ab1f0c21","0x148a91011d57b056b90bbbc47bc6e8bebe6b5d69a6c9b763bf75d05de9f92899","0xa69f9d31097a624de75fdb28f7c7253010bdc65de323e8455e9a5e41b6bab230","0x56ec0333e1e20e3c0c76dbde20a0b95e8d546ca977948be9982b50dc6efda6e5","0x6cc40646ab049a719a9b35d91e211b10dad5851d14ef4b5d4a6b7e9206fffcc0","0x523cc5cc468a09b8377ac1a1570d42438914cb7612752ac8202f0de1190c86a6","0x48ab67e1715aa2545f8efb1b139dbfccca805e07610a4faa98a7d183b51cfda3","0x06fa8b658e439077e0e65ffec056b98af0e9bee568edf0d4913cc2f264bbe97c","0x126a277f3b6961d26e9009e1ebbcb43243c6faf39b22c73a363bb1a1e8f609bf","0x6cede3688b92a25589b108940064e48addf0884444882d2adcbba878765ce85d","0x1007d2462718bca7a3c974ee84206a7635e08de2288fca90a2db40a3268b863a","0xd2eccca12bc7d9c4f16802705005c7903e03a71122f2b28a2fd30930b191e4cb","0x78d1d9310b9eabded10aeb2d6d402c6092ad08f8bbe7a3486f72f6a9ebc62744","0xdf5ef922c6c4dc17eb175e155f5663f22fc95e848bcfcd068c70b4cd008981ad","0xc0ceaeb3e60150e4d236f7a7c4fe770cdb2265f12c17f4e9e325d28027536e16","0x0b39b9a69d7d839f0a631bbac9e104a5e0f1ab9e8ed110b2d80786c67fadc534","0x1a7eb8962a6084fb02d7a9b23cbf58842a7f6040120bec370d36793f31060ebe","0xf23bb2c4b5d34eabde6d68863a83b40a611c3c3f23cb35fa0054bb554d7e342e","0x715fb4c5cdcfdbf0358e228a703c3efeeb2201c09314629befb33e55aa4a340b","0x0a204cff1f0bd31162cb4ff9f6d64310adc86d86163269c5f10de0248065e9a0","0xdea6a0604de25cf777b9292f614ae8be0d42ba84cd2164e88564d743b9066801","0x82e8ee420fbb8c01ddf7ef0768a501585cf38658214d0c6b0ee8c63a022a551f","0xba1850d6849c5f72e138583920e45c3fecb2cc842579d0c0d2005b679b0f08f7","0x5d82291483e9dca550f56bd14d0a3e5bd4ae1229978b75670f4010f44a6e98a2","0x14c5ab086840147694c0f6b0bdc669c2bede4f04b4531bf9fd3d933ab00b9a75","0x2eb12121bb4bc8354cd382095aaf0d86790222dcdd07fa39d0007baee7cca752","0x3e7baa0ca0a1c65dcc5c042b5cc1f961be50d9d958fc5d4a12cfd9023f804155","0x6ed420dcc93d61a2046ca36fcb7ef9bb906b1b4e15d6d5d0c99b0a9e403d591a","0x42a675de54b62ec6748cd9214ca9339481f83587f16ce2b962efc6f09e723eb9","0x6cc88152997246ffbb8c2d553dff7ef4d8693c6fdd1a554afdb45f800c459fba","0x3e4466d2c9ba9ad27310282d5ba4d8160e90734d76f962d0c54ea4e2124c352b","0x8891a29324f9867f1c6179dc3ba85b65f5abbcd49d9f63f961e145f6de526ba7","0xbb4b16d11fcc3cf6ebc75095eab471a7bac1bf2c5c9e236185401e1fe3bce996","0x9a78f882d7f0f71d4f6d8a4755578e0812585f1706ff52e382a9e1f1b1a855b0","0x5e6e9e7bf09538f86344dd351d4069d9f0d3c0838c90a66024946f7aac5ceb18","0x69d1cf1d0956724c2e60aa38dd1899a46f288ee6d92e29711df9ddf2f0522fe8","0x9db0eddc6355d0e667e14757376964a82ba6314465778471d4579e7078e5840a","0x1b1e064860ec50b463927a07ac4acb92381307b8ab6b2f341b4474a0e2a4e98a","0xfea2a1e9923c27c845ef633026fc6b7343e45c1450b869999c93ea904069ddf9","0xa2ee0dc5f7daa11a7bdb6701551143216516fa72e80b4fe31a978f0981583014","0x3cbc68f2c5c8633a708ee2ea882017f2e15648d27e49fc299ef54ce763f03be3","0xfe5344cf524d3b34c4846ee9c030cdfb6851ace7d1aaec062709c5e48d115f6a","0x70dab6d3c52f6efb38f2d74d7d899ec14e8e6be9dfe5876ed632821279e85cfc","0x045f6d12c74920cf50cd1bf16ec41c1a54695331b7508d8f6c2fe2dbd782db3a","0xf8837d046d7b87f78dcde07d2de9823a27f0e0db83fb0631c204754c9a12eeb2","0x268f7077fce5602253b77b182b82206b8e67fefe9a14128c62c35ee23898008c","0xe6eab3e3997451831f83e558a37c3a0a52cc36d148943ff1d9066925eafb25c3","0x30328cd97d5cec2f291043653e4cdc66df1c3ea7631dc1f867153ae8905c27a5","0x0d0967f73ba653b57a9fda3a220f786cb70c5dabc8fc4b3cf50627bfa03c7708","0x8c19e74767d3320a437414b2df92a47f1500298b1b8c530a4e568060431ee9d2","0x699a7b3e166905e46e66ecdcefcc4fcace144b8513a786fe3fd3a33ab0478c7f","0x7ca2600962dec884a9f223d5aa9910ceb3350a46af888592c047f780b3e86fce","0xa7dc21e1b0d3a379a7ee5eb15c315a2c90c32e6283349b51d37a25641d8623ed","0x69e53b8ea70882fb72516688a4173a8ff34f50cf5f8e8e9ab60e721049fdcd3a","0xe3ab8108ecb94c3ce53eac435dbf8499993290bb1b90b011f7d22147331c7be9","0xe77c23dc194d7ac09dd1e38243b587bd6426de6ed0a3f96fad4428a0ccf86c7a","0x550c69fe16fe4a4991384d08bafea9457f9dba6df19dcecdb75e47f19a25ad67","0x569ac8461db2ecfe3d1b2b015a8f5e2811b15abcb9de74fd07f0d0017229351b","0x2c9bd11470bc0b0590ff86a0eb87282b309ad8ef93dea6cccd38e1badab03c07","0x2929f848aec9581286b81e4d98a8575d1d2826b97e9b096459d5d1b5a4912cb0","0xe4f76169f61060aaceb91cb271b34f940a5ce3e40451a94301db13c06c1846be","0x0883ae3b60cf149d7f984a16abd836022b99838a29278ec041714cf5add6f28e","0x4ea7ede16833fbd9b832ef2a0d2c6f0783d190a91e9638e6e8d80583c7740c52","0x8d46cf9c07f18b0f091e03397694318b1fa467578a3c7bc04168948a7185a295","0x6979eb82e1e9ab642780ad1c040c8f713dc9cb2dd8109db703602450cfd3e9a9","0x48931e44eeaa67871da09d3edc5ab41a1f33e8bf3c13b2c6c776bae8ada596c1","0x60441300e6c90e585e2cdb1e202a00529366637ce3cdffa583f0d03a85ed83eb","0xce95912b3249607ee50e69f7c6a8abff3ecb78438d97d96e03455682352c2afa","0x0899b86d926592145c7b569840ebdf9a37b33e01ccb7d734fc958d405389a48a","0x1b990dc1953a461929203e3a158d7c57f1c06c6a353bef42208dcfd1359f78f6","0x8223cf1bce35aca29c4789e0795a1ba894c1c7a5e88bfb167d68d629886b01ca","0x1f8cf9f5671f309c579848b3adbc271f1c5a35877da7a9fce7ef0462c32eae42","0x22e6ee495248cc6e9fa0cf64f0edd01a48410bb5e8e9baec2f9725522fee79f3"]} diff --git a/cmd/workload/testsuite.go b/cmd/workload/testsuite.go index e8e25e773142..39eeb8e3c201 100644 --- a/cmd/workload/testsuite.go +++ b/cmd/workload/testsuite.go @@ -21,7 +21,6 @@ import ( "fmt" "io/fs" "os" - "slices" "github.com/ethereum/go-ethereum/core/history" "github.com/ethereum/go-ethereum/internal/flags" @@ -45,10 +44,13 @@ var ( testPatternFlag, testTAPFlag, testSlowFlag, + testArchiveFlag, testSepoliaFlag, testMainnetFlag, filterQueryFileFlag, historyTestFileFlag, + traceTestFileFlag, + traceTestInvalidOutputFlag, }, } testPatternFlag = &cli.StringFlag{ @@ -67,6 +69,12 @@ var ( Value: false, Category: flags.TestingCategory, } + testArchiveFlag = &cli.BoolFlag{ + Name: "archive", + Usage: "Enable archive tests", + Value: false, + Category: flags.TestingCategory, + } testSepoliaFlag = &cli.BoolFlag{ Name: "sepolia", Usage: "Use test cases for sepolia network", @@ -86,6 +94,7 @@ type testConfig struct { filterQueryFile string historyTestFile string historyPruneBlock *uint64 + traceTestFile string } var errPrunedHistory = fmt.Errorf("attempt to access pruned history") @@ -121,40 +130,113 @@ func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) { switch { case ctx.Bool(testMainnetFlag.Name): cfg.fsys = builtinTestFiles - cfg.filterQueryFile = "queries/filter_queries_mainnet.json" - cfg.historyTestFile = "queries/history_mainnet.json" + if ctx.IsSet(filterQueryFileFlag.Name) { + cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name) + } else { + cfg.filterQueryFile = "queries/filter_queries_mainnet.json" + } + if ctx.IsSet(historyTestFileFlag.Name) { + cfg.historyTestFile = ctx.String(historyTestFileFlag.Name) + } else { + cfg.historyTestFile = "queries/history_mainnet.json" + } + if ctx.IsSet(traceTestFileFlag.Name) { + cfg.traceTestFile = ctx.String(traceTestFileFlag.Name) + } else { + cfg.traceTestFile = "queries/trace_mainnet.json" + } cfg.historyPruneBlock = new(uint64) *cfg.historyPruneBlock = history.PrunePoints[params.MainnetGenesisHash].BlockNumber case ctx.Bool(testSepoliaFlag.Name): cfg.fsys = builtinTestFiles - cfg.filterQueryFile = "queries/filter_queries_sepolia.json" - cfg.historyTestFile = "queries/history_sepolia.json" + if ctx.IsSet(filterQueryFileFlag.Name) { + cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name) + } else { + cfg.filterQueryFile = "queries/filter_queries_sepolia.json" + } + if ctx.IsSet(historyTestFileFlag.Name) { + cfg.historyTestFile = ctx.String(historyTestFileFlag.Name) + } else { + cfg.historyTestFile = "queries/history_sepolia.json" + } + if ctx.IsSet(traceTestFileFlag.Name) { + cfg.traceTestFile = ctx.String(traceTestFileFlag.Name) + } else { + cfg.traceTestFile = "queries/trace_sepolia.json" + } cfg.historyPruneBlock = new(uint64) *cfg.historyPruneBlock = history.PrunePoints[params.SepoliaGenesisHash].BlockNumber default: cfg.fsys = os.DirFS(".") cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name) cfg.historyTestFile = ctx.String(historyTestFileFlag.Name) + cfg.traceTestFile = ctx.String(traceTestFileFlag.Name) } return cfg } +// workloadTest represents a single test in the workload. It's a wrapper +// of utesting.Test by adding a few additional attributes. +type workloadTest struct { + utesting.Test + + archive bool // Flag whether the archive node (full state history) is required for this test +} + +func newWorkLoadTest(name string, fn func(t *utesting.T)) workloadTest { + return workloadTest{ + Test: utesting.Test{ + Name: name, + Fn: fn, + }, + } +} + +func newSlowWorkloadTest(name string, fn func(t *utesting.T)) workloadTest { + t := newWorkLoadTest(name, fn) + t.Slow = true + return t +} + +func newArchiveWorkloadTest(name string, fn func(t *utesting.T)) workloadTest { + t := newWorkLoadTest(name, fn) + t.archive = true + return t +} + +func filterTests(tests []workloadTest, pattern string, filterFn func(t workloadTest) bool) []utesting.Test { + var utests []utesting.Test + for _, t := range tests { + if filterFn(t) { + utests = append(utests, t.Test) + } + } + if pattern == "" { + return utests + } + return utesting.MatchTests(utests, pattern) +} + func runTestCmd(ctx *cli.Context) error { cfg := testConfigFromCLI(ctx) filterSuite := newFilterTestSuite(cfg) historySuite := newHistoryTestSuite(cfg) + traceSuite := newTraceTestSuite(cfg, ctx) // Filter test cases. tests := filterSuite.allTests() tests = append(tests, historySuite.allTests()...) - if ctx.IsSet(testPatternFlag.Name) { - tests = utesting.MatchTests(tests, ctx.String(testPatternFlag.Name)) - } - if !ctx.Bool(testSlowFlag.Name) { - tests = slices.DeleteFunc(tests, func(test utesting.Test) bool { - return test.Slow - }) - } + tests = append(tests, traceSuite.allTests()...) + + utests := filterTests(tests, ctx.String(testPatternFlag.Name), func(t workloadTest) bool { + if t.Slow && !ctx.Bool(testSlowFlag.Name) { + return false + } + if t.archive && !ctx.Bool(testArchiveFlag.Name) { + return false + } + return true + }) // Disable logging unless explicitly enabled. if !ctx.IsSet("verbosity") && !ctx.IsSet("vmodule") { @@ -166,7 +248,7 @@ func runTestCmd(ctx *cli.Context) error { if ctx.Bool(testTAPFlag.Name) { run = utesting.RunTAP } - results := run(tests, os.Stdout) + results := run(utests, os.Stdout) if utesting.CountFailures(results) > 0 { os.Exit(1) } diff --git a/cmd/workload/tracetest.go b/cmd/workload/tracetest.go new file mode 100644 index 000000000000..3dc549b997ce --- /dev/null +++ b/cmd/workload/tracetest.go @@ -0,0 +1,132 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . + +package main + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/internal/utesting" + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli/v2" +) + +// traceTest is the content of a history test. +type traceTest struct { + BlockHashes []common.Hash `json:"blockHashes"` + TraceConfigs []tracers.TraceConfig `json:"traceConfigs"` + ResultHashes []common.Hash `json:"resultHashes"` +} + +type traceTestSuite struct { + cfg testConfig + tests traceTest + invalidDir string +} + +func newTraceTestSuite(cfg testConfig, ctx *cli.Context) *traceTestSuite { + s := &traceTestSuite{ + cfg: cfg, + invalidDir: ctx.String(traceTestInvalidOutputFlag.Name), + } + if err := s.loadTests(); err != nil { + exit(err) + } + return s +} + +func (s *traceTestSuite) loadTests() error { + file, err := s.cfg.fsys.Open(s.cfg.traceTestFile) + if err != nil { + // If not found in embedded FS, try to load it from disk + if !os.IsNotExist(err) { + return err + } + file, err = os.OpenFile(s.cfg.traceTestFile, os.O_RDONLY, 0666) + if err != nil { + return fmt.Errorf("can't open traceTestFile: %v", err) + } + } + defer file.Close() + if err := json.NewDecoder(file).Decode(&s.tests); err != nil { + return fmt.Errorf("invalid JSON in %s: %v", s.cfg.traceTestFile, err) + } + if len(s.tests.BlockHashes) == 0 { + return fmt.Errorf("traceTestFile %s has no test data", s.cfg.traceTestFile) + } + return nil +} + +func (s *traceTestSuite) allTests() []workloadTest { + return []workloadTest{ + newArchiveWorkloadTest("Trace/Block", s.traceBlock), + } +} + +// traceBlock runs all block tracing tests +func (s *traceTestSuite) traceBlock(t *utesting.T) { + ctx := context.Background() + + for i, hash := range s.tests.BlockHashes { + config := s.tests.TraceConfigs[i] + result, err := s.cfg.client.Geth.TraceBlock(ctx, hash, &config) + if err != nil { + t.Fatalf("Transaction %d (hash %v): error %v", i, hash, err) + } + blob, err := json.Marshal(result) + if err != nil { + t.Fatalf("Transaction %d (hash %v): error %v", i, hash, err) + continue + } + if crypto.Keccak256Hash(blob) != s.tests.ResultHashes[i] { + t.Errorf("Transaction %d (hash %v): invalid result", i, hash) + + writeInvalidTraceResult(s.invalidDir, hash, result) + } + } +} + +func writeInvalidTraceResult(dir string, hash common.Hash, result any) { + if dir == "" { + return + } + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + log.Info("Failed to make output directory", "err", err) + return + } + name := filepath.Join(dir, "invalid"+"_"+hash.String()) + file, err := os.Create(name) + if err != nil { + exit(fmt.Errorf("error creating %s: %v", name, err)) + return + } + defer file.Close() + + data, _ := json.MarshalIndent(result, "", " ") + _, err = file.Write(data) + if err != nil { + exit(fmt.Errorf("error writing %s: %v", name, err)) + return + } +} diff --git a/cmd/workload/tracetestgen.go b/cmd/workload/tracetestgen.go new file mode 100644 index 000000000000..f73f2366c7d4 --- /dev/null +++ b/cmd/workload/tracetestgen.go @@ -0,0 +1,192 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see + +package main + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "math/rand" + "os" + "path/filepath" + "time" + + "github.com/ethereum/go-ethereum/common" + "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/internal/flags" + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli/v2" +) + +var ( + traceGenerateCommand = &cli.Command{ + Name: "tracegen", + Usage: "Generates tests for state tracing", + ArgsUsage: "", + Action: generateTraceTests, + Flags: []cli.Flag{ + traceTestFileFlag, + traceTestResultOutputFlag, + traceTestStartBlockFlag, + traceTestEndBlockFlag, + }, + } + + traceTestFileFlag = &cli.StringFlag{ + Name: "trace-tests", + Usage: "JSON file containing trace test queries", + Value: "trace_tests.json", + Category: flags.TestingCategory, + } + traceTestResultOutputFlag = &cli.StringFlag{ + Name: "trace-output", + Usage: "Folder containing detailed trace output files", + Value: "", + Category: flags.TestingCategory, + } + traceTestStartBlockFlag = &cli.IntFlag{ + Name: "trace-start", + Usage: "The number of starting block for tracing (included)", + Category: flags.TestingCategory, + } + traceTestEndBlockFlag = &cli.IntFlag{ + Name: "trace-end", + Usage: "The number of ending block for tracing (excluded)", + Category: flags.TestingCategory, + } + traceTestInvalidOutputFlag = &cli.StringFlag{ + Name: "trace-invalid", + Usage: "Folder containing the mismatched trace output files", + Value: "", + Category: flags.TestingCategory, + } +) + +func generateTraceTests(clictx *cli.Context) error { + var ( + client = makeClient(clictx) + outputFile = clictx.String(traceTestFileFlag.Name) + outputDir = clictx.String(traceTestResultOutputFlag.Name) + startBlock = clictx.Int(traceTestStartBlockFlag.Name) + endBlock = clictx.Int(traceTestEndBlockFlag.Name) + ctx = context.Background() + test = new(traceTest) + ) + latest, err := client.Eth.BlockNumber(ctx) + if err != nil { + exit(err) + } + if startBlock > endBlock { + exit(fmt.Errorf("invalid block range for tracing, start: %d, end: %d", startBlock, endBlock)) + } + if endBlock-startBlock == 0 { + exit(fmt.Errorf("invalid block range for tracing, start: %d, end: %d", startBlock, endBlock)) + } + if latest < uint64(startBlock) || latest < uint64(endBlock) { + exit(fmt.Errorf("node seems not synced, latest block is %d", latest)) + } + // Get blocks and assign block info into the test + var ( + start = time.Now() + logged = time.Now() + failed int + ) + log.Info("Trace transactions around the chain tip", "head", latest, "start", startBlock, "end", endBlock) + + for i := startBlock; i < endBlock; i++ { + header, err := client.Eth.HeaderByNumber(ctx, big.NewInt(int64(i))) + if err != nil { + exit(err) + } + config, configName := randomTraceOption() + result, err := client.Geth.TraceBlock(ctx, header.Hash(), config) + if err != nil { + failed += 1 + continue + } + blob, err := json.Marshal(result) + if err != nil { + failed += 1 + continue + } + test.BlockHashes = append(test.BlockHashes, header.Hash()) + test.TraceConfigs = append(test.TraceConfigs, *config) + test.ResultHashes = append(test.ResultHashes, crypto.Keccak256Hash(blob)) + writeTraceResult(outputDir, header.Hash(), result, configName) + + if time.Since(logged) > time.Second*8 { + logged = time.Now() + log.Info("Tracing blocks", "executed", len(test.BlockHashes), "failed", failed, "elapsed", common.PrettyDuration(time.Since(start))) + } + } + log.Info("Traced blocks", "executed", len(test.BlockHashes), "failed", failed, "elapsed", common.PrettyDuration(time.Since(start))) + + // Write output file. + writeJSON(outputFile, test) + return nil +} + +func randomTraceOption() (*tracers.TraceConfig, string) { + x := rand.Intn(10) + if x == 0 { + // default options for struct-logger, with stack and storage capture + // enabled + return &tracers.TraceConfig{ + Config: &logger.Config{}, + }, "structDefault" + } + if x >= 1 && x <= 3 { + // struct-logger with storage capture enabled + return &tracers.TraceConfig{ + Config: &logger.Config{ + DisableStack: true, + }, + }, "structStorage" + } + // Native tracer + loggers := []string{"callTracer", "4byteTracer", "flatCallTracer", "muxTracer", "noopTracer", "prestateTracer"} + return &tracers.TraceConfig{ + Tracer: &loggers[x-4], + }, loggers[x-4] +} + +func writeTraceResult(dir string, hash common.Hash, result any, configName string) { + if dir == "" { + return + } + // Ensure the directory exists + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + exit(fmt.Errorf("failed to create directories: %w", err)) + } + name := filepath.Join(dir, configName+"_"+hash.String()) + file, err := os.Create(name) + if err != nil { + exit(fmt.Errorf("error creating %s: %v", name, err)) + return + } + defer file.Close() + + data, _ := json.MarshalIndent(result, "", " ") + _, err = file.Write(data) + if err != nil { + exit(fmt.Errorf("error writing %s: %v", name, err)) + return + } +} diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index f9a5a3233bc7..196cbc857ce0 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -391,8 +391,12 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea if err != nil { return nil, fmt.Errorf("error opening pre-state tree root: %w", err) } + postTrie := state.GetTrie() + if postTrie == nil { + return nil, errors.New("post-state tree is not available") + } vktPreTrie, okpre := preTrie.(*trie.VerkleTrie) - vktPostTrie, okpost := state.GetTrie().(*trie.VerkleTrie) + vktPostTrie, okpost := postTrie.(*trie.VerkleTrie) // The witness is only attached iff both parent and current block are // using verkle tree. diff --git a/consensus/clique/clique_test.go b/consensus/clique/clique_test.go index bacd2074931e..afcab1d1f763 100644 --- a/consensus/clique/clique_test.go +++ b/consensus/clique/clique_test.go @@ -24,7 +24,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" ) @@ -55,7 +54,7 @@ func TestReimportMirroredState(t *testing.T) { copy(genspec.ExtraData[extraVanity:], addr[:]) // Generate a batch of blocks, each properly signed - chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, engine, vm.Config{}, nil) + chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), genspec, engine, nil) defer chain.Stop() _, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) { @@ -87,7 +86,7 @@ func TestReimportMirroredState(t *testing.T) { } // Insert the first two blocks and make sure the chain is valid db = rawdb.NewMemoryDatabase() - chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil) + chain, _ = core.NewBlockChain(db, genspec, engine, nil) defer chain.Stop() if _, err := chain.InsertChain(blocks[:2]); err != nil { @@ -100,7 +99,7 @@ func TestReimportMirroredState(t *testing.T) { // Simulate a crash by creating a new chain on top of the database, without // flushing the dirty states out. Insert the last block, triggering a sidechain // reimport. - chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil) + chain, _ = core.NewBlockChain(db, genspec, engine, nil) defer chain.Stop() if _, err := chain.InsertChain(blocks[2:]); err != nil { diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go index a83d6ca736ed..ac2355c730c2 100644 --- a/consensus/clique/snapshot_test.go +++ b/consensus/clique/snapshot_test.go @@ -28,7 +28,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" ) @@ -458,7 +457,7 @@ func (tt *cliqueTest) run(t *testing.T) { batches[len(batches)-1] = append(batches[len(batches)-1], block) } // Pass all the headers through clique and ensure tallying succeeds - chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil) + chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, nil) if err != nil { t.Fatalf("failed to create test chain: %v", err) } diff --git a/consensus/misc/eip4844/eip4844.go b/consensus/misc/eip4844/eip4844.go index 32b34f4e53d6..fc143027dd9f 100644 --- a/consensus/misc/eip4844/eip4844.go +++ b/consensus/misc/eip4844/eip4844.go @@ -23,7 +23,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/params/forks" ) var ( @@ -71,52 +70,82 @@ func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header, headTim parentExcessBlobGas = *parent.ExcessBlobGas parentBlobGasUsed = *parent.BlobGasUsed } - excessBlobGas := parentExcessBlobGas + parentBlobGasUsed - targetGas := uint64(targetBlobsPerBlock(config, headTimestamp)) * params.BlobTxBlobGasPerBlob + var ( + excessBlobGas = parentExcessBlobGas + parentBlobGasUsed + target = targetBlobsPerBlock(config, headTimestamp) + targetGas = uint64(target) * params.BlobTxBlobGasPerBlob + ) if excessBlobGas < targetGas { return 0 } + if !config.IsOsaka(config.LondonBlock, headTimestamp) { + // Pre-Osaka, we use the formula defined by EIP-4844. + return excessBlobGas - targetGas + } + + // EIP-7918 (post-Osaka) introduces a different formula for computing excess. + var ( + baseCost = big.NewInt(params.BlobBaseCost) + reservePrice = baseCost.Mul(baseCost, parent.BaseFee) + blobPrice = calcBlobPrice(config, parent) + ) + if reservePrice.Cmp(blobPrice) > 0 { + max := MaxBlobsPerBlock(config, headTimestamp) + scaledExcess := parentBlobGasUsed * uint64(max-target) / uint64(max) + return parentExcessBlobGas + scaledExcess + } return excessBlobGas - targetGas } // CalcBlobFee calculates the blobfee from the header's excess blob gas field. func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int { - var frac uint64 - switch config.LatestFork(header.Time) { - case forks.Osaka: - frac = config.BlobScheduleConfig.Osaka.UpdateFraction - case forks.Prague: - frac = config.BlobScheduleConfig.Prague.UpdateFraction - case forks.Cancun: - frac = config.BlobScheduleConfig.Cancun.UpdateFraction - default: + blobConfig := latestBlobConfig(config, header.Time) + if blobConfig == nil { panic("calculating blob fee on unsupported fork") } - return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(frac)) + return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(blobConfig.UpdateFraction)) } // MaxBlobsPerBlock returns the max blobs per block for a block at the given timestamp. func MaxBlobsPerBlock(cfg *params.ChainConfig, time uint64) int { - if cfg.BlobScheduleConfig == nil { + blobConfig := latestBlobConfig(cfg, time) + if blobConfig == nil { return 0 } + return blobConfig.Max +} + +func latestBlobConfig(cfg *params.ChainConfig, time uint64) *params.BlobConfig { + if cfg.BlobScheduleConfig == nil { + return nil + } var ( london = cfg.LondonBlock s = cfg.BlobScheduleConfig ) switch { + case cfg.IsBPO5(london, time) && s.BPO5 != nil: + return s.BPO5 + case cfg.IsBPO4(london, time) && s.BPO4 != nil: + return s.BPO4 + case cfg.IsBPO3(london, time) && s.BPO3 != nil: + return s.BPO3 + case cfg.IsBPO2(london, time) && s.BPO2 != nil: + return s.BPO2 + case cfg.IsBPO1(london, time) && s.BPO1 != nil: + return s.BPO1 case cfg.IsOsaka(london, time) && s.Osaka != nil: - return s.Osaka.Max + return s.Osaka case cfg.IsPrague(london, time) && s.Prague != nil: - return s.Prague.Max + return s.Prague case cfg.IsCancun(london, time) && s.Cancun != nil: - return s.Cancun.Max + return s.Cancun default: - return 0 + return nil } } -// MaxBlobsPerBlock returns the maximum blob gas that can be spent in a block at the given timestamp. +// MaxBlobGasPerBlock returns the maximum blob gas that can be spent in a block at the given timestamp. func MaxBlobGasPerBlock(cfg *params.ChainConfig, time uint64) uint64 { return uint64(MaxBlobsPerBlock(cfg, time)) * params.BlobTxBlobGasPerBlob } @@ -129,6 +158,16 @@ func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int { return 0 } switch { + case s.BPO5 != nil: + return s.BPO5.Max + case s.BPO4 != nil: + return s.BPO4.Max + case s.BPO3 != nil: + return s.BPO3.Max + case s.BPO2 != nil: + return s.BPO2.Max + case s.BPO1 != nil: + return s.BPO1.Max case s.Osaka != nil: return s.Osaka.Max case s.Prague != nil: @@ -142,23 +181,11 @@ func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int { // targetBlobsPerBlock returns the target number of blobs in a block at the given timestamp. func targetBlobsPerBlock(cfg *params.ChainConfig, time uint64) int { - if cfg.BlobScheduleConfig == nil { - return 0 - } - var ( - london = cfg.LondonBlock - s = cfg.BlobScheduleConfig - ) - switch { - case cfg.IsOsaka(london, time) && s.Osaka != nil: - return s.Osaka.Target - case cfg.IsPrague(london, time) && s.Prague != nil: - return s.Prague.Target - case cfg.IsCancun(london, time) && s.Cancun != nil: - return s.Cancun.Target - default: + blobConfig := latestBlobConfig(cfg, time) + if blobConfig == nil { return 0 } + return blobConfig.Target } // fakeExponential approximates factor * e ** (numerator / denominator) using @@ -177,3 +204,9 @@ func fakeExponential(factor, numerator, denominator *big.Int) *big.Int { } return output.Div(output, denominator) } + +// calcBlobPrice calculates the blob price for a block. +func calcBlobPrice(config *params.ChainConfig, header *types.Header) *big.Int { + blobBaseFee := CalcBlobFee(config, header) + return new(big.Int).Mul(blobBaseFee, big.NewInt(params.BlobTxBlobGasPerBlob)) +} diff --git a/consensus/misc/eip4844/eip4844_test.go b/consensus/misc/eip4844/eip4844_test.go index f4e3cb3d9a5c..555324db6568 100644 --- a/consensus/misc/eip4844/eip4844_test.go +++ b/consensus/misc/eip4844/eip4844_test.go @@ -127,3 +127,43 @@ func TestFakeExponential(t *testing.T) { } } } + +func TestCalcExcessBlobGasEIP7918(t *testing.T) { + var ( + cfg = params.MergedTestChainConfig + targetBlobs = targetBlobsPerBlock(cfg, *cfg.CancunTime) + blobGasTarget = uint64(targetBlobs) * params.BlobTxBlobGasPerBlob + ) + makeHeader := func(parentExcess, parentBaseFee uint64, blobsUsed int) *types.Header { + blobGasUsed := uint64(blobsUsed) * params.BlobTxBlobGasPerBlob + return &types.Header{ + BaseFee: big.NewInt(int64(parentBaseFee)), + ExcessBlobGas: &parentExcess, + BlobGasUsed: &blobGasUsed, + } + } + + tests := []struct { + name string + header *types.Header + wantExcessGas uint64 + }{ + { + name: "BelowReservePrice", + header: makeHeader(0, 1_000_000_000, targetBlobs), + wantExcessGas: blobGasTarget * 3 / 9, + }, + { + name: "AboveReservePrice", + header: makeHeader(0, 1, targetBlobs), + wantExcessGas: 0, + }, + } + for _, tc := range tests { + got := CalcExcessBlobGas(cfg, tc.header, *cfg.CancunTime) + if got != tc.wantExcessGas { + t.Fatalf("%s: excess-blob-gas mismatch – have %d, want %d", + tc.name, got, tc.wantExcessGas) + } + } +} diff --git a/core/bench_test.go b/core/bench_test.go index 155fa6c3b547..283002266209 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -26,7 +26,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/pebble" @@ -200,7 +199,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { // Time the insertion of the new chain. // State and blocks are stored in the same DB. - chainman, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + chainman, _ := NewBlockChain(db, gspec, ethash.NewFaker(), nil) defer chainman.Stop() b.ReportAllocs() b.ResetTimer() @@ -325,9 +324,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) { genesis := &Genesis{Config: params.AllEthashProtocolChanges} makeChainForBench(db, genesis, full, count) db.Close() - cacheConfig := *defaultCacheConfig - cacheConfig.TrieDirtyDisabled = true - + options := DefaultConfig().WithArchive(true) b.ReportAllocs() b.ResetTimer() @@ -338,7 +335,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) { } db = rawdb.NewDatabase(pdb) - chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil) + chain, err := NewBlockChain(db, genesis, ethash.NewFaker(), options) if err != nil { b.Fatalf("error creating chain: %v", err) } diff --git a/core/block_validator.go b/core/block_validator.go index 591e472bc1b0..008444fbbc45 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -49,6 +49,10 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain) *Bloc // header's transaction and uncle roots. The headers are assumed to be already // validated at this point. func (v *BlockValidator) ValidateBody(block *types.Block) error { + // check EIP 7934 RLP-encoded block size cap + if v.config.IsOsaka(block.Number(), block.Time()) && block.Size() > params.MaxBlockSize { + return ErrBlockOversized + } // Check whether the block is already imported. if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) { return ErrKnownBlock diff --git a/core/block_validator_test.go b/core/block_validator_test.go index 5217979236cf..fcc99effd0ef 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -28,7 +28,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" ) @@ -50,7 +49,8 @@ func testHeaderVerification(t *testing.T, scheme string) { headers[i] = block.Header() } // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(scheme) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), options) defer chain.Stop() if err != nil { t.Fatal(err) @@ -166,7 +166,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) { postHeaders[i] = block.Header() } // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil) defer chain.Stop() if err != nil { t.Fatal(err) diff --git a/core/blockchain.go b/core/blockchain.go index 64345bc1a351..2290b6d3cd5e 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -66,7 +66,7 @@ var ( headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil) chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil) - chainMgaspsGauge = metrics.NewRegisteredGauge("chain/mgasps", nil) + chainMgaspsMeter = metrics.NewRegisteredResettingTimer("chain/mgasps", nil) accountReadTimer = metrics.NewRegisteredResettingTimer("chain/account/reads", nil) accountHashTimer = metrics.NewRegisteredResettingTimer("chain/account/hashes", nil) @@ -77,6 +77,16 @@ var ( storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil) storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil) + accountCacheHitMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/process/hit", nil) + accountCacheMissMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/process/miss", nil) + storageCacheHitMeter = metrics.NewRegisteredMeter("chain/storage/reads/cache/process/hit", nil) + storageCacheMissMeter = metrics.NewRegisteredMeter("chain/storage/reads/cache/process/miss", nil) + + accountCacheHitPrefetchMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/prefetch/hit", nil) + accountCacheMissPrefetchMeter = metrics.NewRegisteredMeter("chain/account/reads/cache/prefetch/miss", nil) + storageCacheHitPrefetchMeter = metrics.NewRegisteredMeter("chain/storage/reads/cache/prefetch/hit", nil) + storageCacheMissPrefetchMeter = metrics.NewRegisteredMeter("chain/storage/reads/cache/prefetch/miss", nil) + accountReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/account/single/reads", nil) storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil) @@ -149,72 +159,104 @@ const ( BlockChainVersion uint64 = 9 ) -// CacheConfig contains the configuration values for the trie database -// and state snapshot these are resident in a blockchain. -type CacheConfig struct { - TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory - TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks - TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk - TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node) - TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk - SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory - Preimages bool // Whether to store preimage of trie key to the disk - StateHistory uint64 // Number of blocks from head whose state histories are reserved. - StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top - +// BlockChainConfig contains the configuration of the BlockChain object. +type BlockChainConfig struct { + // Trie database related options + TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory + TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk + TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk + TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed + + Preimages bool // Whether to store preimage of trie key to the disk + StateHistory uint64 // Number of blocks from head whose state histories are reserved. + StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top + ArchiveMode bool // Whether to enable the archive mode + + // State snapshot related options + SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory SnapshotNoBuild bool // Whether the background generation is allowed SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it // This defines the cutoff block for history expiry. // Blocks before this number may be unavailable in the chain database. ChainHistoryMode history.HistoryMode + + // Misc options + NoPrefetch bool // Whether to disable heuristic state prefetching when processing blocks + Overrides *ChainOverrides // Optional chain config overrides + VmConfig vm.Config // Config options for the EVM Interpreter + + // TxLookupLimit specifies the maximum number of blocks from head for which + // transaction hashes will be indexed. + // + // If the value is zero, all transactions of the entire chain will be indexed. + // If the value is -1, indexing is disabled. + TxLookupLimit int64 +} + +// DefaultConfig returns the default config. +// Note the returned object is safe to modify! +func DefaultConfig() *BlockChainConfig { + return &BlockChainConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + StateScheme: rawdb.HashScheme, + SnapshotLimit: 256, + SnapshotWait: true, + ChainHistoryMode: history.KeepAll, + // Transaction indexing is disabled by default. + // This is appropriate for most unit tests. + TxLookupLimit: -1, + } +} + +// WithArchive enables/disables archive mode on the config. +func (cfg BlockChainConfig) WithArchive(on bool) *BlockChainConfig { + cfg.ArchiveMode = on + return &cfg +} + +// WithStateScheme sets the state storage scheme on the config. +func (cfg BlockChainConfig) WithStateScheme(scheme string) *BlockChainConfig { + cfg.StateScheme = scheme + return &cfg +} + +// WithNoAsyncFlush enables/disables asynchronous buffer flushing mode on the config. +func (cfg BlockChainConfig) WithNoAsyncFlush(on bool) *BlockChainConfig { + cfg.TrieNoAsyncFlush = on + return &cfg } // triedbConfig derives the configures for trie database. -func (c *CacheConfig) triedbConfig(isVerkle bool) *triedb.Config { +func (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config { config := &triedb.Config{ - Preimages: c.Preimages, + Preimages: cfg.Preimages, IsVerkle: isVerkle, } - if c.StateScheme == rawdb.HashScheme { + if cfg.StateScheme == rawdb.HashScheme { config.HashDB = &hashdb.Config{ - CleanCacheSize: c.TrieCleanLimit * 1024 * 1024, + CleanCacheSize: cfg.TrieCleanLimit * 1024 * 1024, } } - if c.StateScheme == rawdb.PathScheme { + if cfg.StateScheme == rawdb.PathScheme { config.PathDB = &pathdb.Config{ - StateHistory: c.StateHistory, - TrieCleanSize: c.TrieCleanLimit * 1024 * 1024, - StateCleanSize: c.SnapshotLimit * 1024 * 1024, + StateHistory: cfg.StateHistory, + EnableStateIndexing: cfg.ArchiveMode, + TrieCleanSize: cfg.TrieCleanLimit * 1024 * 1024, + StateCleanSize: cfg.SnapshotLimit * 1024 * 1024, // TODO(rjl493456442): The write buffer represents the memory limit used // for flushing both trie data and state data to disk. The config name // should be updated to eliminate the confusion. - WriteBufferSize: c.TrieDirtyLimit * 1024 * 1024, + WriteBufferSize: cfg.TrieDirtyLimit * 1024 * 1024, + NoAsyncFlush: cfg.TrieNoAsyncFlush, } } return config } -// defaultCacheConfig are the default caching values if none are specified by the -// user (also used during testing). -var defaultCacheConfig = &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 256, - SnapshotWait: true, - StateScheme: rawdb.HashScheme, -} - -// DefaultCacheConfigWithScheme returns a deep copied default cache config with -// a provided trie node scheme. -func DefaultCacheConfigWithScheme(scheme string) *CacheConfig { - config := *defaultCacheConfig - config.StateScheme = scheme - return &config -} - // txLookup is wrapper over transaction lookup along with the corresponding // transaction object. type txLookup struct { @@ -238,7 +280,7 @@ type txLookup struct { // canonical chain. type BlockChain struct { chainConfig *params.ChainConfig // Chain & network configuration - cacheConfig *CacheConfig // Cache configuration for pruning + cfg *BlockChainConfig // Blockchain configuration db ethdb.Database // Low level persistent database to store final content in snaps *snapshot.Tree // Snapshot tree for fast trie leaf access @@ -272,21 +314,19 @@ type BlockChain struct { bodyCache *lru.Cache[common.Hash, *types.Body] bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] - receiptsCache *lru.Cache[common.Hash, []*types.Receipt] + receiptsCache *lru.Cache[common.Hash, []*types.Receipt] // Receipts cache with all fields derived blockCache *lru.Cache[common.Hash, *types.Block] txLookupLock sync.RWMutex txLookupCache *lru.Cache[common.Hash, txLookup] - 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 + stopping atomic.Bool // false if chain is running, true when stopped + procInterrupt atomic.Bool // interrupt signaler for block processing engine consensus.Engine validator Validator // Block and state validator interface prefetcher Prefetcher processor Processor // Block transaction processor interface - vmConfig vm.Config logger *tracing.Hooks lastForkReadyAlert time.Time // Last time there was a fork readiness print out @@ -295,22 +335,23 @@ type BlockChain struct { // NewBlockChain returns a fully initialised block chain using information // available in the database. It initialises the default Ethereum Validator // and Processor. -func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, txLookupLimit *uint64) (*BlockChain, error) { - if cacheConfig == nil { - cacheConfig = defaultCacheConfig +func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine, cfg *BlockChainConfig) (*BlockChain, error) { + if cfg == nil { + cfg = DefaultConfig() } + // Open trie database with provided config enableVerkle, err := EnableVerkleAtGenesis(db, genesis) if err != nil { return nil, err } - triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(enableVerkle)) + triedb := triedb.NewDatabase(db, cfg.triedbConfig(enableVerkle)) // Write the supplied genesis to the database if it has not been initialized // yet. The corresponding chain config will be returned, either from the // provided genesis or from the locally stored configuration if the genesis // has already been initialized. - chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) + chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, genesis, cfg.Overrides) if err != nil { return nil, err } @@ -324,11 +365,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis bc := &BlockChain{ chainConfig: chainConfig, - cacheConfig: cacheConfig, + cfg: cfg, db: db, triedb: triedb, triegc: prque.New[int64, common.Hash](nil), - quit: make(chan struct{}), chainmu: syncx.NewClosableMutex(), bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit), bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit), @@ -336,14 +376,13 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit), txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit), engine: engine, - vmConfig: vmConfig, - logger: vmConfig.Tracer, + logger: cfg.VmConfig.Tracer, } bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped) if err != nil { return nil, err } - bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit)) + bc.flushInterval.Store(int64(cfg.TrieTimeLimit)) bc.statedb = state.NewDatabase(bc.triedb, nil) bc.validator = NewBlockValidator(chainConfig, bc) bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc) @@ -392,7 +431,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis // Note it's unnecessary in path mode which always keep trie data and // state data consistent. var diskRoot common.Hash - if bc.cacheConfig.SnapshotLimit > 0 && bc.cacheConfig.StateScheme == rawdb.HashScheme { + if bc.cfg.SnapshotLimit > 0 && bc.cfg.StateScheme == rawdb.HashScheme { diskRoot = rawdb.ReadSnapshotRoot(bc.db) } if diskRoot != (common.Hash{}) { @@ -479,8 +518,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis } // Start tx indexer if it's enabled. - if txLookupLimit != nil { - bc.txIndexer = newTxIndexer(*txLookupLimit, bc) + if bc.cfg.TxLookupLimit >= 0 { + bc.txIndexer = newTxIndexer(uint64(bc.cfg.TxLookupLimit), bc) } return bc, nil } @@ -488,11 +527,11 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis func (bc *BlockChain) setupSnapshot() { // Short circuit if the chain is established with path scheme, as the // state snapshot has been integrated into path database natively. - if bc.cacheConfig.StateScheme == rawdb.PathScheme { + if bc.cfg.StateScheme == rawdb.PathScheme { return } // Load any existing snapshot, regenerating it if loading failed - if bc.cacheConfig.SnapshotLimit > 0 { + if bc.cfg.SnapshotLimit > 0 { // If the chain was rewound past the snapshot persistent layer (causing // a recovery block number to be persisted to disk), check if we're still // in recovery mode and in that case, don't invalidate the snapshot on a @@ -504,10 +543,10 @@ func (bc *BlockChain) setupSnapshot() { recover = true } snapconfig := snapshot.Config{ - CacheSize: bc.cacheConfig.SnapshotLimit, + CacheSize: bc.cfg.SnapshotLimit, Recovery: recover, - NoBuild: bc.cacheConfig.SnapshotNoBuild, - AsyncBuild: !bc.cacheConfig.SnapshotWait, + NoBuild: bc.cfg.SnapshotNoBuild, + AsyncBuild: !bc.cfg.SnapshotWait, } bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root) @@ -631,7 +670,7 @@ func (bc *BlockChain) loadLastState() error { func (bc *BlockChain) initializeHistoryPruning(latest uint64) error { freezerTail, _ := bc.db.Tail() - switch bc.cacheConfig.ChainHistoryMode { + switch bc.cfg.ChainHistoryMode { case history.KeepAll: if freezerTail == 0 { return nil @@ -652,7 +691,7 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error { // postmerge directly on an existing DB. We could just trigger the pruning // here, but it'd be a bit dangerous since they may not have intended this // action to happen. So just tell them how to do it. - log.Error(fmt.Sprintf("Chain history mode is configured as %q, but database is not pruned.", bc.cacheConfig.ChainHistoryMode.String())) + log.Error(fmt.Sprintf("Chain history mode is configured as %q, but database is not pruned.", bc.cfg.ChainHistoryMode.String())) log.Error(fmt.Sprintf("Run 'geth prune-history' to prune pre-merge history.")) return fmt.Errorf("history pruning requested via configuration") } @@ -668,7 +707,7 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error { return nil default: - return fmt.Errorf("invalid history mode: %d", bc.cacheConfig.ChainHistoryMode) + return fmt.Errorf("invalid history mode: %d", bc.cfg.ChainHistoryMode) } } @@ -1206,8 +1245,7 @@ func (bc *BlockChain) stopWithoutSaving() { bc.scope.Close() // Signal shutdown to all goroutines. - close(bc.quit) - bc.StopInsert() + bc.InterruptInsert(true) // Now wait for all chain modifications to end and persistent goroutines to exit. // @@ -1243,7 +1281,7 @@ func (bc *BlockChain) Stop() { // - HEAD: So we don't need to reprocess any blocks in the general case // - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle // - HEAD-127: So we have a hard limit on the number of blocks reexecuted - if !bc.cacheConfig.TrieDirtyDisabled { + if !bc.cfg.ArchiveMode { triedb := bc.triedb for _, offset := range []uint64{0, 1, state.TriesInMemory - 1} { @@ -1281,11 +1319,15 @@ func (bc *BlockChain) Stop() { log.Info("Blockchain stopped") } -// StopInsert interrupts all insertion methods, causing them to return -// errInsertionInterrupted as soon as possible. Insertion is permanently disabled after -// calling this method. -func (bc *BlockChain) StopInsert() { - bc.procInterrupt.Store(true) +// InterruptInsert interrupts all insertion methods, causing them to return +// errInsertionInterrupted as soon as possible, or resume the chain insertion +// if required. +func (bc *BlockChain) InterruptInsert(on bool) { + if on { + bc.procInterrupt.Store(true) + } else { + bc.procInterrupt.Store(false) + } } // insertStopped returns true after StopInsert has been called. @@ -1549,7 +1591,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. return nil } // If we're running an archive node, always flush - if bc.cacheConfig.TrieDirtyDisabled { + if bc.cfg.ArchiveMode { return bc.triedb.Commit(root, false) } // Full but not archive node, do proper garbage collection @@ -1564,7 +1606,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // If we exceeded our memory allowance, flush matured singleton nodes to disk var ( _, nodes, imgs = bc.triedb.Size() // all memory is contained within the nodes return for hashdb - limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024 + limit = common.StorageSize(bc.cfg.TrieDirtyLimit) * 1024 * 1024 ) if nodes > limit || imgs > 4*1024*1024 { bc.triedb.Cap(limit - ethdb.IdealBatchSize) @@ -1914,7 +1956,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s ) defer interrupt.Store(true) // terminate the prefetch at the end - if bc.cacheConfig.TrieCleanNoPrefetch { + if bc.cfg.NoPrefetch { statedb, err = state.New(parentRoot, bc.statedb) if err != nil { return nil, err @@ -1925,21 +1967,35 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s // // Note: the main processor and prefetcher share the same reader with a local // cache for mitigating the overhead of state access. - reader, err := bc.statedb.ReaderWithCache(parentRoot) + prefetch, process, err := bc.statedb.ReadersWithCacheStats(parentRoot) if err != nil { return nil, err } - throwaway, err := state.NewWithReader(parentRoot, bc.statedb, reader) + throwaway, err := state.NewWithReader(parentRoot, bc.statedb, prefetch) if err != nil { return nil, err } - statedb, err = state.NewWithReader(parentRoot, bc.statedb, reader) + statedb, err = state.NewWithReader(parentRoot, bc.statedb, process) if err != nil { return nil, err } + // Upload the statistics of reader at the end + defer func() { + stats := prefetch.GetStats() + accountCacheHitPrefetchMeter.Mark(stats.AccountHit) + accountCacheMissPrefetchMeter.Mark(stats.AccountMiss) + storageCacheHitPrefetchMeter.Mark(stats.StorageHit) + storageCacheMissPrefetchMeter.Mark(stats.StorageMiss) + stats = process.GetStats() + accountCacheHitMeter.Mark(stats.AccountHit) + accountCacheMissMeter.Mark(stats.AccountMiss) + storageCacheHitMeter.Mark(stats.StorageHit) + storageCacheMissMeter.Mark(stats.StorageMiss) + }() + go func(start time.Time, throwaway *state.StateDB, block *types.Block) { // Disable tracing for prefetcher executions. - vmCfg := bc.vmConfig + vmCfg := bc.cfg.VmConfig vmCfg.Tracer = nil bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt) @@ -1958,7 +2014,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s // Generate witnesses either if we're self-testing, or if it's the // only block being inserted. A bit crude, but witnesses are huge, // so we refuse to make an entire chain of them. - if bc.vmConfig.StatelessSelfValidation || makeWitness { + if bc.cfg.VmConfig.StatelessSelfValidation || makeWitness { witness, err = stateless.NewWitness(block.Header(), bc) if err != nil { return nil, err @@ -1983,7 +2039,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s // Process block using the parent state as reference point pstart := time.Now() - res, err := bc.processor.Process(block, statedb, bc.vmConfig) + res, err := bc.processor.Process(block, statedb, bc.cfg.VmConfig) if err != nil { bc.reportBlock(block, res, err) return nil, err @@ -2003,7 +2059,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s // witness builder/runner, which would otherwise be impossible due to the // various invalid chain states/behaviors being contained in those tests. xvstart := time.Now() - if witness := statedb.Witness(); witness != nil && bc.vmConfig.StatelessSelfValidation { + if witness := statedb.Witness(); witness != nil && bc.cfg.VmConfig.StatelessSelfValidation { log.Warn("Running stateless self-validation", "block", block.Number(), "hash", block.Hash()) // Remove critical computed fields from the block to force true recalculation @@ -2014,7 +2070,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s task := types.NewBlockWithHeader(context).WithBody(*block.Body()) // Run the stateless self-cross-validation - crossStateRoot, crossReceiptRoot, err := ExecuteStateless(bc.chainConfig, bc.vmConfig, task, witness) + crossStateRoot, crossReceiptRoot, err := ExecuteStateless(bc.chainConfig, bc.cfg.VmConfig, task, witness) if err != nil { return nil, fmt.Errorf("stateless self-validation failed: %v", err) } @@ -2067,7 +2123,12 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits) - blockInsertTimer.UpdateSince(startTime) + elapsed := time.Since(startTime) + 1 // prevent zero division + blockInsertTimer.Update(elapsed) + + // TODO(rjl493456442) generalize the ResettingTimer + mgasps := float64(res.GasUsed) * 1000 / float64(elapsed) + chainMgaspsMeter.Update(time.Duration(mgasps)) return &blockProcessingResult{ usedGas: res.GasUsed, diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index d7c2696f0851..ac6a156d3eb1 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -46,9 +46,6 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn elapsed = now.Sub(st.startTime) + 1 // prevent zero division mgasps = float64(st.usedGas) * 1000 / float64(elapsed) ) - // Update the Mgas per second gauge - chainMgaspsGauge.Update(int64(mgasps)) - // If we're at the last block of the batch or report period reached, log if index == len(chain)-1 || elapsed >= statsReportLimit { // Count the number of transactions in this segment diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index c54948122d4c..7626e9e30d28 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -18,9 +18,12 @@ package core import ( "errors" + "fmt" + "math/big" "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/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state/snapshot" @@ -213,6 +216,44 @@ func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*type return } +// GetCanonicalReceipt allows fetching a receipt for a transaction that was +// already looked up on the index. Notably, only receipt in canonical chain +// is visible. +func (bc *BlockChain) GetCanonicalReceipt(tx *types.Transaction, blockHash common.Hash, blockNumber, txIndex uint64) (*types.Receipt, error) { + // The receipt retrieved from the cache contains all previously derived fields + if receipts, ok := bc.receiptsCache.Get(blockHash); ok { + if int(txIndex) >= len(receipts) { + return nil, fmt.Errorf("receipt out of index, length: %d, index: %d", len(receipts), txIndex) + } + return receipts[int(txIndex)], nil + } + header := bc.GetHeader(blockHash, blockNumber) + if header == nil { + return nil, fmt.Errorf("block header is not found, %d, %x", blockNumber, blockHash) + } + var blobGasPrice *big.Int + if header.ExcessBlobGas != nil { + blobGasPrice = eip4844.CalcBlobFee(bc.chainConfig, header) + } + receipt, ctx, err := rawdb.ReadCanonicalRawReceipt(bc.db, blockHash, blockNumber, txIndex) + if err != nil { + return nil, err + } + signer := types.MakeSigner(bc.chainConfig, new(big.Int).SetUint64(blockNumber), header.Time) + receipt.DeriveFields(signer, types.DeriveReceiptContext{ + BlockHash: blockHash, + BlockNumber: blockNumber, + BlockTime: header.Time, + BaseFee: header.BaseFee, + BlobGasPrice: blobGasPrice, + GasUsed: ctx.GasUsed, + LogIndex: ctx.LogIndex, + Tx: tx, + TxIndex: uint(txIndex), + }) + return receipt, nil +} + // GetReceiptsByHash retrieves the receipts for all transactions in a given block. func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { if receipts, ok := bc.receiptsCache.Get(hash); ok { @@ -277,13 +318,15 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) } -// GetTransactionLookup retrieves the lookup along with the transaction +// GetCanonicalTransaction retrieves the lookup along with the transaction // itself associate with the given transaction hash. // // A null will be returned if the transaction is not found. This can be due to // the transaction indexer not being finished. The caller must explicitly check // the indexer progress. -func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction) { +// +// Notably, only the transaction in the canonical chain is visible. +func (bc *BlockChain) GetCanonicalTransaction(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction) { bc.txLookupLock.RLock() defer bc.txLookupLock.RUnlock() @@ -291,7 +334,7 @@ func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLoo if item, exist := bc.txLookupCache.Get(hash); exist { return item.lookup, item.transaction } - tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash) + tx, blockHash, blockNumber, txIndex := rawdb.ReadCanonicalTransaction(bc.db, hash) if tx == nil { return nil, nil } @@ -370,6 +413,13 @@ func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { return state.New(root, bc.statedb) } +// HistoricState returns a historic state specified by the given root. +// Live states are not available and won't be served, please use `State` +// or `StateAt` instead. +func (bc *BlockChain) HistoricState(root common.Hash) (*state.StateDB, error) { + return state.New(root, state.NewHistoricDatabase(bc.db, bc.triedb)) +} + // Config retrieves the chain's fork configuration. func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } @@ -408,7 +458,7 @@ func (bc *BlockChain) Genesis() *types.Block { // GetVMConfig returns the block chain VM config. func (bc *BlockChain) GetVMConfig() *vm.Config { - return &bc.vmConfig + return &bc.cfg.VmConfig } // TxIndexProgress returns the transaction indexing progress. @@ -419,6 +469,11 @@ func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) { return bc.txIndexer.txIndexProgress(), nil } +// StateIndexProgress returns the historical state indexing progress. +func (bc *BlockChain) StateIndexProgress() (uint64, error) { + return bc.triedb.IndexProgress() +} + // HistoryPruningCutoff returns the configured history pruning point. // Blocks before this might not be available in the database. func (bc *BlockChain) HistoryPruningCutoff() (uint64, common.Hash) { diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 9661cee4c7b2..55794c659605 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -30,7 +30,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/params" ) @@ -1782,20 +1781,21 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s Config: params.AllEthashProtocolChanges, } engine = ethash.NewFullFaker() - config = &CacheConfig{ + option = &BlockChainConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, // Disable snapshot by default + SnapshotLimit: 0, // disable snapshot by default + TxLookupLimit: -1, // disable tx indexing StateScheme: scheme, } ) defer engine.Close() if snapshots && scheme == rawdb.HashScheme { - config.SnapshotLimit = 256 - config.SnapshotWait = true + option.SnapshotLimit = 256 + option.SnapshotWait = true } - chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(db, gspec, engine, option) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -1860,7 +1860,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s } defer db.Close() - newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil) + newChain, err := NewBlockChain(db, gspec, engine, option) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -1931,9 +1931,10 @@ func testIssue23496(t *testing.T, scheme string) { Config: params.TestChainConfig, BaseFee: big.NewInt(params.InitialBaseFee), } - engine = ethash.NewFullFaker() + engine = ethash.NewFullFaker() + options = DefaultConfig().WithStateScheme(scheme) ) - chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(db, gspec, engine, options) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -1985,7 +1986,7 @@ func testIssue23496(t *testing.T, scheme string) { } defer db.Close() - chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) + chain, err = NewBlockChain(db, gspec, engine, DefaultConfig().WithStateScheme(scheme)) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index b094ed3b6503..72ca15d7f614 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -32,7 +32,6 @@ 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/core/vm" "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/triedb" @@ -1985,20 +1984,21 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges, } - engine = ethash.NewFullFaker() - config = &CacheConfig{ + engine = ethash.NewFullFaker() + options = &BlockChainConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, // Disable snapshot + SnapshotLimit: 0, // disable snapshot + TxLookupLimit: -1, // disable tx indexing StateScheme: scheme, } ) if snapshots { - config.SnapshotLimit = 256 - config.SnapshotWait = true + options.SnapshotLimit = 256 + options.SnapshotWait = true } - chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(db, gspec, engine, options) if err != nil { t.Fatalf("Failed to create chain: %v", err) } diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go index e12a0c67c4e2..ae9398b97d90 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/blockchain_snapshot_test.go @@ -33,7 +33,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/params" @@ -82,7 +81,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo } engine = ethash.NewFullFaker() ) - chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(basic.scheme), gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(db, gspec, engine, DefaultConfig().WithStateScheme(basic.scheme).WithNoAsyncFlush(true)) if err != nil { t.Fatalf("Failed to create chain: %v", err) } @@ -233,7 +232,7 @@ func (snaptest *snapshotTest) test(t *testing.T) { // Restart the chain normally chain.Stop() - newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + newchain, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme)) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -275,13 +274,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) { // the crash, we do restart twice here: one after the crash and one // after the normal stop. It's used to ensure the broken snapshot // can be detected all the time. - newchain, err := NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + newchain, err := NewBlockChain(newdb, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme)) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } newchain.Stop() - newchain, err = NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + newchain, err = NewBlockChain(newdb, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme)) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -311,14 +310,15 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) { gappedBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.gapped, func(i int, b *BlockGen) {}) // Insert a few more blocks without enabling snapshot - var cacheConfig = &CacheConfig{ + var options = &BlockChainConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, StateScheme: snaptest.scheme, + TxLookupLimit: -1, } - newchain, err := NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + newchain, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, options) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -326,7 +326,8 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) { newchain.Stop() // Restart the chain with enabling the snapshot - newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + options = DefaultConfig().WithStateScheme(snaptest.scheme) + newchain, err = NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, options) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -354,7 +355,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) { chain.SetHead(snaptest.setHead) chain.Stop() - newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + newchain, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme)) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -383,14 +384,15 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) { // and state committed. chain.Stop() - config := &CacheConfig{ + config := &BlockChainConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 0, StateScheme: snaptest.scheme, + TxLookupLimit: -1, } - newchain, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + newchain, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, config) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -399,15 +401,16 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) { newchain.Stop() // Restart the chain, the wiper should start working - config = &CacheConfig{ + config = &BlockChainConfig{ TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, SnapshotLimit: 256, SnapshotWait: false, // Don't wait rebuild StateScheme: snaptest.scheme, + TxLookupLimit: -1, } - tmp, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + tmp, err := NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, config) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -416,7 +419,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) { tmp.triedb.Close() tmp.stopWithoutSaving() - newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) + newchain, err = NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme)) if err != nil { t.Fatalf("Failed to recreate chain: %v", err) } @@ -569,7 +572,7 @@ func TestHighCommitCrashWithNewSnapshot(t *testing.T) { // // Expected head header : C8 // Expected head fast block: C8 - // Expected head block : G (Hash mode), C6 (Hash mode) + // Expected head block : G (Hash mode), C6 (Path mode) // Expected snapshot disk : C4 (Hash mode) for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { expHead := uint64(0) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 2401402f3211..5e768fccdfc4 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -25,10 +25,12 @@ import ( "math/rand" "os" "path" + "reflect" "sync" "testing" "time" + "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/beacon" @@ -46,6 +48,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" + "github.com/stretchr/testify/assert" ) // So we can deterministically seed different blockchains @@ -66,7 +69,8 @@ func newCanonical(engine consensus.Engine, n int, full bool, scheme string) (eth } ) // Initialize a fresh chain with only a genesis block - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(scheme) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, options) // Create and inject the requested chain if n == 0 { @@ -723,7 +727,7 @@ func testFastVsFullChains(t *testing.T, scheme string) { }) // Import the chain as an archive node for the comparison baseline archiveDb := rawdb.NewMemoryDatabase() - archive, _ := NewBlockChain(archiveDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + archive, _ := NewBlockChain(archiveDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer archive.Stop() if n, err := archive.InsertChain(blocks); err != nil { @@ -731,7 +735,7 @@ func testFastVsFullChains(t *testing.T, scheme string) { } // Fast import the chain as a non-archive node to test fastDb := rawdb.NewMemoryDatabase() - fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + fast, _ := NewBlockChain(fastDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer fast.Stop() if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil { @@ -744,7 +748,7 @@ func testFastVsFullChains(t *testing.T, scheme string) { } defer ancientDb.Close() - ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + ancient, _ := NewBlockChain(ancientDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer ancient.Stop() if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(len(blocks)/2)); err != nil { @@ -851,11 +855,8 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { archiveDb := makeDb() defer archiveDb.Close() - archiveCaching := *defaultCacheConfig - archiveCaching.TrieDirtyDisabled = true - archiveCaching.StateScheme = scheme - - archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + options := DefaultConfig().WithArchive(true).WithStateScheme(scheme) + archive, _ := NewBlockChain(archiveDb, gspec, ethash.NewFaker(), options) if n, err := archive.InsertChain(blocks); err != nil { t.Fatalf("failed to process block %d: %v", n, err) } @@ -868,7 +869,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { // Import the chain as a non-archive node and ensure all pointers are updated fastDb := makeDb() defer fastDb.Close() - fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + fast, _ := NewBlockChain(fastDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer fast.Stop() if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil { @@ -881,7 +882,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { // Import the chain as a ancient-first node and ensure all pointers are updated ancientDb := makeDb() defer ancientDb.Close() - ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + ancient, _ := NewBlockChain(ancientDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer ancient.Stop() if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(3*len(blocks)/4)); err != nil { @@ -902,7 +903,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { for i, block := range blocks { headers[i] = block.Header() } - light, _ := NewBlockChain(lightDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + light, _ := NewBlockChain(lightDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) if n, err := light.InsertHeaderChain(headers); err != nil { t.Fatalf("failed to insert header %d: %v", n, err) } @@ -975,7 +976,7 @@ func testChainTxReorgs(t *testing.T, scheme string) { }) // Import the chain. This runs all block validation rules. db := rawdb.NewMemoryDatabase() - blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + blockchain, _ := NewBlockChain(db, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) if i, err := blockchain.InsertChain(chain); err != nil { t.Fatalf("failed to insert original chain[%d]: %v", i, err) } @@ -1006,29 +1007,47 @@ func testChainTxReorgs(t *testing.T, scheme string) { // removed tx for i, tx := range (types.Transactions{pastDrop, freshDrop}) { - if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { + if txn, _, _, _ := rawdb.ReadCanonicalTransaction(db, tx.Hash()); txn != nil { t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) } - if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt != nil { + if rcpt, _, _, _ := rawdb.ReadCanonicalReceipt(db, tx.Hash(), blockchain.Config()); rcpt != nil { t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) } } // added tx for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { - if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { + if txn, _, _, _ := rawdb.ReadCanonicalTransaction(db, tx.Hash()); txn == nil { t.Errorf("add %d: expected tx to be found", i) } - if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { + if rcpt, _, _, index := rawdb.ReadCanonicalReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { t.Errorf("add %d: expected receipt to be found", i) + } else if rawRcpt, ctx, _ := rawdb.ReadCanonicalRawReceipt(db, rcpt.BlockHash, rcpt.BlockNumber.Uint64(), index); rawRcpt == nil { + t.Errorf("add %d: expected raw receipt to be found", i) + } else { + if rcpt.GasUsed != ctx.GasUsed { + t.Errorf("add %d, raw gasUsedSoFar doesn't make sense", i) + } + if len(rcpt.Logs) > 0 && rcpt.Logs[0].Index != ctx.LogIndex { + t.Errorf("add %d, raw startingLogIndex doesn't make sense", i) + } } } // shared tx for i, tx := range (types.Transactions{postponed, swapped}) { - if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { + if txn, _, _, _ := rawdb.ReadCanonicalTransaction(db, tx.Hash()); txn == nil { t.Errorf("share %d: expected tx to be found", i) } - if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { + if rcpt, _, _, index := rawdb.ReadCanonicalReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { t.Errorf("share %d: expected receipt to be found", i) + } else if rawRcpt, ctx, _ := rawdb.ReadCanonicalRawReceipt(db, rcpt.BlockHash, rcpt.BlockNumber.Uint64(), index); rawRcpt == nil { + t.Errorf("add %d: expected raw receipt to be found", i) + } else { + if rcpt.GasUsed != ctx.GasUsed { + t.Errorf("add %d, raw gasUsedSoFar doesn't make sense", i) + } + if len(rcpt.Logs) > 0 && rcpt.Logs[0].Index != ctx.LogIndex { + t.Errorf("add %d, raw startingLogIndex doesn't make sense", i) + } } } } @@ -1049,7 +1068,7 @@ func testLogReorgs(t *testing.T, scheme string) { signer = types.LatestSigner(gspec.Config) ) - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer blockchain.Stop() rmLogsCh := make(chan RemovedLogsEvent) @@ -1105,7 +1124,7 @@ func testLogRebirth(t *testing.T, scheme string) { gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} signer = types.LatestSigner(gspec.Config) engine = ethash.NewFaker() - blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) + blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, DefaultConfig().WithStateScheme(scheme)) ) defer blockchain.Stop() @@ -1186,7 +1205,7 @@ func testSideLogRebirth(t *testing.T, scheme string) { addr1 = crypto.PubkeyToAddress(key1.PublicKey) gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} signer = types.LatestSigner(gspec.Config) - blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) ) defer blockchain.Stop() @@ -1385,7 +1404,7 @@ func testEIP155Transition(t *testing.T, scheme string) { } }) - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer blockchain.Stop() if _, err := blockchain.InsertChain(blocks); err != nil { @@ -1478,7 +1497,7 @@ func testEIP161AccountRemoval(t *testing.T, scheme string) { block.AddTx(tx) }) // account must exist pre eip 161 - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer blockchain.Stop() if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { @@ -1536,7 +1555,7 @@ func testBlockchainHeaderchainReorgConsistency(t *testing.T, scheme string) { } // Import the canonical and fork chain side by side, verifying the current block // and current header consistency - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, DefaultConfig().WithStateScheme(scheme)) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1580,7 +1599,7 @@ func TestTrieForkGC(t *testing.T) { forks[i] = fork[0] } // Import the canonical and fork chain side by side, forcing the trie cache to cache both - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1626,7 +1645,7 @@ func testLargeReorgTrieGC(t *testing.T, scheme string) { db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer db.Close() - chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(db, genesis, engine, DefaultConfig().WithStateScheme(scheme)) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1694,7 +1713,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) { t.Fatalf("failed to create temp freezer db: %v", err) } defer ancientDb.Close() - ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + ancient, _ := NewBlockChain(ancientDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(3*len(blocks)/4)); err != nil { t.Fatalf("failed to insert receipt %d: %v", n, err) @@ -1707,7 +1726,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) { rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash()) // Reopen broken blockchain again - ancient, _ = NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + ancient, _ = NewBlockChain(ancientDb, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(scheme)) defer ancient.Stop() if num := ancient.CurrentBlock().Number.Uint64(); num != 0 { t.Errorf("head block mismatch: have #%v, want #%v", num, 0) @@ -1750,7 +1769,7 @@ func testLowDiffLongChain(t *testing.T, scheme string) { diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer diskdb.Close() - chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(diskdb, genesis, engine, DefaultConfig().WithStateScheme(scheme)) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1811,7 +1830,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon mergeBlock = gomath.MaxInt32 ) // Generate and import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1965,7 +1984,7 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) { } defer chaindb.Close() - chain, err := NewBlockChain(chaindb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(chaindb, genesis, engine, DefaultConfig().WithStateScheme(scheme)) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2128,7 +2147,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i } defer chaindb.Close() - chain, err := NewBlockChain(chaindb, nil, genesis, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(chaindb, genesis, engine, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2234,7 +2253,7 @@ func getLongAndShortChains(scheme string) (*BlockChain, []*types.Block, []*types genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, DefaultConfig().WithStateScheme(scheme)) if err != nil { return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) } @@ -2410,7 +2429,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in b.ResetTimer() for i := 0; i < b.N; i++ { // Import the shared chain and the original canonical one - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil) if err != nil { b.Fatalf("failed to create tester chain: %v", err) } @@ -2502,7 +2521,7 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) { } defer db.Close() - chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(db, genesis, engine, DefaultConfig().WithStateScheme(scheme)) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2601,7 +2620,8 @@ func testDeleteCreateRevert(t *testing.T, scheme string) { b.AddTx(tx) }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(scheme) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2714,9 +2734,11 @@ func testDeleteRecreateSlots(t *testing.T, scheme string) { b.AddTx(tx) }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ + options := DefaultConfig().WithStateScheme(scheme) + options.VmConfig = vm.Config{ Tracer: logger.NewJSONLogger(nil, os.Stdout), - }, nil) + } + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2796,9 +2818,11 @@ func testDeleteRecreateAccount(t *testing.T, scheme string) { b.AddTx(tx) }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ + options := DefaultConfig().WithStateScheme(scheme) + options.VmConfig = vm.Config{ Tracer: logger.NewJSONLogger(nil, os.Stdout), - }, nil) + } + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -2971,10 +2995,12 @@ func testDeleteRecreateSlotsAcrossManyBlocks(t *testing.T, scheme string) { current = exp }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ + options := DefaultConfig().WithStateScheme(scheme) + options.VmConfig = vm.Config{ //Debug: true, //Tracer: vm.NewJSONLogger(nil, os.Stdout), - }, nil) + } + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3109,10 +3135,12 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) { }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ + options := DefaultConfig().WithStateScheme(scheme) + options.VmConfig = vm.Config{ //Debug: true, //Tracer: vm.NewJSONLogger(nil, os.Stdout), - }, nil) + } + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3199,7 +3227,8 @@ func testEIP2718Transition(t *testing.T, scheme string) { }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(scheme) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3293,7 +3322,8 @@ func testEIP1559Transition(t *testing.T, scheme string) { b.AddTx(tx) }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(scheme) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3406,7 +3436,8 @@ func testSetCanonical(t *testing.T, scheme string) { diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer diskdb.Close() - chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(scheme) + chain, err := NewBlockChain(diskdb, gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3515,7 +3546,8 @@ func testCanonicalHashMarker(t *testing.T, scheme string) { _, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {}) // Initialize test chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(scheme) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3649,10 +3681,7 @@ func testCreateThenDelete(t *testing.T, config *params.ChainConfig) { nonce++ }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{ - //Debug: true, - //Tracer: logger.NewJSONLogger(nil, os.Stdout), - }, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3764,7 +3793,7 @@ func TestDeleteThenCreate(t *testing.T) { } }) // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3849,7 +3878,9 @@ func TestTransientStorageReset(t *testing.T) { }) // Initialize the blockchain with 1153 enabled. - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vmConfig, nil) + options := DefaultConfig() + options.VmConfig = vmConfig + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -3943,7 +3974,11 @@ func TestEIP3651(t *testing.T) { b.AddTx(tx) }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr).Hooks()}, nil) + options := DefaultConfig() + options.VmConfig = vm.Config{ + Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr).Hooks(), + } + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -4052,7 +4087,7 @@ func TestPragueRequests(t *testing.T) { } // Insert block to check validation. - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -4124,7 +4159,7 @@ func TestEIP7702(t *testing.T) { tx := types.MustSignNewTx(key1, signer, txdata) b.AddTx(tx) }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil) + chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -4202,7 +4237,8 @@ func testChainReorgSnapSync(t *testing.T, ancientLimit uint64) { db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer db.Close() - chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(rawdb.PathScheme) + chain, _ := NewBlockChain(db, gspec, beacon.New(ethash.NewFaker()), options) defer chain.Stop() if n, err := chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), ancientLimit); err != nil { @@ -4312,12 +4348,14 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64, }() // Enable pruning in cache config. - config := DefaultCacheConfigWithScheme(rawdb.PathScheme) + config := DefaultConfig().WithStateScheme(rawdb.PathScheme) config.ChainHistoryMode = history.KeepPostMerge db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) defer db.Close() - chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) + + options := DefaultConfig().WithStateScheme(rawdb.PathScheme) + chain, _ := NewBlockChain(db, genesis, beacon.New(ethash.NewFaker()), options) defer chain.Stop() var ( @@ -4387,6 +4425,93 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64, if receipts == nil || len(receipts) != 1 { t.Fatalf("Missed block receipts: %d, cutoff: %d", num, cutoffBlock.NumberU64()) } + for indx, receipt := range receipts { + receiptByLookup, err := chain.GetCanonicalReceipt(body.Transactions[indx], receipt.BlockHash, + receipt.BlockNumber.Uint64(), uint64(indx)) + assert.NoError(t, err) + assert.Equal(t, receipt, receiptByLookup) + } + } + } +} + +func TestGetCanonicalReceipt(t *testing.T) { + const chainLength = 64 + + // Configure and generate a sample block chain + var ( + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + address = crypto.PubkeyToAddress(key.PublicKey) + funds = big.NewInt(1000000000000000000) + gspec = &Genesis{ + Config: params.MergedTestChainConfig, + Alloc: types.GenesisAlloc{address: {Balance: funds}}, + BaseFee: big.NewInt(params.InitialBaseFee), + } + signer = types.LatestSigner(gspec.Config) + engine = beacon.New(ethash.NewFaker()) + codeBin = common.FromHex("0x608060405234801561000f575f5ffd5b507f8ae1c8c6e5f91159d0bc1c4b9a47ce45301753843012cbe641e4456bfc73538b33426040516100419291906100ff565b60405180910390a1610139565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100778261004e565b9050919050565b6100878161006d565b82525050565b5f819050919050565b61009f8161008d565b82525050565b5f82825260208201905092915050565b7f436f6e7374727563746f72207761732063616c6c6564000000000000000000005f82015250565b5f6100e96016836100a5565b91506100f4826100b5565b602082019050919050565b5f6060820190506101125f83018561007e565b61011f6020830184610096565b8181036040830152610130816100dd565b90509392505050565b603e806101455f395ff3fe60806040525f5ffdfea2646970667358221220e8bc3c31e3ac337eab702e8fdfc1c71894f4df1af4221bcde4a2823360f403fb64736f6c634300081e0033") + ) + _, blocks, receipts := GenerateChainWithGenesis(gspec, engine, chainLength, func(i int, block *BlockGen) { + // SPDX-License-Identifier: MIT + // pragma solidity ^0.8.0; + // + // contract ConstructorLogger { + // event ConstructorLog(address sender, uint256 timestamp, string message); + // + // constructor() { + // emit ConstructorLog(msg.sender, block.timestamp, "Constructor was called"); + // } + // } + // + // 608060405234801561000f575f5ffd5b507f8ae1c8c6e5f91159d0bc1c4b9a47ce45301753843012cbe641e4456bfc73538b33426040516100419291906100ff565b60405180910390a1610139565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100778261004e565b9050919050565b6100878161006d565b82525050565b5f819050919050565b61009f8161008d565b82525050565b5f82825260208201905092915050565b7f436f6e7374727563746f72207761732063616c6c6564000000000000000000005f82015250565b5f6100e96016836100a5565b91506100f4826100b5565b602082019050919050565b5f6060820190506101125f83018561007e565b61011f6020830184610096565b8181036040830152610130816100dd565b90509392505050565b603e806101455f395ff3fe60806040525f5ffdfea2646970667358221220e8bc3c31e3ac337eab702e8fdfc1c71894f4df1af4221bcde4a2823360f403fb64736f6c634300081e0033 + nonce := block.TxNonce(address) + tx, err := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 100_000, block.header.BaseFee, codeBin), signer, key) + if err != nil { + panic(err) + } + block.AddTx(tx) + + tx2, err := types.SignTx(types.NewContractCreation(nonce+1, big.NewInt(0), 100_000, block.header.BaseFee, codeBin), signer, key) + if err != nil { + panic(err) + } + block.AddTx(tx2) + + tx3, err := types.SignTx(types.NewContractCreation(nonce+2, big.NewInt(0), 100_000, block.header.BaseFee, codeBin), signer, key) + if err != nil { + panic(err) + } + block.AddTx(tx3) + }) + + db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{}) + defer db.Close() + options := DefaultConfig().WithStateScheme(rawdb.PathScheme) + chain, _ := NewBlockChain(db, gspec, beacon.New(ethash.NewFaker()), options) + defer chain.Stop() + + chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0) + + for i := 0; i < chainLength; i++ { + block := blocks[i] + blockReceipts := chain.GetReceiptsByHash(block.Hash()) + chain.receiptsCache.Purge() // ugly hack + for txIndex, tx := range block.Body().Transactions { + receipt, err := chain.GetCanonicalReceipt(tx, block.Hash(), block.NumberU64(), uint64(txIndex)) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + if !reflect.DeepEqual(receipts[i][txIndex], receipt) { + want := spew.Sdump(receipts[i][txIndex]) + got := spew.Sdump(receipt) + t.Fatalf("Receipt is not matched, want %s, got: %s", want, got) + } + if !reflect.DeepEqual(blockReceipts[txIndex], receipt) { + want := spew.Sdump(blockReceipts[txIndex]) + got := spew.Sdump(receipt) + t.Fatalf("Receipt is not matched, want %s, got: %s", want, got) + } } } } diff --git a/core/chain_makers.go b/core/chain_makers.go index 37bddcfda59d..b2559495a1a8 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -124,7 +124,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti } // Merge the tx-local access event into the "block-local" one, in order to collect // all values, so that the witness can be built. - if b.statedb.GetTrie().IsVerkle() { + if b.statedb.Database().TrieDB().IsVerkle() { b.statedb.AccessEvents().Merge(evm.AccessEvents) } b.txs = append(b.txs, tx) @@ -579,7 +579,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (common.Hash, ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) { db := rawdb.NewMemoryDatabase() - cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) + cacheConfig := DefaultConfig().WithStateScheme(rawdb.PathScheme) cacheConfig.SnapshotLimit = 0 triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true)) defer triedb.Close() diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index d81a52e9154c..cc9672199ec1 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -28,7 +28,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/triedb" @@ -119,7 +118,7 @@ func TestGeneratePOSChain(t *testing.T) { }) // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil) + blockchain, _ := NewBlockChain(db, gspec, engine, nil) defer blockchain.Stop() if i, err := blockchain.InsertChain(genchain); err != nil { @@ -234,7 +233,7 @@ func ExampleGenerateChain() { }) // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.HashScheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + blockchain, _ := NewBlockChain(db, gspec, ethash.NewFaker(), DefaultConfig().WithStateScheme(rawdb.HashScheme)) defer blockchain.Stop() if i, err := blockchain.InsertChain(chain); err != nil { diff --git a/core/dao_test.go b/core/dao_test.go index 5da9e91b036c..2d4a20e6b953 100644 --- a/core/dao_test.go +++ b/core/dao_test.go @@ -22,7 +22,6 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" ) @@ -50,7 +49,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { BaseFee: big.NewInt(params.InitialBaseFee), Config: &proConf, } - proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil) + proBc, _ := NewBlockChain(proDb, progspec, ethash.NewFaker(), nil) defer proBc.Stop() conDb := rawdb.NewMemoryDatabase() @@ -62,7 +61,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { BaseFee: big.NewInt(params.InitialBaseFee), Config: &conConf, } - conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil) + conBc, _ := NewBlockChain(conDb, congspec, ethash.NewFaker(), nil) defer conBc.Stop() if _, err := proBc.InsertChain(prefix); err != nil { @@ -74,7 +73,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { // Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ { // Create a pro-fork block, and try to feed into the no-fork chain - bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil) + bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), congspec, ethash.NewFaker(), nil) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64())) for j := 0; j < len(blocks)/2; j++ { @@ -97,7 +96,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err) } // Create a no-fork block, and try to feed into the pro-fork chain - bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil) + bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), progspec, ethash.NewFaker(), nil) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64())) for j := 0; j < len(blocks)/2; j++ { @@ -121,7 +120,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { } } // Verify that contra-forkers accept pro-fork extra-datas after forking finishes - bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil) + bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), congspec, ethash.NewFaker(), nil) defer bc.Stop() blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64())) @@ -139,7 +138,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err) } // Verify that pro-forkers accept contra-fork extra-datas after forking finishes - bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil) + bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), progspec, ethash.NewFaker(), nil) defer bc.Stop() blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64())) diff --git a/core/error.go b/core/error.go index de95e6463620..b9e894bd9b8e 100644 --- a/core/error.go +++ b/core/error.go @@ -28,6 +28,10 @@ var ( // ErrNoGenesis is returned when there is no Genesis Block. ErrNoGenesis = errors.New("genesis not found in chain") + + // ErrBlockOversized is returned if the size of the RLP-encoded block + // exceeds the cap established by EIP 7934 + ErrBlockOversized = errors.New("block RLP-encoded size exceeds maximum") ) // List of evm-call-message pre-checking errors. All state transition messages will @@ -122,6 +126,9 @@ var ( // Message validation errors: ErrEmptyAuthList = errors.New("EIP-7702 transaction with empty auth list") ErrSetCodeTxCreate = errors.New("EIP-7702 transaction cannot be used to create contract") + + // -- EIP-7825 errors -- + ErrGasLimitTooHigh = errors.New("transaction gas limit too high") ) // EIP-7702 state transition errors. diff --git a/core/filtermaps/chain_view.go b/core/filtermaps/chain_view.go index 433ca07cd0f8..7c48048ad954 100644 --- a/core/filtermaps/chain_view.go +++ b/core/filtermaps/chain_view.go @@ -55,7 +55,9 @@ func NewChainView(chain blockchain, number uint64, hash common.Hash) *ChainView headNumber: number, hashes: []common.Hash{hash}, } - cv.extendNonCanonical() + if !cv.extendNonCanonical() { + return nil + } return cv } @@ -129,7 +131,11 @@ func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] { return common.Range[uint64]{} } var sharedLen uint64 - for n := min(cv.headNumber+1-uint64(len(cv.hashes)), cv2.headNumber+1-uint64(len(cv2.hashes))); n <= cv.headNumber && n <= cv2.headNumber && cv.blockHash(n) == cv2.blockHash(n); n++ { + for n := min(cv.headNumber+1-uint64(len(cv.hashes)), cv2.headNumber+1-uint64(len(cv2.hashes))); n <= cv.headNumber && n <= cv2.headNumber; n++ { + h1, h2 := cv.blockHash(n), cv2.blockHash(n) + if h1 != h2 || h1 == (common.Hash{}) { + break + } sharedLen = n + 1 } return common.NewRange(0, sharedLen) @@ -153,10 +159,13 @@ func matchViews(cv1, cv2 *ChainView, number uint64) bool { if cv1.headNumber < number || cv2.headNumber < number { return false } + var h1, h2 common.Hash if number == cv1.headNumber || number == cv2.headNumber { - return cv1.BlockId(number) == cv2.BlockId(number) + h1, h2 = cv1.BlockId(number), cv2.BlockId(number) + } else { + h1, h2 = cv1.BlockHash(number), cv2.BlockHash(number) } - return cv1.BlockHash(number) == cv2.BlockHash(number) + return h1 == h2 && h1 != common.Hash{} } // extendNonCanonical checks whether the previously known reverse list of head @@ -175,7 +184,10 @@ func (cv *ChainView) extendNonCanonical() bool { } header := cv.chain.GetHeader(hash, number) if header == nil { - log.Error("Header not found", "number", number, "hash", hash) + // Header not found - this can happen after debug_setHead operations + // where blocks have been deleted. Return false to indicate the chain view + // is no longer valid rather than logging repeated errors. + log.Debug("Header not found during chain view extension", "number", number, "hash", hash) return false } cv.hashes = append(cv.hashes, header.ParentHash) diff --git a/core/filtermaps/filtermaps.go b/core/filtermaps/filtermaps.go index cb155e9a8b74..fede54df5745 100644 --- a/core/filtermaps/filtermaps.go +++ b/core/filtermaps/filtermaps.go @@ -185,11 +185,14 @@ type filterMapsRange struct { initialized bool headIndexed bool headDelimiter uint64 // zero if headIndexed is false + // if initialized then all maps are rendered in the maps range maps common.Range[uint32] + // if tailPartialEpoch > 0 then maps between firstRenderedMap-mapsPerEpoch and // firstRenderedMap-mapsPerEpoch+tailPartialEpoch-1 are rendered tailPartialEpoch uint32 + // if initialized then all log values in the blocks range are fully // rendered // blockLvPointers are available in the blocks range @@ -223,13 +226,15 @@ type Config struct { } // NewFilterMaps creates a new FilterMaps and starts the indexer. -func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, finalBlock uint64, params Params, config Config) *FilterMaps { +func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, finalBlock uint64, params Params, config Config) (*FilterMaps, error) { rs, initialized, err := rawdb.ReadFilterMapsRange(db) if err != nil || (initialized && rs.Version != databaseVersion) { rs, initialized = rawdb.FilterMapsRange{}, false log.Warn("Invalid log index database version; resetting log index") } - params.deriveFields() + if err := params.sanitize(); err != nil { + return nil, err + } f := &FilterMaps{ db: db, closeCh: make(chan struct{}), @@ -254,25 +259,24 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f }, // deleting last unindexed epoch might have been interrupted by shutdown cleanedEpochsBefore: max(rs.MapsFirst>>params.logMapsPerEpoch, 1) - 1, - - historyCutoff: historyCutoff, - finalBlock: finalBlock, - matcherSyncCh: make(chan *FilterMapsMatcherBackend), - matchers: make(map[*FilterMapsMatcherBackend]struct{}), - filterMapCache: lru.NewCache[uint32, filterMap](cachedFilterMaps), - lastBlockCache: lru.NewCache[uint32, lastBlockOfMap](cachedLastBlocks), - lvPointerCache: lru.NewCache[uint64, uint64](cachedLvPointers), - renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots), + historyCutoff: historyCutoff, + finalBlock: finalBlock, + matcherSyncCh: make(chan *FilterMapsMatcherBackend), + matchers: make(map[*FilterMapsMatcherBackend]struct{}), + filterMapCache: lru.NewCache[uint32, filterMap](cachedFilterMaps), + lastBlockCache: lru.NewCache[uint32, lastBlockOfMap](cachedLastBlocks), + lvPointerCache: lru.NewCache[uint64, uint64](cachedLvPointers), + renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots), } f.checkRevertRange() // revert maps that are inconsistent with the current chain view if f.indexedRange.hasIndexedBlocks() { log.Info("Initialized log indexer", - "first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(), - "first map", f.indexedRange.maps.First(), "last map", f.indexedRange.maps.Last(), - "head indexed", f.indexedRange.headIndexed) + "firstblock", f.indexedRange.blocks.First(), "lastblock", f.indexedRange.blocks.Last(), + "firstmap", f.indexedRange.maps.First(), "lastmap", f.indexedRange.maps.Last(), + "headindexed", f.indexedRange.headIndexed) } - return f + return f, nil } // Start starts the indexer. @@ -399,7 +403,7 @@ func (f *FilterMaps) init() error { batch := f.db.NewBatch() for epoch := range bestLen { cp := checkpoints[bestIdx][epoch] - f.storeLastBlockOfMap(batch, (uint32(epoch+1)< 0 { cp := checkpoints[bestIdx][bestLen-1] fmr.blocks = common.NewRange(cp.BlockNumber+1, 0) - fmr.maps = common.NewRange(uint32(bestLen)< ptr { - baseRowGroup := mapIndices[ptr] / f.baseRowGroupLength - groupLength := 1 - for ptr+groupLength < len(mapIndices) && mapIndices[ptr+groupLength]/f.baseRowGroupLength == baseRowGroup { + var ( + groupIndex = f.mapGroupIndex(mapIndices[ptr]) + groupLength = 1 + ) + for ptr+groupLength < len(mapIndices) && f.mapGroupIndex(mapIndices[ptr+groupLength]) == groupIndex { groupLength++ } if err := f.getFilterMapRowsOfGroup(rows[ptr:ptr+groupLength], mapIndices[ptr:ptr+groupLength], rowIndex, baseLayerOnly); err != nil { @@ -594,17 +600,19 @@ func (f *FilterMaps) getFilterMapRows(mapIndices []uint32, rowIndex uint32, base // getFilterMapRowsOfGroup fetches a set of filter map rows at map indices // belonging to the same base row group. func (f *FilterMaps) getFilterMapRowsOfGroup(target []FilterRow, mapIndices []uint32, rowIndex uint32, baseLayerOnly bool) error { - baseRowGroup := mapIndices[0] / f.baseRowGroupLength - baseMapRowIndex := f.mapRowIndex(baseRowGroup*f.baseRowGroupLength, rowIndex) - baseRows, err := rawdb.ReadFilterMapBaseRows(f.db, baseMapRowIndex, f.baseRowGroupLength, f.logMapWidth) + var ( + groupIndex = f.mapGroupIndex(mapIndices[0]) + mapRowIndex = f.mapRowIndex(groupIndex, rowIndex) + ) + baseRows, err := rawdb.ReadFilterMapBaseRows(f.db, mapRowIndex, f.baseRowGroupSize, f.logMapWidth) if err != nil { - return fmt.Errorf("failed to retrieve base row group %d of row %d: %v", baseRowGroup, rowIndex, err) + return fmt.Errorf("failed to retrieve base row group %d of row %d: %v", groupIndex, rowIndex, err) } for i, mapIndex := range mapIndices { - if mapIndex/f.baseRowGroupLength != baseRowGroup { - panic("mapIndices are not in the same base row group") + if f.mapGroupIndex(mapIndex) != groupIndex { + return fmt.Errorf("maps are not in the same base row group, index: %d, group: %d", mapIndex, groupIndex) } - row := baseRows[mapIndex&(f.baseRowGroupLength-1)] + row := baseRows[f.mapGroupOffset(mapIndex)] if !baseLayerOnly { extRow, err := rawdb.ReadFilterMapExtRow(f.db, f.mapRowIndex(mapIndex, rowIndex), f.logMapWidth) if err != nil { @@ -621,15 +629,17 @@ func (f *FilterMaps) getFilterMapRowsOfGroup(target []FilterRow, mapIndices []ui // indices and a shared row index. func (f *FilterMaps) storeFilterMapRows(batch ethdb.Batch, mapIndices []uint32, rowIndex uint32, rows []FilterRow) error { for len(mapIndices) > 0 { - baseRowGroup := mapIndices[0] / f.baseRowGroupLength - groupLength := 1 - for groupLength < len(mapIndices) && mapIndices[groupLength]/f.baseRowGroupLength == baseRowGroup { - groupLength++ - } - if err := f.storeFilterMapRowsOfGroup(batch, mapIndices[:groupLength], rowIndex, rows[:groupLength]); err != nil { + var ( + pos = 1 + groupIndex = f.mapGroupIndex(mapIndices[0]) + ) + for pos < len(mapIndices) && f.mapGroupIndex(mapIndices[pos]) == groupIndex { + pos++ + } + if err := f.storeFilterMapRowsOfGroup(batch, mapIndices[:pos], rowIndex, rows[:pos]); err != nil { return err } - mapIndices, rows = mapIndices[groupLength:], rows[groupLength:] + mapIndices, rows = mapIndices[pos:], rows[pos:] } return nil } @@ -637,21 +647,23 @@ func (f *FilterMaps) storeFilterMapRows(batch ethdb.Batch, mapIndices []uint32, // storeFilterMapRowsOfGroup stores a set of filter map rows at map indices // belonging to the same base row group. func (f *FilterMaps) storeFilterMapRowsOfGroup(batch ethdb.Batch, mapIndices []uint32, rowIndex uint32, rows []FilterRow) error { - baseRowGroup := mapIndices[0] / f.baseRowGroupLength - baseMapRowIndex := f.mapRowIndex(baseRowGroup*f.baseRowGroupLength, rowIndex) - var baseRows [][]uint32 - if uint32(len(mapIndices)) != f.baseRowGroupLength { // skip base rows read if all rows are replaced + var ( + baseRows [][]uint32 + groupIndex = f.mapGroupIndex(mapIndices[0]) + mapRowIndex = f.mapRowIndex(groupIndex, rowIndex) + ) + if uint32(len(mapIndices)) != f.baseRowGroupSize { // skip base rows read if all rows are replaced var err error - baseRows, err = rawdb.ReadFilterMapBaseRows(f.db, baseMapRowIndex, f.baseRowGroupLength, f.logMapWidth) + baseRows, err = rawdb.ReadFilterMapBaseRows(f.db, mapRowIndex, f.baseRowGroupSize, f.logMapWidth) if err != nil { - return fmt.Errorf("failed to retrieve base row group %d of row %d for modification: %v", baseRowGroup, rowIndex, err) + return fmt.Errorf("failed to retrieve filter map %d base rows %d for modification: %v", groupIndex, rowIndex, err) } } else { - baseRows = make([][]uint32, f.baseRowGroupLength) + baseRows = make([][]uint32, f.baseRowGroupSize) } for i, mapIndex := range mapIndices { - if mapIndex/f.baseRowGroupLength != baseRowGroup { - panic("mapIndices are not in the same base row group") + if f.mapGroupIndex(mapIndex) != groupIndex { + return fmt.Errorf("maps are not in the same base row group, index: %d, group: %d", mapIndex, groupIndex) } baseRow := []uint32(rows[i]) var extRow FilterRow @@ -659,10 +671,10 @@ func (f *FilterMaps) storeFilterMapRowsOfGroup(batch ethdb.Batch, mapIndices []u extRow = baseRow[f.baseRowLength:] baseRow = baseRow[:f.baseRowLength] } - baseRows[mapIndex&(f.baseRowGroupLength-1)] = baseRow + baseRows[f.mapGroupOffset(mapIndex)] = baseRow rawdb.WriteFilterMapExtRow(batch, f.mapRowIndex(mapIndex, rowIndex), extRow, f.logMapWidth) } - rawdb.WriteFilterMapBaseRows(batch, baseMapRowIndex, baseRows, f.logMapWidth) + rawdb.WriteFilterMapBaseRows(batch, mapRowIndex, baseRows, f.logMapWidth) return nil } @@ -747,12 +759,12 @@ func (f *FilterMaps) deleteTailEpoch(epoch uint32) (bool, error) { defer f.indexLock.Unlock() // determine epoch boundaries - firstMap := epoch << f.logMapsPerEpoch - lastBlock, _, err := f.getLastBlockOfMap(firstMap + f.mapsPerEpoch - 1) + lastBlock, _, err := f.getLastBlockOfMap(f.lastEpochMap(epoch)) if err != nil { return false, fmt.Errorf("failed to retrieve last block of deleted epoch %d: %v", epoch, err) } var firstBlock uint64 + firstMap := f.firstEpochMap(epoch) if epoch > 0 { firstBlock, _, err = f.getLastBlockOfMap(firstMap - 1) if err != nil { @@ -763,8 +775,8 @@ func (f *FilterMaps) deleteTailEpoch(epoch uint32) (bool, error) { // update rendered range if necessary var ( fmr = f.indexedRange - firstEpoch = f.indexedRange.maps.First() >> f.logMapsPerEpoch - afterLastEpoch = (f.indexedRange.maps.AfterLast() + f.mapsPerEpoch - 1) >> f.logMapsPerEpoch + firstEpoch = f.mapEpoch(f.indexedRange.maps.First()) + afterLastEpoch = f.mapEpoch(f.indexedRange.maps.AfterLast() + f.mapsPerEpoch - 1) ) if f.indexedRange.tailPartialEpoch != 0 && firstEpoch > 0 { firstEpoch-- @@ -776,7 +788,7 @@ func (f *FilterMaps) deleteTailEpoch(epoch uint32) (bool, error) { // first fully or partially rendered epoch and there is at least one // rendered map in the next epoch; remove from indexed range fmr.tailPartialEpoch = 0 - fmr.maps.SetFirst((epoch + 1) << f.logMapsPerEpoch) + fmr.maps.SetFirst(f.firstEpochMap(epoch + 1)) fmr.blocks.SetFirst(lastBlock + 1) f.setRange(f.db, f.indexedView, fmr, false) default: @@ -857,7 +869,7 @@ func (f *FilterMaps) exportCheckpoints() { w.WriteString("[\n") comma := "," for epoch := uint32(0); epoch < epochCount; epoch++ { - lastBlock, lastBlockId, err := f.getLastBlockOfMap((epoch+1)<> f.logMapsPerEpoch + firstEpoch := f.mapEpoch(f.indexedRange.maps.First()) if firstEpoch == 0 || !f.needTailEpoch(firstEpoch-1) { break } @@ -359,7 +359,7 @@ func (f *FilterMaps) tryIndexTail() (bool, error) { // Note that unindexing is very quick as it only removes continuous ranges of // data from the database and is also called while running head indexing. func (f *FilterMaps) tryUnindexTail() (bool, error) { - firstEpoch := f.indexedRange.maps.First() >> f.logMapsPerEpoch + firstEpoch := f.mapEpoch(f.indexedRange.maps.First()) if f.indexedRange.tailPartialEpoch > 0 && firstEpoch > 0 { firstEpoch-- } @@ -380,9 +380,9 @@ func (f *FilterMaps) tryUnindexTail() (bool, error) { } if f.startedTailUnindex && f.indexedRange.hasIndexedBlocks() { log.Info("Log index tail unindexing finished", - "first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(), - "removed maps", f.indexedRange.maps.First()-f.ptrTailUnindexMap, - "removed blocks", f.indexedRange.blocks.First()-f.tailPartialBlocks()-f.ptrTailUnindexBlock, + "firstblock", f.indexedRange.blocks.First(), "lastblock", f.indexedRange.blocks.Last(), + "removedmaps", f.indexedRange.maps.First()-f.ptrTailUnindexMap, + "removedblocks", f.indexedRange.blocks.First()-f.tailPartialBlocks()-f.ptrTailUnindexBlock, "elapsed", common.PrettyDuration(time.Since(f.startedTailUnindexAt))) f.startedTailUnindex = false } @@ -392,11 +392,11 @@ func (f *FilterMaps) tryUnindexTail() (bool, error) { // needTailEpoch returns true if the given tail epoch needs to be kept // according to the current tail target, false if it can be removed. func (f *FilterMaps) needTailEpoch(epoch uint32) bool { - firstEpoch := f.indexedRange.maps.First() >> f.logMapsPerEpoch + firstEpoch := f.mapEpoch(f.indexedRange.maps.First()) if epoch > firstEpoch { return true } - if (epoch+1)<= f.indexedRange.maps.AfterLast() { + if f.firstEpochMap(epoch+1) >= f.indexedRange.maps.AfterLast() { return true } if epoch+1 < firstEpoch { @@ -405,7 +405,7 @@ func (f *FilterMaps) needTailEpoch(epoch uint32) bool { var lastBlockOfPrevEpoch uint64 if epoch > 0 { var err error - lastBlockOfPrevEpoch, _, err = f.getLastBlockOfMap(epoch<= firstEpoch @@ -414,7 +414,7 @@ func (f *FilterMaps) needTailEpoch(epoch uint32) bool { if f.historyCutoff > lastBlockOfPrevEpoch { return false } - lastBlockOfEpoch, _, err := f.getLastBlockOfMap((epoch+1)<= firstEpoch diff --git a/core/filtermaps/indexer_test.go b/core/filtermaps/indexer_test.go index 4144f4ccccfa..35441905b7f3 100644 --- a/core/filtermaps/indexer_test.go +++ b/core/filtermaps/indexer_test.go @@ -41,7 +41,7 @@ var testParams = Params{ logMapWidth: 24, logMapsPerEpoch: 4, logValuesPerMap: 4, - baseRowGroupLength: 4, + baseRowGroupSize: 4, baseRowLengthRatio: 2, logLayerDiff: 2, } @@ -370,7 +370,7 @@ func (ts *testSetup) setHistory(history uint64, noHistory bool) { History: history, Disabled: noHistory, } - ts.fm = NewFilterMaps(ts.db, view, 0, 0, ts.params, config) + ts.fm, _ = NewFilterMaps(ts.db, view, 0, 0, ts.params, config) ts.fm.testDisableSnapshots = ts.testDisableSnapshots ts.fm.Start() } diff --git a/core/filtermaps/map_renderer.go b/core/filtermaps/map_renderer.go index 5379cbb15792..e1284a382977 100644 --- a/core/filtermaps/map_renderer.go +++ b/core/filtermaps/map_renderer.go @@ -284,7 +284,7 @@ func (r *mapRenderer) run(stopCb func() bool, writeCb func()) (bool, error) { // map finished r.finishedMaps[r.currentMap.mapIndex] = r.currentMap r.finished.SetLast(r.finished.AfterLast()) - if len(r.finishedMaps) >= maxMapsPerBatch || r.finished.AfterLast()&(r.f.baseRowGroupLength-1) == 0 { + if len(r.finishedMaps) >= maxMapsPerBatch || r.f.mapGroupOffset(r.finished.AfterLast()) == 0 { if err := r.writeFinishedMaps(stopCb); err != nil { return false, err } diff --git a/core/filtermaps/matcher.go b/core/filtermaps/matcher.go index 82ea2ceee6c4..238723fe1d99 100644 --- a/core/filtermaps/matcher.go +++ b/core/filtermaps/matcher.go @@ -844,7 +844,7 @@ func (m *matchSequenceInstance) dropNext(mapIndex uint32) bool { // results at mapIndex and mapIndex+1. Note that acquiring nextNextRes may be // skipped and it can be substituted with an empty list if baseRes has no potential // matches that could be sequence matched with anything that could be in nextNextRes. -func (params *Params) matchResults(mapIndex uint32, offset uint64, baseRes, nextRes potentialMatches) potentialMatches { +func (p *Params) matchResults(mapIndex uint32, offset uint64, baseRes, nextRes potentialMatches) potentialMatches { if nextRes == nil || (baseRes != nil && len(baseRes) == 0) { // if nextRes is a wild card or baseRes is empty then the sequence matcher // result equals baseRes. @@ -854,7 +854,7 @@ func (params *Params) matchResults(mapIndex uint32, offset uint64, baseRes, next // if baseRes is a wild card or nextRes is empty then the sequence matcher // result is the items of nextRes with a negative offset applied. result := make(potentialMatches, 0, len(nextRes)) - min := (uint64(mapIndex) << params.logValuesPerMap) + offset + min := (uint64(mapIndex) << p.logValuesPerMap) + offset for _, v := range nextRes { if v >= min { result = append(result, v-offset) diff --git a/core/filtermaps/math.go b/core/filtermaps/math.go index 762a99be9e25..33ac07f721e3 100644 --- a/core/filtermaps/math.go +++ b/core/filtermaps/math.go @@ -19,6 +19,7 @@ package filtermaps import ( "crypto/sha256" "encoding/binary" + "fmt" "hash/fnv" "math" "sort" @@ -28,19 +29,36 @@ import ( // Params defines the basic parameters of the log index structure. type Params struct { - logMapHeight uint // log2(mapHeight) - logMapWidth uint // log2(mapWidth) - logMapsPerEpoch uint // log2(mapsPerEpoch) - logValuesPerMap uint // log2(logValuesPerMap) - baseRowLengthRatio uint // baseRowLength / average row length - logLayerDiff uint // maxRowLength log2 growth per layer - // derived fields - mapHeight uint32 // filter map height (number of rows) - mapsPerEpoch uint32 // number of maps in an epoch + logMapHeight uint // The number of bits required to represent the map height + logMapWidth uint // The number of bits required to represent the map width + logMapsPerEpoch uint // The number of bits required to represent the number of maps per epoch + logValuesPerMap uint // The number of bits required to represent the number of log values per map + + // baseRowLengthRatio represents the ratio of base row length + // to the average row length. + baseRowLengthRatio uint + + // logLayerDiff defines the logarithmic growth factor (base 2) of + // the maximum row length per layer. It indicates how much the maximum + // row length increases as the layer depth increases. + // + // Specifically: + // - the row length in base layer (layer == 0) is baseRowLength + // - the row length in layer x is baseRowLength << (logLayerDiff * x) + logLayerDiff uint + + // These fields can be derived with the information above + mapHeight uint32 // The number of rows in the filter map + mapsPerEpoch uint32 // The number of maps in an epoch + valuesPerMap uint64 // The number of log values marked on each filter map baseRowLength uint32 // maximum number of log values per row on layer 0 - valuesPerMap uint64 // number of log values marked on each filter map - // not affecting consensus - baseRowGroupLength uint32 // length of base row groups in local database + + // baseRowGroupSize defines the number of base row entries grouped together + // as a single database entry in the local database to optimize storage + // and retrieval efficiency. + // + // This value can be configured based on the specific implementation. + baseRowGroupSize uint32 } // DefaultParams is the set of parameters used on mainnet. @@ -49,7 +67,7 @@ var DefaultParams = Params{ logMapWidth: 24, logMapsPerEpoch: 10, logValuesPerMap: 16, - baseRowGroupLength: 32, + baseRowGroupSize: 32, baseRowLengthRatio: 8, logLayerDiff: 4, } @@ -60,7 +78,7 @@ var RangeTestParams = Params{ logMapWidth: 24, logMapsPerEpoch: 0, logValuesPerMap: 0, - baseRowGroupLength: 32, + baseRowGroupSize: 32, baseRowLengthRatio: 16, // baseRowLength >= 1 logLayerDiff: 4, } @@ -91,6 +109,44 @@ func topicValue(topic common.Hash) common.Hash { return result } +// sanitize derives any missing fields and validates the parameter values. +func (p *Params) sanitize() error { + p.deriveFields() + if p.logMapWidth%8 != 0 { + return fmt.Errorf("invalid configuration: logMapWidth (%d) must be a multiple of 8", p.logMapWidth) + } + if p.baseRowGroupSize == 0 || (p.baseRowGroupSize&(p.baseRowGroupSize-1)) != 0 { + return fmt.Errorf("invalid configuration: baseRowGroupSize (%d) must be a power of 2", p.baseRowGroupSize) + } + return nil +} + +// mapGroupIndex returns the start index of the base row group that contains the +// given map index. Assumes baseRowGroupSize is a power of 2. +func (p *Params) mapGroupIndex(index uint32) uint32 { + return index & ^(p.baseRowGroupSize - 1) +} + +// mapGroupOffset returns the offset of the given map index within its base row group. +func (p *Params) mapGroupOffset(index uint32) uint32 { + return index & (p.baseRowGroupSize - 1) +} + +// mapEpoch returns the epoch number that the given map index belongs to. +func (p *Params) mapEpoch(index uint32) uint32 { + return index >> p.logMapsPerEpoch +} + +// firstEpochMap returns the index of the first map in the specified epoch. +func (p *Params) firstEpochMap(epoch uint32) uint32 { + return epoch << p.logMapsPerEpoch +} + +// lastEpochMap returns the index of the last map in the specified epoch. +func (p *Params) lastEpochMap(epoch uint32) uint32 { + return (epoch+1)<>(64-hashBits)) ^ uint32(hash)>>(32-hashBits)) } -// maxRowLength returns the maximum length filter rows are populated up to -// when using the given mapping layer. A log value can be marked on the map -// according to a given mapping layer if the row mapping on that layer points -// to a row that has not yet reached the maxRowLength belonging to that layer. +// maxRowLength returns the maximum length filter rows are populated up to when +// using the given mapping layer. +// +// A log value can be marked on the map according to a given mapping layer if +// the row mapping on that layer points to a row that has not yet reached the +// maxRowLength belonging to that layer. +// // This means that a row that is considered full on a given layer may still be // extended further on a higher order layer. +// // Each value is marked on the lowest order layer possible, assuming that marks -// are added in ascending log value index order. -// When searching for a log value one should consider all layers and process -// corresponding rows up until the first one where the row mapped to the given -// layer is not full. +// are added in ascending log value index order. When searching for a log value +// one should consider all layers and process corresponding rows up until the +// first one where the row mapped to the given layer is not full. func (p *Params) maxRowLength(layerIndex uint32) uint32 { logLayerDiff := uint(layerIndex) * p.logLayerDiff if logLayerDiff > p.logMapsPerEpoch { diff --git a/core/genesis.go b/core/genesis.go index 080f8a3c5f4e..f1a620da579d 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -258,7 +258,7 @@ func (e *GenesisMismatchError) Error() string { // ChainOverrides contains the changes to chain config. type ChainOverrides struct { - OverridePrague *uint64 + OverrideOsaka *uint64 OverrideVerkle *uint64 } @@ -267,8 +267,8 @@ func (o *ChainOverrides) apply(cfg *params.ChainConfig) error { if o == nil || cfg == nil { return nil } - if o.OverridePrague != nil { - cfg.PragueTime = o.OverridePrague + if o.OverrideOsaka != nil { + cfg.OsakaTime = o.OverrideOsaka } if o.OverrideVerkle != nil { cfg.VerkleTime = o.OverrideVerkle diff --git a/core/genesis_test.go b/core/genesis_test.go index 726bda86bb00..a41dfce5783e 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -28,7 +28,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/triedb" @@ -131,7 +130,7 @@ func testSetupGenesis(t *testing.T, scheme string) { tdb := triedb.NewDatabase(db, newDbConfig(scheme)) oldcustomg.Commit(db, tdb) - bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil) + bc, _ := NewBlockChain(db, &oldcustomg, ethash.NewFullFaker(), DefaultConfig().WithStateScheme(scheme)) defer bc.Stop() _, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil) @@ -257,7 +256,9 @@ func newDbConfig(scheme string) *triedb.Config { if scheme == rawdb.HashScheme { return triedb.HashDefaults } - return &triedb.Config{PathDB: pathdb.Defaults} + config := *pathdb.Defaults + config.NoAsyncFlush = true + return &triedb.Config{PathDB: &config} } func TestVerkleGenesisCommit(t *testing.T) { @@ -314,7 +315,14 @@ func TestVerkleGenesisCommit(t *testing.T) { } db := rawdb.NewMemoryDatabase() - triedb := triedb.NewDatabase(db, triedb.VerkleDefaults) + + config := *pathdb.Defaults + config.NoAsyncFlush = true + + triedb := triedb.NewDatabase(db, &triedb.Config{ + IsVerkle: true, + PathDB: &config, + }) block := genesis.MustCommit(db, triedb) if !bytes.Equal(block.Root().Bytes(), expected) { t.Fatalf("invalid genesis state root, expected %x, got %x", expected, block.Root()) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 2386246caf76..4426c6a9e7ed 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -449,9 +449,10 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue return data } -// ReadCanonicalBodyRLP retrieves the block body (transactions and uncles) for the canonical -// block at number, in RLP encoding. -func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { +// ReadCanonicalBodyRLP retrieves the block body (transactions and uncles) for the +// canonical block at number, in RLP encoding. Optionally it takes the block hash +// to avoid looking it up +func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.RawValue { var data []byte db.ReadAncients(func(reader ethdb.AncientReaderOp) error { data, _ = reader.Ancient(ChainFreezerBodiesTable, number) @@ -459,10 +460,14 @@ func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { return nil } // Block is not in ancients, read from leveldb by hash and number. - // Note: ReadCanonicalHash cannot be used here because it also - // calls ReadAncients internally. - hash, _ := db.Get(headerHashKey(number)) - data, _ = db.Get(blockBodyKey(number, common.BytesToHash(hash))) + if hash != nil { + data, _ = db.Get(blockBodyKey(number, *hash)) + } else { + // Note: ReadCanonicalHash cannot be used here because it also + // calls ReadAncients internally. + hashBytes, _ := db.Get(headerHashKey(number)) + data, _ = db.Get(blockBodyKey(number, common.BytesToHash(hashBytes))) + } return nil }) return data @@ -544,6 +549,29 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa return data } +// ReadCanonicalReceiptsRLP retrieves the receipts RLP for the canonical block at +// number, in RLP encoding. Optionally it takes the block hash to avoid looking it up. +func ReadCanonicalReceiptsRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.RawValue { + var data []byte + db.ReadAncients(func(reader ethdb.AncientReaderOp) error { + data, _ = reader.Ancient(ChainFreezerReceiptTable, number) + if len(data) > 0 { + return nil + } + // Block is not in ancients, read from leveldb by hash and number. + if hash != nil { + data, _ = db.Get(blockReceiptsKey(number, *hash)) + } else { + // Note: ReadCanonicalHash cannot be used here because it also + // calls ReadAncients internally. + hashBytes, _ := db.Get(headerHashKey(number)) + data, _ = db.Get(blockReceiptsKey(number, common.BytesToHash(hashBytes))) + } + return nil + }) + return data +} + // ReadRawReceipts retrieves all the transaction receipts belonging to a block. // The receipt metadata fields and the Bloom are not guaranteed to be populated, // so they should not be used. Use ReadReceipts instead if the metadata is needed. diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 862b8cd2fd0c..196f3dac8f3d 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -441,6 +441,9 @@ func TestAncientStorage(t *testing.T) { if blob := ReadReceiptsRLP(db, hash, number); len(blob) > 0 { t.Fatalf("non existent receipts returned") } + if blob := ReadCanonicalReceiptsRLP(db, number, &hash); len(blob) > 0 { + t.Fatalf("non existent receipts returned") + } // Write and verify the header in the database WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil})) @@ -454,6 +457,9 @@ func TestAncientStorage(t *testing.T) { if blob := ReadReceiptsRLP(db, hash, number); len(blob) == 0 { t.Fatalf("no receipts returned") } + if blob := ReadCanonicalReceiptsRLP(db, number, &hash); len(blob) == 0 { + t.Fatalf("no receipts returned") + } // Use a fake hash for data retrieval, nothing should be returned. fakeHash := common.BytesToHash([]byte{0x01, 0x02, 0x03}) @@ -680,26 +686,28 @@ func makeTestReceipts(n int, nPerBlock int) []types.Receipts { } type fullLogRLP struct { - Address common.Address - Topics []common.Hash - Data []byte - BlockNumber uint64 - TxHash common.Hash - TxIndex uint - BlockHash common.Hash - Index uint + Address common.Address + Topics []common.Hash + Data []byte + BlockNumber uint64 + BlockTimestamp uint64 + TxHash common.Hash + TxIndex uint + BlockHash common.Hash + Index uint } func newFullLogRLP(l *types.Log) *fullLogRLP { return &fullLogRLP{ - Address: l.Address, - Topics: l.Topics, - Data: l.Data, - BlockNumber: l.BlockNumber, - TxHash: l.TxHash, - TxIndex: l.TxIndex, - BlockHash: l.BlockHash, - Index: l.Index, + Address: l.Address, + Topics: l.Topics, + Data: l.Data, + BlockNumber: l.BlockNumber, + BlockTimestamp: l.BlockTimestamp, + TxHash: l.TxHash, + TxIndex: l.TxIndex, + BlockHash: l.BlockHash, + Index: l.Index, } } @@ -834,7 +842,7 @@ func TestDeriveLogFields(t *testing.T) { // Derive log metadata fields number := big.NewInt(1) hash := common.BytesToHash([]byte{0x03, 0x14}) - types.Receipts(receipts).DeriveFields(params.TestChainConfig, hash, number.Uint64(), 0, big.NewInt(0), big.NewInt(0), txs) + types.Receipts(receipts).DeriveFields(params.TestChainConfig, hash, number.Uint64(), 12, big.NewInt(0), big.NewInt(0), txs) // Iterate over all the computed fields and check that they're correct logIndex := uint(0) @@ -846,6 +854,9 @@ func TestDeriveLogFields(t *testing.T) { if receipts[i].Logs[j].BlockHash != hash { t.Errorf("receipts[%d].Logs[%d].BlockHash = %s, want %s", i, j, receipts[i].Logs[j].BlockHash.String(), hash.String()) } + if receipts[i].Logs[j].BlockTimestamp != 12 { + t.Errorf("receipts[%d].Logs[%d].BlockTimestamp = %d, want %d", i, j, receipts[i].Logs[j].BlockTimestamp, 12) + } if receipts[i].Logs[j].TxHash != txs[i].Hash() { t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String()) } diff --git a/core/rawdb/accessors_history.go b/core/rawdb/accessors_history.go new file mode 100644 index 000000000000..cf1073f387a8 --- /dev/null +++ b/core/rawdb/accessors_history.go @@ -0,0 +1,179 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rawdb + +import ( + "bytes" + "errors" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" +) + +// ReadStateHistoryIndexMetadata retrieves the metadata of state history index. +func ReadStateHistoryIndexMetadata(db ethdb.KeyValueReader) []byte { + data, _ := db.Get(headStateHistoryIndexKey) + return data +} + +// WriteStateHistoryIndexMetadata stores the metadata of state history index +// into database. +func WriteStateHistoryIndexMetadata(db ethdb.KeyValueWriter, blob []byte) { + if err := db.Put(headStateHistoryIndexKey, blob); err != nil { + log.Crit("Failed to store the metadata of state history index", "err", err) + } +} + +// DeleteStateHistoryIndexMetadata removes the metadata of state history index. +func DeleteStateHistoryIndexMetadata(db ethdb.KeyValueWriter) { + if err := db.Delete(headStateHistoryIndexKey); err != nil { + log.Crit("Failed to delete the metadata of state history index", "err", err) + } +} + +// ReadAccountHistoryIndex retrieves the account history index with the provided +// account address. +func ReadAccountHistoryIndex(db ethdb.KeyValueReader, addressHash common.Hash) []byte { + data, err := db.Get(accountHistoryIndexKey(addressHash)) + if err != nil || len(data) == 0 { + return nil + } + return data +} + +// WriteAccountHistoryIndex writes the provided account history index into database. +func WriteAccountHistoryIndex(db ethdb.KeyValueWriter, addressHash common.Hash, data []byte) { + if err := db.Put(accountHistoryIndexKey(addressHash), data); err != nil { + log.Crit("Failed to store account history index", "err", err) + } +} + +// DeleteAccountHistoryIndex deletes the specified account history index from +// the database. +func DeleteAccountHistoryIndex(db ethdb.KeyValueWriter, addressHash common.Hash) { + if err := db.Delete(accountHistoryIndexKey(addressHash)); err != nil { + log.Crit("Failed to delete account history index", "err", err) + } +} + +// ReadStorageHistoryIndex retrieves the storage history index with the provided +// account address and storage key hash. +func ReadStorageHistoryIndex(db ethdb.KeyValueReader, addressHash common.Hash, storageHash common.Hash) []byte { + data, err := db.Get(storageHistoryIndexKey(addressHash, storageHash)) + if err != nil || len(data) == 0 { + return nil + } + return data +} + +// WriteStorageHistoryIndex writes the provided storage history index into database. +func WriteStorageHistoryIndex(db ethdb.KeyValueWriter, addressHash common.Hash, storageHash common.Hash, data []byte) { + if err := db.Put(storageHistoryIndexKey(addressHash, storageHash), data); err != nil { + log.Crit("Failed to store storage history index", "err", err) + } +} + +// DeleteStorageHistoryIndex deletes the specified state index from the database. +func DeleteStorageHistoryIndex(db ethdb.KeyValueWriter, addressHash common.Hash, storageHash common.Hash) { + if err := db.Delete(storageHistoryIndexKey(addressHash, storageHash)); err != nil { + log.Crit("Failed to delete storage history index", "err", err) + } +} + +// ReadAccountHistoryIndexBlock retrieves the index block with the provided +// account address along with the block id. +func ReadAccountHistoryIndexBlock(db ethdb.KeyValueReader, addressHash common.Hash, blockID uint32) []byte { + data, err := db.Get(accountHistoryIndexBlockKey(addressHash, blockID)) + if err != nil || len(data) == 0 { + return nil + } + return data +} + +// WriteAccountHistoryIndexBlock writes the provided index block into database. +func WriteAccountHistoryIndexBlock(db ethdb.KeyValueWriter, addressHash common.Hash, blockID uint32, data []byte) { + if err := db.Put(accountHistoryIndexBlockKey(addressHash, blockID), data); err != nil { + log.Crit("Failed to store account index block", "err", err) + } +} + +// DeleteAccountHistoryIndexBlock deletes the specified index block from the database. +func DeleteAccountHistoryIndexBlock(db ethdb.KeyValueWriter, addressHash common.Hash, blockID uint32) { + if err := db.Delete(accountHistoryIndexBlockKey(addressHash, blockID)); err != nil { + log.Crit("Failed to delete account index block", "err", err) + } +} + +// ReadStorageHistoryIndexBlock retrieves the index block with the provided state +// identifier along with the block id. +func ReadStorageHistoryIndexBlock(db ethdb.KeyValueReader, addressHash common.Hash, storageHash common.Hash, blockID uint32) []byte { + data, err := db.Get(storageHistoryIndexBlockKey(addressHash, storageHash, blockID)) + if err != nil || len(data) == 0 { + return nil + } + return data +} + +// WriteStorageHistoryIndexBlock writes the provided index block into database. +func WriteStorageHistoryIndexBlock(db ethdb.KeyValueWriter, addressHash common.Hash, storageHash common.Hash, id uint32, data []byte) { + if err := db.Put(storageHistoryIndexBlockKey(addressHash, storageHash, id), data); err != nil { + log.Crit("Failed to store storage index block", "err", err) + } +} + +// DeleteStorageHistoryIndexBlock deletes the specified index block from the database. +func DeleteStorageHistoryIndexBlock(db ethdb.KeyValueWriter, addressHash common.Hash, storageHash common.Hash, id uint32) { + if err := db.Delete(storageHistoryIndexBlockKey(addressHash, storageHash, id)); err != nil { + log.Crit("Failed to delete storage index block", "err", err) + } +} + +// increaseKey increase the input key by one bit. Return nil if the entire +// addition operation overflows. +func increaseKey(key []byte) []byte { + for i := len(key) - 1; i >= 0; i-- { + key[i]++ + if key[i] != 0x0 { + return key + } + } + return nil +} + +// DeleteStateHistoryIndex completely removes all history indexing data, including +// indexes for accounts and storages. +// +// Note, this method assumes the storage space with prefix `StateHistoryIndexPrefix` +// is exclusively occupied by the history indexing data! +func DeleteStateHistoryIndex(db ethdb.KeyValueRangeDeleter) { + start := StateHistoryIndexPrefix + limit := increaseKey(bytes.Clone(StateHistoryIndexPrefix)) + + // Try to remove the data in the range by a loop, as the leveldb + // doesn't support the native range deletion. + for { + err := db.DeleteRange(start, limit) + if err == nil { + return + } + if errors.Is(err, ethdb.ErrTooManyKeys) { + continue + } + log.Crit("Failed to delete history index range", "err", err) + } +} diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go index fafde25606bb..f71bbb500bda 100644 --- a/core/rawdb/accessors_indexes.go +++ b/core/rawdb/accessors_indexes.go @@ -20,10 +20,12 @@ import ( "bytes" "encoding/binary" "errors" + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -128,9 +130,50 @@ func DeleteAllTxLookupEntries(db ethdb.KeyValueStore, condition func(common.Hash } } -// ReadTransaction retrieves a specific transaction from the database, along with -// its added positional metadata. -func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { +// findTxInBlockBody traverses the given RLP-encoded block body, searching for +// the transaction specified by its hash. +func findTxInBlockBody(blockbody rlp.RawValue, target common.Hash) (*types.Transaction, uint64, error) { + txnListRLP, _, err := rlp.SplitList(blockbody) + if err != nil { + return nil, 0, err + } + iter, err := rlp.NewListIterator(txnListRLP) + if err != nil { + return nil, 0, err + } + txIndex := uint64(0) + for iter.Next() { + if iter.Err() != nil { + return nil, 0, err + } + // The preimage for the hash calculation of legacy transactions + // is just their RLP encoding. For typed (EIP-2718) transactions, + // which are encoded as byte arrays, the preimage is the content of + // the byte array, so trim their prefix here. + txRLP := iter.Value() + kind, txHashPayload, _, err := rlp.Split(txRLP) + if err != nil { + return nil, 0, err + } + if kind == rlp.List { // Legacy transaction + txHashPayload = txRLP + } + if crypto.Keccak256Hash(txHashPayload) == target { + var tx types.Transaction + if err := rlp.DecodeBytes(txRLP, &tx); err != nil { + return nil, 0, err + } + return &tx, txIndex, nil + } + txIndex++ + } + return nil, 0, errors.New("transaction not found") +} + +// ReadCanonicalTransaction retrieves a specific transaction from the database, along +// with its added positional metadata. Notably, only the transaction in the canonical +// chain is visible. +func ReadCanonicalTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { blockNumber := ReadTxLookupEntry(db, hash) if blockNumber == nil { return nil, common.Hash{}, 0, 0 @@ -139,23 +182,23 @@ func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, com if blockHash == (common.Hash{}) { return nil, common.Hash{}, 0, 0 } - body := ReadBody(db, blockHash, *blockNumber) - if body == nil { + bodyRLP := ReadCanonicalBodyRLP(db, *blockNumber, &blockHash) + if bodyRLP == nil { log.Error("Transaction referenced missing", "number", *blockNumber, "hash", blockHash) return nil, common.Hash{}, 0, 0 } - for txIndex, tx := range body.Transactions { - if tx.Hash() == hash { - return tx, blockHash, *blockNumber, uint64(txIndex) - } + tx, txIndex, err := findTxInBlockBody(bodyRLP, hash) + if err != nil { + log.Error("Transaction not found", "number", *blockNumber, "hash", blockHash, "txhash", hash, "err", err) + return nil, common.Hash{}, 0, 0 } - log.Error("Transaction not found", "number", *blockNumber, "hash", blockHash, "txhash", hash) - return nil, common.Hash{}, 0, 0 + return tx, blockHash, *blockNumber, txIndex } -// ReadReceipt retrieves a specific transaction receipt from the database, along with -// its added positional metadata. -func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig) (*types.Receipt, common.Hash, uint64, uint64) { +// ReadCanonicalReceipt retrieves a specific transaction receipt from the database, +// along with its added positional metadata. Notably, only the receipt in the canonical +// chain is visible. +func ReadCanonicalReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig) (*types.Receipt, common.Hash, uint64, uint64) { // Retrieve the context of the receipt based on the transaction hash blockNumber := ReadTxLookupEntry(db, hash) if blockNumber == nil { @@ -180,7 +223,91 @@ func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig) return nil, common.Hash{}, 0, 0 } -// ReadFilterMapRow retrieves a filter map row at the given mapRowIndex +// extractReceiptFields takes a raw RLP-encoded receipt blob and extracts +// specific fields from it. +func extractReceiptFields(receiptRLP rlp.RawValue) (uint64, uint, error) { + receiptList, _, err := rlp.SplitList(receiptRLP) + if err != nil { + return 0, 0, err + } + // Decode the field: receipt status + // for receipt before the byzantium fork: + // - bytes: post state root + // for receipt after the byzantium fork: + // - bytes: receipt status flag + _, _, rest, err := rlp.Split(receiptList) + if err != nil { + return 0, 0, err + } + // Decode the field: cumulative gas used (type: uint64) + gasUsed, rest, err := rlp.SplitUint64(rest) + if err != nil { + return 0, 0, err + } + // Decode the field: logs (type: rlp list) + logList, _, err := rlp.SplitList(rest) + if err != nil { + return 0, 0, err + } + logCount, err := rlp.CountValues(logList) + if err != nil { + return 0, 0, err + } + return gasUsed, uint(logCount), nil +} + +// RawReceiptContext carries the contextual information that is needed to derive +// a complete receipt from a raw one. +type RawReceiptContext struct { + GasUsed uint64 // Amount of gas used by the associated transaction + LogIndex uint // Starting index of the logs within the block +} + +// ReadCanonicalRawReceipt reads a raw receipt at the specified position. It also +// returns the gas used by the associated transaction and the starting index of +// the logs within the block. The main difference with ReadCanonicalReceipt is +// that the additional positional fields are not directly included in the receipt. +// Notably, only receipts from the canonical chain are visible. +func ReadCanonicalRawReceipt(db ethdb.Reader, blockHash common.Hash, blockNumber, txIndex uint64) (*types.Receipt, RawReceiptContext, error) { + receiptIt, err := rlp.NewListIterator(ReadCanonicalReceiptsRLP(db, blockNumber, &blockHash)) + if err != nil { + return nil, RawReceiptContext{}, err + } + var ( + cumulativeGasUsed uint64 + logIndex uint + ) + for i := uint64(0); i <= txIndex; i++ { + // Unexpected iteration error + if receiptIt.Err() != nil { + return nil, RawReceiptContext{}, receiptIt.Err() + } + // Unexpected end of iteration + if !receiptIt.Next() { + return nil, RawReceiptContext{}, fmt.Errorf("receipt not found, %d, %x, %d", blockNumber, blockHash, txIndex) + } + if i == txIndex { + var stored types.ReceiptForStorage + if err := rlp.DecodeBytes(receiptIt.Value(), &stored); err != nil { + return nil, RawReceiptContext{}, err + } + return (*types.Receipt)(&stored), RawReceiptContext{ + GasUsed: stored.CumulativeGasUsed - cumulativeGasUsed, + LogIndex: logIndex, + }, nil + } else { + gas, logs, err := extractReceiptFields(receiptIt.Value()) + if err != nil { + return nil, RawReceiptContext{}, err + } + cumulativeGasUsed = gas + logIndex += logs + } + } + return nil, RawReceiptContext{}, fmt.Errorf("receipt not found, %d, %x, %d", blockNumber, blockHash, txIndex) +} + +// ReadFilterMapExtRow retrieves a filter map row at the given mapRowIndex // (see filtermaps.mapRowIndex for the storage index encoding). // Note that zero length rows are not stored in the database and therefore all // non-existent entries are interpreted as empty rows and return no error. @@ -207,7 +334,7 @@ func ReadFilterMapExtRow(db ethdb.KeyValueReader, mapRowIndex uint64, bitLength return nil, err } if len(encRow)%byteLength != 0 { - return nil, errors.New("Invalid encoded extended filter row length") + return nil, errors.New("invalid encoded extended filter row length") } row := make([]uint32, len(encRow)/byteLength) var b [4]byte @@ -261,7 +388,7 @@ func ReadFilterMapBaseRows(db ethdb.KeyValueReader, mapRowIndex uint64, rowCount headerBits-- } if headerLen+byteLength*entryCount > encLen { - return nil, errors.New("Invalid encoded base filter rows length") + return nil, errors.New("invalid encoded base filter rows length") } if entriesInRow > 0 { rows[rowIndex] = make([]uint32, entriesInRow) @@ -278,8 +405,8 @@ func ReadFilterMapBaseRows(db ethdb.KeyValueReader, mapRowIndex uint64, rowCount return rows, nil } -// WriteFilterMapRow stores a filter map row at the given mapRowIndex or deletes -// any existing entry if the row is empty. +// WriteFilterMapExtRow stores an extended filter map row at the given mapRowIndex +// or deletes any existing entry if the row is empty. func WriteFilterMapExtRow(db ethdb.KeyValueWriter, mapRowIndex uint64, row []uint32, bitLength uint) { byteLength := int(bitLength) / 8 if int(bitLength) != byteLength*8 { diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go index 29b468fb2a60..a812fefeaa33 100644 --- a/core/rawdb/accessors_indexes_test.go +++ b/core/rawdb/accessors_indexes_test.go @@ -17,14 +17,17 @@ package rawdb import ( + "errors" "math/big" "testing" + "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/blocktest" "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" ) var newTestHasher = blocktest.NewHasher @@ -72,13 +75,21 @@ func TestLookupStorage(t *testing.T) { tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}) tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}) - txs := []*types.Transaction{tx1, tx2, tx3} + tx4 := types.NewTx(&types.DynamicFeeTx{ + To: new(common.Address), + Nonce: 5, + Value: big.NewInt(5), + Gas: 5, + GasTipCap: big.NewInt(55), + GasFeeCap: big.NewInt(1055), + }) + txs := []*types.Transaction{tx1, tx2, tx3, tx4} block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, &types.Body{Transactions: txs}, nil, newTestHasher()) // Check that no transactions entries are in a pristine database for i, tx := range txs { - if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { + if txn, _, _, _ := ReadCanonicalTransaction(db, tx.Hash()); txn != nil { t.Fatalf("tx #%d [%x]: non existent transaction returned: %v", i, tx.Hash(), txn) } } @@ -88,7 +99,7 @@ func TestLookupStorage(t *testing.T) { tc.writeTxLookupEntriesByBlock(db, block) for i, tx := range txs { - if txn, hash, number, index := ReadTransaction(db, tx.Hash()); txn == nil { + if txn, hash, number, index := ReadCanonicalTransaction(db, tx.Hash()); txn == nil { t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash()) } else { if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { @@ -102,10 +113,187 @@ func TestLookupStorage(t *testing.T) { // Delete the transactions and check purge for i, tx := range txs { DeleteTxLookupEntry(db, tx.Hash()) - if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { + if txn, _, _, _ := ReadCanonicalTransaction(db, tx.Hash()); txn != nil { t.Fatalf("tx #%d [%x]: deleted transaction returned: %v", i, tx.Hash(), txn) } } }) } } + +func TestFindTxInBlockBody(t *testing.T) { + tx1 := types.NewTx(&types.LegacyTx{ + Nonce: 1, + GasPrice: big.NewInt(1), + Gas: 1, + To: new(common.Address), + Value: big.NewInt(5), + Data: []byte{0x11, 0x11, 0x11}, + }) + tx2 := types.NewTx(&types.AccessListTx{ + Nonce: 1, + GasPrice: big.NewInt(1), + Gas: 1, + To: new(common.Address), + Value: big.NewInt(5), + Data: []byte{0x11, 0x11, 0x11}, + AccessList: []types.AccessTuple{ + { + Address: common.Address{0x1}, + StorageKeys: []common.Hash{{0x1}, {0x2}}, + }, + }, + }) + tx3 := types.NewTx(&types.DynamicFeeTx{ + Nonce: 1, + Gas: 1, + To: new(common.Address), + Value: big.NewInt(5), + Data: []byte{0x11, 0x11, 0x11}, + GasTipCap: big.NewInt(55), + GasFeeCap: big.NewInt(1055), + AccessList: []types.AccessTuple{ + { + Address: common.Address{0x1}, + StorageKeys: []common.Hash{{0x1}, {0x2}}, + }, + }, + }) + tx4 := types.NewTx(&types.BlobTx{ + Nonce: 1, + Gas: 1, + To: common.Address{0x1}, + Value: uint256.NewInt(5), + Data: []byte{0x11, 0x11, 0x11}, + GasTipCap: uint256.NewInt(55), + GasFeeCap: uint256.NewInt(1055), + AccessList: []types.AccessTuple{ + { + Address: common.Address{0x1}, + StorageKeys: []common.Hash{{0x1}, {0x2}}, + }, + }, + BlobFeeCap: uint256.NewInt(1), + BlobHashes: []common.Hash{{0x1}, {0x2}}, + }) + tx5 := types.NewTx(&types.SetCodeTx{ + Nonce: 1, + Gas: 1, + To: common.Address{0x1}, + Value: uint256.NewInt(5), + Data: []byte{0x11, 0x11, 0x11}, + GasTipCap: uint256.NewInt(55), + GasFeeCap: uint256.NewInt(1055), + AccessList: []types.AccessTuple{ + { + Address: common.Address{0x1}, + StorageKeys: []common.Hash{{0x1}, {0x2}}, + }, + }, + AuthList: []types.SetCodeAuthorization{ + { + ChainID: uint256.Int{1}, + Address: common.Address{0x1}, + }, + }, + }) + + txs := []*types.Transaction{tx1, tx2, tx3, tx4, tx5} + + block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, &types.Body{Transactions: txs}, nil, newTestHasher()) + db := NewMemoryDatabase() + WriteBlock(db, block) + + rlp := ReadBodyRLP(db, block.Hash(), block.NumberU64()) + for i := 0; i < len(txs); i++ { + tx, txIndex, err := findTxInBlockBody(rlp, txs[i].Hash()) + if err != nil { + t.Fatalf("Failed to retrieve tx, err: %v", err) + } + if txIndex != uint64(i) { + t.Fatalf("Unexpected transaction index, want: %d, got: %d", i, txIndex) + } + if tx.Hash() != txs[i].Hash() { + want := spew.Sdump(txs[i]) + got := spew.Sdump(tx) + t.Fatalf("Unexpected transaction, want: %s, got: %s", want, got) + } + } +} + +func TestExtractReceiptFields(t *testing.T) { + receiptWithPostState := types.ReceiptForStorage(types.Receipt{ + Type: types.LegacyTxType, + PostState: []byte{0x1, 0x2, 0x3}, + CumulativeGasUsed: 100, + }) + receiptWithPostStateBlob, _ := rlp.EncodeToBytes(&receiptWithPostState) + + receiptNoLogs := types.ReceiptForStorage(types.Receipt{ + Type: types.LegacyTxType, + Status: types.ReceiptStatusSuccessful, + CumulativeGasUsed: 100, + }) + receiptNoLogBlob, _ := rlp.EncodeToBytes(&receiptNoLogs) + + receiptWithLogs := types.ReceiptForStorage(types.Receipt{ + Type: types.LegacyTxType, + Status: types.ReceiptStatusSuccessful, + CumulativeGasUsed: 100, + Logs: []*types.Log{ + { + Address: common.BytesToAddress([]byte{0x1}), + Topics: []common.Hash{ + common.BytesToHash([]byte{0x1}), + }, + Data: []byte{0x1}, + }, + { + Address: common.BytesToAddress([]byte{0x2}), + Topics: []common.Hash{ + common.BytesToHash([]byte{0x2}), + }, + Data: []byte{0x2}, + }, + }, + }) + receiptWithLogBlob, _ := rlp.EncodeToBytes(&receiptWithLogs) + + invalidReceipt := types.ReceiptForStorage(types.Receipt{ + Type: types.LegacyTxType, + Status: types.ReceiptStatusSuccessful, + CumulativeGasUsed: 100, + }) + invalidReceiptBlob, _ := rlp.EncodeToBytes(&invalidReceipt) + invalidReceiptBlob[len(invalidReceiptBlob)-1] = 0xf + + var cases = []struct { + logs rlp.RawValue + expErr error + expGasUsed uint64 + expLogs uint + }{ + {receiptWithPostStateBlob, nil, 100, 0}, + {receiptNoLogBlob, nil, 100, 0}, + {receiptWithLogBlob, nil, 100, 2}, + {invalidReceiptBlob, rlp.ErrExpectedList, 100, 0}, + } + for _, c := range cases { + gasUsed, logs, err := extractReceiptFields(c.logs) + if c.expErr != nil { + if !errors.Is(err, c.expErr) { + t.Fatalf("Unexpected error, want: %v, got: %v", c.expErr, err) + } + } else { + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + if gasUsed != c.expGasUsed { + t.Fatalf("Unexpected gas used, want %d, got %d", c.expGasUsed, gasUsed) + } + if logs != c.expLogs { + t.Fatalf("Unexpected logs, want %d, got %d", c.expLogs, logs) + } + } + } +} diff --git a/core/rawdb/accessors_state.go b/core/rawdb/accessors_state.go index 41e15debe94d..7d7b37641bf2 100644 --- a/core/rawdb/accessors_state.go +++ b/core/rawdb/accessors_state.go @@ -18,6 +18,7 @@ package rawdb import ( "encoding/binary" + "errors" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" @@ -255,6 +256,36 @@ func ReadStateHistory(db ethdb.AncientReaderOp, id uint64) ([]byte, []byte, []by return meta, accountIndex, storageIndex, accountData, storageData, nil } +// ReadStateHistoryList retrieves a list of state histories from database with +// specific range. Compute the position of state history in freezer by minus one +// since the id of first state history starts from one(zero for initial state). +func ReadStateHistoryList(db ethdb.AncientReaderOp, start uint64, count uint64) ([][]byte, [][]byte, [][]byte, [][]byte, [][]byte, error) { + metaList, err := db.AncientRange(stateHistoryMeta, start-1, count, 0) + if err != nil { + return nil, nil, nil, nil, nil, err + } + aIndexList, err := db.AncientRange(stateHistoryAccountIndex, start-1, count, 0) + if err != nil { + return nil, nil, nil, nil, nil, err + } + sIndexList, err := db.AncientRange(stateHistoryStorageIndex, start-1, count, 0) + if err != nil { + return nil, nil, nil, nil, nil, err + } + aDataList, err := db.AncientRange(stateHistoryAccountData, start-1, count, 0) + if err != nil { + return nil, nil, nil, nil, nil, err + } + sDataList, err := db.AncientRange(stateHistoryStorageData, start-1, count, 0) + if err != nil { + return nil, nil, nil, nil, nil, err + } + if len(metaList) != len(aIndexList) || len(metaList) != len(sIndexList) || len(metaList) != len(aDataList) || len(metaList) != len(sDataList) { + return nil, nil, nil, nil, nil, errors.New("state history is corrupted") + } + return metaList, aIndexList, sIndexList, aDataList, sDataList, nil +} + // WriteStateHistory writes the provided state history to database. Compute the // position of state history in freezer by minus one since the id of first state // history starts from one(zero for initial state). diff --git a/core/rawdb/chain_iterator.go b/core/rawdb/chain_iterator.go index ecbc44e1f1ee..e7c89ca8d911 100644 --- a/core/rawdb/chain_iterator.go +++ b/core/rawdb/chain_iterator.go @@ -118,7 +118,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool } defer close(rlpCh) for n != end { - data := ReadCanonicalBodyRLP(db, n) + data := ReadCanonicalBodyRLP(db, n, nil) // Feed the block to the aggregator, or abort on interrupt select { case rlpCh <- &numberRlp{n, data}: diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 86f4ac19cbc9..9681c39c582e 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -412,6 +412,9 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { filterMapLastBlock stat filterMapBlockLV stat + // Path-mode archive data + stateIndex stat + // Verkle statistics verkleTries stat verkleStateLookups stat @@ -489,6 +492,10 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { case bytes.HasPrefix(key, bloomBitsMetaPrefix) && len(key) < len(bloomBitsMetaPrefix)+8: bloomBits.Add(size) + // Path-based historic state indexes + case bytes.HasPrefix(key, StateHistoryIndexPrefix) && len(key) >= len(StateHistoryIndexPrefix)+common.HashLength: + stateIndex.Add(size) + // Verkle trie data is detected, determine the sub-category case bytes.HasPrefix(key, VerklePrefix): remain := key[len(VerklePrefix):] @@ -544,6 +551,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { {"Key-Value store", "Path trie state lookups", stateLookups.Size(), stateLookups.Count()}, {"Key-Value store", "Path trie account nodes", accountTries.Size(), accountTries.Count()}, {"Key-Value store", "Path trie storage nodes", storageTries.Size(), storageTries.Count()}, + {"Key-Value store", "Path state history indexes", stateIndex.Size(), stateIndex.Count()}, {"Key-Value store", "Verkle trie nodes", verkleTries.Size(), verkleTries.Count()}, {"Key-Value store", "Verkle trie state lookups", verkleStateLookups.Size(), verkleStateLookups.Count()}, {"Key-Value store", "Trie preimages", preimages.Size(), preimages.Count()}, @@ -591,7 +599,7 @@ var knownMetadataKeys = [][]byte{ snapshotGeneratorKey, snapshotRecoveryKey, txIndexTailKey, fastTxLookupLimitKey, uncleanShutdownKey, badBlockKey, transitionStatusKey, skeletonSyncStatusKey, persistentStateIDKey, trieJournalKey, snapshotSyncStatusKey, snapSyncStatusFlagKey, - filterMapsRangeKey, + filterMapsRangeKey, headStateHistoryIndexKey, } // printChainMetadata prints out chain metadata to stderr. @@ -667,7 +675,6 @@ func SafeDeleteRange(db ethdb.KeyValueStore, start, end []byte, hashScheme bool, var ( count, deleted, skipped int - buff = crypto.NewKeccakState() startTime = time.Now() ) @@ -680,7 +687,7 @@ func SafeDeleteRange(db ethdb.KeyValueStore, start, end []byte, hashScheme bool, for it.Next() && bytes.Compare(end, it.Key()) > 0 { // Prevent deletion for trie nodes in hash mode - if len(it.Key()) != 32 || crypto.HashData(buff, it.Value()) != common.BytesToHash(it.Key()) { + if len(it.Key()) != 32 || crypto.Keccak256Hash(it.Value()) != common.BytesToHash(it.Key()) { if err := batch.Delete(it.Key()); err != nil { return err } diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index fa125cecc053..388a08f2434a 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -76,6 +76,10 @@ var ( // trieJournalKey tracks the in-memory trie node layers across restarts. trieJournalKey = []byte("TrieJournal") + // headStateHistoryIndexKey tracks the ID of the latest state history that has + // been indexed. + headStateHistoryIndexKey = []byte("LastStateHistoryIndex") + // txIndexTailKey tracks the oldest block whose transactions have been indexed. txIndexTailKey = []byte("TransactionIndexTail") @@ -117,6 +121,13 @@ var ( TrieNodeStoragePrefix = []byte("O") // TrieNodeStoragePrefix + accountHash + hexPath -> trie node stateIDPrefix = []byte("L") // stateIDPrefix + state root -> state id + // State history indexing within path-based storage scheme + StateHistoryIndexPrefix = []byte("m") // The global prefix of state history index data + StateHistoryAccountMetadataPrefix = []byte("ma") // StateHistoryAccountMetadataPrefix + account address hash => account metadata + StateHistoryStorageMetadataPrefix = []byte("ms") // StateHistoryStorageMetadataPrefix + account address hash + storage slot hash => slot metadata + StateHistoryAccountBlockPrefix = []byte("mba") // StateHistoryAccountBlockPrefix + account address hash + blockID => account block + StateHistoryStorageBlockPrefix = []byte("mbs") // StateHistoryStorageBlockPrefix + account address hash + storage slot hash + blockID => slot block + // VerklePrefix is the database prefix for Verkle trie data, which includes: // (a) Trie nodes // (b) In-memory trie node journal @@ -362,3 +373,27 @@ func filterMapBlockLVKey(number uint64) []byte { binary.BigEndian.PutUint64(key[l:], number) return key } + +// accountHistoryIndexKey = StateHistoryAccountMetadataPrefix + addressHash +func accountHistoryIndexKey(addressHash common.Hash) []byte { + return append(StateHistoryAccountMetadataPrefix, addressHash.Bytes()...) +} + +// storageHistoryIndexKey = StateHistoryStorageMetadataPrefix + addressHash + storageHash +func storageHistoryIndexKey(addressHash common.Hash, storageHash common.Hash) []byte { + return append(append(StateHistoryStorageMetadataPrefix, addressHash.Bytes()...), storageHash.Bytes()...) +} + +// accountHistoryIndexBlockKey = StateHistoryAccountBlockPrefix + addressHash + blockID +func accountHistoryIndexBlockKey(addressHash common.Hash, blockID uint32) []byte { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], blockID) + return append(append(StateHistoryAccountBlockPrefix, addressHash.Bytes()...), buf[:]...) +} + +// storageHistoryIndexBlockKey = StateHistoryStorageBlockPrefix + addressHash + storageHash + blockID +func storageHistoryIndexBlockKey(addressHash common.Hash, storageHash common.Hash, blockID uint32) []byte { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], blockID) + return append(append(append(StateHistoryStorageBlockPrefix, addressHash.Bytes()...), storageHash.Bytes()...), buf[:]...) +} diff --git a/core/rawdb/table.go b/core/rawdb/table.go index 5eb3fe45d192..45c8aecf0c06 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -126,6 +126,11 @@ func (t *table) Delete(key []byte) error { // DeleteRange deletes all of the keys (and values) in the range [start,end) // (inclusive on start, exclusive on end). func (t *table) DeleteRange(start, end []byte) error { + // The nilness will be lost by adding the prefix, explicitly converting it + // to a special flag representing the end of key range. + if end == nil { + end = ethdb.MaximumKey + } return t.db.DeleteRange(append([]byte(t.prefix), start...), append([]byte(t.prefix), end...)) } @@ -217,6 +222,16 @@ func (b *tableBatch) Delete(key []byte) error { return b.batch.Delete(append([]byte(b.prefix), key...)) } +// DeleteRange removes all keys in the range [start, end) from the batch for later committing. +func (b *tableBatch) DeleteRange(start, end []byte) error { + // The nilness will be lost by adding the prefix, explicitly converting it + // to a special flag representing the end of key range. + if end == nil { + end = ethdb.MaximumKey + } + return b.batch.DeleteRange(append([]byte(b.prefix), start...), append([]byte(b.prefix), end...)) +} + // ValueSize retrieves the amount of data queued up for writing. func (b *tableBatch) ValueSize() int { return b.batch.ValueSize() diff --git a/core/rawdb/table_test.go b/core/rawdb/table_test.go index aa6adf3e72b1..36fd33105952 100644 --- a/core/rawdb/table_test.go +++ b/core/rawdb/table_test.go @@ -125,4 +125,28 @@ func testTableDatabase(t *testing.T, prefix string) { // Test iterators with prefix and start point check(db.NewIterator([]byte{0xee}, nil), 0, 0) check(db.NewIterator(nil, []byte{0x00}), 6, 0) + + // Test range deletion + db.DeleteRange(nil, nil) + for _, entry := range entries { + _, err := db.Get(entry.key) + if err == nil { + t.Fatal("Unexpected item after deletion") + } + } + // Test range deletion by batch + batch = db.NewBatch() + for _, entry := range entries { + batch.Put(entry.key, entry.value) + } + batch.Write() + batch.Reset() + batch.DeleteRange(nil, nil) + batch.Write() + for _, entry := range entries { + _, err := db.Get(entry.key) + if err == nil { + t.Fatal("Unexpected item after deletion") + } + } } diff --git a/core/state/database.go b/core/state/database.go index aec841f59b59..5fb198a6298d 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -209,13 +209,16 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) { return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), combined), nil } -// ReaderWithCache creates a state reader with internal local cache. -func (db *CachingDB) ReaderWithCache(stateRoot common.Hash) (Reader, error) { +// ReadersWithCacheStats creates a pair of state readers sharing the same internal cache and +// same backing Reader, but exposing separate statistics. +// and statistics. +func (db *CachingDB) ReadersWithCacheStats(stateRoot common.Hash) (ReaderWithStats, ReaderWithStats, error) { reader, err := db.Reader(stateRoot) if err != nil { - return nil, err + return nil, nil, err } - return newReaderWithCache(reader), nil + shared := newReaderWithCache(reader) + return newReaderWithCacheStats(shared), newReaderWithCacheStats(shared), nil } // OpenTrie opens the main account trie at a specific root hash. diff --git a/core/state/database_history.go b/core/state/database_history.go new file mode 100644 index 000000000000..314c56c4708a --- /dev/null +++ b/core/state/database_history.go @@ -0,0 +1,155 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package state + +import ( + "errors" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/lru" + "github.com/ethereum/go-ethereum/core/state/snapshot" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie/utils" + "github.com/ethereum/go-ethereum/triedb" + "github.com/ethereum/go-ethereum/triedb/pathdb" +) + +// historicReader wraps a historical state reader defined in path database, +// providing historic state serving over the path scheme. +// +// TODO(rjl493456442): historicReader is not thread-safe and does not fully +// comply with the StateReader interface requirements, needs to be fixed. +// Currently, it is only used in a non-concurrent context, so it is safe for now. +type historicReader struct { + reader *pathdb.HistoricalStateReader +} + +// newHistoricReader constructs a reader for historic state serving. +func newHistoricReader(r *pathdb.HistoricalStateReader) *historicReader { + return &historicReader{reader: r} +} + +// Account implements StateReader, retrieving the account specified by the address. +// +// An error will be returned if the associated snapshot is already stale or +// the requested account is not yet covered by the snapshot. +// +// The returned account might be nil if it's not existent. +func (r *historicReader) Account(addr common.Address) (*types.StateAccount, error) { + account, err := r.reader.Account(addr) + if err != nil { + return nil, err + } + if account == nil { + return nil, nil + } + acct := &types.StateAccount{ + Nonce: account.Nonce, + Balance: account.Balance, + CodeHash: account.CodeHash, + Root: common.BytesToHash(account.Root), + } + if len(acct.CodeHash) == 0 { + acct.CodeHash = types.EmptyCodeHash.Bytes() + } + if acct.Root == (common.Hash{}) { + acct.Root = types.EmptyRootHash + } + return acct, nil +} + +// Storage implements StateReader, retrieving the storage slot specified by the +// address and slot key. +// +// An error will be returned if the associated snapshot is already stale or +// the requested storage slot is not yet covered by the snapshot. +// +// The returned storage slot might be empty if it's not existent. +func (r *historicReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) { + blob, err := r.reader.Storage(addr, key) + if err != nil { + return common.Hash{}, err + } + if len(blob) == 0 { + return common.Hash{}, nil + } + _, content, _, err := rlp.Split(blob) + if err != nil { + return common.Hash{}, err + } + var slot common.Hash + slot.SetBytes(content) + return slot, nil +} + +// HistoricDB is the implementation of Database interface, with the ability to +// access historical state. +type HistoricDB struct { + disk ethdb.KeyValueStore + triedb *triedb.Database + codeCache *lru.SizeConstrainedCache[common.Hash, []byte] + codeSizeCache *lru.Cache[common.Hash, int] + pointCache *utils.PointCache +} + +// NewHistoricDatabase creates a historic state database. +func NewHistoricDatabase(disk ethdb.KeyValueStore, triedb *triedb.Database) *HistoricDB { + return &HistoricDB{ + disk: disk, + triedb: triedb, + codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize), + codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), + pointCache: utils.NewPointCache(pointCacheSize), + } +} + +// Reader implements Database interface, returning a reader of the specific state. +func (db *HistoricDB) Reader(stateRoot common.Hash) (Reader, error) { + hr, err := db.triedb.HistoricReader(stateRoot) + if err != nil { + return nil, err + } + return newReader(newCachingCodeReader(db.disk, db.codeCache, db.codeSizeCache), newHistoricReader(hr)), nil +} + +// OpenTrie opens the main account trie. It's not supported by historic database. +func (db *HistoricDB) OpenTrie(root common.Hash) (Trie, error) { + return nil, errors.New("not implemented") +} + +// OpenStorageTrie opens the storage trie of an account. It's not supported by +// historic database. +func (db *HistoricDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error) { + return nil, errors.New("not implemented") +} + +// PointCache returns the cache holding points used in verkle tree key computation +func (db *HistoricDB) PointCache() *utils.PointCache { + return db.pointCache +} + +// TrieDB returns the underlying trie database for managing trie nodes. +func (db *HistoricDB) TrieDB() *triedb.Database { + return db.triedb +} + +// Snapshot returns the underlying state snapshot. +func (db *HistoricDB) Snapshot() *snapshot.Tree { + return nil +} diff --git a/core/state/dump.go b/core/state/dump.go index 11b5c327827f..a4abc33733f1 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -112,6 +112,9 @@ func (d iterativeDump) OnRoot(root common.Hash) { // DumpToCollector iterates the state according to the given options and inserts // the items into a collector for aggregation or serialization. +// +// The state iterator is still trie-based and can be converted to snapshot-based +// once the state snapshot is fully integrated into database. TODO(rjl493456442). func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte) { // Sanitize the input to allow nil configs if conf == nil { @@ -123,15 +126,20 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey [] start = time.Now() logged = time.Now() ) - log.Info("Trie dumping started", "root", s.trie.Hash()) - c.OnRoot(s.trie.Hash()) + log.Info("Trie dumping started", "root", s.originalRoot) + c.OnRoot(s.originalRoot) - trieIt, err := s.trie.NodeIterator(conf.Start) + tr, err := s.db.OpenTrie(s.originalRoot) + if err != nil { + return nil + } + trieIt, err := tr.NodeIterator(conf.Start) if err != nil { log.Error("Trie dumping error", "err", err) return nil } it := trie.NewIterator(trieIt) + for it.Next() { var data types.StateAccount if err := rlp.DecodeBytes(it.Value, &data); err != nil { @@ -147,7 +155,7 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey [] } address *common.Address addr common.Address - addrBytes = s.trie.GetKey(it.Key) + addrBytes = tr.GetKey(it.Key) ) if addrBytes == nil { missingPreimages++ @@ -165,12 +173,13 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey [] } if !conf.SkipStorage { account.Storage = make(map[common.Hash]string) - tr, err := obj.getTrie() + + storageTr, err := s.db.OpenStorageTrie(s.originalRoot, addr, obj.Root(), tr) if err != nil { log.Error("Failed to load storage trie", "err", err) continue } - trieIt, err := tr.NodeIterator(nil) + trieIt, err := storageTr.NodeIterator(nil) if err != nil { log.Error("Failed to create trie iterator", "err", err) continue @@ -182,7 +191,11 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey [] log.Error("Failed to decode the value returned by iterator", "error", err) continue } - account.Storage[common.BytesToHash(s.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(content) + key := storageTr.GetKey(storageIt.Key) + if key == nil { + continue + } + account.Storage[common.BytesToHash(key)] = common.Bytes2Hex(content) } } c.OnAccount(address, account) diff --git a/core/state/iterator.go b/core/state/iterator.go index 5ea52c618357..0abae091d954 100644 --- a/core/state/iterator.go +++ b/core/state/iterator.go @@ -32,6 +32,7 @@ import ( // required in order to resolve the contract address. type nodeIterator struct { state *StateDB // State being iterated + tr Trie // Primary account trie for traversal stateIt trie.NodeIterator // Primary iterator for the global state trie dataIt trie.NodeIterator // Secondary iterator for the data trie of a contract @@ -75,13 +76,20 @@ func (it *nodeIterator) step() error { if it.state == nil { return nil } + if it.tr == nil { + tr, err := it.state.db.OpenTrie(it.state.originalRoot) + if err != nil { + return err + } + it.tr = tr + } // Initialize the iterator if we've just started - var err error if it.stateIt == nil { - it.stateIt, err = it.state.trie.NodeIterator(nil) + stateIt, err := it.tr.NodeIterator(nil) if err != nil { return err } + it.stateIt = stateIt } // If we had data nodes previously, we surely have at least state nodes if it.dataIt != nil { @@ -116,14 +124,14 @@ func (it *nodeIterator) step() error { return err } // Lookup the preimage of account hash - preimage := it.state.trie.GetKey(it.stateIt.LeafKey()) + preimage := it.tr.GetKey(it.stateIt.LeafKey()) if preimage == nil { return errors.New("account address is not available") } address := common.BytesToAddress(preimage) // Traverse the storage slots belong to the account - dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, address, account.Root, it.state.trie) + dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, address, account.Root, it.tr) if err != nil { return err } diff --git a/core/state/reader.go b/core/state/reader.go index 09edf6ab8dbb..4628f4d5dbad 100644 --- a/core/state/reader.go +++ b/core/state/reader.go @@ -19,6 +19,7 @@ package state import ( "errors" "sync" + "sync/atomic" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/lru" @@ -82,6 +83,20 @@ type Reader interface { StateReader } +// ReaderStats wraps the statistics of reader. +type ReaderStats struct { + AccountHit int64 + AccountMiss int64 + StorageHit int64 + StorageMiss int64 +} + +// ReaderWithStats wraps the additional method to retrieve the reader statistics from. +type ReaderWithStats interface { + Reader + GetStats() ReaderStats +} + // cachingCodeReader implements ContractCodeReader, accessing contract code either in // local key-value store or the shared code cache. // @@ -204,9 +219,8 @@ func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash, // // trieReader is safe for concurrent read. type trieReader struct { - root common.Hash // State root which uniquely represent a state - db *triedb.Database // Database for loading trie - buff crypto.KeccakState // Buffer for keccak256 hashing + root common.Hash // State root which uniquely represent a state + db *triedb.Database // Database for loading trie // Main trie, resolved in constructor. Note either the Merkle-Patricia-tree // or Verkle-tree is not safe for concurrent read. @@ -235,7 +249,6 @@ func newTrieReader(root common.Hash, db *triedb.Database, cache *utils.PointCach return &trieReader{ root: root, db: db, - buff: crypto.NewKeccakState(), mainTrie: tr, subRoots: make(map[common.Address]common.Hash), subTries: make(map[common.Address]Trie), @@ -298,7 +311,7 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, root = r.subRoots[addr] } var err error - tr, err = trie.NewStateTrie(trie.StorageTrieID(r.root, crypto.HashData(r.buff, addr.Bytes()), root), r.db) + tr, err = trie.NewStateTrie(trie.StorageTrieID(r.root, crypto.Keccak256Hash(addr.Bytes()), root), r.db) if err != nil { return common.Hash{}, err } @@ -416,35 +429,43 @@ func newReaderWithCache(reader Reader) *readerWithCache { return r } -// Account implements StateReader, retrieving the account specified by the address. -// The returned account might be nil if it's not existent. +// account retrieves the account specified by the address along with a flag +// indicating whether it's found in the cache or not. The returned account +// might be nil if it's not existent. // // An error will be returned if the state is corrupted in the underlying reader. -func (r *readerWithCache) Account(addr common.Address) (*types.StateAccount, error) { +func (r *readerWithCache) account(addr common.Address) (*types.StateAccount, bool, error) { // Try to resolve the requested account in the local cache r.accountLock.RLock() acct, ok := r.accounts[addr] r.accountLock.RUnlock() if ok { - return acct, nil + return acct, true, nil } // Try to resolve the requested account from the underlying reader acct, err := r.Reader.Account(addr) if err != nil { - return nil, err + return nil, false, err } r.accountLock.Lock() r.accounts[addr] = acct r.accountLock.Unlock() - return acct, nil + return acct, false, nil } -// Storage implements StateReader, retrieving the storage slot specified by the -// address and slot key. The returned storage slot might be empty if it's not -// existent. +// Account implements StateReader, retrieving the account specified by the address. +// The returned account might be nil if it's not existent. // // An error will be returned if the state is corrupted in the underlying reader. -func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common.Hash, error) { +func (r *readerWithCache) Account(addr common.Address) (*types.StateAccount, error) { + account, _, err := r.account(addr) + return account, err +} + +// storage retrieves the storage slot specified by the address and slot key, along +// with a flag indicating whether it's found in the cache or not. The returned +// storage slot might be empty if it's not existent. +func (r *readerWithCache) storage(addr common.Address, slot common.Hash) (common.Hash, bool, error) { var ( value common.Hash ok bool @@ -458,12 +479,12 @@ func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common } bucket.lock.RUnlock() if ok { - return value, nil + return value, true, nil } // Try to resolve the requested storage slot from the underlying reader value, err := r.Reader.Storage(addr, slot) if err != nil { - return common.Hash{}, err + return common.Hash{}, false, err } bucket.lock.Lock() slots, ok = bucket.storages[addr] @@ -474,5 +495,75 @@ func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common slots[slot] = value bucket.lock.Unlock() + return value, false, nil +} + +// Storage implements StateReader, retrieving the storage slot specified by the +// address and slot key. The returned storage slot might be empty if it's not +// existent. +// +// An error will be returned if the state is corrupted in the underlying reader. +func (r *readerWithCache) Storage(addr common.Address, slot common.Hash) (common.Hash, error) { + value, _, err := r.storage(addr, slot) + return value, err +} + +type readerWithCacheStats struct { + *readerWithCache + accountHit atomic.Int64 + accountMiss atomic.Int64 + storageHit atomic.Int64 + storageMiss atomic.Int64 +} + +// newReaderWithCacheStats constructs the reader with additional statistics tracked. +func newReaderWithCacheStats(reader *readerWithCache) *readerWithCacheStats { + return &readerWithCacheStats{ + readerWithCache: reader, + } +} + +// Account implements StateReader, retrieving the account specified by the address. +// The returned account might be nil if it's not existent. +// +// An error will be returned if the state is corrupted in the underlying reader. +func (r *readerWithCacheStats) Account(addr common.Address) (*types.StateAccount, error) { + account, incache, err := r.readerWithCache.account(addr) + if err != nil { + return nil, err + } + if incache { + r.accountHit.Add(1) + } else { + r.accountMiss.Add(1) + } + return account, nil +} + +// Storage implements StateReader, retrieving the storage slot specified by the +// address and slot key. The returned storage slot might be empty if it's not +// existent. +// +// An error will be returned if the state is corrupted in the underlying reader. +func (r *readerWithCacheStats) Storage(addr common.Address, slot common.Hash) (common.Hash, error) { + value, incache, err := r.readerWithCache.storage(addr, slot) + if err != nil { + return common.Hash{}, err + } + if incache { + r.storageHit.Add(1) + } else { + r.storageMiss.Add(1) + } return value, nil } + +// GetStats implements ReaderWithStats, returning the statistics of state reader. +func (r *readerWithCacheStats) GetStats() ReaderStats { + return ReaderStats{ + AccountHit: r.accountHit.Load(), + AccountMiss: r.accountMiss.Load(), + StorageHit: r.storageHit.Load(), + StorageMiss: r.storageMiss.Load(), + } +} diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go index 3f83cb1a00b8..44886300958e 100644 --- a/core/state/snapshot/generate_test.go +++ b/core/state/snapshot/generate_test.go @@ -168,6 +168,7 @@ func newHelper(scheme string) *testHelper { if scheme == rawdb.PathScheme { config.PathDB = &pathdb.Config{ SnapshotNoBuild: true, + NoAsyncFlush: true, } // disable caching } else { config.HashDB = &hashdb.Config{} // disable caching diff --git a/core/state/state_object.go b/core/state/state_object.go index a6979bd3612f..767f469bfde5 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -124,6 +124,7 @@ func (s *stateObject) touch() { // subsequent reads to expand the same trie instead of reloading from disk. func (s *stateObject) getTrie() (Trie, error) { if s.trie == nil { + // Assumes the primary account trie is already loaded tr, err := s.db.db.OpenStorageTrie(s.db.originalRoot, s.address, s.data.Root, s.db.trie) if err != nil { return nil, err @@ -377,7 +378,6 @@ func (s *stateObject) updateRoot() { // fulfills the storage diffs into the given accountUpdate struct. func (s *stateObject) commitStorage(op *accountUpdate) { var ( - buf = crypto.NewKeccakState() encode = func(val common.Hash) []byte { if val == (common.Hash{}) { return nil @@ -394,7 +394,7 @@ func (s *stateObject) commitStorage(op *accountUpdate) { if val == s.originStorage[key] { continue } - hash := crypto.HashData(buf, key[:]) + hash := crypto.Keccak256Hash(key[:]) if op.storages == nil { op.storages = make(map[common.Hash][]byte) } diff --git a/core/state/state_test.go b/core/state/state_test.go index b443411f1bff..eeeb7fa2df87 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -54,8 +54,6 @@ func TestDump(t *testing.T) { obj3.SetBalance(uint256.NewInt(44)) // write some of them to the trie - s.state.updateStateObject(obj1) - s.state.updateStateObject(obj2) root, _ := s.state.Commit(0, false, false) // check that DumpToCollector contains the state objects that are in trie @@ -114,8 +112,6 @@ func TestIterativeDump(t *testing.T) { obj4.AddBalance(uint256.NewInt(1337)) // write some of them to the trie - s.state.updateStateObject(obj1) - s.state.updateStateObject(obj2) root, _ := s.state.Commit(0, false, false) s.state, _ = New(root, tdb) diff --git a/core/state/statedb.go b/core/state/statedb.go index 51453055c3cf..e80588507981 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -79,8 +79,8 @@ func (m *mutation) isDelete() bool { type StateDB struct { db Database prefetcher *triePrefetcher - trie Trie reader Reader + trie Trie // it's resolved on first access // originalRoot is the pre-state root, before any changes were made. // It will be updated when the Commit is called. @@ -169,13 +169,8 @@ func New(root common.Hash, db Database) (*StateDB, error) { // NewWithReader creates a new state for the specified state root. Unlike New, // this function accepts an additional Reader which is bound to the given root. func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, error) { - tr, err := db.OpenTrie(root) - if err != nil { - return nil, err - } sdb := &StateDB{ db: db, - trie: tr, originalRoot: root, reader: reader, stateObjects: make(map[common.Address]*stateObject), @@ -252,11 +247,12 @@ func (s *StateDB) AddLog(log *types.Log) { // GetLogs returns the logs matching the specified transaction hash, and annotates // them with the given blockNumber and blockHash. -func (s *StateDB) GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log { +func (s *StateDB) GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash, blockTime uint64) []*types.Log { logs := s.logs[hash] for _, l := range logs { l.BlockNumber = blockNumber l.BlockHash = blockHash + l.BlockTimestamp = blockTime } return logs } @@ -393,6 +389,15 @@ func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) commo return common.Hash{} } +// GetStateAndCommittedState returns the current value and the original value. +func (s *StateDB) GetStateAndCommittedState(addr common.Address, hash common.Hash) (common.Hash, common.Hash) { + stateObject := s.getStateObject(addr) + if stateObject != nil { + return stateObject.getState(hash) + } + return common.Hash{}, common.Hash{} +} + // Database retrieves the low level database supporting the lower level trie ops. func (s *StateDB) Database() Database { return s.db @@ -663,7 +668,6 @@ func (s *StateDB) Copy() *StateDB { // Copy all the basic fields, initialize the memory ones state := &StateDB{ db: s.db, - trie: mustCopyTrie(s.trie), reader: s.reader, originalRoot: s.originalRoot, stateObjects: make(map[common.Address]*stateObject, len(s.stateObjects)), @@ -687,6 +691,9 @@ func (s *StateDB) Copy() *StateDB { transientStorage: s.transientStorage.Copy(), journal: s.journal.copy(), } + if s.trie != nil { + state.trie = mustCopyTrie(s.trie) + } if s.witness != nil { state.witness = s.witness.Copy() } @@ -782,6 +789,20 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { // Finalise all the dirty storage states and write them into the tries s.Finalise(deleteEmptyObjects) + // Initialize the trie if it's not constructed yet. If the prefetch + // is enabled, the trie constructed below will be replaced by the + // prefetched one. + // + // This operation must be done before state object storage hashing, + // as it assumes the main trie is already loaded. + if s.trie == nil { + tr, err := s.db.OpenTrie(s.originalRoot) + if err != nil { + s.setError(err) + return common.Hash{} + } + s.trie = tr + } // If there was a trie prefetcher operating, terminate it async so that the // individual storage tries can be updated as soon as the disk load finishes. if s.prefetcher != nil { @@ -1063,7 +1084,6 @@ func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root func (s *StateDB) handleDestruction(noStorageWiping bool) (map[common.Hash]*accountDelete, []*trienode.NodeSet, error) { var ( nodes []*trienode.NodeSet - buf = crypto.NewKeccakState() deletes = make(map[common.Hash]*accountDelete) ) for addr, prevObj := range s.stateObjectsDestruct { @@ -1078,7 +1098,7 @@ func (s *StateDB) handleDestruction(noStorageWiping bool) (map[common.Hash]*acco continue } // The account was existent, it can be either case (c) or (d). - addrHash := crypto.HashData(buf, addr.Bytes()) + addrHash := crypto.Keccak256Hash(addr.Bytes()) op := &accountDelete{ address: addr, origin: types.SlimAccountRLP(*prev), diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index a2fdfe9a217a..3d1ef1503180 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -85,8 +85,8 @@ func (s *hookedStateDB) GetRefund() uint64 { return s.inner.GetRefund() } -func (s *hookedStateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { - return s.inner.GetCommittedState(addr, hash) +func (s *hookedStateDB) GetStateAndCommittedState(addr common.Address, hash common.Hash) (common.Hash, common.Hash) { + return s.inner.GetStateAndCommittedState(addr, hash) } func (s *hookedStateDB) GetState(addr common.Address, hash common.Hash) common.Hash { diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index 709b5ed510bc..67e27cc832dc 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -171,7 +171,6 @@ func TestCopy(t *testing.T) { for i := byte(0); i < 255; i++ { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) obj.AddBalance(uint256.NewInt(uint64(i))) - orig.updateStateObject(obj) } orig.Finalise(false) @@ -190,10 +189,6 @@ func TestCopy(t *testing.T) { 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) - ccopy.updateStateObject(copyObj) } // Finalise the changes on all concurrently @@ -238,7 +233,6 @@ func TestCopyWithDirtyJournal(t *testing.T) { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) obj.AddBalance(uint256.NewInt(uint64(i))) obj.data.Root = common.HexToHash("0xdeadbeef") - orig.updateStateObject(obj) } root, _ := orig.Commit(0, true, false) orig, _ = New(root, db) @@ -248,8 +242,6 @@ func TestCopyWithDirtyJournal(t *testing.T) { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) amount := uint256.NewInt(uint64(i)) obj.SetBalance(new(uint256.Int).Sub(obj.Balance(), amount)) - - orig.updateStateObject(obj) } cpy := orig.Copy() @@ -284,7 +276,6 @@ func TestCopyObjectState(t *testing.T) { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) obj.AddBalance(uint256.NewInt(uint64(i))) obj.data.Root = common.HexToHash("0xdeadbeef") - orig.updateStateObject(obj) } orig.Finalise(true) cpy := orig.Copy() @@ -573,7 +564,7 @@ func forEachStorage(s *StateDB, addr common.Address, cb func(key, value common.H ) for it.Next() { - key := common.BytesToHash(s.trie.GetKey(it.Key)) + key := common.BytesToHash(tr.GetKey(it.Key)) visited[key] = true if value, dirty := so.dirtyStorage[key]; dirty { if !cb(key, value) { @@ -669,9 +660,9 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", state.GetRefund(), checkstate.GetRefund()) } - if !reflect.DeepEqual(state.GetLogs(common.Hash{}, 0, common.Hash{}), checkstate.GetLogs(common.Hash{}, 0, common.Hash{})) { + if !reflect.DeepEqual(state.GetLogs(common.Hash{}, 0, common.Hash{}, 0), checkstate.GetLogs(common.Hash{}, 0, common.Hash{}, 0)) { return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", - state.GetLogs(common.Hash{}, 0, common.Hash{}), checkstate.GetLogs(common.Hash{}, 0, common.Hash{})) + state.GetLogs(common.Hash{}, 0, common.Hash{}, 0), checkstate.GetLogs(common.Hash{}, 0, common.Hash{}, 0)) } if !maps.Equal(state.journal.dirties, checkstate.journal.dirties) { getKeys := func(dirty map[common.Address]int) string { @@ -982,6 +973,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) { TrieCleanSize: 0, StateCleanSize: 0, WriteBufferSize: 0, + NoAsyncFlush: true, }}) // disable caching } else { tdb = triedb.NewDatabase(memDb, &triedb.Config{HashDB: &hashdb.Config{ @@ -1004,18 +996,25 @@ func testMissingTrieNodes(t *testing.T, scheme string) { // force-flush tdb.Commit(root, false) } - // Create a new state on the old root - state, _ = New(root, db) // Now we clear out the memdb it := memDb.NewIterator(nil, nil) for it.Next() { k := it.Key() - // Leave the root intact - if !bytes.Equal(k, root[:]) { - t.Logf("key: %x", k) - memDb.Delete(k) + if scheme == rawdb.HashScheme { + if !bytes.Equal(k, root[:]) { + t.Logf("key: %x", k) + memDb.Delete(k) + } + } + if scheme == rawdb.PathScheme { + rk := k[len(rawdb.TrieNodeAccountPrefix):] + if len(rk) != 0 { + t.Logf("key: %x", k) + memDb.Delete(k) + } } } + state, _ = New(root, db) balance := state.GetBalance(addr) // The removed elem should lead to it returning zero balance if exp, got := uint64(0), balance.Uint64(); got != exp { diff --git a/core/state/sync_test.go b/core/state/sync_test.go index 5c8b5a90f763..cae0e0a936bc 100644 --- a/core/state/sync_test.go +++ b/core/state/sync_test.go @@ -46,7 +46,9 @@ func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, c // Create an empty state config := &triedb.Config{Preimages: true} if scheme == rawdb.PathScheme { - config.PathDB = pathdb.Defaults + pconfig := *pathdb.Defaults + pconfig.NoAsyncFlush = true + config.PathDB = &pconfig } else { config.HashDB = hashdb.Defaults } diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index f3129f57cdbf..c0ce705c77ae 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -57,7 +57,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c workers errgroup.Group reader = statedb.Reader() ) - workers.SetLimit(runtime.NumCPU() / 2) + workers.SetLimit(max(1, 4*runtime.NumCPU()/5)) // Aggressively run the prefetching // Iterate over and process the individual transactions for i, tx := range block.Transactions() { diff --git a/core/state_processor.go b/core/state_processor.go index 322bd24f410a..ee98326467f4 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -97,7 +97,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } statedb.SetTxContext(tx.Hash(), i) - receipt, err := ApplyTransactionWithEVM(msg, gp, statedb, blockNumber, blockHash, tx, usedGas, evm) + receipt, err := ApplyTransactionWithEVM(msg, gp, statedb, blockNumber, blockHash, context.Time, tx, usedGas, evm) if err != nil { return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -136,7 +136,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // ApplyTransactionWithEVM attempts to apply a transaction to the given state database // and uses the input parameters for its environment similar to ApplyTransaction. However, // this method takes an already created EVM instance as input. -func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) { +func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, blockTime uint64, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) { if hooks := evm.Config.Tracer; hooks != nil { if hooks.OnTxStart != nil { hooks.OnTxStart(evm.GetVMContext(), tx, msg.From) @@ -161,15 +161,14 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, // Merge the tx-local access event into the "block-local" one, in order to collect // all values, so that the witness can be built. - if statedb.GetTrie().IsVerkle() { + if statedb.Database().TrieDB().IsVerkle() { statedb.AccessEvents().Merge(evm.AccessEvents) } - - return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), nil + return MakeReceipt(evm, result, statedb, blockNumber, blockHash, blockTime, tx, *usedGas, root), nil } // MakeReceipt generates the receipt object for a transaction given its execution result. -func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas uint64, root []byte) *types.Receipt { +func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, blockTime uint64, tx *types.Transaction, usedGas uint64, root []byte) *types.Receipt { // Create a new receipt for the transaction, storing the intermediate root and gas used // by the tx. receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: usedGas} @@ -192,7 +191,7 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b } // Set the receipt logs and create the bloom filter. - receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash) + receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash, blockTime) receipt.Bloom = types.CreateBloom(receipt) receipt.BlockHash = blockHash receipt.BlockNumber = blockNumber @@ -210,7 +209,7 @@ func ApplyTransaction(evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header * return nil, err } // Create a new context to be used in the EVM environment - return ApplyTransactionWithEVM(msg, gp, statedb, header.Number, header.Hash(), tx, usedGas, evm) + return ApplyTransactionWithEVM(msg, gp, statedb, header.Number, header.Hash(), header.Time, tx, usedGas, evm) } // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root diff --git a/core/state_processor_test.go b/core/state_processor_test.go index ffdf06381223..d175b5eac59a 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -30,7 +30,6 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/rawdb" "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/params" "github.com/ethereum/go-ethereum/trie" @@ -125,7 +124,7 @@ func TestStateProcessorErrors(t *testing.T) { }, }, } - blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) + blockchain, _ = NewBlockChain(db, gspec, beacon.New(ethash.NewFaker()), nil) tooBigInitCode = [params.MaxInitCodeSize + 1]byte{} ) @@ -293,7 +292,7 @@ func TestStateProcessorErrors(t *testing.T) { }, }, } - blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + blockchain, _ = NewBlockChain(db, gspec, ethash.NewFaker(), nil) ) defer blockchain.Stop() for i, tt := range []struct { @@ -332,7 +331,7 @@ func TestStateProcessorErrors(t *testing.T) { }, }, } - blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) + blockchain, _ = NewBlockChain(db, gspec, beacon.New(ethash.NewFaker()), nil) ) defer blockchain.Stop() for i, tt := range []struct { diff --git a/core/state_transition.go b/core/state_transition.go index 4f172682d075..de4558253b5e 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -394,6 +394,10 @@ func (st *stateTransition) preCheck() error { return fmt.Errorf("%w (sender %v)", ErrEmptyAuthList, msg.From) } } + // Verify tx gas limit does not exceed EIP-7825 cap. + if st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber, st.evm.Context.Time) && msg.GasLimit > params.MaxTxGas { + return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, msg.GasLimit) + } return st.buyGas() } @@ -534,10 +538,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { effectiveTip := msg.GasPrice if rules.IsLondon { - effectiveTip = new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee) - if effectiveTip.Cmp(msg.GasTipCap) > 0 { - effectiveTip = msg.GasTipCap - } + effectiveTip = new(big.Int).Sub(msg.GasPrice, st.evm.Context.BaseFee) } effectiveTipU256, _ := uint256.FromBig(effectiveTip) diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 2602d821040a..dbf65033f8a0 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -36,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" @@ -1302,27 +1301,13 @@ func (p *BlobPool) GetMetadata(hash common.Hash) *txpool.TxMetadata { } } -// GetBlobs returns a number of blobs are proofs for the given versioned hashes. +// GetBlobs returns a number of blobs and proofs for the given versioned hashes. // This is a utility method for the engine API, enabling consensus clients to // retrieve blobs from the pools directly instead of the network. -func (p *BlobPool) GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Proof) { - // Create a map of the blob hash to indices for faster fills - var ( - blobs = make([]*kzg4844.Blob, len(vhashes)) - proofs = make([]*kzg4844.Proof, len(vhashes)) - ) - index := make(map[common.Hash]int) - for i, vhash := range vhashes { - index[vhash] = i - } - // Iterate over the blob hashes, pulling transactions that fill it. Take care - // to also fill anything else the transaction might include (probably will). - for i, vhash := range vhashes { - // If already filled by a previous fetch, skip - if blobs[i] != nil { - continue - } - // Unfilled, retrieve the datastore item (in a short lock) +func (p *BlobPool) GetBlobs(vhashes []common.Hash) []*types.BlobTxSidecar { + sidecars := make([]*types.BlobTxSidecar, len(vhashes)) + for idx, vhash := range vhashes { + // Retrieve the datastore item (in a short lock) p.lock.RLock() id, exists := p.lookup.storeidOfBlob(vhash) if !exists { @@ -1342,16 +1327,24 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844. log.Error("Blobs corrupted for traced transaction", "id", id, "err", err) continue } - // Fill anything requested, not just the current versioned hash - sidecar := item.BlobTxSidecar() - for j, blobhash := range item.BlobHashes() { - if idx, ok := index[blobhash]; ok { - blobs[idx] = &sidecar.Blobs[j] - proofs[idx] = &sidecar.Proofs[j] - } + sidecars[idx] = item.BlobTxSidecar() + } + return sidecars +} + +// AvailableBlobs returns the number of blobs that are available in the subpool. +func (p *BlobPool) AvailableBlobs(vhashes []common.Hash) int { + available := 0 + for _, vhash := range vhashes { + // Retrieve the datastore item (in a short lock) + p.lock.RLock() + _, exists := p.lookup.storeidOfBlob(vhash) + p.lock.RUnlock() + if exists { + available++ } } - return blobs, proofs + return available } // Add inserts a set of blob transactions into the pool if they pass validation (both @@ -1645,6 +1638,11 @@ func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*tx break // blobfee too low, cannot be included, discard rest of txs from the account } } + if filter.GasLimitCap != 0 { + if tx.execGas > filter.GasLimitCap { + break // execution gas limit is too high + } + } // Transaction was accepted according to the filter, append to the pending list lazies = append(lazies, &txpool.LazyTransaction{ Pool: p, diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index 12b64bf67488..f8d3f38412c5 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -417,8 +417,23 @@ func verifyBlobRetrievals(t *testing.T, pool *BlobPool) { for i := range testBlobVHashes { copy(hashes[i][:], testBlobVHashes[i][:]) } - blobs, proofs := pool.GetBlobs(hashes) - + sidecars := pool.GetBlobs(hashes) + var blobs []*kzg4844.Blob + var proofs []*kzg4844.Proof + for idx, sidecar := range sidecars { + if sidecar == nil { + blobs = append(blobs, nil) + proofs = append(proofs, nil) + continue + } + blobHashes := sidecar.BlobHashes() + for i, hash := range blobHashes { + if hash == hashes[idx] { + blobs = append(blobs, &sidecar.Blobs[i]) + proofs = append(proofs, &sidecar.Proofs[i]) + } + } + } // Cross validate what we received vs what we wanted if len(blobs) != len(hashes) || len(proofs) != len(hashes) { t.Errorf("retrieved blobs/proofs size mismatch: have %d/%d, want %d", len(blobs), len(proofs), len(hashes)) diff --git a/core/txpool/blobpool/limbo.go b/core/txpool/blobpool/limbo.go index d5992f2906db..99d1b4ad6b3f 100644 --- a/core/txpool/blobpool/limbo.go +++ b/core/txpool/blobpool/limbo.go @@ -116,7 +116,7 @@ func (l *limbo) finalize(final *types.Header) { // Just in case there's no final block yet (network not yet merged, weird // restart, sethead, etc), fail gracefully. if final == nil { - log.Error("Nil finalized block cannot evict old blobs") + log.Warn("Nil finalized block cannot evict old blobs") return } for block, ids := range l.groups { @@ -139,11 +139,11 @@ 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.Hash()]; ok { - log.Error("Limbo cannot push already tracked blobs", "tx", tx) + log.Error("Limbo cannot push already tracked blobs", "tx", tx.Hash()) return errors.New("already tracked blob transaction") } if err := l.setAndIndex(tx, block); err != nil { - log.Error("Failed to set and index limboed blobs", "tx", tx, "err", err) + log.Error("Failed to set and index limboed blobs", "tx", tx.Hash(), "err", err) return err } return nil diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 0223b456e659..93a003c172ba 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -35,7 +35,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" @@ -531,11 +530,19 @@ func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address] txs := list.Flatten() // If the miner requests tip enforcement, cap the lists now - if minTipBig != nil { + if minTipBig != nil || filter.GasLimitCap != 0 { for i, tx := range txs { - if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 { - txs = txs[:i] - break + if minTipBig != nil { + if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 { + txs = txs[:i] + break + } + } + if filter.GasLimitCap != 0 { + if tx.Gas() > filter.GasLimitCap { + txs = txs[:i] + break + } } } } @@ -1063,12 +1070,6 @@ func (pool *LegacyPool) GetMetadata(hash common.Hash) *txpool.TxMetadata { } } -// GetBlobs is not supported by the legacy transaction pool, it is just here to -// implement the txpool.SubPool interface. -func (pool *LegacyPool) GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Proof) { - return nil, nil -} - // Has returns an indicator whether txpool has a transaction cached with the // given hash. func (pool *LegacyPool) Has(hash common.Hash) bool { @@ -1262,6 +1263,21 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, } pool.mu.Lock() if reset != nil { + if reset.newHead != nil && reset.oldHead != nil { + // Discard the transactions with the gas limit higher than the cap. + if pool.chainconfig.IsOsaka(reset.newHead.Number, reset.newHead.Time) && !pool.chainconfig.IsOsaka(reset.oldHead.Number, reset.oldHead.Time) { + var hashes []common.Hash + pool.all.Range(func(hash common.Hash, tx *types.Transaction) bool { + if tx.Gas() > params.MaxTxGas { + hashes = append(hashes, hash) + } + return true + }) + for _, hash := range hashes { + pool.removeTx(hash, true, true) + } + } + } // Reset from the old head to the new, rescheduling any reorged transactions pool.reset(reset.oldHead, reset.newHead) diff --git a/core/txpool/locals/tx_tracker_test.go b/core/txpool/locals/tx_tracker_test.go index 0668d243fcd6..367fb6b6daca 100644 --- a/core/txpool/locals/tx_tracker_test.go +++ b/core/txpool/locals/tx_tracker_test.go @@ -28,7 +28,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" @@ -65,7 +64,7 @@ func newTestEnv(t *testing.T, n int, gasTip uint64, journal string) *testEnv { }) db := rawdb.NewMemoryDatabase() - chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + chain, _ := core.NewBlockChain(db, gspec, ethash.NewFaker(), nil) legacyPool := legacypool.New(legacypool.DefaultConfig, chain) pool, err := txpool.New(gasTip, chain, []txpool.SubPool{legacyPool}) diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go index 8cfc14f16407..f1f605668697 100644 --- a/core/txpool/subpool.go +++ b/core/txpool/subpool.go @@ -23,7 +23,6 @@ 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" "github.com/holiman/uint256" ) @@ -74,9 +73,10 @@ type LazyResolver interface { // a very specific call site in mind and each one can be evaluated very cheaply // by the pool implementations. Only add new ones that satisfy those constraints. type PendingFilter struct { - MinTip *uint256.Int // Minimum miner tip required to include a transaction - BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction - BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction + MinTip *uint256.Int // Minimum miner tip required to include a transaction + BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction + BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction + GasLimitCap uint64 // Maximum gas can be used for a single transaction execution (0 means no limit) OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling) OnlyBlobTxs bool // Return only blob transactions (block blob-space filling) @@ -133,11 +133,6 @@ type SubPool interface { // given transaction hash. GetMetadata(hash common.Hash) *TxMetadata - // GetBlobs returns a number of blobs are proofs for the given versioned hashes. - // This is a utility method for the engine API, enabling consensus clients to - // retrieve blobs from the pools directly instead of the network. - GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Proof) - // ValidateTxBasics checks whether a transaction is valid according to the consensus // rules, but does not check state-dependent validation such as sufficient balance. // This check is meant as a static check which can be performed without holding the diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index cc8f74c1b8e5..b5470cd7fc0c 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -26,7 +26,6 @@ import ( "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/crypto/kzg4844" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -308,22 +307,6 @@ func (p *TxPool) GetMetadata(hash common.Hash) *TxMetadata { return nil } -// GetBlobs returns a number of blobs are proofs for the given versioned hashes. -// This is a utility method for the engine API, enabling consensus clients to -// retrieve blobs from the pools directly instead of the network. -func (p *TxPool) GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Proof) { - for _, subpool := range p.subpools { - // It's an ugly to assume that only one pool will be capable of returning - // anything meaningful for this call, but anythingh else requires merging - // partial responses and that's too annoying to do until we get a second - // blobpool (probably never). - if blobs, proofs := subpool.GetBlobs(vhashes); blobs != nil { - return blobs, proofs - } - } - return nil, nil -} - // 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. diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 720d0d3b722c..92381fd76c82 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -90,6 +90,9 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types if rules.IsShanghai && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) } + if rules.IsOsaka && tx.Gas() > params.MaxTxGas { + return fmt.Errorf("%w (cap: %d, tx: %d)", core.ErrGasLimitTooHigh, params.MaxTxGas, tx.Gas()) + } // Transactions can't be negative. This may never happen using RLP decoded // transactions but may occur for transactions created using the RPC. if tx.Value().Sign() < 0 { @@ -138,28 +141,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types return fmt.Errorf("%w: gas tip cap %v, minimum needed %v", ErrTxGasPriceTooLow, tx.GasTipCap(), opts.MinTip) } if tx.Type() == types.BlobTxType { - // Ensure the blob fee cap satisfies the minimum blob gas price - if tx.BlobGasFeeCapIntCmp(blobTxMinBlobGasPrice) < 0 { - return fmt.Errorf("%w: blob fee cap %v, minimum needed %v", ErrTxGasPriceTooLow, tx.BlobGasFeeCap(), blobTxMinBlobGasPrice) - } - sidecar := tx.BlobTxSidecar() - if sidecar == nil { - return errors.New("missing sidecar in blob transaction") - } - // Ensure the number of items in the blob transaction and various side - // data match up before doing any expensive validations - hashes := tx.BlobHashes() - if len(hashes) == 0 { - return errors.New("blobless blob transaction") - } - maxBlobs := eip4844.MaxBlobsPerBlock(opts.Config, head.Time) - if len(hashes) > maxBlobs { - return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), maxBlobs) - } - // Ensure commitments, proofs and hashes are valid - if err := validateBlobSidecar(hashes, sidecar); err != nil { - return err - } + return validateBlobTx(tx, head, opts) } if tx.Type() == types.SetCodeTxType { if len(tx.SetCodeAuthorizations()) == 0 { @@ -169,18 +151,46 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types return nil } -func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobTxSidecar) error { +// validateBlobTx implements the blob-transaction specific validations. +func validateBlobTx(tx *types.Transaction, head *types.Header, opts *ValidationOptions) error { + sidecar := tx.BlobTxSidecar() + if sidecar == nil { + return errors.New("missing sidecar in blob transaction") + } + // Ensure the blob fee cap satisfies the minimum blob gas price + if tx.BlobGasFeeCapIntCmp(blobTxMinBlobGasPrice) < 0 { + return fmt.Errorf("%w: blob fee cap %v, minimum needed %v", ErrTxGasPriceTooLow, tx.BlobGasFeeCap(), blobTxMinBlobGasPrice) + } + // Ensure the number of items in the blob transaction and various side + // data match up before doing any expensive validations + hashes := tx.BlobHashes() + if len(hashes) == 0 { + return errors.New("blobless blob transaction") + } + maxBlobs := eip4844.MaxBlobsPerBlock(opts.Config, head.Time) + if len(hashes) > maxBlobs { + return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), maxBlobs) + } 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.Proofs) != len(hashes) { - return fmt.Errorf("invalid number of %d blob proofs compared to %d blob hashes", len(sidecar.Proofs), len(hashes)) - } if err := sidecar.ValidateBlobCommitmentHashes(hashes); err != nil { return err } - // Blob commitments match with the hashes in the transaction, verify the - // blobs themselves via KZG + // Fork-specific sidecar checks, including proof verification. + if opts.Config.IsOsaka(head.Number, head.Time) { + return validateBlobSidecarOsaka(sidecar, hashes) + } + return validateBlobSidecarLegacy(sidecar, hashes) +} + +func validateBlobSidecarLegacy(sidecar *types.BlobTxSidecar, hashes []common.Hash) error { + if sidecar.Version != 0 { + return fmt.Errorf("invalid sidecar version pre-osaka: %v", sidecar.Version) + } + if len(sidecar.Proofs) != len(hashes) { + return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes)) + } 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) @@ -189,6 +199,16 @@ func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobTxSidecar) err return nil } +func validateBlobSidecarOsaka(sidecar *types.BlobTxSidecar, hashes []common.Hash) error { + if sidecar.Version != 1 { + return fmt.Errorf("invalid sidecar version post-osaka: %v", sidecar.Version) + } + if len(sidecar.Proofs) != len(hashes)*kzg4844.CellProofsPerBlob { + return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes)*kzg4844.CellProofsPerBlob) + } + return kzg4844.VerifyCellProofs(sidecar.Blobs, sidecar.Commitments, sidecar.Proofs) +} + // ValidationOptionsWithState define certain differences between stateful transaction // validation across the different pools without having to duplicate those checks. type ValidationOptionsWithState struct { diff --git a/core/types/bal/bal.go b/core/types/bal/bal.go new file mode 100644 index 000000000000..fca54f7681f4 --- /dev/null +++ b/core/types/bal/bal.go @@ -0,0 +1,182 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bal + +import ( + "bytes" + "maps" + + "github.com/ethereum/go-ethereum/common" + "github.com/holiman/uint256" +) + +// CodeChange contains the runtime bytecode deployed at an address and the +// transaction index where the deployment took place. +type CodeChange struct { + TxIndex uint16 + Code []byte `json:"code,omitempty"` +} + +// ConstructionAccountAccess contains post-block account state for mutations as well as +// all storage keys that were read during execution. It is used when building block +// access list during execution. +type ConstructionAccountAccess struct { + // StorageWrites is the post-state values of an account's storage slots + // that were modified in a block, keyed by the slot key and the tx index + // where the modification occurred. + StorageWrites map[common.Hash]map[uint16]common.Hash `json:"storageWrites,omitempty"` + + // StorageReads is the set of slot keys that were accessed during block + // execution. + // + // Storage slots which are both read and written (with changed values) + // appear only in StorageWrites. + StorageReads map[common.Hash]struct{} `json:"storageReads,omitempty"` + + // BalanceChanges contains the post-transaction balances of an account, + // keyed by transaction indices where it was changed. + BalanceChanges map[uint16]*uint256.Int `json:"balanceChanges,omitempty"` + + // NonceChanges contains the post-state nonce values of an account keyed + // by tx index. + NonceChanges map[uint16]uint64 `json:"nonceChanges,omitempty"` + + // CodeChange is only set for contract accounts which were deployed in + // the block. + CodeChange *CodeChange `json:"codeChange,omitempty"` +} + +// NewConstructionAccountAccess initializes the account access object. +func NewConstructionAccountAccess() *ConstructionAccountAccess { + return &ConstructionAccountAccess{ + StorageWrites: make(map[common.Hash]map[uint16]common.Hash), + StorageReads: make(map[common.Hash]struct{}), + BalanceChanges: make(map[uint16]*uint256.Int), + NonceChanges: make(map[uint16]uint64), + } +} + +// ConstructionBlockAccessList contains post-block modified state and some state accessed +// in execution (account addresses and storage keys). +type ConstructionBlockAccessList struct { + Accounts map[common.Address]*ConstructionAccountAccess +} + +// NewConstructionBlockAccessList instantiates an empty access list. +func NewConstructionBlockAccessList() ConstructionBlockAccessList { + return ConstructionBlockAccessList{ + Accounts: make(map[common.Address]*ConstructionAccountAccess), + } +} + +// AccountRead records the address of an account that has been read during execution. +func (b *ConstructionBlockAccessList) AccountRead(addr common.Address) { + if _, ok := b.Accounts[addr]; !ok { + b.Accounts[addr] = NewConstructionAccountAccess() + } +} + +// StorageRead records a storage key read during execution. +func (b *ConstructionBlockAccessList) StorageRead(address common.Address, key common.Hash) { + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewConstructionAccountAccess() + } + if _, ok := b.Accounts[address].StorageWrites[key]; ok { + return + } + b.Accounts[address].StorageReads[key] = struct{}{} +} + +// StorageWrite records the post-transaction value of a mutated storage slot. +// The storage slot is removed from the list of read slots. +func (b *ConstructionBlockAccessList) StorageWrite(txIdx uint16, address common.Address, key, value common.Hash) { + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewConstructionAccountAccess() + } + if _, ok := b.Accounts[address].StorageWrites[key]; !ok { + b.Accounts[address].StorageWrites[key] = make(map[uint16]common.Hash) + } + b.Accounts[address].StorageWrites[key][txIdx] = value + + delete(b.Accounts[address].StorageReads, key) +} + +// CodeChange records the code of a newly-created contract. +func (b *ConstructionBlockAccessList) CodeChange(address common.Address, txIndex uint16, code []byte) { + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewConstructionAccountAccess() + } + b.Accounts[address].CodeChange = &CodeChange{ + TxIndex: txIndex, + Code: bytes.Clone(code), + } +} + +// NonceChange records tx post-state nonce of any contract-like accounts whose +// nonce was incremented. +func (b *ConstructionBlockAccessList) NonceChange(address common.Address, txIdx uint16, postNonce uint64) { + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewConstructionAccountAccess() + } + b.Accounts[address].NonceChanges[txIdx] = postNonce +} + +// BalanceChange records the post-transaction balance of an account whose +// balance changed. +func (b *ConstructionBlockAccessList) BalanceChange(txIdx uint16, address common.Address, balance *uint256.Int) { + if _, ok := b.Accounts[address]; !ok { + b.Accounts[address] = NewConstructionAccountAccess() + } + b.Accounts[address].BalanceChanges[txIdx] = balance.Clone() +} + +// PrettyPrint returns a human-readable representation of the access list +func (b *ConstructionBlockAccessList) PrettyPrint() string { + enc := b.toEncodingObj() + return enc.PrettyPrint() +} + +// Copy returns a deep copy of the access list. +func (b *ConstructionBlockAccessList) Copy() *ConstructionBlockAccessList { + res := NewConstructionBlockAccessList() + for addr, aa := range b.Accounts { + var aaCopy ConstructionAccountAccess + + slotWrites := make(map[common.Hash]map[uint16]common.Hash, len(aa.StorageWrites)) + for key, m := range aa.StorageWrites { + slotWrites[key] = maps.Clone(m) + } + aaCopy.StorageWrites = slotWrites + aaCopy.StorageReads = maps.Clone(aa.StorageReads) + + balances := make(map[uint16]*uint256.Int, len(aa.BalanceChanges)) + for index, balance := range aa.BalanceChanges { + balances[index] = balance.Clone() + } + aaCopy.BalanceChanges = balances + aaCopy.NonceChanges = maps.Clone(aa.NonceChanges) + + if aa.CodeChange != nil { + aaCopy.CodeChange = &CodeChange{ + TxIndex: aa.CodeChange.TxIndex, + Code: bytes.Clone(aa.CodeChange.Code), + } + } + res.Accounts[addr] = &aaCopy + } + return &res +} diff --git a/core/types/bal/bal_encoding.go b/core/types/bal/bal_encoding.go new file mode 100644 index 000000000000..d7d08801b111 --- /dev/null +++ b/core/types/bal/bal_encoding.go @@ -0,0 +1,344 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bal + +import ( + "bytes" + "cmp" + "errors" + "fmt" + "io" + "maps" + "slices" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" +) + +//go:generate go run github.com/ethereum/go-ethereum/rlp/rlpgen -out bal_encoding_rlp_generated.go -type BlockAccessList -decoder + +// These are objects used as input for the access list encoding. They mirror +// the spec format. + +// BlockAccessList is the encoding format of ConstructionBlockAccessList. +type BlockAccessList struct { + Accesses []AccountAccess `ssz-max:"300000"` +} + +// Validate returns an error if the contents of the access list are not ordered +// according to the spec or any code changes are contained which exceed protocol +// max code size. +func (e *BlockAccessList) Validate() error { + if !slices.IsSortedFunc(e.Accesses, func(a, b AccountAccess) int { + return bytes.Compare(a.Address[:], b.Address[:]) + }) { + return errors.New("block access list accounts not in lexicographic order") + } + for _, entry := range e.Accesses { + if err := entry.validate(); err != nil { + return err + } + } + return nil +} + +// Hash computes the keccak256 hash of the access list +func (e *BlockAccessList) Hash() common.Hash { + var enc bytes.Buffer + err := e.EncodeRLP(&enc) + if err != nil { + // errors here are related to BAL values exceeding maximum size defined + // by the spec. Hard-fail because these cases are not expected to be hit + // under reasonable conditions. + panic(err) + } + return crypto.Keccak256Hash(enc.Bytes()) +} + +// encodeBalance encodes the provided balance into 16-bytes. +func encodeBalance(val *uint256.Int) [16]byte { + valBytes := val.Bytes() + if len(valBytes) > 16 { + panic("can't encode value that is greater than 16 bytes in size") + } + var enc [16]byte + copy(enc[16-len(valBytes):], valBytes[:]) + return enc +} + +// encodingBalanceChange is the encoding format of BalanceChange. +type encodingBalanceChange struct { + TxIdx uint16 `ssz-size:"2"` + Balance [16]byte `ssz-size:"16"` +} + +// encodingAccountNonce is the encoding format of NonceChange. +type encodingAccountNonce struct { + TxIdx uint16 `ssz-size:"2"` + Nonce uint64 `ssz-size:"8"` +} + +// encodingStorageWrite is the encoding format of StorageWrites. +type encodingStorageWrite struct { + TxIdx uint16 + ValueAfter [32]byte `ssz-size:"32"` +} + +// encodingStorageWrite is the encoding format of SlotWrites. +type encodingSlotWrites struct { + Slot [32]byte `ssz-size:"32"` + Accesses []encodingStorageWrite `ssz-max:"300000"` +} + +// validate returns an instance of the encoding-representation slot writes in +// working representation. +func (e *encodingSlotWrites) validate() error { + if slices.IsSortedFunc(e.Accesses, func(a, b encodingStorageWrite) int { + return cmp.Compare[uint16](a.TxIdx, b.TxIdx) + }) { + return nil + } + return errors.New("storage write tx indices not in order") +} + +// AccountAccess is the encoding format of ConstructionAccountAccess. +type AccountAccess struct { + Address [20]byte `ssz-size:"20"` // 20-byte Ethereum address + StorageWrites []encodingSlotWrites `ssz-max:"300000"` // Storage changes (slot -> [tx_index -> new_value]) + StorageReads [][32]byte `ssz-max:"300000"` // Read-only storage keys + BalanceChanges []encodingBalanceChange `ssz-max:"300000"` // Balance changes ([tx_index -> post_balance]) + NonceChanges []encodingAccountNonce `ssz-max:"300000"` // Nonce changes ([tx_index -> new_nonce]) + Code []CodeChange `ssz-max:"1"` // Code changes ([tx_index -> new_code]) +} + +// validate converts the account accesses out of encoding format. +// If any of the keys in the encoding object are not ordered according to the +// spec, an error is returned. +func (e *AccountAccess) validate() error { + // Check the storage write slots are sorted in order + if !slices.IsSortedFunc(e.StorageWrites, func(a, b encodingSlotWrites) int { + return bytes.Compare(a.Slot[:], b.Slot[:]) + }) { + return errors.New("storage writes slots not in lexicographic order") + } + for _, write := range e.StorageWrites { + if err := write.validate(); err != nil { + return err + } + } + + // Check the storage read slots are sorted in order + if !slices.IsSortedFunc(e.StorageReads, func(a, b [32]byte) int { + return bytes.Compare(a[:], b[:]) + }) { + return errors.New("storage read slots not in lexicographic order") + } + + // Check the balance changes are sorted in order + if !slices.IsSortedFunc(e.BalanceChanges, func(a, b encodingBalanceChange) int { + return cmp.Compare[uint16](a.TxIdx, b.TxIdx) + }) { + return errors.New("balance changes not in ascending order by tx index") + } + + // Check the nonce changes are sorted in order + if !slices.IsSortedFunc(e.NonceChanges, func(a, b encodingAccountNonce) int { + return cmp.Compare[uint16](a.TxIdx, b.TxIdx) + }) { + return errors.New("nonce changes not in ascending order by tx index") + } + + // Convert code change + if len(e.Code) == 1 { + if len(e.Code[0].Code) > params.MaxCodeSize { + return fmt.Errorf("code change contained oversized code") + } + } + return nil +} + +// Copy returns a deep copy of the account access +func (e *AccountAccess) Copy() AccountAccess { + res := AccountAccess{ + Address: e.Address, + StorageReads: slices.Clone(e.StorageReads), + BalanceChanges: slices.Clone(e.BalanceChanges), + NonceChanges: slices.Clone(e.NonceChanges), + } + for _, storageWrite := range e.StorageWrites { + res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{ + Slot: storageWrite.Slot, + Accesses: slices.Clone(storageWrite.Accesses), + }) + } + if len(e.Code) == 1 { + res.Code = []CodeChange{ + { + e.Code[0].TxIndex, + bytes.Clone(e.Code[0].Code), + }, + } + } + return res +} + +// EncodeRLP returns the RLP-encoded access list +func (b *ConstructionBlockAccessList) EncodeRLP(wr io.Writer) error { + return b.toEncodingObj().EncodeRLP(wr) +} + +var _ rlp.Encoder = &ConstructionBlockAccessList{} + +// toEncodingObj creates an instance of the ConstructionAccountAccess of the type that is +// used as input for the encoding. +func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAccess { + res := AccountAccess{ + Address: addr, + StorageWrites: make([]encodingSlotWrites, 0), + StorageReads: make([][32]byte, 0), + BalanceChanges: make([]encodingBalanceChange, 0), + NonceChanges: make([]encodingAccountNonce, 0), + Code: nil, + } + + // Convert write slots + writeSlots := slices.Collect(maps.Keys(a.StorageWrites)) + slices.SortFunc(writeSlots, common.Hash.Cmp) + for _, slot := range writeSlots { + var obj encodingSlotWrites + obj.Slot = slot + + slotWrites := a.StorageWrites[slot] + obj.Accesses = make([]encodingStorageWrite, 0, len(slotWrites)) + + indices := slices.Collect(maps.Keys(slotWrites)) + slices.SortFunc(indices, cmp.Compare[uint16]) + for _, index := range indices { + obj.Accesses = append(obj.Accesses, encodingStorageWrite{ + TxIdx: index, + ValueAfter: slotWrites[index], + }) + } + res.StorageWrites = append(res.StorageWrites, obj) + } + + // Convert read slots + readSlots := slices.Collect(maps.Keys(a.StorageReads)) + slices.SortFunc(readSlots, common.Hash.Cmp) + for _, slot := range readSlots { + res.StorageReads = append(res.StorageReads, slot) + } + + // Convert balance changes + balanceIndices := slices.Collect(maps.Keys(a.BalanceChanges)) + slices.SortFunc(balanceIndices, cmp.Compare[uint16]) + for _, idx := range balanceIndices { + res.BalanceChanges = append(res.BalanceChanges, encodingBalanceChange{ + TxIdx: idx, + Balance: encodeBalance(a.BalanceChanges[idx]), + }) + } + + // Convert nonce changes + nonceIndices := slices.Collect(maps.Keys(a.NonceChanges)) + slices.SortFunc(nonceIndices, cmp.Compare[uint16]) + for _, idx := range nonceIndices { + res.NonceChanges = append(res.NonceChanges, encodingAccountNonce{ + TxIdx: idx, + Nonce: a.NonceChanges[idx], + }) + } + + // Convert code change + if a.CodeChange != nil { + res.Code = []CodeChange{ + { + a.CodeChange.TxIndex, + bytes.Clone(a.CodeChange.Code), + }, + } + } + return res +} + +// toEncodingObj returns an instance of the access list expressed as the type +// which is used as input for the encoding/decoding. +func (b *ConstructionBlockAccessList) toEncodingObj() *BlockAccessList { + var addresses []common.Address + for addr := range b.Accounts { + addresses = append(addresses, addr) + } + slices.SortFunc(addresses, common.Address.Cmp) + + var res BlockAccessList + for _, addr := range addresses { + res.Accesses = append(res.Accesses, b.Accounts[addr].toEncodingObj(addr)) + } + return &res +} + +func (e *BlockAccessList) PrettyPrint() string { + var res bytes.Buffer + printWithIndent := func(indent int, text string) { + fmt.Fprintf(&res, "%s%s\n", strings.Repeat(" ", indent), text) + } + for _, accountDiff := range e.Accesses { + printWithIndent(0, fmt.Sprintf("%x:", accountDiff.Address)) + + printWithIndent(1, "storage writes:") + for _, sWrite := range accountDiff.StorageWrites { + printWithIndent(2, fmt.Sprintf("%x:", sWrite.Slot)) + for _, access := range sWrite.Accesses { + printWithIndent(3, fmt.Sprintf("%d: %x", access.TxIdx, access.ValueAfter)) + } + } + + printWithIndent(1, "storage reads:") + for _, slot := range accountDiff.StorageReads { + printWithIndent(2, fmt.Sprintf("%x", slot)) + } + + printWithIndent(1, "balance changes:") + for _, change := range accountDiff.BalanceChanges { + balance := new(uint256.Int).SetBytes(change.Balance[:]).String() + printWithIndent(2, fmt.Sprintf("%d: %s", change.TxIdx, balance)) + } + + printWithIndent(1, "nonce changes:") + for _, change := range accountDiff.NonceChanges { + printWithIndent(2, fmt.Sprintf("%d: %d", change.TxIdx, change.Nonce)) + } + + if len(accountDiff.Code) > 0 { + printWithIndent(1, "code:") + printWithIndent(2, fmt.Sprintf("%d: %x", accountDiff.Code[0].TxIndex, accountDiff.Code[0].Code)) + } + } + return res.String() +} + +// Copy returns a deep copy of the access list +func (e *BlockAccessList) Copy() (res BlockAccessList) { + for _, accountAccess := range e.Accesses { + res.Accesses = append(res.Accesses, accountAccess.Copy()) + } + return +} diff --git a/core/types/bal/bal_encoding_rlp_generated.go b/core/types/bal/bal_encoding_rlp_generated.go new file mode 100644 index 000000000000..0d5239532904 --- /dev/null +++ b/core/types/bal/bal_encoding_rlp_generated.go @@ -0,0 +1,280 @@ +// Code generated by rlpgen. DO NOT EDIT. + +package bal + +import "github.com/ethereum/go-ethereum/rlp" +import "io" + +func (obj *BlockAccessList) EncodeRLP(_w io.Writer) error { + w := rlp.NewEncoderBuffer(_w) + _tmp0 := w.List() + _tmp1 := w.List() + for _, _tmp2 := range obj.Accesses { + _tmp3 := w.List() + w.WriteBytes(_tmp2.Address[:]) + _tmp4 := w.List() + for _, _tmp5 := range _tmp2.StorageWrites { + _tmp6 := w.List() + w.WriteBytes(_tmp5.Slot[:]) + _tmp7 := w.List() + for _, _tmp8 := range _tmp5.Accesses { + _tmp9 := w.List() + w.WriteUint64(uint64(_tmp8.TxIdx)) + w.WriteBytes(_tmp8.ValueAfter[:]) + w.ListEnd(_tmp9) + } + w.ListEnd(_tmp7) + w.ListEnd(_tmp6) + } + w.ListEnd(_tmp4) + _tmp10 := w.List() + for _, _tmp11 := range _tmp2.StorageReads { + w.WriteBytes(_tmp11[:]) + } + w.ListEnd(_tmp10) + _tmp12 := w.List() + for _, _tmp13 := range _tmp2.BalanceChanges { + _tmp14 := w.List() + w.WriteUint64(uint64(_tmp13.TxIdx)) + w.WriteBytes(_tmp13.Balance[:]) + w.ListEnd(_tmp14) + } + w.ListEnd(_tmp12) + _tmp15 := w.List() + for _, _tmp16 := range _tmp2.NonceChanges { + _tmp17 := w.List() + w.WriteUint64(uint64(_tmp16.TxIdx)) + w.WriteUint64(_tmp16.Nonce) + w.ListEnd(_tmp17) + } + w.ListEnd(_tmp15) + _tmp18 := w.List() + for _, _tmp19 := range _tmp2.Code { + _tmp20 := w.List() + w.WriteUint64(uint64(_tmp19.TxIndex)) + w.WriteBytes(_tmp19.Code) + w.ListEnd(_tmp20) + } + w.ListEnd(_tmp18) + w.ListEnd(_tmp3) + } + w.ListEnd(_tmp1) + w.ListEnd(_tmp0) + return w.Flush() +} + +func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error { + var _tmp0 BlockAccessList + { + if _, err := dec.List(); err != nil { + return err + } + // Accesses: + var _tmp1 []AccountAccess + if _, err := dec.List(); err != nil { + return err + } + for dec.MoreDataInList() { + var _tmp2 AccountAccess + { + if _, err := dec.List(); err != nil { + return err + } + // Address: + var _tmp3 [20]byte + if err := dec.ReadBytes(_tmp3[:]); err != nil { + return err + } + _tmp2.Address = _tmp3 + // StorageWrites: + var _tmp4 []encodingSlotWrites + if _, err := dec.List(); err != nil { + return err + } + for dec.MoreDataInList() { + var _tmp5 encodingSlotWrites + { + if _, err := dec.List(); err != nil { + return err + } + // Slot: + var _tmp6 [32]byte + if err := dec.ReadBytes(_tmp6[:]); err != nil { + return err + } + _tmp5.Slot = _tmp6 + // Accesses: + var _tmp7 []encodingStorageWrite + if _, err := dec.List(); err != nil { + return err + } + for dec.MoreDataInList() { + var _tmp8 encodingStorageWrite + { + if _, err := dec.List(); err != nil { + return err + } + // TxIdx: + _tmp9, err := dec.Uint16() + if err != nil { + return err + } + _tmp8.TxIdx = _tmp9 + // ValueAfter: + var _tmp10 [32]byte + if err := dec.ReadBytes(_tmp10[:]); err != nil { + return err + } + _tmp8.ValueAfter = _tmp10 + if err := dec.ListEnd(); err != nil { + return err + } + } + _tmp7 = append(_tmp7, _tmp8) + } + if err := dec.ListEnd(); err != nil { + return err + } + _tmp5.Accesses = _tmp7 + if err := dec.ListEnd(); err != nil { + return err + } + } + _tmp4 = append(_tmp4, _tmp5) + } + if err := dec.ListEnd(); err != nil { + return err + } + _tmp2.StorageWrites = _tmp4 + // StorageReads: + var _tmp11 [][32]byte + if _, err := dec.List(); err != nil { + return err + } + for dec.MoreDataInList() { + var _tmp12 [32]byte + if err := dec.ReadBytes(_tmp12[:]); err != nil { + return err + } + _tmp11 = append(_tmp11, _tmp12) + } + if err := dec.ListEnd(); err != nil { + return err + } + _tmp2.StorageReads = _tmp11 + // BalanceChanges: + var _tmp13 []encodingBalanceChange + if _, err := dec.List(); err != nil { + return err + } + for dec.MoreDataInList() { + var _tmp14 encodingBalanceChange + { + if _, err := dec.List(); err != nil { + return err + } + // TxIdx: + _tmp15, err := dec.Uint16() + if err != nil { + return err + } + _tmp14.TxIdx = _tmp15 + // Balance: + var _tmp16 [16]byte + if err := dec.ReadBytes(_tmp16[:]); err != nil { + return err + } + _tmp14.Balance = _tmp16 + if err := dec.ListEnd(); err != nil { + return err + } + } + _tmp13 = append(_tmp13, _tmp14) + } + if err := dec.ListEnd(); err != nil { + return err + } + _tmp2.BalanceChanges = _tmp13 + // NonceChanges: + var _tmp17 []encodingAccountNonce + if _, err := dec.List(); err != nil { + return err + } + for dec.MoreDataInList() { + var _tmp18 encodingAccountNonce + { + if _, err := dec.List(); err != nil { + return err + } + // TxIdx: + _tmp19, err := dec.Uint16() + if err != nil { + return err + } + _tmp18.TxIdx = _tmp19 + // Nonce: + _tmp20, err := dec.Uint64() + if err != nil { + return err + } + _tmp18.Nonce = _tmp20 + if err := dec.ListEnd(); err != nil { + return err + } + } + _tmp17 = append(_tmp17, _tmp18) + } + if err := dec.ListEnd(); err != nil { + return err + } + _tmp2.NonceChanges = _tmp17 + // Code: + var _tmp21 []CodeChange + if _, err := dec.List(); err != nil { + return err + } + for dec.MoreDataInList() { + var _tmp22 CodeChange + { + if _, err := dec.List(); err != nil { + return err + } + // TxIndex: + _tmp23, err := dec.Uint16() + if err != nil { + return err + } + _tmp22.TxIndex = _tmp23 + // Code: + _tmp24, err := dec.Bytes() + if err != nil { + return err + } + _tmp22.Code = _tmp24 + if err := dec.ListEnd(); err != nil { + return err + } + } + _tmp21 = append(_tmp21, _tmp22) + } + if err := dec.ListEnd(); err != nil { + return err + } + _tmp2.Code = _tmp21 + if err := dec.ListEnd(); err != nil { + return err + } + } + _tmp1 = append(_tmp1, _tmp2) + } + if err := dec.ListEnd(); err != nil { + return err + } + _tmp0.Accesses = _tmp1 + if err := dec.ListEnd(); err != nil { + return err + } + } + *obj = _tmp0 + return nil +} diff --git a/core/types/bal/bal_test.go b/core/types/bal/bal_test.go new file mode 100644 index 000000000000..29414e414e82 --- /dev/null +++ b/core/types/bal/bal_test.go @@ -0,0 +1,252 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package bal + +import ( + "bytes" + "cmp" + "reflect" + "slices" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/internal/testrand" + "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" +) + +func equalBALs(a *BlockAccessList, b *BlockAccessList) bool { + if !reflect.DeepEqual(a, b) { + return false + } + return true +} + +func makeTestConstructionBAL() *ConstructionBlockAccessList { + return &ConstructionBlockAccessList{ + map[common.Address]*ConstructionAccountAccess{ + common.BytesToAddress([]byte{0xff, 0xff}): { + StorageWrites: map[common.Hash]map[uint16]common.Hash{ + common.BytesToHash([]byte{0x01}): { + 1: common.BytesToHash([]byte{1, 2, 3, 4}), + 2: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6}), + }, + common.BytesToHash([]byte{0x10}): { + 20: common.BytesToHash([]byte{1, 2, 3, 4}), + }, + }, + StorageReads: map[common.Hash]struct{}{ + common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7}): {}, + }, + BalanceChanges: map[uint16]*uint256.Int{ + 1: uint256.NewInt(100), + 2: uint256.NewInt(500), + }, + NonceChanges: map[uint16]uint64{ + 1: 2, + 2: 6, + }, + CodeChange: &CodeChange{ + TxIndex: 0, + Code: common.Hex2Bytes("deadbeef"), + }, + }, + common.BytesToAddress([]byte{0xff, 0xff, 0xff}): { + StorageWrites: map[common.Hash]map[uint16]common.Hash{ + common.BytesToHash([]byte{0x01}): { + 2: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6}), + 3: common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7, 8}), + }, + common.BytesToHash([]byte{0x10}): { + 21: common.BytesToHash([]byte{1, 2, 3, 4, 5}), + }, + }, + StorageReads: map[common.Hash]struct{}{ + common.BytesToHash([]byte{1, 2, 3, 4, 5, 6, 7, 8}): {}, + }, + BalanceChanges: map[uint16]*uint256.Int{ + 2: uint256.NewInt(100), + 3: uint256.NewInt(500), + }, + NonceChanges: map[uint16]uint64{ + 1: 2, + }, + }, + }, + } +} + +// TestBALEncoding tests that a populated access list can be encoded/decoded correctly. +func TestBALEncoding(t *testing.T) { + var buf bytes.Buffer + bal := makeTestConstructionBAL() + err := bal.EncodeRLP(&buf) + if err != nil { + t.Fatalf("encoding failed: %v\n", err) + } + var dec BlockAccessList + if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 10000000)); err != nil { + t.Fatalf("decoding failed: %v\n", err) + } + if dec.Hash() != bal.toEncodingObj().Hash() { + t.Fatalf("encoded block hash doesn't match decoded") + } + if !equalBALs(bal.toEncodingObj(), &dec) { + t.Fatal("decoded BAL doesn't match") + } +} + +func makeTestAccountAccess(sort bool) AccountAccess { + var ( + storageWrites []encodingSlotWrites + storageReads [][32]byte + balances []encodingBalanceChange + nonces []encodingAccountNonce + ) + for i := 0; i < 5; i++ { + slot := encodingSlotWrites{ + Slot: testrand.Hash(), + } + for j := 0; j < 3; j++ { + slot.Accesses = append(slot.Accesses, encodingStorageWrite{ + TxIdx: uint16(2 * j), + ValueAfter: testrand.Hash(), + }) + } + if sort { + slices.SortFunc(slot.Accesses, func(a, b encodingStorageWrite) int { + return cmp.Compare[uint16](a.TxIdx, b.TxIdx) + }) + } + storageWrites = append(storageWrites, slot) + } + if sort { + slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int { + return bytes.Compare(a.Slot[:], b.Slot[:]) + }) + } + + for i := 0; i < 5; i++ { + storageReads = append(storageReads, testrand.Hash()) + } + if sort { + slices.SortFunc(storageReads, func(a, b [32]byte) int { + return bytes.Compare(a[:], b[:]) + }) + } + + for i := 0; i < 5; i++ { + balances = append(balances, encodingBalanceChange{ + TxIdx: uint16(2 * i), + Balance: [16]byte(testrand.Bytes(16)), + }) + } + if sort { + slices.SortFunc(balances, func(a, b encodingBalanceChange) int { + return cmp.Compare[uint16](a.TxIdx, b.TxIdx) + }) + } + + for i := 0; i < 5; i++ { + nonces = append(nonces, encodingAccountNonce{ + TxIdx: uint16(2 * i), + Nonce: uint64(i + 100), + }) + } + if sort { + slices.SortFunc(nonces, func(a, b encodingAccountNonce) int { + return cmp.Compare[uint16](a.TxIdx, b.TxIdx) + }) + } + + return AccountAccess{ + Address: [20]byte(testrand.Bytes(20)), + StorageWrites: storageWrites, + StorageReads: storageReads, + BalanceChanges: balances, + NonceChanges: nonces, + Code: []CodeChange{ + { + TxIndex: 100, + Code: testrand.Bytes(256), + }, + }, + } +} + +func makeTestBAL(sort bool) BlockAccessList { + list := BlockAccessList{} + for i := 0; i < 5; i++ { + list.Accesses = append(list.Accesses, makeTestAccountAccess(sort)) + } + if sort { + slices.SortFunc(list.Accesses, func(a, b AccountAccess) int { + return bytes.Compare(a.Address[:], b.Address[:]) + }) + } + return list +} + +func TestBlockAccessListCopy(t *testing.T) { + list := makeTestBAL(true) + cpy := list.Copy() + cpyCpy := cpy.Copy() + + if !reflect.DeepEqual(list, cpy) { + t.Fatal("block access mismatch") + } + if !reflect.DeepEqual(cpy, cpyCpy) { + t.Fatal("block access mismatch") + } + + // Make sure the mutations on copy won't affect the origin + for _, aa := range cpyCpy.Accesses { + for i := 0; i < len(aa.StorageReads); i++ { + aa.StorageReads[i] = [32]byte(testrand.Bytes(32)) + } + } + if !reflect.DeepEqual(list, cpy) { + t.Fatal("block access mismatch") + } +} + +func TestBlockAccessListValidation(t *testing.T) { + // Validate the block access list after RLP decoding + enc := makeTestBAL(true) + if err := enc.Validate(); err != nil { + t.Fatalf("Unexpected validation error: %v", err) + } + var buf bytes.Buffer + if err := enc.EncodeRLP(&buf); err != nil { + t.Fatalf("Unexpected encoding error: %v", err) + } + + var dec BlockAccessList + if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 0)); err != nil { + t.Fatalf("Unexpected RLP-decode error: %v", err) + } + if err := dec.Validate(); err != nil { + t.Fatalf("Unexpected validation error: %v", err) + } + + // Validate the derived block access list + cBAL := makeTestConstructionBAL() + listB := cBAL.toEncodingObj() + if err := listB.Validate(); err != nil { + t.Fatalf("Unexpected validation error: %v", err) + } +} diff --git a/core/types/block_test.go b/core/types/block_test.go index 1f61be89a5d6..2130a2fcf3b2 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -24,11 +24,13 @@ import ( "testing" "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/crypto" "github.com/ethereum/go-ethereum/internal/blocktest" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" ) // from bcValidBlockTest.json, "SimpleTx" @@ -194,6 +196,60 @@ func TestEIP2718BlockEncoding(t *testing.T) { } } +func TestEIP4844BlockEncoding(t *testing.T) { + // https://github.com/ethereum/tests/blob/develop/BlockchainTests/ValidBlocks/bcEIP4844-blobtransactions/blockWithAllTransactionTypes.json + blockEnc := common.FromHex("0xf90417f90244a05eb7f6da0f3e237c62bcae48b7fb5f4506d392616b62890429c8b76b4a1d4104a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ba5e000000000000000000000000000000000000a011639dcca0b44f2acb5b630a82c8a69cb82742b3711383ec4e111a554d27aea5a05cb644f722e31f9792a8ef6e2a762334e1a862e8b40c1612e1e9507fd7121ef9a00c82719448356ba6807d6edfcd8e5aea575a5e97f36038ffb3e395749b26d41cb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800188016345785d8a00008301482082079e42a00000000000000000000000000000000000000000000000000000000000020000880000000000000000820314a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218302000080a00000000000000000000000000000000000000000000000000000000000000000f901cbf864808203e885e8d4a5100094100000000000000000000000000000000000000a01801ca09de4adda6288582a6700dbcd8eb70c0a4a7fc9487d965f7bf22424e0bd121095a01cdb078764cc3770d5db847e99e10333aa7c356247baaf09b03eae04d64e7926b86901f86601018203e885e8d4a5100094100000000000000000000000000000000000000a0380c080a025090740da12684493e4fb466a3979e365b194e8cf462edf3c2c3be2f130bb2ea034fa18fb4c1bff4d957d72e28535d27f1352517a942aeaca0ed944085f0cd8bbb86a02f8670102018203e885e8d4a5100094100000000000000000000000000000000000000a0580c080a0352a7be5002ce111bc5167f3addf97a75e2e0b810d826af71d2caae18aed284ea065d38f8a5c8948ce706842e8861fb21020b93a4d5e489162a0e6d419a457b735b88c03f8890103018203e885e8d4a5100094100000000000000000000000000000000000000a0780c00ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8809f638144c46d5de7a9e630c0e7c5c63ae829ecfd8cc94715d9c29fe17c464de0a06c5fc54c3aa868ba35ef31a4e12431611631ab7bcdceb4214dd273d83f73b5e1c0c0") + var block Block + if err := rlp.DecodeBytes(blockEnc, &block); err != nil { + t.Fatal("decode error: ", err) + } + + check := func(f string, got, want interface{}) { + if !reflect.DeepEqual(got, want) { + t.Errorf("%s mismatch: got %v, want %v", f, got, want) + } + } + check("Difficulty", block.Difficulty(), big.NewInt(0)) + check("GasLimit", block.GasLimit(), hexutil.MustDecodeUint64("0x16345785d8a0000")) + check("GasUsed", block.GasUsed(), hexutil.MustDecodeUint64("0x14820")) + check("Coinbase", block.Coinbase(), common.HexToAddress("0xba5e000000000000000000000000000000000000")) + check("MixDigest", block.MixDigest(), common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000020000")) + check("Root", block.Root(), common.HexToHash("0x11639dcca0b44f2acb5b630a82c8a69cb82742b3711383ec4e111a554d27aea5")) + check("WithdrawalRoot", *block.Header().WithdrawalsHash, common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")) + check("Nonce", block.Nonce(), uint64(0)) + check("Time", block.Time(), hexutil.MustDecodeUint64("0x79e")) + check("Size", block.Size(), uint64(len(blockEnc))) + + // Create blob tx. + tx := NewTx(&BlobTx{ + ChainID: uint256.NewInt(1), + Nonce: 3, + To: common.HexToAddress("0x100000000000000000000000000000000000000a"), + Gas: hexutil.MustDecodeUint64("0xe8d4a51000"), + GasTipCap: uint256.MustFromHex("0x1"), + GasFeeCap: uint256.MustFromHex("0x3e8"), + BlobFeeCap: uint256.MustFromHex("0xa"), + BlobHashes: []common.Hash{ + common.BytesToHash(hexutil.MustDecode("0x01a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8")), + }, + Value: uint256.MustFromHex("0x7"), + }) + sig := common.Hex2Bytes("00638144c46d5de7a9e630c0e7c5c63ae829ecfd8cc94715d9c29fe17c464de06c5fc54c3aa868ba35ef31a4e12431611631ab7bcdceb4214dd273d83f73b5e100") + tx, _ = tx.WithSignature(LatestSignerForChainID(big.NewInt(1)), sig) + + check("len(Transactions)", len(block.Transactions()), 4) + check("Transactions[3].Hash", block.Transactions()[3].Hash(), tx.Hash()) + check("Transactions[3].Type()", block.Transactions()[3].Type(), uint8(BlobTxType)) + + ourBlockEnc, err := rlp.EncodeToBytes(&block) + if err != nil { + t.Fatal("encode error: ", err) + } + if !bytes.Equal(ourBlockEnc, blockEnc) { + t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc) + } +} + func TestUncleHash(t *testing.T) { uncles := make([]*Header, 0) h := CalcUncleHash(uncles) diff --git a/core/types/gen_log_json.go b/core/types/gen_log_json.go index 3ffa9c2feb1a..ad7ccca8fcca 100644 --- a/core/types/gen_log_json.go +++ b/core/types/gen_log_json.go @@ -15,15 +15,16 @@ var _ = (*logMarshaling)(nil) // MarshalJSON marshals as JSON. func (l Log) MarshalJSON() ([]byte, error) { type Log struct { - 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" 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:"-"` + 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" rlp:"-"` + TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"` + TxIndex hexutil.Uint `json:"transactionIndex" rlp:"-"` + BlockHash common.Hash `json:"blockHash" rlp:"-"` + BlockTimestamp hexutil.Uint64 `json:"blockTimestamp" rlp:"-"` + Index hexutil.Uint `json:"logIndex" rlp:"-"` + Removed bool `json:"removed" rlp:"-"` } var enc Log enc.Address = l.Address @@ -33,6 +34,7 @@ func (l Log) MarshalJSON() ([]byte, error) { enc.TxHash = l.TxHash enc.TxIndex = hexutil.Uint(l.TxIndex) enc.BlockHash = l.BlockHash + enc.BlockTimestamp = hexutil.Uint64(l.BlockTimestamp) enc.Index = hexutil.Uint(l.Index) enc.Removed = l.Removed return json.Marshal(&enc) @@ -41,15 +43,16 @@ func (l Log) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (l *Log) UnmarshalJSON(input []byte) error { type Log struct { - 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" 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:"-"` + 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" rlp:"-"` + TxHash *common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"` + TxIndex *hexutil.Uint `json:"transactionIndex" rlp:"-"` + BlockHash *common.Hash `json:"blockHash" rlp:"-"` + BlockTimestamp *hexutil.Uint64 `json:"blockTimestamp" rlp:"-"` + Index *hexutil.Uint `json:"logIndex" rlp:"-"` + Removed *bool `json:"removed" rlp:"-"` } var dec Log if err := json.Unmarshal(input, &dec); err != nil { @@ -80,6 +83,9 @@ func (l *Log) UnmarshalJSON(input []byte) error { if dec.BlockHash != nil { l.BlockHash = *dec.BlockHash } + if dec.BlockTimestamp != nil { + l.BlockTimestamp = uint64(*dec.BlockTimestamp) + } if dec.Index != nil { l.Index = uint(*dec.Index) } diff --git a/core/types/log.go b/core/types/log.go index 54c7ff6372c8..f0e6a3a74596 100644 --- a/core/types/log.go +++ b/core/types/log.go @@ -45,6 +45,8 @@ type Log struct { TxIndex uint `json:"transactionIndex" rlp:"-"` // hash of the block in which the transaction was included BlockHash common.Hash `json:"blockHash" rlp:"-"` + // timestamp of the block in which the transaction was included + BlockTimestamp uint64 `json:"blockTimestamp" rlp:"-"` // index of the log in the block Index uint `json:"logIndex" rlp:"-"` @@ -54,8 +56,9 @@ type Log struct { } type logMarshaling struct { - Data hexutil.Bytes - BlockNumber hexutil.Uint64 - TxIndex hexutil.Uint - Index hexutil.Uint + Data hexutil.Bytes + BlockNumber hexutil.Uint64 + TxIndex hexutil.Uint + BlockTimestamp hexutil.Uint64 + Index hexutil.Uint } diff --git a/core/types/receipt.go b/core/types/receipt.go index ec99fbf888f6..5b6669f2741b 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -258,6 +258,62 @@ func (r *Receipt) Size() common.StorageSize { return size } +// DeriveReceiptContext holds the contextual information needed to derive a receipt +type DeriveReceiptContext struct { + BlockHash common.Hash + BlockNumber uint64 + BlockTime uint64 + BaseFee *big.Int + BlobGasPrice *big.Int + GasUsed uint64 + LogIndex uint // Number of logs in the block until this receipt + Tx *Transaction + TxIndex uint +} + +// DeriveFields fills the receipt with computed fields based on consensus +// data and contextual infos like containing block and transactions. +func (r *Receipt) DeriveFields(signer Signer, context DeriveReceiptContext) { + // The transaction type and hash can be retrieved from the transaction itself + r.Type = context.Tx.Type() + r.TxHash = context.Tx.Hash() + r.GasUsed = context.GasUsed + r.EffectiveGasPrice = context.Tx.inner.effectiveGasPrice(new(big.Int), context.BaseFee) + + // EIP-4844 blob transaction fields + if context.Tx.Type() == BlobTxType { + r.BlobGasUsed = context.Tx.BlobGas() + r.BlobGasPrice = context.BlobGasPrice + } + + // Block location fields + r.BlockHash = context.BlockHash + r.BlockNumber = new(big.Int).SetUint64(context.BlockNumber) + r.TransactionIndex = context.TxIndex + + // The contract address can be derived from the transaction itself + if context.Tx.To() == nil { + // Deriving the signer is expensive, only do if it's actually needed + from, _ := Sender(signer, context.Tx) + r.ContractAddress = crypto.CreateAddress(from, context.Tx.Nonce()) + } else { + r.ContractAddress = common.Address{} + } + // The derived log fields can simply be set from the block and transaction + logIndex := context.LogIndex + for j := 0; j < len(r.Logs); j++ { + r.Logs[j].BlockNumber = context.BlockNumber + r.Logs[j].BlockHash = context.BlockHash + r.Logs[j].BlockTimestamp = context.BlockTime + r.Logs[j].TxHash = r.TxHash + r.Logs[j].TxIndex = context.TxIndex + r.Logs[j].Index = logIndex + logIndex++ + } + // Also derive the Bloom if not derived yet + r.Bloom = CreateBloom(r) +} + // ReceiptForStorage is a wrapper around a Receipt with RLP serialization // that omits the Bloom field. The Bloom field is recomputed by DeriveFields. type ReceiptForStorage Receipt @@ -323,57 +379,30 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) { // DeriveFields fills the receipts with their computed fields based on consensus // data and contextual infos like containing block and transactions. -func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee *big.Int, blobGasPrice *big.Int, txs []*Transaction) error { - signer := MakeSigner(config, new(big.Int).SetUint64(number), time) +func (rs Receipts) DeriveFields(config *params.ChainConfig, blockHash common.Hash, blockNumber uint64, blockTime uint64, baseFee *big.Int, blobGasPrice *big.Int, txs []*Transaction) error { + signer := MakeSigner(config, new(big.Int).SetUint64(blockNumber), blockTime) logIndex := uint(0) if len(txs) != len(rs) { return errors.New("transaction and receipt count mismatch") } for i := 0; i < len(rs); i++ { - // The transaction type and hash can be retrieved from the transaction itself - rs[i].Type = txs[i].Type() - rs[i].TxHash = txs[i].Hash() - rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), baseFee) - - // EIP-4844 blob transaction fields - if txs[i].Type() == BlobTxType { - rs[i].BlobGasUsed = txs[i].BlobGas() - rs[i].BlobGasPrice = blobGasPrice - } - - // block location fields - rs[i].BlockHash = hash - rs[i].BlockNumber = new(big.Int).SetUint64(number) - rs[i].TransactionIndex = uint(i) - - // The contract address can be derived from the transaction itself - if txs[i].To() == nil { - // Deriving the signer is expensive, only do if it's actually needed - from, _ := Sender(signer, txs[i]) - rs[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce()) - } else { - rs[i].ContractAddress = common.Address{} - } - - // The used gas can be calculated based on previous r - if i == 0 { - rs[i].GasUsed = rs[i].CumulativeGasUsed - } else { - rs[i].GasUsed = rs[i].CumulativeGasUsed - rs[i-1].CumulativeGasUsed - } - - // The derived log fields can simply be set from the block and transaction - for j := 0; j < len(rs[i].Logs); j++ { - rs[i].Logs[j].BlockNumber = number - rs[i].Logs[j].BlockHash = hash - rs[i].Logs[j].TxHash = rs[i].TxHash - rs[i].Logs[j].TxIndex = uint(i) - rs[i].Logs[j].Index = logIndex - logIndex++ + var cumulativeGasUsed uint64 + if i > 0 { + cumulativeGasUsed = rs[i-1].CumulativeGasUsed } - // also derive the Bloom if not derived yet - rs[i].Bloom = CreateBloom(rs[i]) + rs[i].DeriveFields(signer, DeriveReceiptContext{ + BlockHash: blockHash, + BlockNumber: blockNumber, + BlockTime: blockTime, + BaseFee: baseFee, + BlobGasPrice: blobGasPrice, + GasUsed: rs[i].CumulativeGasUsed - cumulativeGasUsed, + LogIndex: logIndex, + Tx: txs[i], + TxIndex: uint(i), + }) + logIndex += uint(len(rs[i].Logs)) } return nil } diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go index 06cd0ff14cfc..8f805ff09619 100644 --- a/core/types/receipt_test.go +++ b/core/types/receipt_test.go @@ -173,21 +173,23 @@ func getTestReceipts() Receipts { Address: common.BytesToAddress([]byte{0x11}), Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[0].Hash(), - TxIndex: 0, - BlockHash: blockHash, - Index: 0, + BlockNumber: blockNumber.Uint64(), + TxHash: txs[0].Hash(), + TxIndex: 0, + BlockHash: blockHash, + BlockTimestamp: blockTime, + Index: 0, }, { Address: common.BytesToAddress([]byte{0x01, 0x11}), Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[0].Hash(), - TxIndex: 0, - BlockHash: blockHash, - Index: 1, + BlockNumber: blockNumber.Uint64(), + TxHash: txs[0].Hash(), + TxIndex: 0, + BlockHash: blockHash, + BlockTimestamp: blockTime, + Index: 1, }, }, // derived fields: @@ -207,21 +209,23 @@ func getTestReceipts() Receipts { Address: common.BytesToAddress([]byte{0x22}), Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[1].Hash(), - TxIndex: 1, - BlockHash: blockHash, - Index: 2, + BlockNumber: blockNumber.Uint64(), + TxHash: txs[1].Hash(), + TxIndex: 1, + BlockHash: blockHash, + BlockTimestamp: blockTime, + Index: 2, }, { Address: common.BytesToAddress([]byte{0x02, 0x22}), Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[1].Hash(), - TxIndex: 1, - BlockHash: blockHash, - Index: 3, + BlockNumber: blockNumber.Uint64(), + TxHash: txs[1].Hash(), + TxIndex: 1, + BlockHash: blockHash, + BlockTimestamp: blockTime, + Index: 3, }, }, // derived fields: diff --git a/core/types/transaction.go b/core/types/transaction.go index 934feb735316..733b6510f148 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -449,14 +449,18 @@ func (tx *Transaction) BlobGasFeeCapIntCmp(other *big.Int) int { // WithoutBlobTxSidecar returns a copy of tx with the blob sidecar removed. func (tx *Transaction) WithoutBlobTxSidecar() *Transaction { blobtx, ok := tx.inner.(*BlobTx) - if !ok { + if !ok || blobtx.Sidecar == nil { 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 size := tx.size.Load(); size != 0 { + // The tx had a sidecar before, so we need to subtract it from the size. + scSize := rlp.ListSize(blobtx.Sidecar.encodedSize()) + cpy.size.Store(size - scSize) + } if h := tx.hash.Load(); h != nil { cpy.hash.Store(h) } diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go index 9b1d53958fed..93a76a28b73d 100644 --- a/core/types/tx_blob.go +++ b/core/types/tx_blob.go @@ -19,9 +19,12 @@ package types import ( "bytes" "crypto/sha256" + "errors" "fmt" "math/big" + "slices" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/params" @@ -55,6 +58,7 @@ type BlobTx struct { // BlobTxSidecar contains the blobs of a blob transaction. type BlobTxSidecar struct { + Version byte // Version 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 @@ -70,6 +74,20 @@ func (sc *BlobTxSidecar) BlobHashes() []common.Hash { return h } +// CellProofsAt returns the cell proofs for blob with index idx. +func (sc *BlobTxSidecar) CellProofsAt(idx int) []kzg4844.Proof { + var cellProofs []kzg4844.Proof + for i := range kzg4844.CellProofsPerBlob { + index := idx*kzg4844.CellProofsPerBlob + i + if index > len(sc.Proofs) { + return nil + } + proof := sc.Proofs[index] + cellProofs = append(cellProofs, proof) + } + return cellProofs +} + // 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 { @@ -102,14 +120,55 @@ func (sc *BlobTxSidecar) ValidateBlobCommitmentHashes(hashes []common.Hash) erro return nil } -// blobTxWithBlobs is used for encoding of transactions when blobs are present. -type blobTxWithBlobs struct { +// blobTxWithBlobs represents blob tx with its corresponding sidecar. +// This is an interface because sidecars are versioned. +type blobTxWithBlobs interface { + tx() *BlobTx + assign(*BlobTxSidecar) error +} + +type blobTxWithBlobsV0 struct { + BlobTx *BlobTx + Blobs []kzg4844.Blob + Commitments []kzg4844.Commitment + Proofs []kzg4844.Proof +} + +type blobTxWithBlobsV1 struct { BlobTx *BlobTx + Version byte Blobs []kzg4844.Blob Commitments []kzg4844.Commitment Proofs []kzg4844.Proof } +func (btx *blobTxWithBlobsV0) tx() *BlobTx { + return btx.BlobTx +} + +func (btx *blobTxWithBlobsV0) assign(sc *BlobTxSidecar) error { + sc.Version = 0 + sc.Blobs = btx.Blobs + sc.Commitments = btx.Commitments + sc.Proofs = btx.Proofs + return nil +} + +func (btx *blobTxWithBlobsV1) tx() *BlobTx { + return btx.BlobTx +} + +func (btx *blobTxWithBlobsV1) assign(sc *BlobTxSidecar) error { + if btx.Version != 1 { + return fmt.Errorf("unsupported blob tx version %d", btx.Version) + } + sc.Version = 1 + sc.Blobs = btx.Blobs + sc.Commitments = btx.Commitments + sc.Proofs = btx.Proofs + return nil +} + // copy creates a deep copy of the transaction data and initializes all fields. func (tx *BlobTx) copy() TxData { cpy := &BlobTx{ @@ -158,9 +217,9 @@ func (tx *BlobTx) copy() TxData { } 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...), + Blobs: slices.Clone(tx.Sidecar.Blobs), + Commitments: slices.Clone(tx.Sidecar.Commitments), + Proofs: slices.Clone(tx.Sidecar.Proofs), } } return cpy @@ -215,48 +274,98 @@ func (tx *BlobTx) withSidecar(sideCar *BlobTxSidecar) *BlobTx { } func (tx *BlobTx) encode(b *bytes.Buffer) error { - if tx.Sidecar == nil { + switch { + case tx.Sidecar == nil: return rlp.Encode(b, tx) + + case tx.Sidecar.Version == 0: + return rlp.Encode(b, &blobTxWithBlobsV0{ + BlobTx: tx, + Blobs: tx.Sidecar.Blobs, + Commitments: tx.Sidecar.Commitments, + Proofs: tx.Sidecar.Proofs, + }) + + case tx.Sidecar.Version == 1: + return rlp.Encode(b, &blobTxWithBlobsV1{ + BlobTx: tx, + Version: tx.Sidecar.Version, + Blobs: tx.Sidecar.Blobs, + Commitments: tx.Sidecar.Commitments, + Proofs: tx.Sidecar.Proofs, + }) + + default: + return errors.New("unsupported sidecar version") } - 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. + // Here we need to support two outer 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. + // The canonical encoding is just a list of fields: + // + // [chainID, nonce, ...] + // + // The network encoding is a list where the first element is the tx in the canonical encoding, + // and the remaining elements are the 'sidecar': + // + // [[chainID, nonce, ...], ...] + // + // The two outer encodings can be distinguished by checking whether the first element + // of the input list is itself a list. If it's the canonical encoding, the first + // element is the chainID, which is a number. - outerList, _, err := rlp.SplitList(input) + firstElem, _, err := rlp.SplitList(input) if err != nil { return err } - firstElemKind, _, _, err := rlp.Split(outerList) + firstElemKind, _, secondElem, err := rlp.Split(firstElem) if err != nil { return err } - if firstElemKind != rlp.List { + // Blob tx without blobs. return rlp.DecodeBytes(input, tx) } - // It's a tx with blobs. - var inner blobTxWithBlobs - if err := rlp.DecodeBytes(input, &inner); err != nil { + + // Now we know it's the network encoding with the blob sidecar. Here we again need to + // support multiple encodings: legacy sidecars (v0) with a blob proof, and versioned + // sidecars. + // + // The legacy encoding is: + // + // [tx, blobs, commitments, proofs] + // + // The versioned encoding is: + // + // [tx, version, blobs, ...] + // + // We can tell the two apart by checking whether the second element is the version byte. + // For legacy sidecar the second element is a list of blobs. + + secondElemKind, _, _, err := rlp.Split(secondElem) + if err != nil { return err } - *tx = *inner.BlobTx - tx.Sidecar = &BlobTxSidecar{ - Blobs: inner.Blobs, - Commitments: inner.Commitments, - Proofs: inner.Proofs, + var payload blobTxWithBlobs + if secondElemKind == rlp.List { + // No version byte: blob sidecar v0. + payload = new(blobTxWithBlobsV0) + } else { + // It has a version byte. Decode as v1, version is checked by assign() + payload = new(blobTxWithBlobsV1) + } + if err := rlp.DecodeBytes(input, payload); err != nil { + return err + } + sc := new(BlobTxSidecar) + if err := payload.assign(sc); err != nil { + return err } + *tx = *payload.tx() + tx.Sidecar = sc return nil } diff --git a/core/verkle_witness_test.go b/core/verkle_witness_test.go index de2280ced1c7..a89672e6e529 100644 --- a/core/verkle_witness_test.go +++ b/core/verkle_witness_test.go @@ -119,9 +119,9 @@ func TestProcessVerkle(t *testing.T) { // Verkle trees use the snapshot, which must be enabled before the // data is saved into the tree+database. // genesis := gspec.MustCommit(bcdb, triedb) - cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) - cacheConfig.SnapshotLimit = 0 - blockchain, _ := NewBlockChain(bcdb, cacheConfig, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil) + options := DefaultConfig().WithStateScheme(rawdb.PathScheme) + options.SnapshotLimit = 0 + blockchain, _ := NewBlockChain(bcdb, gspec, beacon.New(ethash.NewFaker()), options) defer blockchain.Stop() txCost1 := params.TxGas @@ -255,7 +255,7 @@ func TestProcessParentBlockHash(t *testing.T) { }) t.Run("Verkle", func(t *testing.T) { db := rawdb.NewMemoryDatabase() - cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) + cacheConfig := DefaultConfig().WithStateScheme(rawdb.PathScheme) cacheConfig.SnapshotLimit = 0 triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true)) statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil)) diff --git a/core/vm/analysis_eof.go b/core/vm/analysis_eof.go deleted file mode 100644 index eb78904cfd21..000000000000 --- a/core/vm/analysis_eof.go +++ /dev/null @@ -1,98 +0,0 @@ -// 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 vm - -// eofCodeBitmap collects data locations in code. -func eofCodeBitmap(code []byte) bitvec { - // The bitmap is 4 bytes longer than necessary, in case the code - // ends with a PUSH32, the algorithm will push zeroes onto the - // bitvector outside the bounds of the actual code. - bits := make(bitvec, len(code)/8+1+4) - return eofCodeBitmapInternal(code, bits) -} - -// eofCodeBitmapInternal is the internal implementation of codeBitmap for EOF -// code validation. -func eofCodeBitmapInternal(code, bits bitvec) bitvec { - for pc := uint64(0); pc < uint64(len(code)); { - var ( - op = OpCode(code[pc]) - numbits uint16 - ) - pc++ - - if op == RJUMPV { - // RJUMPV is unique as it has a variable sized operand. - // The total size is determined by the count byte which - // immediate follows RJUMPV. Truncation will be caught - // in other validation steps -- for now, just return a - // valid bitmap for as much of the code as is - // available. - end := uint64(len(code)) - if pc >= end { - // Count missing, no more bits to mark. - return bits - } - numbits = uint16(code[pc])*2 + 3 - if pc+uint64(numbits) > end { - // Jump table is truncated, mark as many bits - // as possible. - numbits = uint16(end - pc) - } - } else { - numbits = uint16(Immediates(op)) - if numbits == 0 { - continue - } - } - - if numbits >= 8 { - for ; numbits >= 16; numbits -= 16 { - bits.set16(pc) - pc += 16 - } - for ; numbits >= 8; numbits -= 8 { - bits.set8(pc) - pc += 8 - } - } - switch numbits { - case 1: - bits.set1(pc) - pc += 1 - case 2: - bits.setN(set2BitsMask, pc) - pc += 2 - case 3: - bits.setN(set3BitsMask, pc) - pc += 3 - case 4: - bits.setN(set4BitsMask, pc) - pc += 4 - case 5: - bits.setN(set5BitsMask, pc) - pc += 5 - case 6: - bits.setN(set6BitsMask, pc) - pc += 6 - case 7: - bits.setN(set7BitsMask, pc) - pc += 7 - } - } - return bits -} diff --git a/core/vm/analysis_legacy_test.go b/core/vm/analysis_legacy_test.go index 7f5de225e280..471d2b4ffbac 100644 --- a/core/vm/analysis_legacy_test.go +++ b/core/vm/analysis_legacy_test.go @@ -105,31 +105,3 @@ func BenchmarkJumpdestOpAnalysis(bench *testing.B) { op = STOP bench.Run(op.String(), bencher) } - -func BenchmarkJumpdestOpEOFAnalysis(bench *testing.B) { - var op OpCode - bencher := func(b *testing.B) { - code := make([]byte, analysisCodeSize) - b.SetBytes(analysisCodeSize) - for i := range code { - code[i] = byte(op) - } - bits := make(bitvec, len(code)/8+1+4) - b.ResetTimer() - for i := 0; i < b.N; i++ { - clear(bits) - eofCodeBitmapInternal(code, bits) - } - } - for op = PUSH1; op <= PUSH32; op++ { - bench.Run(op.String(), bencher) - } - op = JUMPDEST - bench.Run(op.String(), bencher) - op = STOP - bench.Run(op.String(), bencher) - op = RJUMPV - bench.Run(op.String(), bencher) - op = EOFCREATE - bench.Run(op.String(), bencher) -} diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 8dd7b9f0568d..91ff93dff403 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/crypto/blake2b" "github.com/ethereum/go-ethereum/crypto/bn256" "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/ethereum/go-ethereum/crypto/secp256r1" "github.com/ethereum/go-ethereum/params" "golang.org/x/crypto/ripemd160" ) @@ -161,6 +162,14 @@ var PrecompiledContractsOsaka = PrecompiledContracts{ common.BytesToAddress([]byte{0x0f}): &bls12381Pairing{}, common.BytesToAddress([]byte{0x10}): &bls12381MapG1{}, common.BytesToAddress([]byte{0x11}): &bls12381MapG2{}, + + common.BytesToAddress([]byte{0x1, 0x00}): &p256Verify{}, +} + +// PrecompiledContractsP256Verify contains the precompiled Ethereum +// contract specified in EIP-7212. This is exported for testing purposes. +var PrecompiledContractsP256Verify = PrecompiledContracts{ + common.BytesToAddress([]byte{0x1, 0x00}): &p256Verify{}, } var ( @@ -459,6 +468,8 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { minPrice = 500 if maxLenOver32 { gas.Add(gas, gas) + } else { + gas = big.NewInt(16) } } @@ -1230,3 +1241,31 @@ func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash { return h } + +// P256VERIFY (secp256r1 signature verification) +// implemented as a native contract +type p256Verify struct{} + +// RequiredGas returns the gas required to execute the precompiled contract +func (c *p256Verify) RequiredGas(input []byte) uint64 { + return params.P256VerifyGas +} + +// Run executes the precompiled contract with given 160 bytes of param, returning the output and the used gas +func (c *p256Verify) Run(input []byte) ([]byte, error) { + const p256VerifyInputLength = 160 + if len(input) != p256VerifyInputLength { + return nil, nil + } + + // Extract hash, r, s, x, y from the input. + hash := input[0:32] + r, s := new(big.Int).SetBytes(input[32:64]), new(big.Int).SetBytes(input[64:96]) + x, y := new(big.Int).SetBytes(input[96:128]), new(big.Int).SetBytes(input[128:160]) + + // Verify the signature. + if secp256r1.Verify(hash, r, s, x, y) { + return true32Byte, nil + } + return nil, nil +} diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index f86a8919a9a6..da44e250e1e7 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -66,6 +66,8 @@ var allPrecompiles = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{0x0f, 0x0e}): &bls12381Pairing{}, common.BytesToAddress([]byte{0x0f, 0x0f}): &bls12381MapG1{}, common.BytesToAddress([]byte{0x0f, 0x10}): &bls12381MapG2{}, + + common.BytesToAddress([]byte{0x0b}): &p256Verify{}, } // EIP-152 test vectors @@ -397,3 +399,15 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) { } benchmarkPrecompiled("f0d", testcase, b) } + +// Benchmarks the sample inputs from the P256VERIFY precompile. +func BenchmarkPrecompiledP256Verify(bench *testing.B) { + t := precompiledTest{ + Input: "4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e", + Expected: "0000000000000000000000000000000000000000000000000000000000000001", + Name: "p256Verify", + } + benchmarkPrecompiled("0b", t, bench) +} + +func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "0b", t) } diff --git a/core/vm/eips.go b/core/vm/eips.go index d95fa5128438..7764bd20b624 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -41,6 +41,7 @@ var activators = map[int]func(*JumpTable){ 1153: enable1153, 4762: enable4762, 7702: enable7702, + 7939: enable7939, } // EnableEIP enables the given EIP on the config. @@ -293,6 +294,13 @@ func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) return nil, nil } +// opCLZ implements the CLZ opcode (count leading zero bytes) +func opCLZ(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x := scope.Stack.peek() + x.SetUint64(256 - uint64(x.BitLen())) + return nil, nil +} + // enable4844 applies EIP-4844 (BLOBHASH opcode) func enable4844(jt *JumpTable) { jt[BLOBHASH] = &operation{ @@ -303,6 +311,16 @@ func enable4844(jt *JumpTable) { } } +// enable7939 enables EIP-7939 (CLZ opcode) +func enable7939(jt *JumpTable) { + jt[CLZ] = &operation{ + execute: opCLZ, + constantGas: GasFastStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + } +} + // enable7516 applies EIP-7516 (BLOBBASEFEE opcode) func enable7516(jt *JumpTable) { jt[BLOBBASEFEE] = &operation{ @@ -531,176 +549,6 @@ func enable4762(jt *JumpTable) { } } -// enableEOF applies the EOF changes. -// OBS! For EOF, there are two changes: -// 1. Two separate jumptables are required. One, EOF-jumptable, is used by -// eof contracts. This one contains things like RJUMP. -// 2. The regular non-eof jumptable also needs to be modified, specifically to -// modify how EXTCODECOPY works under the hood. -// -// This method _only_ deals with case 1. -func enableEOF(jt *JumpTable) { - // Deprecate opcodes - undefined := &operation{ - execute: opUndefined, - constantGas: 0, - minStack: minStack(0, 0), - maxStack: maxStack(0, 0), - undefined: true, - } - jt[CALL] = undefined - jt[CALLCODE] = undefined - jt[DELEGATECALL] = undefined - jt[STATICCALL] = undefined - jt[SELFDESTRUCT] = undefined - jt[JUMP] = undefined - jt[JUMPI] = undefined - jt[PC] = undefined - jt[CREATE] = undefined - jt[CREATE2] = undefined - jt[CODESIZE] = undefined - jt[CODECOPY] = undefined - jt[EXTCODESIZE] = undefined - jt[EXTCODECOPY] = undefined - jt[EXTCODEHASH] = undefined - jt[GAS] = undefined - // Allow 0xFE to terminate sections - jt[INVALID] = &operation{ - execute: opUndefined, - constantGas: 0, - minStack: minStack(0, 0), - maxStack: maxStack(0, 0), - } - - // New opcodes - jt[RJUMP] = &operation{ - execute: opRjump, - constantGas: GasQuickStep, - minStack: minStack(0, 0), - maxStack: maxStack(0, 0), - } - jt[RJUMPI] = &operation{ - execute: opRjumpi, - constantGas: GasFastishStep, - minStack: minStack(1, 0), - maxStack: maxStack(1, 0), - } - jt[RJUMPV] = &operation{ - execute: opRjumpv, - constantGas: GasFastishStep, - minStack: minStack(1, 0), - maxStack: maxStack(1, 0), - } - jt[CALLF] = &operation{ - execute: opCallf, - constantGas: GasFastStep, - minStack: minStack(0, 0), - maxStack: maxStack(0, 0), - } - jt[RETF] = &operation{ - execute: opRetf, - constantGas: GasFastestStep, - minStack: minStack(0, 0), - maxStack: maxStack(0, 0), - } - jt[JUMPF] = &operation{ - execute: opJumpf, - constantGas: GasFastStep, - minStack: minStack(0, 0), - maxStack: maxStack(0, 0), - } - jt[EOFCREATE] = &operation{ - execute: opEOFCreate, - constantGas: params.Create2Gas, - dynamicGas: gasEOFCreate, - minStack: minStack(4, 1), - maxStack: maxStack(4, 1), - memorySize: memoryEOFCreate, - } - jt[RETURNCONTRACT] = &operation{ - execute: opReturnContract, - // returncontract has zero constant gas cost - dynamicGas: pureMemoryGascost, - minStack: minStack(2, 0), - maxStack: maxStack(2, 0), - memorySize: memoryReturnContract, - } - jt[DATALOAD] = &operation{ - execute: opDataLoad, - constantGas: GasFastishStep, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - } - jt[DATALOADN] = &operation{ - execute: opDataLoadN, - constantGas: GasFastestStep, - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - } - jt[DATASIZE] = &operation{ - execute: opDataSize, - constantGas: GasQuickStep, - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - } - jt[DATACOPY] = &operation{ - execute: opDataCopy, - constantGas: GasFastestStep, - dynamicGas: memoryCopierGas(2), - minStack: minStack(3, 0), - maxStack: maxStack(3, 0), - memorySize: memoryDataCopy, - } - jt[DUPN] = &operation{ - execute: opDupN, - constantGas: GasFastestStep, - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - } - jt[SWAPN] = &operation{ - execute: opSwapN, - constantGas: GasFastestStep, - minStack: minStack(0, 0), - maxStack: maxStack(0, 0), - } - jt[EXCHANGE] = &operation{ - execute: opExchange, - constantGas: GasFastestStep, - minStack: minStack(0, 0), - maxStack: maxStack(0, 0), - } - jt[RETURNDATALOAD] = &operation{ - execute: opReturnDataLoad, - constantGas: GasFastestStep, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - } - jt[EXTCALL] = &operation{ - execute: opExtCall, - constantGas: params.WarmStorageReadCostEIP2929, - dynamicGas: makeCallVariantGasCallEIP2929(gasExtCall, 0), - minStack: minStack(4, 1), - maxStack: maxStack(4, 1), - memorySize: memoryExtCall, - } - jt[EXTDELEGATECALL] = &operation{ - execute: opExtDelegateCall, - dynamicGas: makeCallVariantGasCallEIP2929(gasExtDelegateCall, 0), - constantGas: params.WarmStorageReadCostEIP2929, - minStack: minStack(3, 1), - maxStack: maxStack(3, 1), - memorySize: memoryExtCall, - } - jt[EXTSTATICCALL] = &operation{ - execute: opExtStaticCall, - constantGas: params.WarmStorageReadCostEIP2929, - dynamicGas: makeCallVariantGasCallEIP2929(gasExtStaticCall, 0), - minStack: minStack(3, 1), - maxStack: maxStack(3, 1), - memorySize: memoryExtCall, - } -} - // enable7702 the EIP-7702 changes to support delegation designators. func enable7702(jt *JumpTable) { jt[CALL].dynamicGas = gasCallEIP7702 diff --git a/core/vm/eof.go b/core/vm/eof.go deleted file mode 100644 index a5406283d5a4..000000000000 --- a/core/vm/eof.go +++ /dev/null @@ -1,501 +0,0 @@ -// 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 vm - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "strings" - - "github.com/ethereum/go-ethereum/params" -) - -const ( - offsetVersion = 2 - offsetTypesKind = 3 - offsetCodeKind = 6 - - kindTypes = 1 - kindCode = 2 - kindContainer = 3 - kindData = 4 - - eofFormatByte = 0xef - eof1Version = 1 - - maxInputItems = 127 - maxOutputItems = 128 - maxStackHeight = 1023 - maxContainerSections = 256 -) - -var eofMagic = []byte{0xef, 0x00} - -// HasEOFByte returns true if code starts with 0xEF byte -func HasEOFByte(code []byte) bool { - return len(code) != 0 && code[0] == eofFormatByte -} - -// hasEOFMagic returns true if code starts with magic defined by EIP-3540 -func hasEOFMagic(code []byte) bool { - return len(eofMagic) <= len(code) && bytes.Equal(eofMagic, code[0:len(eofMagic)]) -} - -// isEOFVersion1 returns true if the code's version byte equals eof1Version. It -// does not verify the EOF magic is valid. -func isEOFVersion1(code []byte) bool { - return 2 < len(code) && code[2] == byte(eof1Version) -} - -// Container is an EOF container object. -type Container struct { - types []*functionMetadata - codeSections [][]byte - subContainers []*Container - subContainerCodes [][]byte - data []byte - dataSize int // might be more than len(data) -} - -// functionMetadata is an EOF function signature. -type functionMetadata struct { - inputs uint8 - outputs uint8 - maxStackHeight uint16 -} - -// stackDelta returns the #outputs - #inputs -func (meta *functionMetadata) stackDelta() int { - return int(meta.outputs) - int(meta.inputs) -} - -// checkInputs checks the current minimum stack (stackMin) against the required inputs -// of the metadata, and returns an error if the stack is too shallow. -func (meta *functionMetadata) checkInputs(stackMin int) error { - if int(meta.inputs) > stackMin { - return ErrStackUnderflow{stackLen: stackMin, required: int(meta.inputs)} - } - return nil -} - -// checkStackMax checks the if current maximum stack combined with the -// function max stack will result in a stack overflow, and if so returns an error. -func (meta *functionMetadata) checkStackMax(stackMax int) error { - newMaxStack := stackMax + int(meta.maxStackHeight) - int(meta.inputs) - if newMaxStack > int(params.StackLimit) { - return ErrStackOverflow{stackLen: newMaxStack, limit: int(params.StackLimit)} - } - return nil -} - -// MarshalBinary encodes an EOF container into binary format. -func (c *Container) MarshalBinary() []byte { - // Build EOF prefix. - b := make([]byte, 2) - copy(b, eofMagic) - b = append(b, eof1Version) - - // Write section headers. - b = append(b, kindTypes) - b = binary.BigEndian.AppendUint16(b, uint16(len(c.types)*4)) - b = append(b, kindCode) - b = binary.BigEndian.AppendUint16(b, uint16(len(c.codeSections))) - for _, codeSection := range c.codeSections { - b = binary.BigEndian.AppendUint16(b, uint16(len(codeSection))) - } - var encodedContainer [][]byte - if len(c.subContainers) != 0 { - b = append(b, kindContainer) - b = binary.BigEndian.AppendUint16(b, uint16(len(c.subContainers))) - for _, section := range c.subContainers { - encoded := section.MarshalBinary() - b = binary.BigEndian.AppendUint16(b, uint16(len(encoded))) - encodedContainer = append(encodedContainer, encoded) - } - } - b = append(b, kindData) - b = binary.BigEndian.AppendUint16(b, uint16(c.dataSize)) - b = append(b, 0) // terminator - - // Write section contents. - for _, ty := range c.types { - b = append(b, []byte{ty.inputs, ty.outputs, byte(ty.maxStackHeight >> 8), byte(ty.maxStackHeight & 0x00ff)}...) - } - for _, code := range c.codeSections { - b = append(b, code...) - } - for _, section := range encodedContainer { - b = append(b, section...) - } - b = append(b, c.data...) - - return b -} - -// UnmarshalBinary decodes an EOF container. -func (c *Container) UnmarshalBinary(b []byte, isInitcode bool) error { - return c.unmarshalContainer(b, isInitcode, true) -} - -// UnmarshalSubContainer decodes an EOF container that is inside another container. -func (c *Container) UnmarshalSubContainer(b []byte, isInitcode bool) error { - return c.unmarshalContainer(b, isInitcode, false) -} - -func (c *Container) unmarshalContainer(b []byte, isInitcode bool, topLevel bool) error { - if !hasEOFMagic(b) { - return fmt.Errorf("%w: want %x", errInvalidMagic, eofMagic) - } - if len(b) < 14 { - return io.ErrUnexpectedEOF - } - if len(b) > params.MaxInitCodeSize { - return ErrMaxInitCodeSizeExceeded - } - if !isEOFVersion1(b) { - return fmt.Errorf("%w: have %d, want %d", errInvalidVersion, b[2], eof1Version) - } - - var ( - kind, typesSize, dataSize int - codeSizes []int - err error - ) - - // Parse type section header. - kind, typesSize, err = parseSection(b, offsetTypesKind) - if err != nil { - return err - } - if kind != kindTypes { - return fmt.Errorf("%w: found section kind %x instead", errMissingTypeHeader, kind) - } - if typesSize < 4 || typesSize%4 != 0 { - return fmt.Errorf("%w: type section size must be divisible by 4, have %d", errInvalidTypeSize, typesSize) - } - if typesSize/4 > 1024 { - return fmt.Errorf("%w: type section must not exceed 4*1024, have %d", errInvalidTypeSize, typesSize) - } - - // Parse code section header. - kind, codeSizes, err = parseSectionList(b, offsetCodeKind) - if err != nil { - return err - } - if kind != kindCode { - return fmt.Errorf("%w: found section kind %x instead", errMissingCodeHeader, kind) - } - if len(codeSizes) != typesSize/4 { - return fmt.Errorf("%w: mismatch of code sections found and type signatures, types %d, code %d", errInvalidCodeSize, typesSize/4, len(codeSizes)) - } - - // Parse (optional) container section header. - var containerSizes []int - offset := offsetCodeKind + 2 + 2*len(codeSizes) + 1 - if offset < len(b) && b[offset] == kindContainer { - kind, containerSizes, err = parseSectionList(b, offset) - if err != nil { - return err - } - if kind != kindContainer { - panic("somethings wrong") - } - if len(containerSizes) == 0 { - return fmt.Errorf("%w: total container count must not be zero", errInvalidContainerSectionSize) - } - offset = offset + 2 + 2*len(containerSizes) + 1 - } - - // Parse data section header. - kind, dataSize, err = parseSection(b, offset) - if err != nil { - return err - } - if kind != kindData { - return fmt.Errorf("%w: found section %x instead", errMissingDataHeader, kind) - } - c.dataSize = dataSize - - // Check for terminator. - offsetTerminator := offset + 3 - if len(b) < offsetTerminator { - return fmt.Errorf("%w: invalid offset terminator", io.ErrUnexpectedEOF) - } - if b[offsetTerminator] != 0 { - return fmt.Errorf("%w: have %x", errMissingTerminator, b[offsetTerminator]) - } - - // Verify overall container size. - expectedSize := offsetTerminator + typesSize + sum(codeSizes) + dataSize + 1 - if len(containerSizes) != 0 { - expectedSize += sum(containerSizes) - } - if len(b) < expectedSize-dataSize { - return fmt.Errorf("%w: have %d, want %d", errInvalidContainerSize, len(b), expectedSize) - } - // Only check that the expected size is not exceed on non-initcode - if (!topLevel || !isInitcode) && len(b) > expectedSize { - return fmt.Errorf("%w: have %d, want %d", errInvalidContainerSize, len(b), expectedSize) - } - - // Parse types section. - idx := offsetTerminator + 1 - var types = make([]*functionMetadata, 0, typesSize/4) - for i := 0; i < typesSize/4; i++ { - sig := &functionMetadata{ - inputs: b[idx+i*4], - outputs: b[idx+i*4+1], - maxStackHeight: binary.BigEndian.Uint16(b[idx+i*4+2:]), - } - if sig.inputs > maxInputItems { - return fmt.Errorf("%w for section %d: have %d", errTooManyInputs, i, sig.inputs) - } - if sig.outputs > maxOutputItems { - return fmt.Errorf("%w for section %d: have %d", errTooManyOutputs, i, sig.outputs) - } - if sig.maxStackHeight > maxStackHeight { - return fmt.Errorf("%w for section %d: have %d", errTooLargeMaxStackHeight, i, sig.maxStackHeight) - } - types = append(types, sig) - } - if types[0].inputs != 0 || types[0].outputs != 0x80 { - return fmt.Errorf("%w: have %d, %d", errInvalidSection0Type, types[0].inputs, types[0].outputs) - } - c.types = types - - // Parse code sections. - idx += typesSize - codeSections := make([][]byte, len(codeSizes)) - for i, size := range codeSizes { - if size == 0 { - return fmt.Errorf("%w for section %d: size must not be 0", errInvalidCodeSize, i) - } - codeSections[i] = b[idx : idx+size] - idx += size - } - c.codeSections = codeSections - // Parse the optional container sizes. - if len(containerSizes) != 0 { - if len(containerSizes) > maxContainerSections { - return fmt.Errorf("%w number of container section exceed: %v: have %v", errInvalidContainerSectionSize, maxContainerSections, len(containerSizes)) - } - subContainerCodes := make([][]byte, 0, len(containerSizes)) - subContainers := make([]*Container, 0, len(containerSizes)) - for i, size := range containerSizes { - if size == 0 || idx+size > len(b) { - return fmt.Errorf("%w for section %d: size must not be 0", errInvalidContainerSectionSize, i) - } - subC := new(Container) - end := min(idx+size, len(b)) - if err := subC.unmarshalContainer(b[idx:end], isInitcode, false); err != nil { - if topLevel { - return fmt.Errorf("%w in sub container %d", err, i) - } - return err - } - subContainers = append(subContainers, subC) - subContainerCodes = append(subContainerCodes, b[idx:end]) - - idx += size - } - c.subContainers = subContainers - c.subContainerCodes = subContainerCodes - } - - //Parse data section. - end := len(b) - if !isInitcode { - end = min(idx+dataSize, len(b)) - } - if topLevel && len(b) != idx+dataSize { - return errTruncatedTopLevelContainer - } - c.data = b[idx:end] - - return nil -} - -// ValidateCode validates each code section of the container against the EOF v1 -// rule set. -func (c *Container) ValidateCode(jt *JumpTable, isInitCode bool) error { - refBy := notRefByEither - if isInitCode { - refBy = refByEOFCreate - } - return c.validateSubContainer(jt, refBy) -} - -func (c *Container) validateSubContainer(jt *JumpTable, refBy int) error { - visited := make(map[int]struct{}) - subContainerVisited := make(map[int]int) - toVisit := []int{0} - for len(toVisit) > 0 { - // TODO check if this can be used as a DOS - // Theres and edge case here where we mark something as visited that we visit before, - // This should not trigger a re-visit - // e.g. 0 -> 1, 2, 3 - // 1 -> 2, 3 - // should not mean 2 and 3 should be visited twice - var ( - index = toVisit[0] - code = c.codeSections[index] - ) - if _, ok := visited[index]; !ok { - res, err := validateCode(code, index, c, jt, refBy == refByEOFCreate) - if err != nil { - return err - } - visited[index] = struct{}{} - // Mark all sections that can be visited from here. - for idx := range res.visitedCode { - if _, ok := visited[idx]; !ok { - toVisit = append(toVisit, idx) - } - } - // Mark all subcontainer that can be visited from here. - for idx, reference := range res.visitedSubContainers { - // Make sure subcontainers are only ever referenced by either EOFCreate or ReturnContract - if ref, ok := subContainerVisited[idx]; ok && ref != reference { - return errors.New("section referenced by both EOFCreate and ReturnContract") - } - subContainerVisited[idx] = reference - } - if refBy == refByReturnContract && res.isInitCode { - return errIncompatibleContainerKind - } - if refBy == refByEOFCreate && res.isRuntime { - return errIncompatibleContainerKind - } - } - toVisit = toVisit[1:] - } - // Make sure every code section is visited at least once. - if len(visited) != len(c.codeSections) { - return errUnreachableCode - } - for idx, container := range c.subContainers { - reference, ok := subContainerVisited[idx] - if !ok { - return errOrphanedSubcontainer - } - if err := container.validateSubContainer(jt, reference); err != nil { - return err - } - } - return nil -} - -// parseSection decodes a (kind, size) pair from an EOF header. -func parseSection(b []byte, idx int) (kind, size int, err error) { - if idx+3 >= len(b) { - return 0, 0, io.ErrUnexpectedEOF - } - kind = int(b[idx]) - size = int(binary.BigEndian.Uint16(b[idx+1:])) - return kind, size, nil -} - -// parseSectionList decodes a (kind, len, []codeSize) section list from an EOF -// header. -func parseSectionList(b []byte, idx int) (kind int, list []int, err error) { - if idx >= len(b) { - return 0, nil, io.ErrUnexpectedEOF - } - kind = int(b[idx]) - list, err = parseList(b, idx+1) - if err != nil { - return 0, nil, err - } - return kind, list, nil -} - -// parseList decodes a list of uint16.. -func parseList(b []byte, idx int) ([]int, error) { - if len(b) < idx+2 { - return nil, io.ErrUnexpectedEOF - } - count := binary.BigEndian.Uint16(b[idx:]) - if len(b) <= idx+2+int(count)*2 { - return nil, io.ErrUnexpectedEOF - } - list := make([]int, count) - for i := 0; i < int(count); i++ { - list[i] = int(binary.BigEndian.Uint16(b[idx+2+2*i:])) - } - return list, nil -} - -// parseUint16 parses a 16 bit unsigned integer. -func parseUint16(b []byte) (int, error) { - if len(b) < 2 { - return 0, io.ErrUnexpectedEOF - } - return int(binary.BigEndian.Uint16(b)), nil -} - -// parseInt16 parses a 16 bit signed integer. -func parseInt16(b []byte) int { - return int(int16(b[1]) | int16(b[0])<<8) -} - -// sum computes the sum of a slice. -func sum(list []int) (s int) { - for _, n := range list { - s += n - } - return -} - -func (c *Container) String() string { - var output = []string{ - "Header", - fmt.Sprintf(" - EOFMagic: %02x", eofMagic), - fmt.Sprintf(" - EOFVersion: %02x", eof1Version), - fmt.Sprintf(" - KindType: %02x", kindTypes), - fmt.Sprintf(" - TypesSize: %04x", len(c.types)*4), - fmt.Sprintf(" - KindCode: %02x", kindCode), - fmt.Sprintf(" - KindData: %02x", kindData), - fmt.Sprintf(" - DataSize: %04x", len(c.data)), - fmt.Sprintf(" - Number of code sections: %d", len(c.codeSections)), - } - for i, code := range c.codeSections { - output = append(output, fmt.Sprintf(" - Code section %d length: %04x", i, len(code))) - } - - output = append(output, fmt.Sprintf(" - Number of subcontainers: %d", len(c.subContainers))) - if len(c.subContainers) > 0 { - for i, section := range c.subContainers { - output = append(output, fmt.Sprintf(" - subcontainer %d length: %04x\n", i, len(section.MarshalBinary()))) - } - } - output = append(output, "Body") - for i, typ := range c.types { - output = append(output, fmt.Sprintf(" - Type %v: %x", i, - []byte{typ.inputs, typ.outputs, byte(typ.maxStackHeight >> 8), byte(typ.maxStackHeight & 0x00ff)})) - } - for i, code := range c.codeSections { - output = append(output, fmt.Sprintf(" - Code section %d: %#x", i, code)) - } - for i, section := range c.subContainers { - output = append(output, fmt.Sprintf(" - Subcontainer %d: %x", i, section.MarshalBinary())) - } - output = append(output, fmt.Sprintf(" - Data: %#x", c.data)) - return strings.Join(output, "\n") -} diff --git a/core/vm/eof_control_flow.go b/core/vm/eof_control_flow.go deleted file mode 100644 index c0a44599067d..000000000000 --- a/core/vm/eof_control_flow.go +++ /dev/null @@ -1,235 +0,0 @@ -// 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 vm - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/params" -) - -func validateControlFlow(code []byte, section int, metadata []*functionMetadata, jt *JumpTable) (int, error) { - var ( - maxStackHeight = int(metadata[section].inputs) - visitCount = 0 - next = make([]int, 0, 1) - ) - var ( - stackBoundsMax = make([]uint16, len(code)) - stackBoundsMin = make([]uint16, len(code)) - ) - setBounds := func(pos, min, maxi int) { - // The stackboundMax slice is a bit peculiar. We use `0` to denote - // not set. Therefore, we use `1` to represent the value `0`, and so on. - // So if the caller wants to store `1` as max bound, we internally store it as - // `2`. - if stackBoundsMax[pos] == 0 { // Not yet set - visitCount++ - } - if maxi < 65535 { - stackBoundsMax[pos] = uint16(maxi + 1) - } - stackBoundsMin[pos] = uint16(min) - maxStackHeight = max(maxStackHeight, maxi) - } - getStackMaxMin := func(pos int) (ok bool, min, max int) { - maxi := stackBoundsMax[pos] - if maxi == 0 { // Not yet set - return false, 0, 0 - } - return true, int(stackBoundsMin[pos]), int(maxi - 1) - } - // set the initial stack bounds - setBounds(0, int(metadata[section].inputs), int(metadata[section].inputs)) - - qualifiedExit := false - for pos := 0; pos < len(code); pos++ { - op := OpCode(code[pos]) - ok, currentStackMin, currentStackMax := getStackMaxMin(pos) - if !ok { - return 0, errUnreachableCode - } - - switch op { - case CALLF: - arg, _ := parseUint16(code[pos+1:]) - newSection := metadata[arg] - if err := newSection.checkInputs(currentStackMin); err != nil { - return 0, fmt.Errorf("%w: at pos %d", err, pos) - } - if err := newSection.checkStackMax(currentStackMax); err != nil { - return 0, fmt.Errorf("%w: at pos %d", err, pos) - } - delta := newSection.stackDelta() - currentStackMax += delta - currentStackMin += delta - case RETF: - /* From the spec: - > for RETF the following must hold: stack_height_max == stack_height_min == types[current_code_index].outputs, - - In other words: RETF must unambiguously return all items remaining on the stack. - */ - if currentStackMax != currentStackMin { - return 0, fmt.Errorf("%w: max %d, min %d, at pos %d", errInvalidOutputs, currentStackMax, currentStackMin, pos) - } - numOutputs := int(metadata[section].outputs) - if numOutputs >= maxOutputItems { - return 0, fmt.Errorf("%w: at pos %d", errInvalidNonReturningFlag, pos) - } - if numOutputs != currentStackMin { - return 0, fmt.Errorf("%w: have %d, want %d, at pos %d", errInvalidOutputs, numOutputs, currentStackMin, pos) - } - qualifiedExit = true - case JUMPF: - arg, _ := parseUint16(code[pos+1:]) - newSection := metadata[arg] - - if err := newSection.checkStackMax(currentStackMax); err != nil { - return 0, fmt.Errorf("%w: at pos %d", err, pos) - } - - if newSection.outputs == 0x80 { - if err := newSection.checkInputs(currentStackMin); err != nil { - return 0, fmt.Errorf("%w: at pos %d", err, pos) - } - } else { - if currentStackMax != currentStackMin { - return 0, fmt.Errorf("%w: max %d, min %d, at pos %d", errInvalidOutputs, currentStackMax, currentStackMin, pos) - } - wantStack := int(metadata[section].outputs) - newSection.stackDelta() - if currentStackMax != wantStack { - return 0, fmt.Errorf("%w: at pos %d", errInvalidOutputs, pos) - } - } - qualifiedExit = qualifiedExit || newSection.outputs < maxOutputItems - case DUPN: - arg := int(code[pos+1]) + 1 - if want, have := arg, currentStackMin; want > have { - return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos) - } - case SWAPN: - arg := int(code[pos+1]) + 1 - if want, have := arg+1, currentStackMin; want > have { - return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos) - } - case EXCHANGE: - arg := int(code[pos+1]) - n := arg>>4 + 1 - m := arg&0x0f + 1 - if want, have := n+m+1, currentStackMin; want > have { - return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos) - } - default: - if want, have := jt[op].minStack, currentStackMin; want > have { - return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos) - } - } - if !terminals[op] && op != CALLF { - change := int(params.StackLimit) - jt[op].maxStack - currentStackMax += change - currentStackMin += change - } - next = next[:0] - switch op { - case RJUMP: - nextPos := pos + 2 + parseInt16(code[pos+1:]) - next = append(next, nextPos) - // We set the stack bounds of the destination - // and skip the argument, only for RJUMP, all other opcodes are handled later - if nextPos+1 < pos { - ok, nextMin, nextMax := getStackMaxMin(nextPos + 1) - if !ok { - return 0, errInvalidBackwardJump - } - if nextMax != currentStackMax || nextMin != currentStackMin { - return 0, errInvalidMaxStackHeight - } - } else { - ok, nextMin, nextMax := getStackMaxMin(nextPos + 1) - if !ok { - setBounds(nextPos+1, currentStackMin, currentStackMax) - } else { - setBounds(nextPos+1, min(nextMin, currentStackMin), max(nextMax, currentStackMax)) - } - } - case RJUMPI: - arg := parseInt16(code[pos+1:]) - next = append(next, pos+2) - next = append(next, pos+2+arg) - case RJUMPV: - count := int(code[pos+1]) + 1 - next = append(next, pos+1+2*count) - for i := 0; i < count; i++ { - arg := parseInt16(code[pos+2+2*i:]) - next = append(next, pos+1+2*count+arg) - } - default: - if imm := int(immediates[op]); imm != 0 { - next = append(next, pos+imm) - } else { - // Simple op, no operand. - next = append(next, pos) - } - } - - if op != RJUMP && !terminals[op] { - for _, instr := range next { - nextPC := instr + 1 - if nextPC >= len(code) { - return 0, fmt.Errorf("%w: end with %s, pos %d", errInvalidCodeTermination, op, pos) - } - if nextPC > pos { - // target reached via forward jump or seq flow - ok, nextMin, nextMax := getStackMaxMin(nextPC) - if !ok { - setBounds(nextPC, currentStackMin, currentStackMax) - } else { - setBounds(nextPC, min(nextMin, currentStackMin), max(nextMax, currentStackMax)) - } - } else { - // target reached via backwards jump - ok, nextMin, nextMax := getStackMaxMin(nextPC) - if !ok { - return 0, errInvalidBackwardJump - } - if currentStackMax != nextMax { - return 0, fmt.Errorf("%w want %d as current max got %d at pos %d,", errInvalidBackwardJump, currentStackMax, nextMax, pos) - } - if currentStackMin != nextMin { - return 0, fmt.Errorf("%w want %d as current min got %d at pos %d,", errInvalidBackwardJump, currentStackMin, nextMin, pos) - } - } - } - } - - if op == RJUMP { - pos += 2 // skip the immediate - } else { - pos = next[0] - } - } - if qualifiedExit != (metadata[section].outputs < maxOutputItems) { - return 0, fmt.Errorf("%w no RETF or qualified JUMPF", errInvalidNonReturningFlag) - } - if maxStackHeight >= int(params.StackLimit) { - return 0, ErrStackOverflow{maxStackHeight, int(params.StackLimit)} - } - if maxStackHeight != int(metadata[section].maxStackHeight) { - return 0, fmt.Errorf("%w in code section %d: have %d, want %d", errInvalidMaxStackHeight, section, maxStackHeight, metadata[section].maxStackHeight) - } - return visitCount, nil -} diff --git a/core/vm/eof_immediates.go b/core/vm/eof_immediates.go deleted file mode 100644 index 9cb7d999a226..000000000000 --- a/core/vm/eof_immediates.go +++ /dev/null @@ -1,70 +0,0 @@ -// 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 vm - -// immediate denotes how many immediate bytes an operation uses. This information -// is not required during runtime, only during EOF-validation, so is not -// places into the op-struct in the instruction table. -// Note: the immediates is fork-agnostic, and assumes that validity of opcodes at -// the given time is performed elsewhere. -var immediates [256]uint8 - -// terminals denotes whether instructions can be the final opcode in a code section. -// Note: the terminals is fork-agnostic, and assumes that validity of opcodes at -// the given time is performed elsewhere. -var terminals [256]bool - -func init() { - // The legacy pushes - for i := uint8(1); i < 33; i++ { - immediates[int(PUSH0)+int(i)] = i - } - // And new eof opcodes. - immediates[DATALOADN] = 2 - immediates[RJUMP] = 2 - immediates[RJUMPI] = 2 - immediates[RJUMPV] = 3 - immediates[CALLF] = 2 - immediates[JUMPF] = 2 - immediates[DUPN] = 1 - immediates[SWAPN] = 1 - immediates[EXCHANGE] = 1 - immediates[EOFCREATE] = 1 - immediates[RETURNCONTRACT] = 1 - - // Define the terminals. - terminals[STOP] = true - terminals[RETF] = true - terminals[JUMPF] = true - terminals[RETURNCONTRACT] = true - terminals[RETURN] = true - terminals[REVERT] = true - terminals[INVALID] = true -} - -// Immediates returns the number bytes of immediates (argument not from -// stack but from code) a given opcode has. -// OBS: -// - This function assumes EOF instruction-set. It cannot be upon in -// a. pre-EOF code -// b. post-EOF but legacy code -// - RJUMPV is unique as it has a variable sized operand. The total size is -// determined by the count byte which immediately follows RJUMPV. This method -// will return '3' for RJUMPV, which is the minimum. -func Immediates(op OpCode) int { - return int(immediates[op]) -} diff --git a/core/vm/eof_instructions.go b/core/vm/eof_instructions.go deleted file mode 100644 index 800d14d7b85a..000000000000 --- a/core/vm/eof_instructions.go +++ /dev/null @@ -1,112 +0,0 @@ -// 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 vm - -// opRjump implements the RJUMP opcode. -func opRjump(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opRjumpi implements the RJUMPI opcode -func opRjumpi(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opRjumpv implements the RJUMPV opcode -func opRjumpv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opCallf implements the CALLF opcode -func opCallf(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opRetf implements the RETF opcode -func opRetf(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opJumpf implements the JUMPF opcode -func opJumpf(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opEOFCreate implements the EOFCREATE opcode -func opEOFCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opReturnContract implements the RETURNCONTRACT opcode -func opReturnContract(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opDataLoad implements the DATALOAD opcode -func opDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opDataLoadN implements the DATALOADN opcode -func opDataLoadN(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opDataSize implements the DATASIZE opcode -func opDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opDataCopy implements the DATACOPY opcode -func opDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opDupN implements the DUPN opcode -func opDupN(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opSwapN implements the SWAPN opcode -func opSwapN(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opExchange implements the EXCHANGE opcode -func opExchange(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opReturnDataLoad implements the RETURNDATALOAD opcode -func opReturnDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opExtCall implements the EOFCREATE opcode -func opExtCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opExtDelegateCall implements the EXTDELEGATECALL opcode -func opExtDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} - -// opExtStaticCall implements the EXTSTATICCALL opcode -func opExtStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - panic("not implemented") -} diff --git a/core/vm/eof_test.go b/core/vm/eof_test.go deleted file mode 100644 index 0a9cf638ceba..000000000000 --- a/core/vm/eof_test.go +++ /dev/null @@ -1,117 +0,0 @@ -// 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 vm - -import ( - "encoding/hex" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func TestEOFMarshaling(t *testing.T) { - for i, test := range []struct { - want Container - err error - }{ - { - want: Container{ - types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - codeSections: [][]byte{common.Hex2Bytes("604200")}, - data: []byte{0x01, 0x02, 0x03}, - dataSize: 3, - }, - }, - { - want: Container{ - types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - codeSections: [][]byte{common.Hex2Bytes("604200")}, - data: []byte{0x01, 0x02, 0x03}, - dataSize: 3, - }, - }, - { - want: Container{ - types: []*functionMetadata{ - {inputs: 0, outputs: 0x80, maxStackHeight: 1}, - {inputs: 2, outputs: 3, maxStackHeight: 4}, - {inputs: 1, outputs: 1, maxStackHeight: 1}, - }, - codeSections: [][]byte{ - common.Hex2Bytes("604200"), - common.Hex2Bytes("6042604200"), - common.Hex2Bytes("00"), - }, - data: []byte{}, - }, - }, - } { - var ( - b = test.want.MarshalBinary() - got Container - ) - t.Logf("b: %#x", b) - if err := got.UnmarshalBinary(b, true); err != nil && err != test.err { - t.Fatalf("test %d: got error \"%v\", want \"%v\"", i, err, test.err) - } - if !reflect.DeepEqual(got, test.want) { - t.Fatalf("test %d: got %+v, want %+v", i, got, test.want) - } - } -} - -func TestEOFSubcontainer(t *testing.T) { - var subcontainer = new(Container) - if err := subcontainer.UnmarshalBinary(common.Hex2Bytes("ef000101000402000100010400000000800000fe"), true); err != nil { - t.Fatal(err) - } - container := Container{ - types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - codeSections: [][]byte{common.Hex2Bytes("604200")}, - subContainers: []*Container{subcontainer}, - data: []byte{0x01, 0x02, 0x03}, - dataSize: 3, - } - var ( - b = container.MarshalBinary() - got Container - ) - if err := got.UnmarshalBinary(b, true); err != nil { - t.Fatal(err) - } - if res := got.MarshalBinary(); !reflect.DeepEqual(res, b) { - t.Fatalf("invalid marshalling, want %v got %v", b, res) - } -} - -func TestMarshaling(t *testing.T) { - tests := []string{ - "EF000101000402000100040400000000800000E0000000", - "ef0001010004020001000d04000000008000025fe100055f5fe000035f600100", - } - for i, test := range tests { - s, err := hex.DecodeString(test) - if err != nil { - t.Fatalf("test %d: error decoding: %v", i, err) - } - var got Container - if err := got.UnmarshalBinary(s, true); err != nil { - t.Fatalf("test %d: got error %v", i, err) - } - } -} diff --git a/core/vm/eof_validation.go b/core/vm/eof_validation.go deleted file mode 100644 index 514f9fb58cf9..000000000000 --- a/core/vm/eof_validation.go +++ /dev/null @@ -1,255 +0,0 @@ -// 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 vm - -import ( - "errors" - "fmt" - "io" -) - -// Below are all possible errors that can occur during validation of -// EOF containers. -var ( - errInvalidMagic = errors.New("invalid magic") - errUndefinedInstruction = errors.New("undefined instruction") - errTruncatedImmediate = errors.New("truncated immediate") - errInvalidSectionArgument = errors.New("invalid section argument") - errInvalidCallArgument = errors.New("callf into non-returning section") - errInvalidDataloadNArgument = errors.New("invalid dataloadN argument") - errInvalidJumpDest = errors.New("invalid jump destination") - errInvalidBackwardJump = errors.New("invalid backward jump") - errInvalidOutputs = errors.New("invalid number of outputs") - errInvalidMaxStackHeight = errors.New("invalid max stack height") - errInvalidCodeTermination = errors.New("invalid code termination") - errEOFCreateWithTruncatedSection = errors.New("eofcreate with truncated section") - errOrphanedSubcontainer = errors.New("subcontainer not referenced at all") - errIncompatibleContainerKind = errors.New("incompatible container kind") - errStopAndReturnContract = errors.New("Stop/Return and Returncontract in the same code section") - errStopInInitCode = errors.New("initcode contains a RETURN or STOP opcode") - errTruncatedTopLevelContainer = errors.New("truncated top level container") - errUnreachableCode = errors.New("unreachable code") - errInvalidNonReturningFlag = errors.New("invalid non-returning flag, bad RETF") - errInvalidVersion = errors.New("invalid version") - errMissingTypeHeader = errors.New("missing type header") - errInvalidTypeSize = errors.New("invalid type section size") - errMissingCodeHeader = errors.New("missing code header") - errInvalidCodeSize = errors.New("invalid code size") - errInvalidContainerSectionSize = errors.New("invalid container section size") - errMissingDataHeader = errors.New("missing data header") - errMissingTerminator = errors.New("missing header terminator") - errTooManyInputs = errors.New("invalid type content, too many inputs") - errTooManyOutputs = errors.New("invalid type content, too many outputs") - errInvalidSection0Type = errors.New("invalid section 0 type, input and output should be zero and non-returning (0x80)") - errTooLargeMaxStackHeight = errors.New("invalid type content, max stack height exceeds limit") - errInvalidContainerSize = errors.New("invalid container size") -) - -const ( - notRefByEither = iota - refByReturnContract - refByEOFCreate -) - -type validationResult struct { - visitedCode map[int]struct{} - visitedSubContainers map[int]int - isInitCode bool - isRuntime bool -} - -// validateCode validates the code parameter against the EOF v1 validity requirements. -func validateCode(code []byte, section int, container *Container, jt *JumpTable, isInitCode bool) (*validationResult, error) { - var ( - i = 0 - // Tracks the number of actual instructions in the code (e.g. - // non-immediate values). This is used at the end to determine - // if each instruction is reachable. - count = 0 - op OpCode - analysis bitvec - visitedCode map[int]struct{} - visitedSubcontainers map[int]int - hasReturnContract bool - hasStop bool - ) - // This loop visits every single instruction and verifies: - // * if the instruction is valid for the given jump table. - // * if the instruction has an immediate value, it is not truncated. - // * if performing a relative jump, all jump destinations are valid. - // * if changing code sections, the new code section index is valid and - // will not cause a stack overflow. - for i < len(code) { - count++ - op = OpCode(code[i]) - if jt[op].undefined { - return nil, fmt.Errorf("%w: op %s, pos %d", errUndefinedInstruction, op, i) - } - size := int(immediates[op]) - if size != 0 && len(code) <= i+size { - return nil, fmt.Errorf("%w: op %s, pos %d", errTruncatedImmediate, op, i) - } - switch op { - case RJUMP, RJUMPI: - if err := checkDest(code, &analysis, i+1, i+3, len(code)); err != nil { - return nil, err - } - case RJUMPV: - maxSize := int(code[i+1]) - length := maxSize + 1 - if len(code) <= i+length { - return nil, fmt.Errorf("%w: jump table truncated, op %s, pos %d", errTruncatedImmediate, op, i) - } - offset := i + 2 - for j := 0; j < length; j++ { - if err := checkDest(code, &analysis, offset+j*2, offset+(length*2), len(code)); err != nil { - return nil, err - } - } - i += 2 * maxSize - case CALLF: - arg, _ := parseUint16(code[i+1:]) - if arg >= len(container.types) { - return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidSectionArgument, arg, len(container.types), i) - } - if container.types[arg].outputs == 0x80 { - return nil, fmt.Errorf("%w: section %v", errInvalidCallArgument, arg) - } - if visitedCode == nil { - visitedCode = make(map[int]struct{}) - } - visitedCode[arg] = struct{}{} - case JUMPF: - arg, _ := parseUint16(code[i+1:]) - if arg >= len(container.types) { - return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidSectionArgument, arg, len(container.types), i) - } - if container.types[arg].outputs != 0x80 && container.types[arg].outputs > container.types[section].outputs { - return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidOutputs, arg, len(container.types), i) - } - if visitedCode == nil { - visitedCode = make(map[int]struct{}) - } - visitedCode[arg] = struct{}{} - case DATALOADN: - arg, _ := parseUint16(code[i+1:]) - // TODO why are we checking this? We should just pad - if arg+32 > len(container.data) { - return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidDataloadNArgument, arg, len(container.data), i) - } - case RETURNCONTRACT: - if !isInitCode { - return nil, errIncompatibleContainerKind - } - arg := int(code[i+1]) - if arg >= len(container.subContainers) { - return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errUnreachableCode, arg, len(container.subContainers), i) - } - if visitedSubcontainers == nil { - visitedSubcontainers = make(map[int]int) - } - // We need to store per subcontainer how it was referenced - if v, ok := visitedSubcontainers[arg]; ok && v != refByReturnContract { - return nil, fmt.Errorf("section already referenced, arg :%d", arg) - } - if hasStop { - return nil, errStopAndReturnContract - } - hasReturnContract = true - visitedSubcontainers[arg] = refByReturnContract - case EOFCREATE: - arg := int(code[i+1]) - if arg >= len(container.subContainers) { - return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errUnreachableCode, arg, len(container.subContainers), i) - } - if ct := container.subContainers[arg]; len(ct.data) != ct.dataSize { - return nil, fmt.Errorf("%w: container %d, have %d, claimed %d, pos %d", errEOFCreateWithTruncatedSection, arg, len(ct.data), ct.dataSize, i) - } - if visitedSubcontainers == nil { - visitedSubcontainers = make(map[int]int) - } - // We need to store per subcontainer how it was referenced - if v, ok := visitedSubcontainers[arg]; ok && v != refByEOFCreate { - return nil, fmt.Errorf("section already referenced, arg :%d", arg) - } - visitedSubcontainers[arg] = refByEOFCreate - case STOP, RETURN: - if isInitCode { - return nil, errStopInInitCode - } - if hasReturnContract { - return nil, errStopAndReturnContract - } - hasStop = true - } - i += size + 1 - } - // Code sections may not "fall through" and require proper termination. - // Therefore, the last instruction must be considered terminal or RJUMP. - if !terminals[op] && op != RJUMP { - return nil, fmt.Errorf("%w: end with %s, pos %d", errInvalidCodeTermination, op, i) - } - if paths, err := validateControlFlow(code, section, container.types, jt); err != nil { - return nil, err - } else if paths != count { - // TODO(matt): return actual position of unreachable code - return nil, errUnreachableCode - } - return &validationResult{ - visitedCode: visitedCode, - visitedSubContainers: visitedSubcontainers, - isInitCode: hasReturnContract, - isRuntime: hasStop, - }, nil -} - -// checkDest parses a relative offset at code[0:2] and checks if it is a valid jump destination. -func checkDest(code []byte, analysis *bitvec, imm, from, length int) error { - if len(code) < imm+2 { - return io.ErrUnexpectedEOF - } - if analysis != nil && *analysis == nil { - *analysis = eofCodeBitmap(code) - } - offset := parseInt16(code[imm:]) - dest := from + offset - if dest < 0 || dest >= length { - return fmt.Errorf("%w: out-of-bounds offset: offset %d, dest %d, pos %d", errInvalidJumpDest, offset, dest, imm) - } - if !analysis.codeSegment(uint64(dest)) { - return fmt.Errorf("%w: offset into immediate: offset %d, dest %d, pos %d", errInvalidJumpDest, offset, dest, imm) - } - return nil -} - -//// disasm is a helper utility to show a sequence of comma-separated operations, -//// with immediates shown inline, -//// e.g: PUSH1(0x00),EOFCREATE(0x00), -//func disasm(code []byte) string { -// var ops []string -// for i := 0; i < len(code); i++ { -// var op string -// if args := immediates[code[i]]; args > 0 { -// op = fmt.Sprintf("%v(%#x)", OpCode(code[i]).String(), code[i+1:i+1+int(args)]) -// i += int(args) -// } else { -// op = OpCode(code[i]).String() -// } -// ops = append(ops, op) -// } -// return strings.Join(ops, ",") -//} diff --git a/core/vm/eof_validation_test.go b/core/vm/eof_validation_test.go deleted file mode 100644 index f7b0e78f2695..000000000000 --- a/core/vm/eof_validation_test.go +++ /dev/null @@ -1,517 +0,0 @@ -// 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 vm - -import ( - "encoding/binary" - "errors" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/params" -) - -func TestValidateCode(t *testing.T) { - for i, test := range []struct { - code []byte - section int - metadata []*functionMetadata - err error - }{ - { - code: []byte{ - byte(CALLER), - byte(POP), - byte(STOP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - }, - { - code: []byte{ - byte(CALLF), 0x00, 0x00, - byte(RETF), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0, maxStackHeight: 0}}, - }, - { - code: []byte{ - byte(ADDRESS), - byte(CALLF), 0x00, 0x00, - byte(POP), - byte(RETF), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0, maxStackHeight: 1}}, - }, - { - code: []byte{ - byte(CALLER), - byte(POP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - err: errInvalidCodeTermination, - }, - { - code: []byte{ - byte(RJUMP), - byte(0x00), - byte(0x01), - byte(CALLER), - byte(STOP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 0}}, - err: errUnreachableCode, - }, - { - code: []byte{ - byte(PUSH1), - byte(0x42), - byte(ADD), - byte(STOP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - err: ErrStackUnderflow{stackLen: 1, required: 2}, - }, - { - code: []byte{ - byte(PUSH1), - byte(0x42), - byte(POP), - byte(STOP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 2}}, - err: errInvalidMaxStackHeight, - }, - { - code: []byte{ - byte(PUSH0), - byte(RJUMPI), - byte(0x00), - byte(0x01), - byte(PUSH1), - byte(0x42), // jumps to here - byte(POP), - byte(STOP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - err: errInvalidJumpDest, - }, - { - code: []byte{ - byte(PUSH0), - byte(RJUMPV), - byte(0x01), - byte(0x00), - byte(0x01), - byte(0x00), - byte(0x02), - byte(PUSH1), - byte(0x42), // jumps to here - byte(POP), // and here - byte(STOP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - err: errInvalidJumpDest, - }, - { - code: []byte{ - byte(PUSH0), - byte(RJUMPV), - byte(0x00), - byte(STOP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - err: errTruncatedImmediate, - }, - { - code: []byte{ - byte(RJUMP), 0x00, 0x03, - byte(JUMPDEST), // this code is unreachable to forward jumps alone - byte(JUMPDEST), - byte(RETURN), - byte(PUSH1), 20, - byte(PUSH1), 39, - byte(PUSH1), 0x00, - byte(DATACOPY), - byte(PUSH1), 20, - byte(PUSH1), 0x00, - byte(RJUMP), 0xff, 0xef, - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 3}}, - err: errUnreachableCode, - }, - { - code: []byte{ - byte(PUSH1), 1, - byte(RJUMPI), 0x00, 0x03, - byte(JUMPDEST), - byte(JUMPDEST), - byte(STOP), - byte(PUSH1), 20, - byte(PUSH1), 39, - byte(PUSH1), 0x00, - byte(DATACOPY), - byte(PUSH1), 20, - byte(PUSH1), 0x00, - byte(RETURN), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 3}}, - }, - { - code: []byte{ - byte(PUSH1), 1, - byte(RJUMPV), 0x01, 0x00, 0x03, 0xff, 0xf8, - byte(JUMPDEST), - byte(JUMPDEST), - byte(STOP), - byte(PUSH1), 20, - byte(PUSH1), 39, - byte(PUSH1), 0x00, - byte(DATACOPY), - byte(PUSH1), 20, - byte(PUSH1), 0x00, - byte(RETURN), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 3}}, - }, - { - code: []byte{ - byte(STOP), - byte(STOP), - byte(INVALID), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 0}}, - err: errUnreachableCode, - }, - { - code: []byte{ - byte(RETF), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 1, maxStackHeight: 0}}, - err: errInvalidOutputs, - }, - { - code: []byte{ - byte(RETF), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 3, outputs: 3, maxStackHeight: 3}}, - }, - { - code: []byte{ - byte(CALLF), 0x00, 0x01, - byte(POP), - byte(STOP), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}, {inputs: 0, outputs: 1, maxStackHeight: 0}}, - }, - { - code: []byte{ - byte(ORIGIN), - byte(ORIGIN), - byte(CALLF), 0x00, 0x01, - byte(POP), - byte(RETF), - }, - section: 0, - metadata: []*functionMetadata{{inputs: 0, outputs: 0, maxStackHeight: 2}, {inputs: 2, outputs: 1, maxStackHeight: 2}}, - }, - } { - container := &Container{ - types: test.metadata, - data: make([]byte, 0), - subContainers: make([]*Container, 0), - } - _, err := validateCode(test.code, test.section, container, &eofInstructionSet, false) - if !errors.Is(err, test.err) { - t.Errorf("test %d (%s): unexpected error (want: %v, got: %v)", i, common.Bytes2Hex(test.code), test.err, err) - } - } -} - -// BenchmarkRJUMPI tries to benchmark the RJUMPI opcode validation -// For this we do a bunch of RJUMPIs that jump backwards (in a potential infinite loop). -func BenchmarkRJUMPI(b *testing.B) { - snippet := []byte{ - byte(PUSH0), - byte(RJUMPI), 0xFF, 0xFC, - } - code := []byte{} - for i := 0; i < params.MaxCodeSize/len(snippet)-1; i++ { - code = append(code, snippet...) - } - code = append(code, byte(STOP)) - container := &Container{ - types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - data: make([]byte, 0), - subContainers: make([]*Container, 0), - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := validateCode(code, 0, container, &eofInstructionSet, false) - if err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkRJUMPV tries to benchmark the validation of the RJUMPV opcode -// for this we set up as many RJUMPV opcodes with a full jumptable (containing 0s) as possible. -func BenchmarkRJUMPV(b *testing.B) { - snippet := []byte{ - byte(PUSH0), - byte(RJUMPV), - 0xff, // count - 0x00, 0x00, - } - for i := 0; i < 255; i++ { - snippet = append(snippet, []byte{0x00, 0x00}...) - } - code := []byte{} - for i := 0; i < 24576/len(snippet)-1; i++ { - code = append(code, snippet...) - } - code = append(code, byte(PUSH0)) - code = append(code, byte(STOP)) - container := &Container{ - types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - data: make([]byte, 0), - subContainers: make([]*Container, 0), - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := validateCode(code, 0, container, &pragueInstructionSet, false) - if err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkEOFValidation tries to benchmark the code validation for the CALLF/RETF operation. -// For this we set up code that calls into 1024 code sections which can either -// - just contain a RETF opcode -// - or code to again call into 1024 code sections. -// We can't have all code sections calling each other, otherwise we would exceed 48KB. -func BenchmarkEOFValidation(b *testing.B) { - var container Container - var code []byte - maxSections := 1024 - for i := 0; i < maxSections; i++ { - code = append(code, byte(CALLF)) - code = binary.BigEndian.AppendUint16(code, uint16(i%(maxSections-1))+1) - } - // First container - container.codeSections = append(container.codeSections, append(code, byte(STOP))) - container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0x80, maxStackHeight: 0}) - - inner := []byte{ - byte(RETF), - } - - for i := 0; i < 1023; i++ { - container.codeSections = append(container.codeSections, inner) - container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0, maxStackHeight: 0}) - } - - for i := 0; i < 12; i++ { - container.codeSections[i+1] = append(code, byte(RETF)) - } - - bin := container.MarshalBinary() - if len(bin) > 48*1024 { - b.Fatal("Exceeds 48Kb") - } - - var container2 Container - b.ResetTimer() - for i := 0; i < b.N; i++ { - if err := container2.UnmarshalBinary(bin, true); err != nil { - b.Fatal(err) - } - if err := container2.ValidateCode(&pragueInstructionSet, false); err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkEOFValidation2 tries to benchmark the code validation for the CALLF/RETF operation. -// For this we set up code that calls into 1024 code sections which -// - contain calls to some other code sections. -// We can't have all code sections calling each other, otherwise we would exceed 48KB. -func BenchmarkEOFValidation2(b *testing.B) { - var container Container - var code []byte - maxSections := 1024 - for i := 0; i < maxSections; i++ { - code = append(code, byte(CALLF)) - code = binary.BigEndian.AppendUint16(code, uint16(i%(maxSections-1))+1) - } - code = append(code, byte(STOP)) - // First container - container.codeSections = append(container.codeSections, code) - container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0x80, maxStackHeight: 0}) - - inner := []byte{ - byte(CALLF), 0x03, 0xE8, - byte(CALLF), 0x03, 0xE9, - byte(CALLF), 0x03, 0xF0, - byte(CALLF), 0x03, 0xF1, - byte(CALLF), 0x03, 0xF2, - byte(CALLF), 0x03, 0xF3, - byte(CALLF), 0x03, 0xF4, - byte(CALLF), 0x03, 0xF5, - byte(CALLF), 0x03, 0xF6, - byte(CALLF), 0x03, 0xF7, - byte(CALLF), 0x03, 0xF8, - byte(CALLF), 0x03, 0xF, - byte(RETF), - } - - for i := 0; i < 1023; i++ { - container.codeSections = append(container.codeSections, inner) - container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0, maxStackHeight: 0}) - } - - bin := container.MarshalBinary() - if len(bin) > 48*1024 { - b.Fatal("Exceeds 48Kb") - } - - var container2 Container - b.ResetTimer() - for i := 0; i < b.N; i++ { - if err := container2.UnmarshalBinary(bin, true); err != nil { - b.Fatal(err) - } - if err := container2.ValidateCode(&pragueInstructionSet, false); err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkEOFValidation3 tries to benchmark the code validation for the CALLF/RETF and RJUMPI/V operations. -// For this we set up code that calls into 1024 code sections which either -// - contain an RJUMP opcode -// - contain calls to other code sections -// We can't have all code sections calling each other, otherwise we would exceed 48KB. -func BenchmarkEOFValidation3(b *testing.B) { - var container Container - var code []byte - snippet := []byte{ - byte(PUSH0), - byte(RJUMPV), - 0xff, // count - 0x00, 0x00, - } - for i := 0; i < 255; i++ { - snippet = append(snippet, []byte{0x00, 0x00}...) - } - code = append(code, snippet...) - // First container, calls into all other containers - maxSections := 1024 - for i := 0; i < maxSections; i++ { - code = append(code, byte(CALLF)) - code = binary.BigEndian.AppendUint16(code, uint16(i%(maxSections-1))+1) - } - code = append(code, byte(STOP)) - container.codeSections = append(container.codeSections, code) - container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0x80, maxStackHeight: 1}) - - // Other containers - for i := 0; i < 1023; i++ { - container.codeSections = append(container.codeSections, []byte{byte(RJUMP), 0x00, 0x00, byte(RETF)}) - container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0, maxStackHeight: 0}) - } - // Other containers - for i := 0; i < 68; i++ { - container.codeSections[i+1] = append(snippet, byte(RETF)) - container.types[i+1] = &functionMetadata{inputs: 0, outputs: 0, maxStackHeight: 1} - } - bin := container.MarshalBinary() - if len(bin) > 48*1024 { - b.Fatal("Exceeds 48Kb") - } - b.ResetTimer() - b.ReportMetric(float64(len(bin)), "bytes") - for i := 0; i < b.N; i++ { - for k := 0; k < 40; k++ { - var container2 Container - if err := container2.UnmarshalBinary(bin, true); err != nil { - b.Fatal(err) - } - if err := container2.ValidateCode(&pragueInstructionSet, false); err != nil { - b.Fatal(err) - } - } - } -} - -func BenchmarkRJUMPI_2(b *testing.B) { - code := []byte{ - byte(PUSH0), - byte(RJUMPI), 0xFF, 0xFC, - } - for i := 0; i < params.MaxCodeSize/4-1; i++ { - code = append(code, byte(PUSH0)) - x := -4 * i - code = append(code, byte(RJUMPI)) - code = binary.BigEndian.AppendUint16(code, uint16(x)) - } - code = append(code, byte(STOP)) - container := &Container{ - types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}}, - data: make([]byte, 0), - subContainers: make([]*Container, 0), - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := validateCode(code, 0, container, &pragueInstructionSet, false) - if err != nil { - b.Fatal(err) - } - } -} - -func FuzzUnmarshalBinary(f *testing.F) { - f.Fuzz(func(_ *testing.T, input []byte) { - var container Container - container.UnmarshalBinary(input, true) - }) -} - -func FuzzValidate(f *testing.F) { - f.Fuzz(func(_ *testing.T, code []byte, maxStack uint16) { - var container Container - container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0x80, maxStackHeight: maxStack}) - validateCode(code, 0, &container, &pragueInstructionSet, true) - }) -} diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index f711aa4a187a..c7c1274bf2f3 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -98,8 +98,8 @@ var ( func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { var ( - y, x = stack.Back(1), stack.Back(0) - current = evm.StateDB.GetState(contract.Address(), x.Bytes32()) + y, x = stack.Back(1), stack.Back(0) + current, original = evm.StateDB.GetStateAndCommittedState(contract.Address(), x.Bytes32()) ) // The legacy gas metering only takes into consideration the current state // Legacy rules should be applied if we are in Petersburg (removal of EIP-1283) @@ -139,7 +139,6 @@ func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySi if current == value { // noop (1) return params.NetSstoreNoopGas, nil } - original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32()) if original == current { if original == (common.Hash{}) { // create slot (2.1.1) return params.NetSstoreInitGas, nil @@ -188,15 +187,14 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m } // Gas sentry honoured, do the actual gas calculation based on the stored value var ( - y, x = stack.Back(1), stack.Back(0) - current = evm.StateDB.GetState(contract.Address(), x.Bytes32()) + y, x = stack.Back(1), stack.Back(0) + current, original = evm.StateDB.GetStateAndCommittedState(contract.Address(), x.Bytes32()) ) value := common.Hash(y.Bytes32()) if current == value { // noop (1) return params.SloadGasEIP2200, nil } - original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32()) if original == current { if original == (common.Hash{}) { // create slot (2.1.1) return params.SstoreSetGasEIP2200, nil @@ -485,20 +483,3 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me } return gas, nil } - -func gasExtCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - panic("not implemented") -} - -func gasExtDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - panic("not implemented") -} -func gasExtStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - panic("not implemented") -} - -// gasEOFCreate returns the gas-cost for EOF-Create. Hashing charge needs to be -// deducted in the opcode itself, since it depends on the immediate -func gasEOFCreate(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - panic("not implemented") -} diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 0902d17c5477..8a82de5d8b1e 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -972,3 +972,43 @@ func TestPush(t *testing.T) { } } } + +func TestOpCLZ(t *testing.T) { + evm := NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{}) + + tests := []struct { + inputHex string + want uint64 // expected CLZ result + }{ + {"0x0", 256}, + {"0x1", 255}, + {"0x6ff", 245}, // 0x6ff = 0b11011111111 (11 bits), so 256-11 = 245 + {"0xffffffffff", 216}, // 40 bits, so 256-40 = 216 + {"0x4000000000000000000000000000000000000000000000000000000000000000", 1}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1}, + {"0x8000000000000000000000000000000000000000000000000000000000000000", 0}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0}, + } + for _, tc := range tests { + // prepare a fresh stack and PC + stack := newstack() + pc := uint64(0) + + // parse input + val := new(uint256.Int) + if err := val.SetFromHex(tc.inputHex); err != nil { + t.Fatal("invalid hex uint256:", tc.inputHex) + } + + stack.push(val) + opCLZ(&pc, evm.interpreter, &ScopeContext{Stack: stack}) + + if gotLen := stack.len(); gotLen != 1 { + t.Fatalf("stack length = %d; want 1", gotLen) + } + result := stack.pop() + if got := result.Uint64(); got != tc.want { + t.Fatalf("clz(%q) = %d; want %d", tc.inputHex, got, tc.want) + } + } +} diff --git a/core/vm/interface.go b/core/vm/interface.go index 86e8c56ab0e3..42a72db48224 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -50,7 +50,7 @@ type StateDB interface { SubRefund(uint64) GetRefund() uint64 - GetCommittedState(common.Address, common.Hash) common.Hash + GetStateAndCommittedState(common.Address, common.Hash) (common.Hash, common.Hash) GetState(common.Address, common.Hash) common.Hash SetState(common.Address, common.Hash, common.Hash) common.Hash GetStorageRoot(addr common.Address) common.Hash diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index d0e5967e6e77..34d19008da7e 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -106,6 +106,8 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter { // If jump table was not initialised we set the default one. var table *JumpTable switch { + case evm.chainRules.IsOsaka: + table = &osakaInstructionSet case evm.chainRules.IsVerkle: // TODO replace with proper instruction set when fork is specified table = &verkleInstructionSet @@ -181,10 +183,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } var ( - op OpCode // current opcode - mem = NewMemory() // bound memory - stack = newstack() // local stack - callContext = &ScopeContext{ + op OpCode // current opcode + jumpTable *JumpTable = in.table + mem = NewMemory() // bound memory + stack = newstack() // local stack + callContext = &ScopeContext{ Memory: mem, Stack: stack, Contract: contract, @@ -227,6 +230,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during // the execution of one of the operations or until the done flag is set by the // parent context. + _ = jumpTable[0] // nil-check the jumpTable out of the loop for { if debug { // Capture pre-execution values for tracing. @@ -247,7 +251,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // Get the operation from the jump table and validate the stack to ensure there are // enough stack items available to perform the operation. op = contract.GetOp(pc) - operation := in.table[op] + operation := jumpTable[op] cost = operation.constantGas // For tracing // Validate stack if sLen := stack.len(); sLen < operation.minStack { diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index 0b93dd59e7e0..8ed512316bc9 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -18,6 +18,7 @@ package vm import ( "math" + "math/big" "testing" "time" @@ -74,3 +75,22 @@ func TestLoopInterrupt(t *testing.T) { } } } + +func BenchmarkInterpreter(b *testing.B) { + var ( + statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + evm = NewEVM(BlockContext{BlockNumber: big.NewInt(1), Time: 1, Random: &common.Hash{}}, statedb, params.MergedTestChainConfig, Config{}) + startGas uint64 = 100_000_000 + value = uint256.NewInt(0) + stack = newstack() + mem = NewMemory() + contract = NewContract(common.Address{}, common.Address{}, value, startGas, nil) + ) + stack.push(uint256.NewInt(123)) + stack.push(uint256.NewInt(123)) + gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529) + b.ResetTimer() + for i := 0; i < b.N; i++ { + gasSStoreEIP3529(evm, contract, stack, mem, 1234) + } +} diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 26b9473fe843..22eed8754fed 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -62,7 +62,7 @@ var ( cancunInstructionSet = newCancunInstructionSet() verkleInstructionSet = newVerkleInstructionSet() pragueInstructionSet = newPragueInstructionSet() - eofInstructionSet = newEOFInstructionSetForTesting() + osakaInstructionSet = newOsakaInstructionSet() ) // JumpTable contains the EVM opcodes supported at a given fork. @@ -92,13 +92,9 @@ func newVerkleInstructionSet() JumpTable { return validate(instructionSet) } -func NewEOFInstructionSetForTesting() JumpTable { - return newEOFInstructionSetForTesting() -} - -func newEOFInstructionSetForTesting() JumpTable { +func newOsakaInstructionSet() JumpTable { instructionSet := newPragueInstructionSet() - enableEOF(&instructionSet) + enable7939(&instructionSet) // EIP-7939 (CLZ opcode) return validate(instructionSet) } diff --git a/core/vm/jump_table_export.go b/core/vm/jump_table_export.go index b8fa6049bb41..89a2ebf6f4f1 100644 --- a/core/vm/jump_table_export.go +++ b/core/vm/jump_table_export.go @@ -29,7 +29,7 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) { case rules.IsVerkle: return newCancunInstructionSet(), errors.New("verkle-fork not defined yet") case rules.IsOsaka: - return newPragueInstructionSet(), errors.New("osaka-fork not defined yet") + return newOsakaInstructionSet(), nil case rules.IsPrague: return newPragueInstructionSet(), nil case rules.IsCancun: diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go index 28746042cf3b..63ad9678501e 100644 --- a/core/vm/memory_table.go +++ b/core/vm/memory_table.go @@ -120,19 +120,3 @@ func memoryRevert(stack *Stack) (uint64, bool) { func memoryLog(stack *Stack) (uint64, bool) { return calcMemSize64(stack.Back(0), stack.Back(1)) } - -func memoryExtCall(stack *Stack) (uint64, bool) { - return calcMemSize64(stack.Back(1), stack.Back(2)) -} - -func memoryDataCopy(stack *Stack) (uint64, bool) { - return calcMemSize64(stack.Back(0), stack.Back(2)) -} - -func memoryEOFCreate(stack *Stack) (uint64, bool) { - return calcMemSize64(stack.Back(2), stack.Back(3)) -} - -func memoryReturnContract(stack *Stack) (uint64, bool) { - return calcMemSize64(stack.Back(0), stack.Back(1)) -} diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index 0820b20fb117..9a32126a80b7 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -62,6 +62,7 @@ const ( SHL OpCode = 0x1b SHR OpCode = 0x1c SAR OpCode = 0x1d + CLZ OpCode = 0x1e ) // 0x20 range - crypto. @@ -282,6 +283,7 @@ var opCodeToString = [256]string{ SHL: "SHL", SHR: "SHR", SAR: "SAR", + CLZ: "CLZ", ADDMOD: "ADDMOD", MULMOD: "MULMOD", @@ -484,6 +486,7 @@ var stringToOp = map[string]OpCode{ "SHL": SHL, "SHR": SHR, "SAR": SAR, + "CLZ": CLZ, "ADDMOD": ADDMOD, "MULMOD": MULMOD, "KECCAK256": KECCAK256, diff --git a/core/vm/operations_acl.go b/core/vm/operations_acl.go index ff3875868f56..085b018e4c42 100644 --- a/core/vm/operations_acl.go +++ b/core/vm/operations_acl.go @@ -34,10 +34,10 @@ func makeGasSStoreFunc(clearingRefund uint64) gasFunc { } // Gas sentry honoured, do the actual gas calculation based on the stored value var ( - y, x = stack.Back(1), stack.peek() - slot = common.Hash(x.Bytes32()) - current = evm.StateDB.GetState(contract.Address(), slot) - cost = uint64(0) + y, x = stack.Back(1), stack.peek() + slot = common.Hash(x.Bytes32()) + current, original = evm.StateDB.GetStateAndCommittedState(contract.Address(), slot) + cost = uint64(0) ) // Check slot presence in the access list if _, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent { @@ -52,7 +52,6 @@ func makeGasSStoreFunc(clearingRefund uint64) gasFunc { // return params.SloadGasEIP2200, nil return cost + params.WarmStorageReadCostEIP2929, nil // SLOAD_GAS } - original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32()) if original == current { if original == (common.Hash{}) { // create slot (2.1.1) return cost + params.SstoreSetGasEIP2200, nil diff --git a/core/vm/testdata/precompiles/p256Verify.json b/core/vm/testdata/precompiles/p256Verify.json new file mode 100644 index 000000000000..30b4e37ba911 --- /dev/null +++ b/core/vm/testdata/precompiles/p256Verify.json @@ -0,0 +1,5476 @@ +[ + { + "Input": "4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "CallP256Verify", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd762927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #1: signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #3: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #5: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b8252927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #8: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #9: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #10: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #11: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #12: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #13: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #14: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #15: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #16: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #17: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #18: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #19: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #20: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #21: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #22: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #23: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #24: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #25: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #26: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #27: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #28: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #29: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #30: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #31: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #32: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #33: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #34: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #35: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #36: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #37: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #38: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #39: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #40: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #41: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #42: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #43: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #44: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #45: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #46: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #47: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #48: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #49: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #50: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #51: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #52: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #53: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #54: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #55: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #56: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #57: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "70239dd877f7c944c422f44dea4ed1a52f2627416faf2f072fa50c772ed6f80764a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #58: Edge case for Shamir multiplication", + "NoBenchmark": false + }, + { + "Input": "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #59: special case hash", + "NoBenchmark": false + }, + { + "Input": "7300000000213f2a525c6035725235c2f696ad3ebb5ee47f140697ad25770d919cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c322927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #60: special case hash", + "NoBenchmark": false + }, + { + "Input": "ddf2000000005e0be0635b245f0b97978afd25daadeb3edb4a0161c27fe0604573b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c886342927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #61: special case hash", + "NoBenchmark": false + }, + { + "Input": "67ab1900000000784769c4ecb9e164d6642b8499588b89855be1ec355d0841a0bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #62: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2bf09460000000076d7dbeffe125eaf02095dff252ee905e296b6350fc311cf204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #63: special case hash", + "NoBenchmark": false + }, + { + "Input": "3554e827c700000000e1e75e624a06b3a0a353171160858129e15c544e4f0e65ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #64: special case hash", + "NoBenchmark": false + }, + { + "Input": "9b6cd3b812610000000026941a0f0bb53255ea4c9fd0cb3426e3a54b9fc6965c060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d36102927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #65: special case hash", + "NoBenchmark": false + }, + { + "Input": "883ae39f50bf0100000000e7561c26fc82a52baa51c71ca877162f93c4ae01869f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e99022927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #66: special case hash", + "NoBenchmark": false + }, + { + "Input": "a1ce5d6e5ecaf28b0000000000fa7cd010540f420fb4ff7401fe9fce011d0ba6a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #67: special case hash", + "NoBenchmark": false + }, + { + "Input": "8ea5f645f373f580930000000038345397330012a8ee836c5494cdffd5ee8054fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d213502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #68: special case hash", + "NoBenchmark": false + }, + { + "Input": "660570d323e9f75fa734000000008792d65ce93eabb7d60d8d9c1bbdcb5ef305b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff22927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #69: special case hash", + "NoBenchmark": false + }, + { + "Input": "d0462673154cce587dde8800000000e98d35f1f45cf9c3bf46ada2de4c568c343b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d992582927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #70: special case hash", + "NoBenchmark": false + }, + { + "Input": "bd90640269a7822680cedfef000000000caef15a6171059ab83e7b4418d7278f30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #71: special case hash", + "NoBenchmark": false + }, + { + "Input": "33239a52d72f1311512e41222a00000000d2dcceb301c54b4beae8e284788a7338686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #72: special case hash", + "NoBenchmark": false + }, + { + "Input": "b8d64fbcd4a1c10f1365d4e6d95c000000007ee4a21a1cbe1dc84c2d941ffaf144a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e862927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #73: special case hash", + "NoBenchmark": false + }, + { + "Input": "01603d3982bf77d7a3fef3183ed092000000003a227420db4088b20fe0e9d84a2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #74: special case hash", + "NoBenchmark": false + }, + { + "Input": "9ea6994f1e0384c8599aa02e6cf66d9c000000004d89ef50b7e9eb0cfbff7363bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #75: special case hash", + "NoBenchmark": false + }, + { + "Input": "d03215a8401bcf16693979371a01068a4700000000e2fa5bf692bc670905b18c50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab2447262927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #76: special case hash", + "NoBenchmark": false + }, + { + "Input": "307bfaaffb650c889c84bf83f0300e5dc87e000000008408fd5f64b582e3bb14f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #77: special case hash", + "NoBenchmark": false + }, + { + "Input": "bab5c4f4df540d7b33324d36bb0c157551527c00000000e4af574bb4d54ea6b89505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c50212927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #78: special case hash", + "NoBenchmark": false + }, + { + "Input": "d4ba47f6ae28f274e4f58d8036f9c36ec2456f5b00000000c3b869197ef5e15ebbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #79: special case hash", + "NoBenchmark": false + }, + { + "Input": "79fd19c7235ea212f29f1fa00984342afe0f10aafd00000000801e47f8c184e12ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a198782927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #80: special case hash", + "NoBenchmark": false + }, + { + "Input": "8c291e8eeaa45adbaf9aba5c0583462d79cbeb7ac97300000000a37ea6700cda54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #81: special case hash", + "NoBenchmark": false + }, + { + "Input": "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #82: special case hash", + "NoBenchmark": false + }, + { + "Input": "e02716d01fb23a5a0068399bf01bab42ef17c6d96e13846c00000000afc0f89d207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf75927672927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #83: special case hash", + "NoBenchmark": false + }, + { + "Input": "9eb0bf583a1a6b9a194e9a16bc7dab2a9061768af89d00659a00000000fc7de16554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f9292927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #84: special case hash", + "NoBenchmark": false + }, + { + "Input": "62aac98818b3b84a2c214f0d5e72ef286e1030cb53d9a82b690e00000000cd15a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #85: special case hash", + "NoBenchmark": false + }, + { + "Input": "3760a7f37cf96218f29ae43732e513efd2b6f552ea4b6895464b9300000000c8975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf9196222927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #86: special case hash", + "NoBenchmark": false + }, + { + "Input": "0da0a1d2851d33023834f2098c0880096b4320bea836cd9cbb6ff6c8000000005694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa42927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #87: special case hash", + "NoBenchmark": false + }, + { + "Input": "ffffffff293886d3086fd567aafd598f0fe975f735887194a764a231e82d289aa0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c654243392927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #88: special case hash", + "NoBenchmark": false + }, + { + "Input": "7bffffffff2376d1e3c03445a072e24326acdc4ce127ec2e0e8d9ca99527e7b7614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #89: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2b5ffffffffebb251b085377605a224bc80872602a6e467fd016807e97fa395bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #90: special case hash", + "NoBenchmark": false + }, + { + "Input": "641227ffffffff6f1b96fa5f097fcf3cc1a3c256870d45a67b83d0967d4b20c0499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d6932927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #91: special case hash", + "NoBenchmark": false + }, + { + "Input": "958415d8ffffffffabad03e2fc662dc3ba203521177502298df56f36600e0f8b08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #92: special case hash", + "NoBenchmark": false + }, + { + "Input": "f1d8de4858ffffffff1281093536f47fe13deb04e1fbe8fb954521b6975420f8be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c892927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #93: special case hash", + "NoBenchmark": false + }, + { + "Input": "0927895f2802ffffffff10782dd14a3b32dc5d47c05ef6f1876b95c81fc31def15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a19391232927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #94: special case hash", + "NoBenchmark": false + }, + { + "Input": "60907984aa7e8effffffff4f332862a10a57c3063fb5a30624cf6a0c3ac80589352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c62927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #95: special case hash", + "NoBenchmark": false + }, + { + "Input": "c6ff198484939170ffffffff0af42cda50f9a5f50636ea6942d6b9b8cd6ae1e24a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc59817257822927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #96: special case hash", + "NoBenchmark": false + }, + { + "Input": "de030419345ca15c75ffffffff8074799b9e0956cc43135d16dfbe4d27d7e68deacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d12927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #97: special case hash", + "NoBenchmark": false + }, + { + "Input": "6f0e3eeaf42b28132b88fffffffff6c8665604d34acb19037e1ab78caaaac6ff2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #98: special case hash", + "NoBenchmark": false + }, + { + "Input": "cdb549f773b3e62b3708d1ffffffffbe48f7c0591ddcae7d2cb222d1f8017ab9ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #99: special case hash", + "NoBenchmark": false + }, + { + "Input": "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #100: special case hash", + "NoBenchmark": false + }, + { + "Input": "ac18f8418c55a2502cb7d53f9affffffff5c31d89fda6a6b8476397c04edf411dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #101: special case hash", + "NoBenchmark": false + }, + { + "Input": "4f9618f98e2d3a15b24094f72bb5ffffffffa2fd3e2893683e5a6ab8cf0ee610ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c1993452927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #102: special case hash", + "NoBenchmark": false + }, + { + "Input": "422e82a3d56ed10a9cc21d31d37a25ffffffff67edf7c40204caae73ab0bc75aac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a82927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #103: special case hash", + "NoBenchmark": false + }, + { + "Input": "7075d245ccc3281b6e7b329ff738fbb417a5ffffffffa0842d9890b5cf95d018677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db552927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #104: special case hash", + "NoBenchmark": false + }, + { + "Input": "3c80de54cd9226989443d593fa4fd6597e280ebeffffffffc1847eb76c217a95479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b24432927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #105: special case hash", + "NoBenchmark": false + }, + { + "Input": "de21754e29b85601980bef3d697ea2770ce891a8cdffffffffc7906aa794b39b43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f495843897722927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #106: special case hash", + "NoBenchmark": false + }, + { + "Input": "8f65d92927cfb86a84dd59623fb531bb599e4d5f7289ffffffff2f1f2f57881c5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d752927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #107: special case hash", + "NoBenchmark": false + }, + { + "Input": "6b63e9a74e092120160bea3877dace8a2cc7cd0e8426cbfffffffffafc8c3ca85e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c202927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #108: special case hash", + "NoBenchmark": false + }, + { + "Input": "fc28259702a03845b6d75219444e8b43d094586e249c8699ffffffffe852512e0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #109: special case hash", + "NoBenchmark": false + }, + { + "Input": "1273b4502ea4e3bccee044ee8e8db7f774ecbcd52e8ceb571757ffffffffe20a7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #110: special case hash", + "NoBenchmark": false + }, + { + "Input": "08fb565610a79baa0c566c66228d81814f8c53a15b96e602fb49ffffffffff6e7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #111: special case hash", + "NoBenchmark": false + }, + { + "Input": "d59291cc2cf89f3087715fcb1aa4e79aa2403f748e97d7cd28ecaefeffffffff914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #112: special case hash", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #114: r too large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254eab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #115: r,s are large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #116: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a54201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #117: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #118: small r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000036627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #120: small r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000055a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #122: small r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #124: small r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325560000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea88d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7a4838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4d7393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b5ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b1d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c70083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #133: r and s^-1 are close to n", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000018aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #134: s == 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000008aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #135: s == 0", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c70b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #136: point at infinity during verify", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #137: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a968ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #138: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502369da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #139: u1 == 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52ed8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #140: u1 == n - 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c703623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #141: u2 == 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #142: u2 == n - 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde91e1ba60fdedb76a46bcb51dc0b8b4b7e019f0a28721885fa5d3a8196623397db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #143: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdea5843ffeb73af94313ba4831b53fe24f799e525b1e8e8c87b59b95b430ad9dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #144: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03ffcabf2f1b4d2a65190db1680d62bb994e41c5251cd73b3c3dfc5e5bafc035d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #145: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4dfbc401f971cd304b33dfdb17d0fed0fe4c1a88ae648e0d2847f74977534989a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #146: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbc4024761cd2ffd43dfdb17d0fed112b988977055cd3a8e54971eba9cda5ca71c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #147: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd788048ed39a5ffa77bfb62fa1fda2257742bf35d128fb3459f2a0c909ee86f915eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #148: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd476d9131fd381bd917d0fed112bc9e0a5924b5ed5b11167edd8b23582b3cb15e5caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #149: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8374253e3e21bd154448d0a8f640fe46fafa8b19ce78d538f6cc0a19662d3601c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #150: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd357cfd3be4d01d413c5b9ede36cba5452c11ee7fe14879e749ae6a2d897a52d63fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #151: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd29798c5c0ee287d4a5e8e6b799fd86b8df5225298e6ffc807cd2f2bc27a0a6d89cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #152: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0b70f22c781092452dca1a5711fa3a5a1f72add1bf52c2ff7cae4820b30078dda3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #153: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd16e1e458f021248a5b9434ae23f474b43ee55ba37ea585fef95c90416600f1baf19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #154: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2252d6856831b6cf895e4f0535eeaf0e5e5809753df848fe760ad86219016a9783a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #155: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd81ffe55f178da695b28c86d8b406b15dab1a9e39661a3ae017fbe390ac0972c3dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #156: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a67e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #157: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f22eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #158: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851e84db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #159: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf291b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #160: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb3669f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #161: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #162: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86000a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #163: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad3d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #164: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f4836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #165: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b0992f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #166: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #167: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e378651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #168: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa6d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #169: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f0ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #170: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #171: point duplication during verification", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #172: duplication bug", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c706adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #175: comparison with point at infinity ", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c704fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #176: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63ccc6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #177: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #178: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaf6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #179: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #180: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb0d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #181: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c705e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #182: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #183: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #184: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa3d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #185: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #186: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb8d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #187: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #188: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #189: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #190: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #191: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e204aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #192: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "dc1921946f4af96a2856e7be399007c9e807bdf4c5332f19f59ec9dd1bb8c7b3530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e904aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #193: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b8604aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #194: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #195: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #196: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f910fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df557374f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #197: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb556774f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #198: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #199: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f914cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe33cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #200: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b553cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #201: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f911158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f2855193cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #202: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a12513363cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #203: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #204: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd1399292829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #205: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f915eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb52829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #206: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #207: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #208: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dbafffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #209: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #210: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb300000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #211: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f916b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #212: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #213: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #214: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #215: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f917e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aabcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #216: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #217: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #218: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #219: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd762927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #1: signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #2: Legacy:ASN encoding of s misses leading 0", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #3: valid", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502329a3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #118: modify first byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e98b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #120: modify last byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568475b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #121: modify last byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1800b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568472927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #124: truncated integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #133: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #134: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #137: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f47aa2bbd0a4c384ee1493b1f518ada018ef05465583885980861905228a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #139: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b8252927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #143: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #177: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #178: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #179: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #180: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #181: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #187: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #188: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #189: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #190: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #191: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #197: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #198: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #199: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #200: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #201: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #207: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #208: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #209: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #210: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #211: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #217: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #218: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #219: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #220: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #221: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "70239dd877f7c944c422f44dea4ed1a52f2627416faf2f072fa50c772ed6f80764a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #230: Edge case for Shamir multiplication", + "NoBenchmark": false + }, + { + "Input": "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #231: special case hash", + "NoBenchmark": false + }, + { + "Input": "7300000000213f2a525c6035725235c2f696ad3ebb5ee47f140697ad25770d919cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c322927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #232: special case hash", + "NoBenchmark": false + }, + { + "Input": "ddf2000000005e0be0635b245f0b97978afd25daadeb3edb4a0161c27fe0604573b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c886342927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #233: special case hash", + "NoBenchmark": false + }, + { + "Input": "67ab1900000000784769c4ecb9e164d6642b8499588b89855be1ec355d0841a0bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #234: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2bf09460000000076d7dbeffe125eaf02095dff252ee905e296b6350fc311cf204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #235: special case hash", + "NoBenchmark": false + }, + { + "Input": "3554e827c700000000e1e75e624a06b3a0a353171160858129e15c544e4f0e65ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #236: special case hash", + "NoBenchmark": false + }, + { + "Input": "9b6cd3b812610000000026941a0f0bb53255ea4c9fd0cb3426e3a54b9fc6965c060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d36102927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #237: special case hash", + "NoBenchmark": false + }, + { + "Input": "883ae39f50bf0100000000e7561c26fc82a52baa51c71ca877162f93c4ae01869f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e99022927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #238: special case hash", + "NoBenchmark": false + }, + { + "Input": "a1ce5d6e5ecaf28b0000000000fa7cd010540f420fb4ff7401fe9fce011d0ba6a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #239: special case hash", + "NoBenchmark": false + }, + { + "Input": "8ea5f645f373f580930000000038345397330012a8ee836c5494cdffd5ee8054fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d213502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #240: special case hash", + "NoBenchmark": false + }, + { + "Input": "660570d323e9f75fa734000000008792d65ce93eabb7d60d8d9c1bbdcb5ef305b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff22927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #241: special case hash", + "NoBenchmark": false + }, + { + "Input": "d0462673154cce587dde8800000000e98d35f1f45cf9c3bf46ada2de4c568c343b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d992582927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #242: special case hash", + "NoBenchmark": false + }, + { + "Input": "bd90640269a7822680cedfef000000000caef15a6171059ab83e7b4418d7278f30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #243: special case hash", + "NoBenchmark": false + }, + { + "Input": "33239a52d72f1311512e41222a00000000d2dcceb301c54b4beae8e284788a7338686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #244: special case hash", + "NoBenchmark": false + }, + { + "Input": "b8d64fbcd4a1c10f1365d4e6d95c000000007ee4a21a1cbe1dc84c2d941ffaf144a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e862927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #245: special case hash", + "NoBenchmark": false + }, + { + "Input": "01603d3982bf77d7a3fef3183ed092000000003a227420db4088b20fe0e9d84a2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #246: special case hash", + "NoBenchmark": false + }, + { + "Input": "9ea6994f1e0384c8599aa02e6cf66d9c000000004d89ef50b7e9eb0cfbff7363bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #247: special case hash", + "NoBenchmark": false + }, + { + "Input": "d03215a8401bcf16693979371a01068a4700000000e2fa5bf692bc670905b18c50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab2447262927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #248: special case hash", + "NoBenchmark": false + }, + { + "Input": "307bfaaffb650c889c84bf83f0300e5dc87e000000008408fd5f64b582e3bb14f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #249: special case hash", + "NoBenchmark": false + }, + { + "Input": "bab5c4f4df540d7b33324d36bb0c157551527c00000000e4af574bb4d54ea6b89505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c50212927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #250: special case hash", + "NoBenchmark": false + }, + { + "Input": "d4ba47f6ae28f274e4f58d8036f9c36ec2456f5b00000000c3b869197ef5e15ebbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #251: special case hash", + "NoBenchmark": false + }, + { + "Input": "79fd19c7235ea212f29f1fa00984342afe0f10aafd00000000801e47f8c184e12ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a198782927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #252: special case hash", + "NoBenchmark": false + }, + { + "Input": "8c291e8eeaa45adbaf9aba5c0583462d79cbeb7ac97300000000a37ea6700cda54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #253: special case hash", + "NoBenchmark": false + }, + { + "Input": "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #254: special case hash", + "NoBenchmark": false + }, + { + "Input": "e02716d01fb23a5a0068399bf01bab42ef17c6d96e13846c00000000afc0f89d207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf75927672927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #255: special case hash", + "NoBenchmark": false + }, + { + "Input": "9eb0bf583a1a6b9a194e9a16bc7dab2a9061768af89d00659a00000000fc7de16554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f9292927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #256: special case hash", + "NoBenchmark": false + }, + { + "Input": "62aac98818b3b84a2c214f0d5e72ef286e1030cb53d9a82b690e00000000cd15a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #257: special case hash", + "NoBenchmark": false + }, + { + "Input": "3760a7f37cf96218f29ae43732e513efd2b6f552ea4b6895464b9300000000c8975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf9196222927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #258: special case hash", + "NoBenchmark": false + }, + { + "Input": "0da0a1d2851d33023834f2098c0880096b4320bea836cd9cbb6ff6c8000000005694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa42927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #259: special case hash", + "NoBenchmark": false + }, + { + "Input": "ffffffff293886d3086fd567aafd598f0fe975f735887194a764a231e82d289aa0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c654243392927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #260: special case hash", + "NoBenchmark": false + }, + { + "Input": "7bffffffff2376d1e3c03445a072e24326acdc4ce127ec2e0e8d9ca99527e7b7614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #261: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2b5ffffffffebb251b085377605a224bc80872602a6e467fd016807e97fa395bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #262: special case hash", + "NoBenchmark": false + }, + { + "Input": "641227ffffffff6f1b96fa5f097fcf3cc1a3c256870d45a67b83d0967d4b20c0499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d6932927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #263: special case hash", + "NoBenchmark": false + }, + { + "Input": "958415d8ffffffffabad03e2fc662dc3ba203521177502298df56f36600e0f8b08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #264: special case hash", + "NoBenchmark": false + }, + { + "Input": "f1d8de4858ffffffff1281093536f47fe13deb04e1fbe8fb954521b6975420f8be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c892927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #265: special case hash", + "NoBenchmark": false + }, + { + "Input": "0927895f2802ffffffff10782dd14a3b32dc5d47c05ef6f1876b95c81fc31def15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a19391232927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #266: special case hash", + "NoBenchmark": false + }, + { + "Input": "60907984aa7e8effffffff4f332862a10a57c3063fb5a30624cf6a0c3ac80589352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c62927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #267: special case hash", + "NoBenchmark": false + }, + { + "Input": "c6ff198484939170ffffffff0af42cda50f9a5f50636ea6942d6b9b8cd6ae1e24a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc59817257822927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #268: special case hash", + "NoBenchmark": false + }, + { + "Input": "de030419345ca15c75ffffffff8074799b9e0956cc43135d16dfbe4d27d7e68deacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d12927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #269: special case hash", + "NoBenchmark": false + }, + { + "Input": "6f0e3eeaf42b28132b88fffffffff6c8665604d34acb19037e1ab78caaaac6ff2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #270: special case hash", + "NoBenchmark": false + }, + { + "Input": "cdb549f773b3e62b3708d1ffffffffbe48f7c0591ddcae7d2cb222d1f8017ab9ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #271: special case hash", + "NoBenchmark": false + }, + { + "Input": "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #272: special case hash", + "NoBenchmark": false + }, + { + "Input": "ac18f8418c55a2502cb7d53f9affffffff5c31d89fda6a6b8476397c04edf411dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #273: special case hash", + "NoBenchmark": false + }, + { + "Input": "4f9618f98e2d3a15b24094f72bb5ffffffffa2fd3e2893683e5a6ab8cf0ee610ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c1993452927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #274: special case hash", + "NoBenchmark": false + }, + { + "Input": "422e82a3d56ed10a9cc21d31d37a25ffffffff67edf7c40204caae73ab0bc75aac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a82927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #275: special case hash", + "NoBenchmark": false + }, + { + "Input": "7075d245ccc3281b6e7b329ff738fbb417a5ffffffffa0842d9890b5cf95d018677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db552927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #276: special case hash", + "NoBenchmark": false + }, + { + "Input": "3c80de54cd9226989443d593fa4fd6597e280ebeffffffffc1847eb76c217a95479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b24432927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #277: special case hash", + "NoBenchmark": false + }, + { + "Input": "de21754e29b85601980bef3d697ea2770ce891a8cdffffffffc7906aa794b39b43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f495843897722927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #278: special case hash", + "NoBenchmark": false + }, + { + "Input": "8f65d92927cfb86a84dd59623fb531bb599e4d5f7289ffffffff2f1f2f57881c5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d752927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #279: special case hash", + "NoBenchmark": false + }, + { + "Input": "6b63e9a74e092120160bea3877dace8a2cc7cd0e8426cbfffffffffafc8c3ca85e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c202927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #280: special case hash", + "NoBenchmark": false + }, + { + "Input": "fc28259702a03845b6d75219444e8b43d094586e249c8699ffffffffe852512e0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #281: special case hash", + "NoBenchmark": false + }, + { + "Input": "1273b4502ea4e3bccee044ee8e8db7f774ecbcd52e8ceb571757ffffffffe20a7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #282: special case hash", + "NoBenchmark": false + }, + { + "Input": "08fb565610a79baa0c566c66228d81814f8c53a15b96e602fb49ffffffffff6e7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #283: special case hash", + "NoBenchmark": false + }, + { + "Input": "d59291cc2cf89f3087715fcb1aa4e79aa2403f748e97d7cd28ecaefeffffffff914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #284: special case hash", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #286: r too large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254eab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #287: r,s are large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #288: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a54201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #289: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c70083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #301: r and s^-1 are close to n", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c70b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #304: point at infinity during verify", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #305: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a968ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #306: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502369da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #307: u1 == 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52ed8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #308: u1 == n - 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c703623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #309: u2 == 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #310: u2 == n - 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde91e1ba60fdedb76a46bcb51dc0b8b4b7e019f0a28721885fa5d3a8196623397db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #311: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdea5843ffeb73af94313ba4831b53fe24f799e525b1e8e8c87b59b95b430ad9dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #312: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03ffcabf2f1b4d2a65190db1680d62bb994e41c5251cd73b3c3dfc5e5bafc035d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #313: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4dfbc401f971cd304b33dfdb17d0fed0fe4c1a88ae648e0d2847f74977534989a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #314: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbc4024761cd2ffd43dfdb17d0fed112b988977055cd3a8e54971eba9cda5ca71c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #315: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd788048ed39a5ffa77bfb62fa1fda2257742bf35d128fb3459f2a0c909ee86f915eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #316: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd476d9131fd381bd917d0fed112bc9e0a5924b5ed5b11167edd8b23582b3cb15e5caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #317: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8374253e3e21bd154448d0a8f640fe46fafa8b19ce78d538f6cc0a19662d3601c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #318: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd357cfd3be4d01d413c5b9ede36cba5452c11ee7fe14879e749ae6a2d897a52d63fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #319: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd29798c5c0ee287d4a5e8e6b799fd86b8df5225298e6ffc807cd2f2bc27a0a6d89cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #320: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0b70f22c781092452dca1a5711fa3a5a1f72add1bf52c2ff7cae4820b30078dda3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #321: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd16e1e458f021248a5b9434ae23f474b43ee55ba37ea585fef95c90416600f1baf19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #322: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2252d6856831b6cf895e4f0535eeaf0e5e5809753df848fe760ad86219016a9783a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #323: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd81ffe55f178da695b28c86d8b406b15dab1a9e39661a3ae017fbe390ac0972c3dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #324: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a67e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #325: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f22eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #326: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851e84db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #327: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf291b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #328: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb3669f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #329: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #330: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86000a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #331: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad3d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #332: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f4836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #333: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b0992f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #334: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #335: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e378651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #336: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa6d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #337: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f0ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #338: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #339: point duplication during verification", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #340: duplication bug", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #343: comparison with point at infinity ", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c704fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #344: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63ccc6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #345: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #346: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaf6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #347: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #348: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb0d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #349: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c705e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #350: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #351: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #352: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa3d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #353: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #354: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb8d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #355: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #356: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #357: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #358: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #359: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e204aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #360: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "dc1921946f4af96a2856e7be399007c9e807bdf4c5332f19f59ec9dd1bb8c7b3530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e904aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #361: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b8604aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #362: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #363: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #364: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f910fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df557374f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #365: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb556774f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #366: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #367: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f914cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe33cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #368: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b553cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #369: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f911158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f2855193cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #370: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a12513363cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #371: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #372: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd1399292829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #373: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f915eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb52829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #374: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #375: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #376: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dbafffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #377: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #378: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb300000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #379: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f916b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #380: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #381: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #382: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #383: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f917e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aabcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #384: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #385: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #386: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #387: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd762927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1: signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #2: Legacy:ASN encoding of s misses leading 0", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #3: valid", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502329a3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #118: modify first byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e98b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #120: modify last byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568475b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #121: modify last byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1800b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568472927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #124: truncated integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #133: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #134: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #137: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f47aa2bbd0a4c384ee1493b1f518ada018ef05465583885980861905228a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #139: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b8252927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #143: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #177: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #178: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #179: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #180: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #181: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #187: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #188: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #189: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #190: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #191: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #197: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #198: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #199: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #200: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #201: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #207: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #208: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #209: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #210: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #211: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #217: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #218: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #219: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #220: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #221: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "70239dd877f7c944c422f44dea4ed1a52f2627416faf2f072fa50c772ed6f80764a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #230: Edge case for Shamir multiplication", + "NoBenchmark": false + }, + { + "Input": "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #231: special case hash", + "NoBenchmark": false + }, + { + "Input": "7300000000213f2a525c6035725235c2f696ad3ebb5ee47f140697ad25770d919cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c322927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #232: special case hash", + "NoBenchmark": false + }, + { + "Input": "ddf2000000005e0be0635b245f0b97978afd25daadeb3edb4a0161c27fe0604573b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c886342927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #233: special case hash", + "NoBenchmark": false + }, + { + "Input": "67ab1900000000784769c4ecb9e164d6642b8499588b89855be1ec355d0841a0bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #234: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2bf09460000000076d7dbeffe125eaf02095dff252ee905e296b6350fc311cf204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #235: special case hash", + "NoBenchmark": false + }, + { + "Input": "3554e827c700000000e1e75e624a06b3a0a353171160858129e15c544e4f0e65ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #236: special case hash", + "NoBenchmark": false + }, + { + "Input": "9b6cd3b812610000000026941a0f0bb53255ea4c9fd0cb3426e3a54b9fc6965c060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d36102927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #237: special case hash", + "NoBenchmark": false + }, + { + "Input": "883ae39f50bf0100000000e7561c26fc82a52baa51c71ca877162f93c4ae01869f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e99022927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #238: special case hash", + "NoBenchmark": false + }, + { + "Input": "a1ce5d6e5ecaf28b0000000000fa7cd010540f420fb4ff7401fe9fce011d0ba6a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #239: special case hash", + "NoBenchmark": false + }, + { + "Input": "8ea5f645f373f580930000000038345397330012a8ee836c5494cdffd5ee8054fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d213502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #240: special case hash", + "NoBenchmark": false + }, + { + "Input": "660570d323e9f75fa734000000008792d65ce93eabb7d60d8d9c1bbdcb5ef305b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff22927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #241: special case hash", + "NoBenchmark": false + }, + { + "Input": "d0462673154cce587dde8800000000e98d35f1f45cf9c3bf46ada2de4c568c343b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d992582927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #242: special case hash", + "NoBenchmark": false + }, + { + "Input": "bd90640269a7822680cedfef000000000caef15a6171059ab83e7b4418d7278f30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #243: special case hash", + "NoBenchmark": false + }, + { + "Input": "33239a52d72f1311512e41222a00000000d2dcceb301c54b4beae8e284788a7338686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #244: special case hash", + "NoBenchmark": false + }, + { + "Input": "b8d64fbcd4a1c10f1365d4e6d95c000000007ee4a21a1cbe1dc84c2d941ffaf144a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e862927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #245: special case hash", + "NoBenchmark": false + }, + { + "Input": "01603d3982bf77d7a3fef3183ed092000000003a227420db4088b20fe0e9d84a2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #246: special case hash", + "NoBenchmark": false + }, + { + "Input": "9ea6994f1e0384c8599aa02e6cf66d9c000000004d89ef50b7e9eb0cfbff7363bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #247: special case hash", + "NoBenchmark": false + }, + { + "Input": "d03215a8401bcf16693979371a01068a4700000000e2fa5bf692bc670905b18c50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab2447262927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #248: special case hash", + "NoBenchmark": false + }, + { + "Input": "307bfaaffb650c889c84bf83f0300e5dc87e000000008408fd5f64b582e3bb14f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #249: special case hash", + "NoBenchmark": false + }, + { + "Input": "bab5c4f4df540d7b33324d36bb0c157551527c00000000e4af574bb4d54ea6b89505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c50212927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #250: special case hash", + "NoBenchmark": false + }, + { + "Input": "d4ba47f6ae28f274e4f58d8036f9c36ec2456f5b00000000c3b869197ef5e15ebbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #251: special case hash", + "NoBenchmark": false + }, + { + "Input": "79fd19c7235ea212f29f1fa00984342afe0f10aafd00000000801e47f8c184e12ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a198782927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #252: special case hash", + "NoBenchmark": false + }, + { + "Input": "8c291e8eeaa45adbaf9aba5c0583462d79cbeb7ac97300000000a37ea6700cda54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #253: special case hash", + "NoBenchmark": false + }, + { + "Input": "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #254: special case hash", + "NoBenchmark": false + }, + { + "Input": "e02716d01fb23a5a0068399bf01bab42ef17c6d96e13846c00000000afc0f89d207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf75927672927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #255: special case hash", + "NoBenchmark": false + }, + { + "Input": "9eb0bf583a1a6b9a194e9a16bc7dab2a9061768af89d00659a00000000fc7de16554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f9292927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #256: special case hash", + "NoBenchmark": false + }, + { + "Input": "62aac98818b3b84a2c214f0d5e72ef286e1030cb53d9a82b690e00000000cd15a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #257: special case hash", + "NoBenchmark": false + }, + { + "Input": "3760a7f37cf96218f29ae43732e513efd2b6f552ea4b6895464b9300000000c8975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf9196222927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #258: special case hash", + "NoBenchmark": false + }, + { + "Input": "0da0a1d2851d33023834f2098c0880096b4320bea836cd9cbb6ff6c8000000005694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa42927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #259: special case hash", + "NoBenchmark": false + }, + { + "Input": "ffffffff293886d3086fd567aafd598f0fe975f735887194a764a231e82d289aa0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c654243392927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #260: special case hash", + "NoBenchmark": false + }, + { + "Input": "7bffffffff2376d1e3c03445a072e24326acdc4ce127ec2e0e8d9ca99527e7b7614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #261: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2b5ffffffffebb251b085377605a224bc80872602a6e467fd016807e97fa395bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #262: special case hash", + "NoBenchmark": false + }, + { + "Input": "641227ffffffff6f1b96fa5f097fcf3cc1a3c256870d45a67b83d0967d4b20c0499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d6932927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #263: special case hash", + "NoBenchmark": false + }, + { + "Input": "958415d8ffffffffabad03e2fc662dc3ba203521177502298df56f36600e0f8b08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #264: special case hash", + "NoBenchmark": false + }, + { + "Input": "f1d8de4858ffffffff1281093536f47fe13deb04e1fbe8fb954521b6975420f8be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c892927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #265: special case hash", + "NoBenchmark": false + }, + { + "Input": "0927895f2802ffffffff10782dd14a3b32dc5d47c05ef6f1876b95c81fc31def15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a19391232927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #266: special case hash", + "NoBenchmark": false + }, + { + "Input": "60907984aa7e8effffffff4f332862a10a57c3063fb5a30624cf6a0c3ac80589352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c62927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #267: special case hash", + "NoBenchmark": false + }, + { + "Input": "c6ff198484939170ffffffff0af42cda50f9a5f50636ea6942d6b9b8cd6ae1e24a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc59817257822927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #268: special case hash", + "NoBenchmark": false + }, + { + "Input": "de030419345ca15c75ffffffff8074799b9e0956cc43135d16dfbe4d27d7e68deacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d12927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #269: special case hash", + "NoBenchmark": false + }, + { + "Input": "6f0e3eeaf42b28132b88fffffffff6c8665604d34acb19037e1ab78caaaac6ff2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #270: special case hash", + "NoBenchmark": false + }, + { + "Input": "cdb549f773b3e62b3708d1ffffffffbe48f7c0591ddcae7d2cb222d1f8017ab9ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #271: special case hash", + "NoBenchmark": false + }, + { + "Input": "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #272: special case hash", + "NoBenchmark": false + }, + { + "Input": "ac18f8418c55a2502cb7d53f9affffffff5c31d89fda6a6b8476397c04edf411dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #273: special case hash", + "NoBenchmark": false + }, + { + "Input": "4f9618f98e2d3a15b24094f72bb5ffffffffa2fd3e2893683e5a6ab8cf0ee610ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c1993452927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #274: special case hash", + "NoBenchmark": false + }, + { + "Input": "422e82a3d56ed10a9cc21d31d37a25ffffffff67edf7c40204caae73ab0bc75aac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a82927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #275: special case hash", + "NoBenchmark": false + }, + { + "Input": "7075d245ccc3281b6e7b329ff738fbb417a5ffffffffa0842d9890b5cf95d018677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db552927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #276: special case hash", + "NoBenchmark": false + }, + { + "Input": "3c80de54cd9226989443d593fa4fd6597e280ebeffffffffc1847eb76c217a95479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b24432927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #277: special case hash", + "NoBenchmark": false + }, + { + "Input": "de21754e29b85601980bef3d697ea2770ce891a8cdffffffffc7906aa794b39b43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f495843897722927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #278: special case hash", + "NoBenchmark": false + }, + { + "Input": "8f65d92927cfb86a84dd59623fb531bb599e4d5f7289ffffffff2f1f2f57881c5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d752927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #279: special case hash", + "NoBenchmark": false + }, + { + "Input": "6b63e9a74e092120160bea3877dace8a2cc7cd0e8426cbfffffffffafc8c3ca85e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c202927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #280: special case hash", + "NoBenchmark": false + }, + { + "Input": "fc28259702a03845b6d75219444e8b43d094586e249c8699ffffffffe852512e0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #281: special case hash", + "NoBenchmark": false + }, + { + "Input": "1273b4502ea4e3bccee044ee8e8db7f774ecbcd52e8ceb571757ffffffffe20a7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #282: special case hash", + "NoBenchmark": false + }, + { + "Input": "08fb565610a79baa0c566c66228d81814f8c53a15b96e602fb49ffffffffff6e7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #283: special case hash", + "NoBenchmark": false + }, + { + "Input": "d59291cc2cf89f3087715fcb1aa4e79aa2403f748e97d7cd28ecaefeffffffff914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #284: special case hash", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #636: r too large", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e3cd8d2f81d6953b0844c09d7b560d527cd2ef67056893eadafa52c8501387d59ee41fdb4d10402ce7a0c5e3b747adfa3a490b62a6b7719068903485c0bb6dc2d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #637: r,s are large", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd48240cd81edd91cb6936133508c3915100e81f332c4545d41189b481196851378e05b06e72d4a1bff80ea5db514aa2f93ea6dd6d9c0ae27b7837dc432f9ce89d9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #638: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a5b062947356748b0fc17f1704c65aa1dca6e1bfe6779756fa616d91eaad13df2c0b38c17f3d0672e7409cfc5992a99fff12b84a4f8432293b431113f1b2fb579d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #639: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c707a736d8e326a9ca62bbe25a34ea4e3633b499a96afa7aaa3fcf3fd88f8e07edeb3e45879d8622b93e818443a686e869eeda7bf9ae46aa3eafcc48a5934864627", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #651: r and s^-1 are close to n", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c700203736fcb198b15d8d7a0c80f66dddd15259240aa78d08aae67c467de04503434383438d5041ea9a387ee8e4d4e84b4471b160c6bcf2568b072f8f20e87a996", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #654: point at infinity during verify", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a878d844dc7f16b73b1f2a39730da5d8cd99fe2e70a18482384e37dcd2bfea02e1ed6572e01eb7a8d113d02c666c45ef22d3b9a6a6dea99aa43a8183c26e75d336", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #655: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a9dec6c8257dde94110eacc8c09d2e5789cc5beb81a958b02b4d62da9599a7401466fae1614174be63970b83f6524421067b06dd6f4e9c56baca4e344fdd690f1d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #656: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25a17f5b75a35ed64623ca5cbf1f91951292db0c23f0c2ea24c3d0cad0988cabc083a7a618625c228940730b4fa3ee64faecbb2fc20fdde7c58b3a3f6300424dc6", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #657: u1 == 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c04ba0cba291a37db13f33bf90dab628c04ec8393a0200419e9eaa1ebcc9fb5c31f3a0a0e6823a49b625ad57b12a32d4047970fc3428f0f0049ecf4265dc12f62", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #658: u1 == n - 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c70692b6c828e0feed63d8aeaa2b7322f9ccbe8723a1ed39f229f204a434b8900efa1f6f6abcb38ea3b8fde38b98c7c271f274af56a8c5628dc3329069ae4dd5716", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #659: u2 == 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e100cefd9162d13e64cb93687a9cd8f9755ebb5a3ef7632f800f84871874ccef09543ecbeaf7e8044ef721be2fb5f549e4b8480d2587404ebf7dbbef2c54bc0cb1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #660: u2 == n - 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd710f8e3edc7c2d5a3fd23de844002bb949d9f794f6d5405f6d97c1bb03dd2bd2b975183b42551cf52f291d5c1921fd5e12f50c8c85a4beb9de03efa3f0f244862243018e6866df922dc313612020311ff21e242ce3fb15bc78c406b25ab43091", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #661: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdedffbc270f722c243069a7e5f40335a61a58525c7b4db2e7a8e269274ffe4e1bc25f1d166f3e211cdf042a26f8abf6094d48b8d17191d74ed71714927446699965d06dd6a88abfa49e8b4c5da6bb922851969adf9604b5accfb52a114e77ccdb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #662: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffda25adcae105ed7ff4f95d2344e24ee523314c3e178525d007904b68919ba4d538fe5e88243a76e41a004236218a3c3a2d6eee398a23c3a0b008d7f0164cbc0ca98a20d1bdcf573513c7cfd9b83c63e3a82d40127c897697c86b8cb387af7f240", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #663: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2e4348c645707dce6760d773de3f3e87346924b2f64bd3dd0297e766b5805ebb02148256b530fbc470c7b341970b38243ecee6d5a840a37beca2efb37e8dff2cc0adbea0882482a7489ca703a399864ba987eeb6ddb738af53a83573473cb30d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #664: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd348c673b07dce3920d773de3f3e87408869e916dbcf797d8f9684fb67753d1dca34db012ce6eda1e9c7375c5fcf3e54ed698e19615124273b3a621d021c76f8e777458d6f55a364c221e39e1205d5510bb4fbb7ddf08d8d8fdde13d1d6df7f14", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #665: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6918ce760fb9c7241aee7bc7e7d0e8110d3d22db79ef2fb1f2d09f6ceea7a3b8b97af3fe78be15f2912b6271dd8a43badb6dd2a1b315b2ce7ae37b4e7778041d930d71ee1992d2466495c42102d08e81154c305307d1dcd52d0fa4c479b278e7", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #666: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd73b3c694391d8eadde3f3e874089464715ac20e4c126bbf6d864d648969f5b5a81e7198a3c3f23901cedc7a1d6eff6e9bf81108e6c35cd8559139af3135dbcbb9ef1568530291a8061b90c9f4285eefcba990d4570a4e3b7b737525b5d580034", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #667: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb07ac7a86948c2c2989a16db1930ef1b89ce112595197656877e53c41457f28ab4d792ca121d1dba39cb9de645149c2ab573e8becc6ddff3cc9960f188ddf737f90ba23664153e93262ff73355415195858d7be1315a69456386de68285a3c8", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #668: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27e4d82cb6c061dd9337c69bf9332ed3d198662d6f2299443f62c861187db648518412b69af43aae084476a68d59bbde51fbfa9e5be80563f587c9c2652f88ef2d3b90d25baa6bdb7b0c55e5240a3a98fbc24afed8523edec1c70503fc10f233", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #669: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde7c5cf3aac2e88923b77850515fff6a12d13b356dfe9ec275c3dd81ae94609a4a08f14a644b9a935dffea4761ebaf592d1f66fe6cd373aa7f5d370af34f8352da54b5bc4025cf335900a914c2934ec2fec7a396d0a7affcad732a5741c7aaaf5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #670: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc77838df91c1e953e016e10bddffea2317f9fee32bacfe553cede9e57a748f68ccf2296a6a89b62b90739d38af4ae3a20e9f45715b90044639241061e33f8f8caace0046491eeaa1c6e9a472b96d88f4af83e7ff1bb84438c7e058034412ae08", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #671: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8ef071c02383d2a6c02dc217bbffd446730d0318b0425e2586220907f885f97f94b0fc1525bcabf82b1f34895e5819a06c02b23e04002276e165f962c86e3927be7c2ab4d0b25303204fb32a1f8292902792225e16a6d2dbfb29fbc89a9c3376", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #672: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5668aaa0b545bbf9a044a32399ffbe69ce20074e34d7bdf5cf56282a769763965351f37e1de0c88c508527d89882d183ccdcf2efca407edb0627cadfd16de6ec44b4b57cdf960d32ebcc4c97847eed218425853b5b675eb781b766a1a1300349", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #673: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd12d6e56882f6c0027cae91a27127728f7fddf478fb4fdc2b65f40a60b0eb952748bbafc320e6735cb64019710a269c6c2b5d147bdc831325cb2fb276ac971a69d655e9a755bc9d800ad21ee3fd4d980d93a7a49a8c5ccd37005177578f51163", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #674: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a14b3bbd75c5e1c0c36535a934d4ab85112410b3b90fa97a31c33038964fd85cc112f7d837f8f9c36b460d636c965a5f818f2b50c5d00fb3f9705561dd6631883", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #675: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f2d823533c04cd8edc6d6f950a8e08ade04a9bafa2f14a590356935671ae9305bf43178d1f88b6a57a96924c265f0ddb75b58312907b195acb59d7797303123775", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #676: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851edb2b3408b3167d91030624c6328e8ce3ec108c105575c2f3d209b92e654bab69c34318139c50b0802c6e612f0fd3189d800df7c996d5d7b7c3d6be82836fa258", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #677: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf209179ce7c59225392216453b2ac1e9d178c24837dfae26bc1dd7ab60638527425556b42e330289f3b826b2db7a86d19d45c2860a59f2be1ddcc3b691f95a9255", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #678: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb366901959fb8deda56e5467b7e4b214ea4c2d0c2fb29d70ff19b6b1eccebd6568d7ed9dbd77a918297fd970bff01e1343f6925167db5a14d098a211c39cc3a413398", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #679: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2567f1fdc387e5350c852b4e8f8ba9d6d947e1c5dd7ccc61a5938245dd6bcab3a9960bebaf919514f9535c22eaaf0b5812857970e26662267b1f3eb1011130a11", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #680: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86003499f974ff4ca6bbb2f51682fd5f51762f9dd6dd2855262660b36d46d3e4bec2f498fae2487807e220119152f0122476c64d4fa46ddce85c4546630f0d5c5e81", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #681: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad32c5c01662cf00c1929596257db13b26ecf30d0f3ec4b9f0351b0f27094473426e986a086060d086eee822ddd2fc744247a0154b57f7a69c51d9fdafa484e4ac7", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #682: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f491d4cba813a04d86dbae94c23be6f52c15774183be7ba5b2d9f3cf010b160501900b8adfea6491019a9ac080d516025a541bf4b952b0ad7be4b1874b02fd544a", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #683: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b09ef7fd0a3a36386638330ecad41e1a3b302af36960831d0210c614b948e8aa124ef0d6d800e4047d6d3c1be0fdeaf11fcd8cab5ab59c730eb34116e35a8c7d098", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #684: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4a521dab13cc9152d8ca77035a607fea06c55cc3ca5dbeb868cea92eafe93df2a7bfb9b28531996635e6a5ccaa2826a406ce1111bdb9c2e0ca36500418a2f43de", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #685: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e37474d58a4eec16e0d565f2187fe11d4e8e7a2683a12f38b4fc01d1237a81a10976e55f73bb7cdda46bdb67ef77f6fd2969df2b67920fb5945fde3a517a6ded4cd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #686: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa692da5cd4309d9a6e5cb525c37da8fa0879f7b57208cdabbf47d223a5b23a62140e0daa78cfdd207a7389aaed61738b17fc5fc3e6a5ed3397d2902e9125e6ab4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #687: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f85689b3e0775c7718a90279f14a8082cfcd4d1f1679274f4e9b8805c570a0670167fcc5ca734552e09afa3640f4a034e15b9b7ca661ec7ff70d3f240ebe705b1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #688: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237e2a964fc00d377a8592b8b61aafa7a4aaa7c7b9fd2b41d6e0e17bd1ba5677edcd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #689: point duplication during verification", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237ed569b03ef2c8857b6d4749e550585b5558384603d4be291f1e842e45a9881232", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #690: duplication bug", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9664ce273320d918d8bdb2e61201b4549b36b7cdc54e33b84adb6f2c10aac831e49e68831f18bda2973ac3d76bfbc8c5ee1cceed2dd862e2dc7c915c736cef1f4", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #693: comparison with point at infinity ", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c70961691a5e960d07a301dbbad4d86247ec27d7089faeb3ddd1add395efff1e0fe7254622cc371866cdf990d2c5377790e37d1f1519817f09a231bd260a9e78aeb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #694: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc5d283e13ce8ca60da868e3b0fb33e6b4f1074793274e2928250e71e2aca63e9c214dc74fa25371fb4d9e506d418ed9a1bfd6d0c8bb6591d3e0f44505a84886ce", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #695: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa70fc351da038ae0803bd1d86514ae0462f9f8216551d9315aa9d297f792eef6a341c74eed786f2d33da35360ca7aa925e753f00d6077a1e9e5fc339d634019c73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #696: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaa1e34c8f16d138673fee55c080547c2bfd4de7550065f638322bba9430ce4b60662be9bb512663aa4d7df8ab3f3b4181c5d44a7bdf42436620b7d8a6b81ac936", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #697: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c1857e1a8a8338d7fd8cf41d322a302d2078a87a23c7186150ed7cda6e52817c1bdfd0a9135a89d21ce821e29014b2898349254d748272b2d4eb8d59ee34c615377f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #698: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb5c19fe227a61abc65c61ee7a018cc9571b2c6f663ea33583f76a686f64be078b7b4a0d734940f613d52bc48673b457c2cf78492490a5cc5606c0541d17b24ddb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #699: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c70db02d1f3421d600e9d9ef9e47419dba3208eed08c2d4189a5db63abeb2739666e0ed26967b9ada9ed7ffe480827f90a0d210d5fd8ec628e31715e6b24125512a", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #700: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc6222d1962655501893c29e441395b6c05711bd3ed5a0ef72cfab338b88229c4baaae079cb44a1af070362aaa520ee24cac2626423b0bf81af1c54311d8e2fd23", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #701: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa74ccfa24c67f3def7fa81bc99c70bb0419c0952ba599f4c03361da184b04cdca5db76b797f7f41d9c729a2219478a7e629728df870800be8cf6ca7a0a82153bfa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #702: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaea1c72c91034036bac71402b6e9ecc4af3dbde7a99dc574061e99fefff9d84dab7dd057e75b78ac6f56e34eb048f0a9d29d5d055408c90d02bc2ea918c18cb63", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #703: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185c2879a66d86cb20b820b7795da2da62b38924f7817d1cd350d936988e90e79bc5431a7268ff6931c7a759de024eff90bcb0177216db6fd1f3aaaa11fa3b6a083", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #704: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bbab1c0f273f74abc2b848c75006f2ef3c54c26df27711b06558f455079aee0ba3df510f2ecef6d9a05997c776f14ad6456c179f0a13af1771e4d6c37fa48b47f2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #705: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #706: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #707: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #708: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #709: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b8604aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1210: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2530e782f964b2e2ff065a051bc7adc20615d8c43a1365713c88268822c253bcce5b16df652aa1ecb2dc8b46c515f9604e2e84cacfa7c6eec30428d2d3f4e08ed504aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1211: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e204aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1212: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1213: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1303: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f910fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df557374f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1304: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb556774f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1305: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1306: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f914cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe33cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1307: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b553cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1308: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f911158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f2855193cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1309: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a12513363cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1310: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1311: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd1399292829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1312: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f915eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb52829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1313: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1314: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1315: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dbafffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1316: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1317: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb300000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1318: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f916b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1319: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1320: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1321: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1322: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f917e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aabcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1323: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1324: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1325: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1326: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd762927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #1: signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #3: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #5: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b8252927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #8: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #9: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #10: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #11: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #12: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #13: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #14: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #15: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #16: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #17: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #18: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #19: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #20: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #21: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #22: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #23: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #24: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #25: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #26: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #27: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #28: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #29: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #30: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #31: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #32: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #33: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #34: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #35: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #36: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #37: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #38: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #39: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #40: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #41: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #42: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #43: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #44: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #45: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #46: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #47: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #48: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #49: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #50: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #51: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #52: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #53: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #54: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #55: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #56: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #57: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "70239dd877f7c944c422f44dea4ed1a52f2627416faf2f072fa50c772ed6f80764a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #58: Edge case for Shamir multiplication", + "NoBenchmark": false + }, + { + "Input": "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #59: special case hash", + "NoBenchmark": false + }, + { + "Input": "7300000000213f2a525c6035725235c2f696ad3ebb5ee47f140697ad25770d919cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c322927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #60: special case hash", + "NoBenchmark": false + }, + { + "Input": "ddf2000000005e0be0635b245f0b97978afd25daadeb3edb4a0161c27fe0604573b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c886342927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #61: special case hash", + "NoBenchmark": false + }, + { + "Input": "67ab1900000000784769c4ecb9e164d6642b8499588b89855be1ec355d0841a0bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #62: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2bf09460000000076d7dbeffe125eaf02095dff252ee905e296b6350fc311cf204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #63: special case hash", + "NoBenchmark": false + }, + { + "Input": "3554e827c700000000e1e75e624a06b3a0a353171160858129e15c544e4f0e65ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #64: special case hash", + "NoBenchmark": false + }, + { + "Input": "9b6cd3b812610000000026941a0f0bb53255ea4c9fd0cb3426e3a54b9fc6965c060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d36102927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #65: special case hash", + "NoBenchmark": false + }, + { + "Input": "883ae39f50bf0100000000e7561c26fc82a52baa51c71ca877162f93c4ae01869f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e99022927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #66: special case hash", + "NoBenchmark": false + }, + { + "Input": "a1ce5d6e5ecaf28b0000000000fa7cd010540f420fb4ff7401fe9fce011d0ba6a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #67: special case hash", + "NoBenchmark": false + }, + { + "Input": "8ea5f645f373f580930000000038345397330012a8ee836c5494cdffd5ee8054fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d213502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #68: special case hash", + "NoBenchmark": false + }, + { + "Input": "660570d323e9f75fa734000000008792d65ce93eabb7d60d8d9c1bbdcb5ef305b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff22927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #69: special case hash", + "NoBenchmark": false + }, + { + "Input": "d0462673154cce587dde8800000000e98d35f1f45cf9c3bf46ada2de4c568c343b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d992582927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #70: special case hash", + "NoBenchmark": false + }, + { + "Input": "bd90640269a7822680cedfef000000000caef15a6171059ab83e7b4418d7278f30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #71: special case hash", + "NoBenchmark": false + }, + { + "Input": "33239a52d72f1311512e41222a00000000d2dcceb301c54b4beae8e284788a7338686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #72: special case hash", + "NoBenchmark": false + }, + { + "Input": "b8d64fbcd4a1c10f1365d4e6d95c000000007ee4a21a1cbe1dc84c2d941ffaf144a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e862927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #73: special case hash", + "NoBenchmark": false + }, + { + "Input": "01603d3982bf77d7a3fef3183ed092000000003a227420db4088b20fe0e9d84a2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #74: special case hash", + "NoBenchmark": false + }, + { + "Input": "9ea6994f1e0384c8599aa02e6cf66d9c000000004d89ef50b7e9eb0cfbff7363bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #75: special case hash", + "NoBenchmark": false + }, + { + "Input": "d03215a8401bcf16693979371a01068a4700000000e2fa5bf692bc670905b18c50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab2447262927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #76: special case hash", + "NoBenchmark": false + }, + { + "Input": "307bfaaffb650c889c84bf83f0300e5dc87e000000008408fd5f64b582e3bb14f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #77: special case hash", + "NoBenchmark": false + }, + { + "Input": "bab5c4f4df540d7b33324d36bb0c157551527c00000000e4af574bb4d54ea6b89505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c50212927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #78: special case hash", + "NoBenchmark": false + }, + { + "Input": "d4ba47f6ae28f274e4f58d8036f9c36ec2456f5b00000000c3b869197ef5e15ebbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #79: special case hash", + "NoBenchmark": false + }, + { + "Input": "79fd19c7235ea212f29f1fa00984342afe0f10aafd00000000801e47f8c184e12ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a198782927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #80: special case hash", + "NoBenchmark": false + }, + { + "Input": "8c291e8eeaa45adbaf9aba5c0583462d79cbeb7ac97300000000a37ea6700cda54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #81: special case hash", + "NoBenchmark": false + }, + { + "Input": "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #82: special case hash", + "NoBenchmark": false + }, + { + "Input": "e02716d01fb23a5a0068399bf01bab42ef17c6d96e13846c00000000afc0f89d207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf75927672927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #83: special case hash", + "NoBenchmark": false + }, + { + "Input": "9eb0bf583a1a6b9a194e9a16bc7dab2a9061768af89d00659a00000000fc7de16554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f9292927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #84: special case hash", + "NoBenchmark": false + }, + { + "Input": "62aac98818b3b84a2c214f0d5e72ef286e1030cb53d9a82b690e00000000cd15a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #85: special case hash", + "NoBenchmark": false + }, + { + "Input": "3760a7f37cf96218f29ae43732e513efd2b6f552ea4b6895464b9300000000c8975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf9196222927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #86: special case hash", + "NoBenchmark": false + }, + { + "Input": "0da0a1d2851d33023834f2098c0880096b4320bea836cd9cbb6ff6c8000000005694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa42927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #87: special case hash", + "NoBenchmark": false + }, + { + "Input": "ffffffff293886d3086fd567aafd598f0fe975f735887194a764a231e82d289aa0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c654243392927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #88: special case hash", + "NoBenchmark": false + }, + { + "Input": "7bffffffff2376d1e3c03445a072e24326acdc4ce127ec2e0e8d9ca99527e7b7614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #89: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2b5ffffffffebb251b085377605a224bc80872602a6e467fd016807e97fa395bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #90: special case hash", + "NoBenchmark": false + }, + { + "Input": "641227ffffffff6f1b96fa5f097fcf3cc1a3c256870d45a67b83d0967d4b20c0499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d6932927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #91: special case hash", + "NoBenchmark": false + }, + { + "Input": "958415d8ffffffffabad03e2fc662dc3ba203521177502298df56f36600e0f8b08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #92: special case hash", + "NoBenchmark": false + }, + { + "Input": "f1d8de4858ffffffff1281093536f47fe13deb04e1fbe8fb954521b6975420f8be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c892927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #93: special case hash", + "NoBenchmark": false + }, + { + "Input": "0927895f2802ffffffff10782dd14a3b32dc5d47c05ef6f1876b95c81fc31def15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a19391232927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #94: special case hash", + "NoBenchmark": false + }, + { + "Input": "60907984aa7e8effffffff4f332862a10a57c3063fb5a30624cf6a0c3ac80589352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c62927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #95: special case hash", + "NoBenchmark": false + }, + { + "Input": "c6ff198484939170ffffffff0af42cda50f9a5f50636ea6942d6b9b8cd6ae1e24a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc59817257822927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #96: special case hash", + "NoBenchmark": false + }, + { + "Input": "de030419345ca15c75ffffffff8074799b9e0956cc43135d16dfbe4d27d7e68deacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d12927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #97: special case hash", + "NoBenchmark": false + }, + { + "Input": "6f0e3eeaf42b28132b88fffffffff6c8665604d34acb19037e1ab78caaaac6ff2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #98: special case hash", + "NoBenchmark": false + }, + { + "Input": "cdb549f773b3e62b3708d1ffffffffbe48f7c0591ddcae7d2cb222d1f8017ab9ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #99: special case hash", + "NoBenchmark": false + }, + { + "Input": "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #100: special case hash", + "NoBenchmark": false + }, + { + "Input": "ac18f8418c55a2502cb7d53f9affffffff5c31d89fda6a6b8476397c04edf411dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #101: special case hash", + "NoBenchmark": false + }, + { + "Input": "4f9618f98e2d3a15b24094f72bb5ffffffffa2fd3e2893683e5a6ab8cf0ee610ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c1993452927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #102: special case hash", + "NoBenchmark": false + }, + { + "Input": "422e82a3d56ed10a9cc21d31d37a25ffffffff67edf7c40204caae73ab0bc75aac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a82927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #103: special case hash", + "NoBenchmark": false + }, + { + "Input": "7075d245ccc3281b6e7b329ff738fbb417a5ffffffffa0842d9890b5cf95d018677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db552927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #104: special case hash", + "NoBenchmark": false + }, + { + "Input": "3c80de54cd9226989443d593fa4fd6597e280ebeffffffffc1847eb76c217a95479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b24432927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #105: special case hash", + "NoBenchmark": false + }, + { + "Input": "de21754e29b85601980bef3d697ea2770ce891a8cdffffffffc7906aa794b39b43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f495843897722927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #106: special case hash", + "NoBenchmark": false + }, + { + "Input": "8f65d92927cfb86a84dd59623fb531bb599e4d5f7289ffffffff2f1f2f57881c5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d752927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #107: special case hash", + "NoBenchmark": false + }, + { + "Input": "6b63e9a74e092120160bea3877dace8a2cc7cd0e8426cbfffffffffafc8c3ca85e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c202927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #108: special case hash", + "NoBenchmark": false + }, + { + "Input": "fc28259702a03845b6d75219444e8b43d094586e249c8699ffffffffe852512e0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #109: special case hash", + "NoBenchmark": false + }, + { + "Input": "1273b4502ea4e3bccee044ee8e8db7f774ecbcd52e8ceb571757ffffffffe20a7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #110: special case hash", + "NoBenchmark": false + }, + { + "Input": "08fb565610a79baa0c566c66228d81814f8c53a15b96e602fb49ffffffffff6e7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #111: special case hash", + "NoBenchmark": false + }, + { + "Input": "d59291cc2cf89f3087715fcb1aa4e79aa2403f748e97d7cd28ecaefeffffffff914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #112: special case hash", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #114: r too large", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e3cd8d2f81d6953b0844c09d7b560d527cd2ef67056893eadafa52c8501387d59ee41fdb4d10402ce7a0c5e3b747adfa3a490b62a6b7719068903485c0bb6dc2d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #115: r,s are large", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd48240cd81edd91cb6936133508c3915100e81f332c4545d41189b481196851378e05b06e72d4a1bff80ea5db514aa2f93ea6dd6d9c0ae27b7837dc432f9ce89d9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #116: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a5b062947356748b0fc17f1704c65aa1dca6e1bfe6779756fa616d91eaad13df2c0b38c17f3d0672e7409cfc5992a99fff12b84a4f8432293b431113f1b2fb579d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #117: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000014a03ef9f92eb268cafa601072489a56380fa0dc43171d7712813b3a19a1eb5e53e213e28a608ce9a2f4a17fd830c6654018a79b3e0263d91a8ba90622df6f2f0", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #118: small r and s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000003091194c1cba17f34e286b4833701606a41cef26177ada8850b601ea1f859e70127242fcec708828758403ce2fe501983a7984e6209f4d6b95db9ad77767f55eb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #120: small r and s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005103c6ecceff59e71ea8f56fee3a4b2b148e81c2bdbdd39c195812c96dcfb41a72303a193dc591be150b883d770ec51ebb4ebce8b09042c2ecb16c448d8e57bf5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #122: small r and s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #124: small r and s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255600000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84ff2f6c24e4a33cd71c09fdcbc74a6233961b874b8c8e0eb94582092cbc50c3084fa9547afda5c66335f3f937d4c79afa120486b534139d59ae82d61ead26420", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea8884b959080bb30859cd53c2fb973cf14d60cdaa8ee00587889b5bc657ac588175a02ce5c1e53cb196113c78b4cb8dc7d360e5ea7850b0f6650b0c45af2c3cd7ca", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7adf4083bd6ecbda5a77ae578e5d835fa7f74a07ebb91e0570e1ff32a563354e9925af80b09a167d9ef647df28e2d9acd0d4bc4f2deec5723818edaf9071e311f8", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4dc2569a3c9bf8c1838ca821f7ba6f000cc8679d278f3736b414a34a7c956a03770387ea85bc4f28804b4a91c9b7d65bc6434c975806795ab7d441a4e9683aeb09", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b4a9f7da2a6c359a16540c271774a6bf1c586357c978256f44a6496d80670968ac496e73a44563f8d56fbd7bb9e4e3ae304c86f2c508eb777b03924755beb40d4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b874146432b3cd2c9e26204c0a34136996067d466dde4917a8ff23a8e95ca106b709b3d50976ef8b385a813bc35f3a20710bdc6edd465e6f43ac4866703a6608c", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c707a736d8e326a9ca62bbe25a34ea4e3633b499a96afa7aaa3fcf3fd88f8e07edeb3e45879d8622b93e818443a686e869eeda7bf9ae46aa3eafcc48a5934864627", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #133: r and s^-1 are close to n", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000001e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #134: s == 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000000e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #135: s == 0", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c700203736fcb198b15d8d7a0c80f66dddd15259240aa78d08aae67c467de04503434383438d5041ea9a387ee8e4d4e84b4471b160c6bcf2568b072f8f20e87a996", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #136: point at infinity during verify", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a878d844dc7f16b73b1f2a39730da5d8cd99fe2e70a18482384e37dcd2bfea02e1ed6572e01eb7a8d113d02c666c45ef22d3b9a6a6dea99aa43a8183c26e75d336", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #137: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a9dec6c8257dde94110eacc8c09d2e5789cc5beb81a958b02b4d62da9599a7401466fae1614174be63970b83f6524421067b06dd6f4e9c56baca4e344fdd690f1d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #138: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25a17f5b75a35ed64623ca5cbf1f91951292db0c23f0c2ea24c3d0cad0988cabc083a7a618625c228940730b4fa3ee64faecbb2fc20fdde7c58b3a3f6300424dc6", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #139: u1 == 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c04ba0cba291a37db13f33bf90dab628c04ec8393a0200419e9eaa1ebcc9fb5c31f3a0a0e6823a49b625ad57b12a32d4047970fc3428f0f0049ecf4265dc12f62", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #140: u1 == n - 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c70692b6c828e0feed63d8aeaa2b7322f9ccbe8723a1ed39f229f204a434b8900efa1f6f6abcb38ea3b8fde38b98c7c271f274af56a8c5628dc3329069ae4dd5716", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #141: u2 == 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e100cefd9162d13e64cb93687a9cd8f9755ebb5a3ef7632f800f84871874ccef09543ecbeaf7e8044ef721be2fb5f549e4b8480d2587404ebf7dbbef2c54bc0cb1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #142: u2 == n - 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd710f8e3edc7c2d5a3fd23de844002bb949d9f794f6d5405f6d97c1bb03dd2bd2b975183b42551cf52f291d5c1921fd5e12f50c8c85a4beb9de03efa3f0f244862243018e6866df922dc313612020311ff21e242ce3fb15bc78c406b25ab43091", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #143: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdedffbc270f722c243069a7e5f40335a61a58525c7b4db2e7a8e269274ffe4e1bc25f1d166f3e211cdf042a26f8abf6094d48b8d17191d74ed71714927446699965d06dd6a88abfa49e8b4c5da6bb922851969adf9604b5accfb52a114e77ccdb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #144: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffda25adcae105ed7ff4f95d2344e24ee523314c3e178525d007904b68919ba4d538fe5e88243a76e41a004236218a3c3a2d6eee398a23c3a0b008d7f0164cbc0ca98a20d1bdcf573513c7cfd9b83c63e3a82d40127c897697c86b8cb387af7f240", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #145: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2e4348c645707dce6760d773de3f3e87346924b2f64bd3dd0297e766b5805ebb02148256b530fbc470c7b341970b38243ecee6d5a840a37beca2efb37e8dff2cc0adbea0882482a7489ca703a399864ba987eeb6ddb738af53a83573473cb30d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #146: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd348c673b07dce3920d773de3f3e87408869e916dbcf797d8f9684fb67753d1dca34db012ce6eda1e9c7375c5fcf3e54ed698e19615124273b3a621d021c76f8e777458d6f55a364c221e39e1205d5510bb4fbb7ddf08d8d8fdde13d1d6df7f14", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #147: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6918ce760fb9c7241aee7bc7e7d0e8110d3d22db79ef2fb1f2d09f6ceea7a3b8b97af3fe78be15f2912b6271dd8a43badb6dd2a1b315b2ce7ae37b4e7778041d930d71ee1992d2466495c42102d08e81154c305307d1dcd52d0fa4c479b278e7", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #148: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd73b3c694391d8eadde3f3e874089464715ac20e4c126bbf6d864d648969f5b5a81e7198a3c3f23901cedc7a1d6eff6e9bf81108e6c35cd8559139af3135dbcbb9ef1568530291a8061b90c9f4285eefcba990d4570a4e3b7b737525b5d580034", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #149: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb07ac7a86948c2c2989a16db1930ef1b89ce112595197656877e53c41457f28ab4d792ca121d1dba39cb9de645149c2ab573e8becc6ddff3cc9960f188ddf737f90ba23664153e93262ff73355415195858d7be1315a69456386de68285a3c8", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #150: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27e4d82cb6c061dd9337c69bf9332ed3d198662d6f2299443f62c861187db648518412b69af43aae084476a68d59bbde51fbfa9e5be80563f587c9c2652f88ef2d3b90d25baa6bdb7b0c55e5240a3a98fbc24afed8523edec1c70503fc10f233", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #151: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde7c5cf3aac2e88923b77850515fff6a12d13b356dfe9ec275c3dd81ae94609a4a08f14a644b9a935dffea4761ebaf592d1f66fe6cd373aa7f5d370af34f8352da54b5bc4025cf335900a914c2934ec2fec7a396d0a7affcad732a5741c7aaaf5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #152: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc77838df91c1e953e016e10bddffea2317f9fee32bacfe553cede9e57a748f68ccf2296a6a89b62b90739d38af4ae3a20e9f45715b90044639241061e33f8f8caace0046491eeaa1c6e9a472b96d88f4af83e7ff1bb84438c7e058034412ae08", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #153: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8ef071c02383d2a6c02dc217bbffd446730d0318b0425e2586220907f885f97f94b0fc1525bcabf82b1f34895e5819a06c02b23e04002276e165f962c86e3927be7c2ab4d0b25303204fb32a1f8292902792225e16a6d2dbfb29fbc89a9c3376", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #154: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5668aaa0b545bbf9a044a32399ffbe69ce20074e34d7bdf5cf56282a769763965351f37e1de0c88c508527d89882d183ccdcf2efca407edb0627cadfd16de6ec44b4b57cdf960d32ebcc4c97847eed218425853b5b675eb781b766a1a1300349", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #155: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd12d6e56882f6c0027cae91a27127728f7fddf478fb4fdc2b65f40a60b0eb952748bbafc320e6735cb64019710a269c6c2b5d147bdc831325cb2fb276ac971a69d655e9a755bc9d800ad21ee3fd4d980d93a7a49a8c5ccd37005177578f51163", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #156: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a14b3bbd75c5e1c0c36535a934d4ab85112410b3b90fa97a31c33038964fd85cc112f7d837f8f9c36b460d636c965a5f818f2b50c5d00fb3f9705561dd6631883", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #157: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f2d823533c04cd8edc6d6f950a8e08ade04a9bafa2f14a590356935671ae9305bf43178d1f88b6a57a96924c265f0ddb75b58312907b195acb59d7797303123775", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #158: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851edb2b3408b3167d91030624c6328e8ce3ec108c105575c2f3d209b92e654bab69c34318139c50b0802c6e612f0fd3189d800df7c996d5d7b7c3d6be82836fa258", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #159: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf209179ce7c59225392216453b2ac1e9d178c24837dfae26bc1dd7ab60638527425556b42e330289f3b826b2db7a86d19d45c2860a59f2be1ddcc3b691f95a9255", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #160: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb366901959fb8deda56e5467b7e4b214ea4c2d0c2fb29d70ff19b6b1eccebd6568d7ed9dbd77a918297fd970bff01e1343f6925167db5a14d098a211c39cc3a413398", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #161: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2567f1fdc387e5350c852b4e8f8ba9d6d947e1c5dd7ccc61a5938245dd6bcab3a9960bebaf919514f9535c22eaaf0b5812857970e26662267b1f3eb1011130a11", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #162: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86003499f974ff4ca6bbb2f51682fd5f51762f9dd6dd2855262660b36d46d3e4bec2f498fae2487807e220119152f0122476c64d4fa46ddce85c4546630f0d5c5e81", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #163: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad32c5c01662cf00c1929596257db13b26ecf30d0f3ec4b9f0351b0f27094473426e986a086060d086eee822ddd2fc744247a0154b57f7a69c51d9fdafa484e4ac7", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #164: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f491d4cba813a04d86dbae94c23be6f52c15774183be7ba5b2d9f3cf010b160501900b8adfea6491019a9ac080d516025a541bf4b952b0ad7be4b1874b02fd544a", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #165: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b09ef7fd0a3a36386638330ecad41e1a3b302af36960831d0210c614b948e8aa124ef0d6d800e4047d6d3c1be0fdeaf11fcd8cab5ab59c730eb34116e35a8c7d098", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #166: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4a521dab13cc9152d8ca77035a607fea06c55cc3ca5dbeb868cea92eafe93df2a7bfb9b28531996635e6a5ccaa2826a406ce1111bdb9c2e0ca36500418a2f43de", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #167: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e37474d58a4eec16e0d565f2187fe11d4e8e7a2683a12f38b4fc01d1237a81a10976e55f73bb7cdda46bdb67ef77f6fd2969df2b67920fb5945fde3a517a6ded4cd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #168: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa692da5cd4309d9a6e5cb525c37da8fa0879f7b57208cdabbf47d223a5b23a62140e0daa78cfdd207a7389aaed61738b17fc5fc3e6a5ed3397d2902e9125e6ab4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #169: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f85689b3e0775c7718a90279f14a8082cfcd4d1f1679274f4e9b8805c570a0670167fcc5ca734552e09afa3640f4a034e15b9b7ca661ec7ff70d3f240ebe705b1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #170: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237e2a964fc00d377a8592b8b61aafa7a4aaa7c7b9fd2b41d6e0e17bd1ba5677edcd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #171: point duplication during verification", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237ed569b03ef2c8857b6d4749e550585b5558384603d4be291f1e842e45a9881232", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #172: duplication bug", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c7038a084ffccc4ae2f8204be2abca9fb8ad4ab283b2aa50f13b6bb2347adabc69ca699799b77b1cc6dad271e88b899c12931986e958e1f5cf5653dddf7389365e2", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9664ce273320d918d8bdb2e61201b4549b36b7cdc54e33b84adb6f2c10aac831e49e68831f18bda2973ac3d76bfbc8c5ee1cceed2dd862e2dc7c915c736cef1f4", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #175: comparison with point at infinity ", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c70961691a5e960d07a301dbbad4d86247ec27d7089faeb3ddd1add395efff1e0fe7254622cc371866cdf990d2c5377790e37d1f1519817f09a231bd260a9e78aeb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #176: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc5d283e13ce8ca60da868e3b0fb33e6b4f1074793274e2928250e71e2aca63e9c214dc74fa25371fb4d9e506d418ed9a1bfd6d0c8bb6591d3e0f44505a84886ce", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #177: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa70fc351da038ae0803bd1d86514ae0462f9f8216551d9315aa9d297f792eef6a341c74eed786f2d33da35360ca7aa925e753f00d6077a1e9e5fc339d634019c73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #178: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaa1e34c8f16d138673fee55c080547c2bfd4de7550065f638322bba9430ce4b60662be9bb512663aa4d7df8ab3f3b4181c5d44a7bdf42436620b7d8a6b81ac936", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #179: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c1857e1a8a8338d7fd8cf41d322a302d2078a87a23c7186150ed7cda6e52817c1bdfd0a9135a89d21ce821e29014b2898349254d748272b2d4eb8d59ee34c615377f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #180: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb5c19fe227a61abc65c61ee7a018cc9571b2c6f663ea33583f76a686f64be078b7b4a0d734940f613d52bc48673b457c2cf78492490a5cc5606c0541d17b24ddb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #181: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c70db02d1f3421d600e9d9ef9e47419dba3208eed08c2d4189a5db63abeb2739666e0ed26967b9ada9ed7ffe480827f90a0d210d5fd8ec628e31715e6b24125512a", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #182: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc6222d1962655501893c29e441395b6c05711bd3ed5a0ef72cfab338b88229c4baaae079cb44a1af070362aaa520ee24cac2626423b0bf81af1c54311d8e2fd23", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #183: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa74ccfa24c67f3def7fa81bc99c70bb0419c0952ba599f4c03361da184b04cdca5db76b797f7f41d9c729a2219478a7e629728df870800be8cf6ca7a0a82153bfa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #184: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaea1c72c91034036bac71402b6e9ecc4af3dbde7a99dc574061e99fefff9d84dab7dd057e75b78ac6f56e34eb048f0a9d29d5d055408c90d02bc2ea918c18cb63", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #185: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185c2879a66d86cb20b820b7795da2da62b38924f7817d1cd350d936988e90e79bc5431a7268ff6931c7a759de024eff90bcb0177216db6fd1f3aaaa11fa3b6a083", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #186: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bbab1c0f273f74abc2b848c75006f2ef3c54c26df27711b06558f455079aee0ba3df510f2ecef6d9a05997c776f14ad6456c179f0a13af1771e4d6c37fa48b47f2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #187: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #188: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #189: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #190: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #191: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b8604aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #269: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2530e782f964b2e2ff065a051bc7adc20615d8c43a1365713c88268822c253bcce5b16df652aa1ecb2dc8b46c515f9604e2e84cacfa7c6eec30428d2d3f4e08ed504aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #270: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e204aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #271: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #272: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #288: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f910fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df557374f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #289: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb556774f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #290: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #291: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f914cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe33cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #292: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b553cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #293: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f911158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f2855193cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #294: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a12513363cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #295: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #296: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd1399292829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #297: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f915eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb52829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #298: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #299: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #300: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dbafffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #301: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #302: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb300000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #303: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f916b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #304: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #305: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #306: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #307: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f917e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aabcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #308: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #309: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #310: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #311: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a90000000000000000000000000000000000000000000000000000000000000000fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "", + "Gas": 6900, + "Name": "invalid public key x param errors", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af0150000000000000000000000000000000000000000000000000000000000000000", + "Expected": "", + "Gas": 6900, + "Name": "invalid public key y param errors", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "", + "Gas": 6900, + "Name": "reference point errors", + "NoBenchmark": false + } +] diff --git a/crypto/bn256/cloudflare/mul_arm64.h b/crypto/bn256/cloudflare/mul_arm64.h index d405eb8f7287..14f879c380c4 100644 --- a/crypto/bn256/cloudflare/mul_arm64.h +++ b/crypto/bn256/cloudflare/mul_arm64.h @@ -1,3 +1,7 @@ +// mul multiplies two 256-bit numbers in little-endian order. +// The inputs are (R1,R2,R3,R4) times (R5,R6,R7,R8) +// and the product is stored in (c0,c1,c2,c3,c4,c5,c6,c7). +// Note that the input registers (R1,R2,R3) are overwritten. #define mul(c0,c1,c2,c3,c4,c5,c6,c7) \ MUL R1, R5, c0 \ UMULH R1, R5, c1 \ @@ -16,54 +20,54 @@ UMULH R2, R5, R26 \ MUL R2, R6, R0 \ ADDS R0, R26 \ - UMULH R2, R6, R27 \ + UMULH R2, R6, c6 \ MUL R2, R7, R0 \ - ADCS R0, R27 \ - UMULH R2, R7, R29 \ + ADCS R0, c6 \ + UMULH R2, R7, c7 \ MUL R2, R8, R0 \ - ADCS R0, R29 \ + ADCS R0, c7 \ UMULH R2, R8, c5 \ ADCS ZR, c5 \ ADDS R1, c1 \ ADCS R26, c2 \ - ADCS R27, c3 \ - ADCS R29, c4 \ + ADCS c6, c3 \ + ADCS c7, c4 \ ADCS ZR, c5 \ \ MUL R3, R5, R1 \ UMULH R3, R5, R26 \ MUL R3, R6, R0 \ ADDS R0, R26 \ - UMULH R3, R6, R27 \ + UMULH R3, R6, R2 \ MUL R3, R7, R0 \ - ADCS R0, R27 \ - UMULH R3, R7, R29 \ + ADCS R0, R2 \ + UMULH R3, R7, c7 \ MUL R3, R8, R0 \ - ADCS R0, R29 \ + ADCS R0, c7 \ UMULH R3, R8, c6 \ ADCS ZR, c6 \ ADDS R1, c2 \ ADCS R26, c3 \ - ADCS R27, c4 \ - ADCS R29, c5 \ + ADCS R2, c4 \ + ADCS c7, c5 \ ADCS ZR, c6 \ \ MUL R4, R5, R1 \ UMULH R4, R5, R26 \ MUL R4, R6, R0 \ ADDS R0, R26 \ - UMULH R4, R6, R27 \ + UMULH R4, R6, R2 \ MUL R4, R7, R0 \ - ADCS R0, R27 \ - UMULH R4, R7, R29 \ + ADCS R0, R2 \ + UMULH R4, R7, R3 \ MUL R4, R8, R0 \ - ADCS R0, R29 \ + ADCS R0, R3 \ UMULH R4, R8, c7 \ ADCS ZR, c7 \ ADDS R1, c3 \ ADCS R26, c4 \ - ADCS R27, c5 \ - ADCS R29, c6 \ + ADCS R2, c5 \ + ADCS R3, c6 \ ADCS ZR, c7 #define gfpReduce() \ diff --git a/crypto/bn256/cloudflare/twist.go b/crypto/bn256/cloudflare/twist.go index 2c7a69a4d751..c2e39c57ca2a 100644 --- a/crypto/bn256/cloudflare/twist.go +++ b/crypto/bn256/cloudflare/twist.go @@ -43,7 +43,7 @@ func (c *twistPoint) Set(a *twistPoint) { c.t.Set(&a.t) } -// IsOnCurve returns true iff c is on the curve. +// IsOnCurve returns true iff c is on the curve and is in the correct subgroup. func (c *twistPoint) IsOnCurve() bool { c.MakeAffine() if c.IsInfinity() { @@ -57,6 +57,8 @@ func (c *twistPoint) IsOnCurve() bool { if *y2 != *x3 { return false } + // Subgroup check: multiply the point by the group order and + // verify that it becomes the point at infinity. cneg := &twistPoint{} cneg.Mul(c, Order) return cneg.z.IsZero() diff --git a/crypto/bn256/gnark/g1.go b/crypto/bn256/gnark/g1.go index 2f933dd53601..59e04cb247f5 100644 --- a/crypto/bn256/gnark/g1.go +++ b/crypto/bn256/gnark/g1.go @@ -1,6 +1,7 @@ package bn256 import ( + "errors" "math/big" "github.com/consensys/gnark-crypto/ecc/bn254" @@ -31,21 +32,62 @@ func (g *G1) ScalarMult(a *G1, scalar *big.Int) { // Unmarshal deserializes `buf` into `g` // -// Note: whether the deserialization is of a compressed -// or an uncompressed point, is encoded in the bytes. -// -// For our purpose, the point will always be serialized -// as uncompressed, ie 64 bytes. +// The input is expected to be in the EVM format: +// 64 bytes: [32-byte x coordinate][32-byte y coordinate] +// where each coordinate is in big-endian format. // // This method also checks whether the point is on the // curve and in the prime order subgroup. func (g *G1) Unmarshal(buf []byte) (int, error) { - return g.inner.SetBytes(buf) + if len(buf) < 64 { + return 0, errors.New("invalid G1 point size") + } + + if allZeroes(buf[:64]) { + // point at infinity + g.inner.X.SetZero() + g.inner.Y.SetZero() + return 64, nil + } + + if err := g.inner.X.SetBytesCanonical(buf[:32]); err != nil { + return 0, err + } + if err := g.inner.Y.SetBytesCanonical(buf[32:64]); err != nil { + return 0, err + } + + if !g.inner.IsOnCurve() { + return 0, errors.New("point is not on curve") + } + if !g.inner.IsInSubGroup() { + return 0, errors.New("point is not in correct subgroup") + } + return 64, nil } // Marshal serializes the point into a byte slice. // -// Note: The point is serialized as uncompressed. +// The output is in EVM format: 64 bytes total. +// [32-byte x coordinate][32-byte y coordinate] +// where each coordinate is a big-endian integer padded to 32 bytes. func (p *G1) Marshal() []byte { - return p.inner.Marshal() + output := make([]byte, 64) + + xBytes := p.inner.X.Bytes() + copy(output[:32], xBytes[:]) + + yBytes := p.inner.Y.Bytes() + copy(output[32:64], yBytes[:]) + + return output +} + +func allZeroes(buf []byte) bool { + for i := range buf { + if buf[i] != 0 { + return false + } + } + return true } diff --git a/crypto/bn256/gnark/g2.go b/crypto/bn256/gnark/g2.go index 205373a59194..48a797e5a722 100644 --- a/crypto/bn256/gnark/g2.go +++ b/crypto/bn256/gnark/g2.go @@ -1,6 +1,8 @@ package bn256 import ( + "errors" + "github.com/consensys/gnark-crypto/ecc/bn254" ) @@ -18,21 +20,66 @@ type G2 struct { // Unmarshal deserializes `buf` into `g` // -// Note: whether the deserialization is of a compressed -// or an uncompressed point, is encoded in the bytes. -// -// For our purpose, the point will always be serialized -// as uncompressed, ie 128 bytes. +// The input is expected to be in the EVM format: +// 128 bytes: [32-byte x.1][32-byte x.0][32-byte y.1][32-byte y.0] +// where each value is a big-endian integer. // // This method also checks whether the point is on the // curve and in the prime order subgroup. func (g *G2) Unmarshal(buf []byte) (int, error) { - return g.inner.SetBytes(buf) + if len(buf) < 128 { + return 0, errors.New("invalid G2 point size") + } + + if allZeroes(buf[:128]) { + // point at infinity + g.inner.X.A0.SetZero() + g.inner.X.A1.SetZero() + g.inner.Y.A0.SetZero() + g.inner.Y.A1.SetZero() + return 128, nil + } + if err := g.inner.X.A1.SetBytesCanonical(buf[0:32]); err != nil { + return 0, err + } + if err := g.inner.X.A0.SetBytesCanonical(buf[32:64]); err != nil { + return 0, err + } + if err := g.inner.Y.A1.SetBytesCanonical(buf[64:96]); err != nil { + return 0, err + } + if err := g.inner.Y.A0.SetBytesCanonical(buf[96:128]); err != nil { + return 0, err + } + + if !g.inner.IsOnCurve() { + return 0, errors.New("point is not on curve") + } + if !g.inner.IsInSubGroup() { + return 0, errors.New("point is not in correct subgroup") + } + return 128, nil } // Marshal serializes the point into a byte slice. // -// Note: The point is serialized as uncompressed. +// The output is in EVM format: 128 bytes total. +// [32-byte x.1][32-byte x.0][32-byte y.1][32-byte y.0] +// where each value is a big-endian integer. func (g *G2) Marshal() []byte { - return g.inner.Marshal() + output := make([]byte, 128) + + xA1Bytes := g.inner.X.A1.Bytes() + copy(output[:32], xA1Bytes[:]) + + xA0Bytes := g.inner.X.A0.Bytes() + copy(output[32:64], xA0Bytes[:]) + + yA1Bytes := g.inner.Y.A1.Bytes() + copy(output[64:96], yA1Bytes[:]) + + yA0Bytes := g.inner.Y.A0.Bytes() + copy(output[96:128], yA0Bytes[:]) + + return output } diff --git a/crypto/bn256/gnark/native_format_test.go b/crypto/bn256/gnark/native_format_test.go new file mode 100644 index 000000000000..e2b67449321a --- /dev/null +++ b/crypto/bn256/gnark/native_format_test.go @@ -0,0 +1,42 @@ +package bn256 + +import ( + "testing" + + "github.com/consensys/gnark-crypto/ecc/bn254" +) + +func TestNativeGnarkFormatIncompatibility(t *testing.T) { + // Use official gnark serialization + _, _, g1Gen, _ := bn254.Generators() + wrongSer := g1Gen.Bytes() + + var evmG1 G1 + _, err := evmG1.Unmarshal(wrongSer[:]) + if err == nil { + t.Fatalf("points serialized using the official bn254 serialization algorithm, should not work with the evm format") + } +} + +func TestSerRoundTrip(t *testing.T) { + _, _, g1Gen, g2Gen := bn254.Generators() + + expectedG1 := G1{inner: g1Gen} + bytesG1 := expectedG1.Marshal() + + expectedG2 := G2{inner: g2Gen} + bytesG2 := expectedG2.Marshal() + + var gotG1 G1 + gotG1.Unmarshal(bytesG1) + + var gotG2 G2 + gotG2.Unmarshal(bytesG2) + + if !expectedG1.inner.Equal(&gotG1.inner) { + t.Errorf("serialization roundtrip failed for G1") + } + if !expectedG2.inner.Equal(&gotG2.inner) { + t.Errorf("serialization roundtrip failed for G2") + } +} diff --git a/crypto/bn256/google/bn256.go b/crypto/bn256/google/bn256.go index aca9cf62de1b..e427b8bf42a3 100644 --- a/crypto/bn256/google/bn256.go +++ b/crypto/bn256/google/bn256.go @@ -128,7 +128,7 @@ func (e *G1) Marshal() []byte { func (e *G1) Unmarshal(m []byte) ([]byte, error) { // Each value is a 256-bit number. const numBytes = 256 / 8 - if len(m) != 2*numBytes { + if len(m) < 2*numBytes { return nil, errors.New("bn256: not enough data") } // Unmarshal the points and check their caps @@ -253,7 +253,7 @@ func (n *G2) Marshal() []byte { func (e *G2) Unmarshal(m []byte) ([]byte, error) { // Each value is a 256-bit number. const numBytes = 256 / 8 - if len(m) != 4*numBytes { + if len(m) < 4*numBytes { return nil, errors.New("bn256: not enough data") } // Unmarshal the points and check their caps diff --git a/crypto/bn256/google/twist.go b/crypto/bn256/google/twist.go index 43364ff5b7bd..631d1ca8df0b 100644 --- a/crypto/bn256/google/twist.go +++ b/crypto/bn256/google/twist.go @@ -67,7 +67,7 @@ func (c *twistPoint) Set(a *twistPoint) { c.t.Set(a.t) } -// IsOnCurve returns true iff c is on the curve where c must be in affine form. +// IsOnCurve returns true iff c is on the curve and is in the correct subgroup, where c must be in affine form. func (c *twistPoint) IsOnCurve() bool { pool := new(bnPool) yy := newGFp2(pool).Square(c.y, pool) @@ -80,6 +80,8 @@ func (c *twistPoint) IsOnCurve() bool { if yy.x.Sign() != 0 || yy.y.Sign() != 0 { return false } + // Subgroup check: multiply the point by the group order and + // verify that it becomes the point at infinity. cneg := newTwistPoint(pool) cneg.Mul(c, Order, pool) return cneg.z.IsZero() diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index 5b0c9c053300..e620d6ee3a12 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -19,6 +19,7 @@ package crypto import ( "bytes" "crypto/ecdsa" + "crypto/rand" "encoding/hex" "math/big" "os" @@ -297,3 +298,38 @@ func TestPythonIntegration(t *testing.T) { t.Logf("msg: %x, privkey: %s sig: %x\n", msg0, kh, sig0) t.Logf("msg: %x, privkey: %s sig: %x\n", msg1, kh, sig1) } + +// goos: darwin +// goarch: arm64 +// pkg: github.com/ethereum/go-ethereum/crypto +// cpu: Apple M1 Pro +// BenchmarkKeccak256Hash +// BenchmarkKeccak256Hash-8 931095 1270 ns/op 32 B/op 1 allocs/op +func BenchmarkKeccak256Hash(b *testing.B) { + var input [512]byte + rand.Read(input[:]) + + b.ReportAllocs() + for i := 0; i < b.N; i++ { + Keccak256Hash(input[:]) + } +} + +// goos: darwin +// goarch: arm64 +// pkg: github.com/ethereum/go-ethereum/crypto +// cpu: Apple M1 Pro +// BenchmarkHashData +// BenchmarkHashData-8 793386 1278 ns/op 32 B/op 1 allocs/op +func BenchmarkHashData(b *testing.B) { + var ( + input [512]byte + buffer = NewKeccakState() + ) + rand.Read(input[:]) + + b.ReportAllocs() + for i := 0; i < b.N; i++ { + HashData(buffer, input[:]) + } +} diff --git a/crypto/kzg4844/kzg4844.go b/crypto/kzg4844/kzg4844.go index fd2e2991fec0..baf9c9655b90 100644 --- a/crypto/kzg4844/kzg4844.go +++ b/crypto/kzg4844/kzg4844.go @@ -34,6 +34,8 @@ var ( blobT = reflect.TypeOf(Blob{}) commitmentT = reflect.TypeOf(Commitment{}) proofT = reflect.TypeOf(Proof{}) + + CellProofsPerBlob = 128 ) // Blob represents a 4844 data blob. @@ -149,6 +151,16 @@ func VerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error { return gokzgVerifyBlobProof(blob, commitment, proof) } +// VerifyCellProofs verifies a batch of proofs corresponding to the blobs and commitments. +// Expects length of blobs and commitments to be equal. +// Expects length of proofs be 128 * length of blobs. +func VerifyCellProofs(blobs []Blob, commitments []Commitment, proofs []Proof) error { + if useCKZG.Load() { + return ckzgVerifyCellProofBatch(blobs, commitments, proofs) + } + return gokzgVerifyCellProofBatch(blobs, commitments, proofs) +} + // ComputeCellProofs returns the KZG cell proofs that are used to verify the blob against // the commitment. // diff --git a/crypto/kzg4844/kzg4844_ckzg_cgo.go b/crypto/kzg4844/kzg4844_ckzg_cgo.go index 49a7046fe0d7..b215b19928be 100644 --- a/crypto/kzg4844/kzg4844_ckzg_cgo.go +++ b/crypto/kzg4844/kzg4844_ckzg_cgo.go @@ -149,3 +149,44 @@ func ckzgComputeCellProofs(blob *Blob) ([]Proof, error) { } return p, nil } + +// ckzgVerifyCellProofs verifies that the blob data corresponds to the provided commitment. +func ckzgVerifyCellProofBatch(blobs []Blob, commitments []Commitment, cellProofs []Proof) error { + ckzgIniter.Do(ckzgInit) + var ( + proofs = make([]ckzg4844.Bytes48, len(cellProofs)) + commits = make([]ckzg4844.Bytes48, 0, len(cellProofs)) + cellIndices = make([]uint64, 0, len(cellProofs)) + cells = make([]ckzg4844.Cell, 0, len(cellProofs)) + ) + // Copy over the cell proofs + for i, proof := range cellProofs { + proofs[i] = (ckzg4844.Bytes48)(proof) + } + // Blow up the commitments to be the same length as the proofs + for _, commitment := range commitments { + for range gokzg4844.CellsPerExtBlob { + commits = append(commits, (ckzg4844.Bytes48)(commitment)) + } + } + // Compute the cells and cell indices + for i := range blobs { + cellsI, err := ckzg4844.ComputeCells((*ckzg4844.Blob)(&blobs[i])) + if err != nil { + return err + } + cells = append(cells, cellsI[:]...) + for idx := range len(cellsI) { + cellIndices = append(cellIndices, uint64(idx)) + } + } + + valid, err := ckzg4844.VerifyCellKZGProofBatch(commits, cellIndices, cells, proofs) + if err != nil { + return err + } + if !valid { + return errors.New("invalid proof") + } + return nil +} diff --git a/crypto/kzg4844/kzg4844_ckzg_nocgo.go b/crypto/kzg4844/kzg4844_ckzg_nocgo.go index 6f4bd3b8236f..7c552e9a18bb 100644 --- a/crypto/kzg4844/kzg4844_ckzg_nocgo.go +++ b/crypto/kzg4844/kzg4844_ckzg_nocgo.go @@ -61,6 +61,11 @@ func ckzgVerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error { panic("unsupported platform") } +// ckzgVerifyCellProofBatch verifies that the blob data corresponds to the provided commitment. +func ckzgVerifyCellProofBatch(blobs []Blob, commitments []Commitment, proof []Proof) error { + panic("unsupported platform") +} + // ckzgComputeCellProofs returns the KZG cell proofs that are used to verify the blob against // the commitment. // diff --git a/crypto/kzg4844/kzg4844_gokzg.go b/crypto/kzg4844/kzg4844_gokzg.go index 46a38a89136d..82ec8379d41e 100644 --- a/crypto/kzg4844/kzg4844_gokzg.go +++ b/crypto/kzg4844/kzg4844_gokzg.go @@ -114,3 +114,37 @@ func gokzgComputeCellProofs(blob *Blob) ([]Proof, error) { } return p, nil } + +// gokzgVerifyCellProofs verifies that the blob data corresponds to the provided commitment. +func gokzgVerifyCellProofBatch(blobs []Blob, commitments []Commitment, cellProofs []Proof) error { + gokzgIniter.Do(gokzgInit) + + var ( + proofs = make([]gokzg4844.KZGProof, len(cellProofs)) + commits = make([]gokzg4844.KZGCommitment, 0, len(cellProofs)) + cellIndices = make([]uint64, 0, len(cellProofs)) + cells = make([]*gokzg4844.Cell, 0, len(cellProofs)) + ) + // Copy over the cell proofs + for i, proof := range cellProofs { + proofs[i] = gokzg4844.KZGProof(proof) + } + // Blow up the commitments to be the same length as the proofs + for _, commitment := range commitments { + for range gokzg4844.CellsPerExtBlob { + commits = append(commits, gokzg4844.KZGCommitment(commitment)) + } + } + // Compute the cell and cell indices + for i := range blobs { + cellsI, err := context.ComputeCells((*gokzg4844.Blob)(&blobs[i]), 2) + if err != nil { + return err + } + cells = append(cells, cellsI[:]...) + for idx := range len(cellsI) { + cellIndices = append(cellIndices, uint64(idx)) + } + } + return context.VerifyCellKZGProofBatch(commits, cellIndices, cells[:], proofs) +} diff --git a/crypto/kzg4844/kzg4844_test.go b/crypto/kzg4844/kzg4844_test.go index 7fa261e523e9..7e73efd85089 100644 --- a/crypto/kzg4844/kzg4844_test.go +++ b/crypto/kzg4844/kzg4844_test.go @@ -193,3 +193,40 @@ func benchmarkVerifyBlobProof(b *testing.B, ckzg bool) { VerifyBlobProof(blob, commitment, proof) } } + +func TestCKZGCells(t *testing.T) { testKZGCells(t, true) } +func TestGoKZGCells(t *testing.T) { testKZGCells(t, false) } +func testKZGCells(t *testing.T, ckzg bool) { + if ckzg && !ckzgAvailable { + t.Skip("CKZG unavailable in this test build") + } + defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) + useCKZG.Store(ckzg) + + blob1 := randBlob() + blob2 := randBlob() + + commitment1, err := BlobToCommitment(blob1) + if err != nil { + t.Fatalf("failed to create KZG commitment from blob: %v", err) + } + commitment2, err := BlobToCommitment(blob2) + if err != nil { + t.Fatalf("failed to create KZG commitment from blob: %v", err) + } + + proofs1, err := ComputeCellProofs(blob1) + if err != nil { + t.Fatalf("failed to create KZG proof at point: %v", err) + } + + proofs2, err := ComputeCellProofs(blob2) + if err != nil { + t.Fatalf("failed to create KZG proof at point: %v", err) + } + proofs := append(proofs1, proofs2...) + blobs := []Blob{*blob1, *blob2} + if err := VerifyCellProofs(blobs, []Commitment{commitment1, commitment2}, proofs); err != nil { + t.Fatalf("failed to verify KZG proof at point: %v", err) + } +} diff --git a/core/rawdb/database_test.go b/crypto/secp256r1/verifier.go similarity index 58% rename from core/rawdb/database_test.go rename to crypto/secp256r1/verifier.go index a0d7b5ec6635..3378af2b21bf 100644 --- a/core/rawdb/database_test.go +++ b/crypto/secp256r1/verifier.go @@ -1,4 +1,4 @@ -// Copyright 2017 The go-ethereum Authors +// 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 @@ -14,4 +14,20 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package rawdb +// Package secp256r1 implements signature verification for the P256VERIFY precompile. +package secp256r1 + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "math/big" +) + +// Verify checks the given signature (r, s) for the given hash and public key (x, y). +func Verify(hash []byte, r, s, x, y *big.Int) bool { + if x == nil || y == nil || !elliptic.P256().IsOnCurve(x, y) { + return false + } + pk := &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y} + return ecdsa.Verify(pk, hash, r, s) +} diff --git a/eth/api_backend.go b/eth/api_backend.go index 8ec19308f938..3ae73e78af18 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -238,7 +238,10 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B } stateDb, err := b.eth.BlockChain().StateAt(header.Root) if err != nil { - return nil, nil, err + stateDb, err = b.eth.BlockChain().HistoricState(header.Root) + if err != nil { + return nil, nil, err + } } return stateDb, header, nil } @@ -260,7 +263,10 @@ func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockN } stateDb, err := b.eth.BlockChain().StateAt(header.Root) if err != nil { - return nil, nil, err + stateDb, err = b.eth.BlockChain().HistoricState(header.Root) + if err != nil { + return nil, nil, err + } } return stateDb, header, nil } @@ -276,6 +282,10 @@ func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (type return b.eth.blockchain.GetReceiptsByHash(hash), nil } +func (b *EthAPIBackend) GetCanonicalReceipt(tx *types.Transaction, blockHash common.Hash, blockNumber, blockIndex uint64) (*types.Receipt, error) { + return b.eth.blockchain.GetCanonicalReceipt(tx, blockHash, blockNumber, blockIndex) +} + func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil } @@ -348,14 +358,16 @@ func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction return b.eth.txPool.Get(hash) } -// GetTransaction retrieves the lookup along with the transaction itself associate -// with the given transaction hash. +// GetCanonicalTransaction retrieves the lookup along with the transaction itself +// associate with the given transaction hash. // // A null will be returned if the transaction is not found. The transaction is not // existent from the node's perspective. This can be due to the transaction indexer // not being finished. The caller must explicitly check the indexer progress. -func (b *EthAPIBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { - lookup, tx := b.eth.blockchain.GetTransactionLookup(txHash) +// +// Notably, only the transaction in the canonical chain is visible. +func (b *EthAPIBackend) GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { + lookup, tx := b.eth.blockchain.GetCanonicalTransaction(txHash) if lookup == nil || tx == nil { return false, nil, common.Hash{}, 0, 0 } @@ -397,6 +409,10 @@ func (b *EthAPIBackend) SyncProgress(ctx context.Context) ethereum.SyncProgress prog.TxIndexFinishedBlocks = txProg.Indexed prog.TxIndexRemainingBlocks = txProg.Remaining } + remain, err := b.eth.blockchain.StateIndexProgress() + if err == nil { + prog.StateIndexRemaining = remain + } return prog } diff --git a/eth/api_backend_test.go b/eth/api_backend_test.go index dfca24aba788..d0718ede1ce2 100644 --- a/eth/api_backend_test.go +++ b/eth/api_backend_test.go @@ -34,7 +34,6 @@ import ( "github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/ethereum/go-ethereum/core/txpool/locals" "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/params" "github.com/holiman/uint256" @@ -61,7 +60,7 @@ func initBackend(withLocal bool) *EthAPIBackend { db = rawdb.NewMemoryDatabase() engine = beacon.New(ethash.NewFaker()) ) - chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil) + chain, _ := core.NewBlockChain(db, gspec, engine, nil) txconfig := legacypool.DefaultConfig txconfig.Journal = "" // Don't litter the disk with test journals diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go index 90fd22498a2e..034026b366a0 100644 --- a/eth/api_debug_test.go +++ b/eth/api_debug_test.go @@ -35,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/tracing" "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/params" "github.com/ethereum/go-ethereum/triedb" @@ -68,15 +67,15 @@ func newTestBlockChain(t *testing.T, n int, gspec *core.Genesis, generator func( _, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator) // Import the canonical chain - cacheConfig := &core.CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, - Preimages: true, - TrieDirtyDisabled: true, // Archive mode + options := &core.BlockChainConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + SnapshotLimit: 0, + Preimages: true, + ArchiveMode: true, // Archive mode } - chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConfig, gspec, nil, engine, vm.Config{}, nil) + chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } diff --git a/eth/backend.go b/eth/backend.go index 7f9e45edeae8..80ffd301cee7 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -21,6 +21,7 @@ import ( "context" "encoding/json" "fmt" + "math" "math/big" "runtime" "sync" @@ -92,6 +93,7 @@ type Ethereum struct { // core protocol objects config *ethconfig.Config txPool *txpool.TxPool + blobTxPool *blobpool.BlobPool localTxTracker *locals.TxTracker blockchain *core.BlockChain @@ -138,7 +140,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice) config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) } - if config.NoPruning && config.TrieDirtyCache > 0 { + if config.NoPruning && config.TrieDirtyCache > 0 && config.StateScheme == rawdb.HashScheme { if config.SnapshotCache > 0 { config.TrieCleanCache += config.TrieDirtyCache * 3 / 5 config.SnapshotCache += config.TrieDirtyCache * 2 / 5 @@ -219,22 +221,24 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } } var ( - vmConfig = vm.Config{ - EnablePreimageRecording: config.EnablePreimageRecording, - } - cacheConfig = &core.CacheConfig{ - TrieCleanLimit: config.TrieCleanCache, - TrieCleanNoPrefetch: config.NoPrefetch, - TrieDirtyLimit: config.TrieDirtyCache, - TrieDirtyDisabled: config.NoPruning, - TrieTimeLimit: config.TrieTimeout, - SnapshotLimit: config.SnapshotCache, - Preimages: config.Preimages, - StateHistory: config.StateHistory, - StateScheme: scheme, - ChainHistoryMode: config.HistoryMode, + options = &core.BlockChainConfig{ + TrieCleanLimit: config.TrieCleanCache, + NoPrefetch: config.NoPrefetch, + TrieDirtyLimit: config.TrieDirtyCache, + ArchiveMode: config.NoPruning, + TrieTimeLimit: config.TrieTimeout, + SnapshotLimit: config.SnapshotCache, + Preimages: config.Preimages, + StateHistory: config.StateHistory, + StateScheme: scheme, + ChainHistoryMode: config.HistoryMode, + TxLookupLimit: int64(min(config.TransactionHistory, math.MaxInt64)), + VmConfig: vm.Config{ + EnablePreimageRecording: config.EnablePreimageRecording, + }, } ) + if config.VMTrace != "" { traceConfig := json.RawMessage("{}") if config.VMTraceJsonConfig != "" { @@ -244,17 +248,19 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if err != nil { return nil, fmt.Errorf("failed to create tracer %s: %v", config.VMTrace, err) } - vmConfig.Tracer = t + options.VmConfig.Tracer = t } // Override the chain config with provided settings. var overrides core.ChainOverrides - if config.OverridePrague != nil { - overrides.OverridePrague = config.OverridePrague + if config.OverrideOsaka != nil { + overrides.OverrideOsaka = config.OverrideOsaka } if config.OverrideVerkle != nil { overrides.OverrideVerkle = config.OverrideVerkle } - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, &config.TransactionHistory) + options.Overrides = &overrides + + eth.blockchain, err = core.NewBlockChain(chainDb, config.Genesis, eth.engine, options) if err != nil { return nil, err } @@ -272,7 +278,11 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if fb := eth.blockchain.CurrentFinalBlock(); fb != nil { finalBlock = fb.Number.Uint64() } - eth.filterMaps = filtermaps.NewFilterMaps(chainDb, chainView, historyCutoff, finalBlock, filtermaps.DefaultParams, fmConfig) + filterMaps, err := filtermaps.NewFilterMaps(chainDb, chainView, historyCutoff, finalBlock, filtermaps.DefaultParams, fmConfig) + if err != nil { + return nil, err + } + eth.filterMaps = filterMaps eth.closeFilterMaps = make(chan chan struct{}) // TxPool @@ -284,9 +294,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if config.BlobPool.Datadir != "" { config.BlobPool.Datadir = stack.ResolvePath(config.BlobPool.Datadir) } - blobPool := blobpool.New(config.BlobPool, eth.blockchain, legacyPool.HasPendingAuth) + eth.blobTxPool = blobpool.New(config.BlobPool, eth.blockchain, legacyPool.HasPendingAuth) - eth.txPool, err = txpool.New(config.TxPool.PriceLimit, eth.blockchain, []txpool.SubPool{legacyPool, blobPool}) + eth.txPool, err = txpool.New(config.TxPool.PriceLimit, eth.blockchain, []txpool.SubPool{legacyPool, eth.blobTxPool}) if err != nil { return nil, err } @@ -302,7 +312,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } // Permit the downloader to use the trie cache allowance during fast sync - cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit + cacheLimit := options.TrieCleanLimit + options.TrieDirtyLimit + options.SnapshotLimit if eth.handler, err = newHandler(&handlerConfig{ NodeID: eth.p2pServer.Self().ID(), Database: chainDb, @@ -395,6 +405,7 @@ func (s *Ethereum) Miner() *miner.Miner { return s.miner } func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool } +func (s *Ethereum) BlobTxPool() *blobpool.BlobPool { return s.blobTxPool } 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 diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 40dae3f6f241..409899d5821b 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -18,6 +18,7 @@ package catalyst import ( + "crypto/sha256" "errors" "fmt" "strconv" @@ -30,10 +31,12 @@ import ( "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/crypto/kzg4844" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/internal/version" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" @@ -92,7 +95,9 @@ var caps = []string{ "engine_getPayloadV2", "engine_getPayloadV3", "engine_getPayloadV4", + "engine_getPayloadV5", "engine_getBlobsV1", + "engine_getBlobsV2", "engine_newPayloadV1", "engine_newPayloadV2", "engine_newPayloadV3", @@ -112,6 +117,17 @@ var caps = []string{ "engine_getClientVersionV1", } +var ( + // Number of blobs requested via getBlobsV2 + getBlobsRequestedCounter = metrics.NewRegisteredCounter("engine/getblobs/requested", nil) + // Number of blobs requested via getBlobsV2 that are present in the blobpool + getBlobsAvailableCounter = metrics.NewRegisteredCounter("engine/getblobs/available", nil) + // Number of times getBlobsV2 responded with “hit” + getBlobsV2RequestHit = metrics.NewRegisteredCounter("engine/getblobs/hit", nil) + // Number of times getBlobsV2 responded with “miss” + getBlobsV2RequestMiss = metrics.NewRegisteredCounter("engine/getblobs/miss", nil) +) + type ConsensusAPI struct { eth *eth.Ethereum @@ -229,7 +245,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa return engine.STATUS_INVALID, attributesErr("missing withdrawals") case params.BeaconRoot == nil: return engine.STATUS_INVALID, attributesErr("missing beacon root") - case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague): + case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague, forks.Osaka): return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun or prague payloads") } } @@ -267,8 +283,14 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl // 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 + log.Warn("Fetching the unknown forkchoice head from network", "hash", update.HeadBlockHash) + retrievedHead, err := api.eth.Downloader().GetHeader(update.HeadBlockHash) + if err != nil { + log.Warn("Could not retrieve unknown head from peers") + return engine.STATUS_SYNCING, nil + } + api.remoteBlocks.put(retrievedHead.Hash(), retrievedHead) + header = retrievedHead } // If the finalized hash is known, we can direct the downloader to move // potentially more data to the freezer from the get go. @@ -450,6 +472,14 @@ func (api *ConsensusAPI) GetPayloadV4(payloadID engine.PayloadID) (*engine.Execu return api.getPayload(payloadID, false) } +// GetPayloadV5 returns a cached payload by id. +func (api *ConsensusAPI) GetPayloadV5(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) @@ -464,14 +494,87 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo if len(hashes) > 128 { return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes))) } - res := make([]*engine.BlobAndProofV1, len(hashes)) + var ( + res = make([]*engine.BlobAndProofV1, len(hashes)) + hasher = sha256.New() + index = make(map[common.Hash]int) + sidecars = api.eth.BlobTxPool().GetBlobs(hashes) + ) + + for i, hash := range hashes { + index[hash] = i + } + for i, sidecar := range sidecars { + if res[i] != nil || sidecar == nil { + // already filled + continue + } + for cIdx, commitment := range sidecar.Commitments { + computed := kzg4844.CalcBlobHashV1(hasher, &commitment) + if idx, ok := index[computed]; ok { + res[idx] = &engine.BlobAndProofV1{ + Blob: sidecar.Blobs[cIdx][:], + Proof: sidecar.Proofs[cIdx][:], + } + } + } + } + return res, nil +} + +// GetBlobsV2 returns a blob from the transaction pool. +func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProofV2, error) { + if len(hashes) > 128 { + return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes))) + } + + available := api.eth.BlobTxPool().AvailableBlobs(hashes) + getBlobsRequestedCounter.Inc(int64(len(hashes))) + getBlobsAvailableCounter.Inc(int64(available)) + // Optimization: check first if all blobs are available, if not, return empty response + if available != len(hashes) { + getBlobsV2RequestMiss.Inc(1) + return nil, nil + } + getBlobsV2RequestHit.Inc(1) + + // pull up the blob hashes + var ( + res = make([]*engine.BlobAndProofV2, len(hashes)) + index = make(map[common.Hash][]int) + sidecars = api.eth.BlobTxPool().GetBlobs(hashes) + ) - blobs, proofs := api.eth.TxPool().GetBlobs(hashes) - for i := 0; i < len(blobs); i++ { - if blobs[i] != nil { - res[i] = &engine.BlobAndProofV1{ - Blob: (*blobs[i])[:], - Proof: (*proofs[i])[:], + for i, hash := range hashes { + index[hash] = append(index[hash], i) + } + for i, sidecar := range sidecars { + if res[i] != nil { + // already filled + continue + } + if sidecar == nil { + // not found, return empty response + return nil, nil + } + if sidecar.Version != 1 { + log.Info("GetBlobs queried V0 transaction: index %v, blobhashes %v", index, sidecar.BlobHashes()) + return nil, nil + } + blobHashes := sidecar.BlobHashes() + for bIdx, hash := range blobHashes { + if idxes, ok := index[hash]; ok { + proofs := sidecar.CellProofsAt(bIdx) + var cellProofs []hexutil.Bytes + for _, proof := range proofs { + cellProofs = append(cellProofs, proof[:]) + } + for _, idx := range idxes { + res[idx] = &engine.BlobAndProofV2{ + Blob: sidecar.Blobs[bIdx][:], + CellProofs: cellProofs, + } + } } } } @@ -544,8 +647,8 @@ func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHas return invalidStatus, paramsErr("nil beaconRoot post-cancun") case executionRequests == nil: return invalidStatus, paramsErr("nil executionRequests post-prague") - case !api.checkFork(params.Timestamp, forks.Prague): - return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") + case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka): + return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague payloads") } requests := convertRequests(executionRequests) if err := validateRequests(requests); err != nil { diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go index b84df9a4d6c0..0642d6a1adad 100644 --- a/eth/catalyst/simulated_beacon.go +++ b/eth/catalyst/simulated_beacon.go @@ -208,6 +208,12 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u return errors.New("chain rewind prevented invocation of payload creation") } + // If the payload was already known, we can skip the rest of the process. + // This edge case is possible due to a race condition between seal and debug.setHead. + if fcResponse.PayloadStatus.Status == engine.VALID && fcResponse.PayloadID == nil { + return nil + } + envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true) if err != nil { return err diff --git a/eth/catalyst/simulated_beacon_api.go b/eth/catalyst/simulated_beacon_api.go index 668780531501..d0115efaa664 100644 --- a/eth/catalyst/simulated_beacon_api.go +++ b/eth/catalyst/simulated_beacon_api.go @@ -70,7 +70,12 @@ func (a *simulatedBeaconAPI) loop() { if executable, _ := a.sim.eth.TxPool().Stats(); executable == 0 { break } - a.sim.Commit() + select { + case <-a.sim.shutdownCh: + return + default: + a.sim.Commit() + } } } }() diff --git a/eth/catalyst/tester.go b/eth/catalyst/tester.go index db2d638701b9..10a480837e25 100644 --- a/eth/catalyst/tester.go +++ b/eth/catalyst/tester.go @@ -34,21 +34,23 @@ import ( // This tester can be applied to different networks, no matter it's pre-merge or // post-merge, but only for full-sync. type FullSyncTester struct { - stack *node.Node - backend *eth.Ethereum - target common.Hash - closed chan struct{} - wg sync.WaitGroup + stack *node.Node + backend *eth.Ethereum + target common.Hash + closed chan struct{} + wg sync.WaitGroup + exitWhenSynced bool } // RegisterFullSyncTester registers the full-sync tester service into the node // stack for launching and stopping the service controlled by node. -func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, target common.Hash) (*FullSyncTester, error) { +func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, target common.Hash, exitWhenSynced bool) (*FullSyncTester, error) { cl := &FullSyncTester{ - stack: stack, - backend: backend, - target: target, - closed: make(chan struct{}), + stack: stack, + backend: backend, + target: target, + closed: make(chan struct{}), + exitWhenSynced: exitWhenSynced, } stack.RegisterLifecycle(cl) return cl, nil @@ -76,7 +78,11 @@ func (tester *FullSyncTester) Start() error { // Stop in case the target block is already stored locally. if block := tester.backend.BlockChain().GetBlockByHash(tester.target); block != nil { log.Info("Full-sync target reached", "number", block.NumberU64(), "hash", block.Hash()) - go tester.stack.Close() // async since we need to close ourselves + + if tester.exitWhenSynced { + go tester.stack.Close() // async since we need to close ourselves + log.Info("Terminating the node") + } return } diff --git a/eth/catalyst/witness.go b/eth/catalyst/witness.go index 570031d98bc0..712539c5e351 100644 --- a/eth/catalyst/witness.go +++ b/eth/catalyst/witness.go @@ -152,7 +152,7 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV4(params engine.ExecutableData, v case executionRequests == nil: return invalidStatus, paramsErr("nil executionRequests post-prague") case !api.checkFork(params.Timestamp, forks.Prague): - return invalidStatus, unsupportedForkErr("newPayloadV3 must only be called for cancun payloads") + return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague payloads") } requests := convertRequests(executionRequests) if err := validateRequests(requests); err != nil { diff --git a/eth/downloader/api.go b/eth/downloader/api.go index ac175672a0ce..c98f9a2c3fe6 100644 --- a/eth/downloader/api.go +++ b/eth/downloader/api.go @@ -81,6 +81,10 @@ func (api *DownloaderAPI) eventLoop() { prog.TxIndexFinishedBlocks = txProg.Indexed prog.TxIndexRemainingBlocks = txProg.Remaining } + remain, err := api.chain.StateIndexProgress() + if err == nil { + prog.StateIndexRemaining = remain + } return prog } ) diff --git a/eth/downloader/beacondevsync.go b/eth/downloader/beacondevsync.go index 9a38fedd463e..0032eb53b966 100644 --- a/eth/downloader/beacondevsync.go +++ b/eth/downloader/beacondevsync.go @@ -21,6 +21,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -48,34 +49,39 @@ func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan st return errors.New("stop requested") default: } - // Pick a random peer to sync from and keep retrying if none are yet - // available due to fresh startup - d.peers.lock.RLock() - var peer *peerConnection - for _, peer = range d.peers.peers { - break + header, err := d.GetHeader(hash) + if err != nil { + time.Sleep(time.Second) + continue } - d.peers.lock.RUnlock() + return d.BeaconSync(mode, header, header) + } +} + +// GetHeader tries to retrieve the header with a given hash from a random peer. +func (d *Downloader) GetHeader(hash common.Hash) (*types.Header, error) { + // Pick a random peer to sync from and keep retrying if none are yet + // available due to fresh startup + d.peers.lock.RLock() + defer d.peers.lock.RUnlock() + for _, peer := range d.peers.peers { if peer == nil { - time.Sleep(time.Second) - continue + return nil, errors.New("could not find peer") } // Found a peer, attempt to retrieve the header whilst blocking and // retry if it fails for whatever reason - log.Info("Attempting to retrieve sync target", "peer", peer.id) + log.Debug("Attempting to retrieve sync target", "peer", peer.id, "hash", hash) headers, metas, err := d.fetchHeadersByHash(peer, hash, 1, 0, false) if err != nil || len(headers) != 1 { - log.Warn("Failed to fetch sync target", "headers", len(headers), "err", err) - time.Sleep(time.Second) continue } // Head header retrieved, if the hash matches, start the actual sync if metas[0] != hash { - log.Error("Received invalid sync target", "want", hash, "have", metas[0]) - time.Sleep(time.Second) + log.Warn("Received invalid sync target", "peer", peer.id, "want", hash, "have", metas[0]) continue } - return d.BeaconSync(mode, headers[0], headers[0]) + return headers[0], nil } + return nil, errors.New("failed to fetch sync target") } diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 762fb9283ea0..dcda4e521cbf 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -199,6 +199,9 @@ type BlockChain interface { // InsertChain inserts a batch of blocks into the local chain. InsertChain(types.Blocks) (int, error) + // InterruptInsert whether disables the chain insertion. + InterruptInsert(on bool) + // InsertReceiptChain inserts a batch of blocks along with their receipts // into the local chain. Blocks older than the specified `ancientLimit` // are stored directly in the ancient store, while newer blocks are stored @@ -532,9 +535,15 @@ func (d *Downloader) syncToHead() (err error) { // If a part of blockchain data has already been written into active store, // disable the ancient style insertion explicitly. - if origin >= frozen && frozen != 0 { + if origin >= frozen && origin != 0 { d.ancientLimit = 0 - log.Info("Disabling direct-ancient mode", "origin", origin, "ancient", frozen-1) + var ancient string + if frozen == 0 { + ancient = "null" + } else { + ancient = fmt.Sprintf("%d", frozen-1) + } + log.Info("Disabling direct-ancient mode", "origin", origin, "ancient", ancient) } else if d.ancientLimit > 0 { log.Debug("Enabling direct-ancient mode", "ancient", d.ancientLimit) } @@ -627,8 +636,10 @@ func (d *Downloader) cancel() { // Cancel aborts all of the operations and waits for all download goroutines to // finish before returning. func (d *Downloader) Cancel() { + d.blockchain.InterruptInsert(true) d.cancel() d.cancelWg.Wait() + d.blockchain.InterruptInsert(false) } // Terminate interrupts the downloader, canceling all pending operations. diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index aeb286b55333..669ce003cfe3 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -30,7 +30,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/event" @@ -68,7 +67,7 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester { Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}}, BaseFee: big.NewInt(params.InitialBaseFee), } - chain, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + chain, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), nil) if err != nil { panic(err) } diff --git a/eth/downloader/skeleton.go b/eth/downloader/skeleton.go index ad74dab84460..206d28414ebd 100644 --- a/eth/downloader/skeleton.go +++ b/eth/downloader/skeleton.go @@ -384,7 +384,7 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) { defer close(done) filled := s.filler.suspend() if filled == nil { - log.Error("Latest filled block is not available") + log.Warn("Latest filled block is not available") return } // If something was filled, try to delete stale sync helpers. If diff --git a/eth/downloader/testchain_test.go b/eth/downloader/testchain_test.go index 8fa2e8341339..ecd7386f42eb 100644 --- a/eth/downloader/testchain_test.go +++ b/eth/downloader/testchain_test.go @@ -27,7 +27,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/triedb" @@ -217,7 +216,7 @@ func newTestBlockchain(blocks []*types.Block) *core.BlockChain { if pregenerated { panic("Requested chain generation outside of init") } - chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, testGspec, nil, ethash.NewFaker(), vm.Config{}, nil) + chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), testGspec, ethash.NewFaker(), nil) if err != nil { panic(err) } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index b6029d497434..97d23744a0ac 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -158,8 +158,8 @@ type Config struct { // send-transaction variants. The unit is ether. RPCTxFeeCap float64 - // OverridePrague (TODO: remove after the fork) - OverridePrague *uint64 `toml:",omitempty"` + // OverrideOsaka (TODO: remove after the fork) + OverrideOsaka *uint64 `toml:",omitempty"` // OverrideVerkle (TODO: remove after the fork) OverrideVerkle *uint64 `toml:",omitempty"` diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 05f07178acf2..0a188ba23c45 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -54,7 +54,7 @@ func (c Config) MarshalTOML() (interface{}, error) { RPCGasCap uint64 RPCEVMTimeout time.Duration RPCTxFeeCap float64 - OverridePrague *uint64 `toml:",omitempty"` + OverrideOsaka *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"` } var enc Config @@ -95,7 +95,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.RPCGasCap = c.RPCGasCap enc.RPCEVMTimeout = c.RPCEVMTimeout enc.RPCTxFeeCap = c.RPCTxFeeCap - enc.OverridePrague = c.OverridePrague + enc.OverrideOsaka = c.OverrideOsaka enc.OverrideVerkle = c.OverrideVerkle return &enc, nil } @@ -140,7 +140,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { RPCGasCap *uint64 RPCEVMTimeout *time.Duration RPCTxFeeCap *float64 - OverridePrague *uint64 `toml:",omitempty"` + OverrideOsaka *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"` } var dec Config @@ -258,8 +258,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.RPCTxFeeCap != nil { c.RPCTxFeeCap = *dec.RPCTxFeeCap } - if dec.OverridePrague != nil { - c.OverridePrague = dec.OverridePrague + if dec.OverrideOsaka != nil { + c.OverrideOsaka = dec.OverrideOsaka } if dec.OverrideVerkle != nil { c.OverrideVerkle = dec.OverrideVerkle diff --git a/eth/filters/api.go b/eth/filters/api.go index f549dc4decdb..232af23957a0 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -40,13 +40,17 @@ var ( errInvalidBlockRange = errors.New("invalid block range params") errPendingLogsUnsupported = errors.New("pending logs are not supported") errExceedMaxTopics = errors.New("exceed max topics") + errExceedMaxAddresses = errors.New("exceed max addresses") ) -// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0 -const maxTopics = 4 - -// The maximum number of allowed topics within a topic criteria -const maxSubTopics = 1000 +const ( + // The maximum number of addresses allowed in a filter criteria + maxAddresses = 1000 + // The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0 + maxTopics = 4 + // The maximum number of allowed topics within a topic criteria + maxSubTopics = 1000 +) // filter is a helper struct that holds meta information over the filter type // and associated subscription in the event system. @@ -341,6 +345,9 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type if len(crit.Topics) > maxTopics { return nil, errExceedMaxTopics } + if len(crit.Addresses) > maxAddresses { + return nil, errExceedMaxAddresses + } var filter *Filter if crit.BlockHash != nil { // Block filter requested, construct a single-shot filter @@ -530,6 +537,9 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error { // raw.Address can contain a single address or an array of addresses switch rawAddr := raw.Addresses.(type) { case []interface{}: + if len(rawAddr) > maxAddresses { + return errExceedMaxAddresses + } for i, addr := range rawAddr { if strAddr, ok := addr.(string); ok { addr, err := decodeAddress(strAddr) diff --git a/eth/filters/api_test.go b/eth/filters/api_test.go index 822bc826f6b0..2eb3ee97b35a 100644 --- a/eth/filters/api_test.go +++ b/eth/filters/api_test.go @@ -19,6 +19,7 @@ package filters import ( "encoding/json" "fmt" + "strings" "testing" "github.com/ethereum/go-ethereum/common" @@ -182,4 +183,15 @@ func TestUnmarshalJSONNewFilterArgs(t *testing.T) { if len(test7.Topics[2]) != 0 { t.Fatalf("expected 0 topics, got %d topics", len(test7.Topics[2])) } + + // multiple address exceeding max + var test8 FilterCriteria + addresses := make([]string, maxAddresses+1) + for i := 0; i < maxAddresses+1; i++ { + addresses[i] = fmt.Sprintf(`"%s"`, common.HexToAddress(fmt.Sprintf("0x%x", i)).Hex()) + } + vector = fmt.Sprintf(`{"address": [%s]}`, strings.Join(addresses, ", ")) + if err := json.Unmarshal([]byte(vector), &test8); err != errExceedMaxAddresses { + t.Fatal("expected errExceedMaxAddresses, got", err) + } } diff --git a/eth/filters/filter.go b/eth/filters/filter.go index dd6643c59e19..ada478ae1d15 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -463,7 +463,7 @@ func (f *Filter) checkMatches(ctx context.Context, header *types.Header) ([]*typ // such as tx index, block hash, etc. // Notably tx hash is NOT filled in because it needs // access to block body data. - cached, err := f.sys.cachedLogElem(ctx, hash, header.Number.Uint64()) + cached, err := f.sys.cachedLogElem(ctx, hash, header.Number.Uint64(), header.Time) if err != nil { return nil, err } diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go index 10e433f09bc7..82c91266c05c 100644 --- a/eth/filters/filter_system.go +++ b/eth/filters/filter_system.go @@ -98,7 +98,7 @@ type logCacheElem struct { } // cachedLogElem loads block logs from the backend and caches the result. -func (sys *FilterSystem) cachedLogElem(ctx context.Context, blockHash common.Hash, number uint64) (*logCacheElem, error) { +func (sys *FilterSystem) cachedLogElem(ctx context.Context, blockHash common.Hash, number, time uint64) (*logCacheElem, error) { cached, ok := sys.logsCache.Get(blockHash) if ok { return cached, nil @@ -119,6 +119,7 @@ func (sys *FilterSystem) cachedLogElem(ctx context.Context, blockHash common.Has for _, log := range txLogs { log.BlockHash = blockHash log.BlockNumber = number + log.BlockTimestamp = time log.TxIndex = uint(i) log.Index = logIdx logIdx++ @@ -290,6 +291,9 @@ func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*typ if len(crit.Topics) > maxTopics { return nil, errExceedMaxTopics } + if len(crit.Addresses) > maxAddresses { + return nil, errExceedMaxAddresses + } var from, to rpc.BlockNumber if crit.FromBlock == nil { from = rpc.LatestBlockNumber diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index 85d4a3391317..10f82364b534 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -175,7 +175,7 @@ func (b *testBackend) startFilterMaps(history uint64, disabled bool, params filt Disabled: disabled, ExportFileName: "", } - b.fm = filtermaps.NewFilterMaps(b.db, chainView, 0, 0, params, config) + b.fm, _ = filtermaps.NewFilterMaps(b.db, chainView, 0, 0, params, config) b.fm.Start() b.fm.WaitIdle() } @@ -435,6 +435,7 @@ func TestInvalidLogFilterCreation(t *testing.T) { 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{{}, {}, {}, {}, {}}}, + 4: {Addresses: make([]common.Address, maxAddresses+1)}, } for i, test := range testCases { @@ -461,6 +462,7 @@ func TestInvalidGetLogsRequest(t *testing.T) { 1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)}, 2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, 3: {BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, + 4: {BlockHash: &blockHash, Addresses: make([]common.Address, maxAddresses+1)}, } for i, test := range testCases { diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index d6065230f8dc..e99b2f6caacd 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -31,7 +31,6 @@ import ( "github.com/ethereum/go-ethereum/core/filtermaps" "github.com/ethereum/go-ethereum/core/rawdb" "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/params" "github.com/ethereum/go-ethereum/rpc" @@ -277,8 +276,9 @@ func testFilters(t *testing.T, history uint64, noHistory bool) { gen.AddTx(tx) } }) - var l uint64 - bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, &l) + options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme) + options.TxLookupLimit = 0 // index all txs + bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options) if err != nil { t.Fatal(err) } @@ -317,26 +317,26 @@ func testFilters(t *testing.T, history uint64, noHistory bool) { }{ { f: sys.NewBlockFilter(chain[2].Hash(), []common.Address{contract}, nil), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`, + want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`, }, { f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{contract}, [][]common.Hash{{hash1, hash2, hash3, hash4}}), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`, + want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`, }, { f: sys.NewRangeFilter(900, 999, []common.Address{contract}, [][]common.Hash{{hash3}}), }, { f: sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{contract2}, [][]common.Hash{{hash3}}), - want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`, + want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false}]`, }, { f: sys.NewRangeFilter(1, 10, []common.Address{contract}, [][]common.Hash{{hash2}, {hash1}}), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`, + want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`, }, { f: sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x0","removed":false},{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xdba3e2ea9a7d690b722d70ee605fd67ba4c00d1d3aecd5cf187a7b92ad8eb3df","transactionIndex":"0x1","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x1","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`, + want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x0","removed":false},{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xdba3e2ea9a7d690b722d70ee605fd67ba4c00d1d3aecd5cf187a7b92ad8eb3df","transactionIndex":"0x1","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","blockTimestamp":"0x14","logIndex":"0x1","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","blockTimestamp":"0x1e","logIndex":"0x0","removed":false}]`, }, { f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}), @@ -349,15 +349,15 @@ func testFilters(t *testing.T, history uint64, noHistory bool) { }, { f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`, + want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`, }, { f: sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), - want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`, + want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","blockTimestamp":"0x2710","logIndex":"0x0","removed":false}]`, }, { f: sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), - want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`, + want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","blockTimestamp":"0x2706","logIndex":"0x0","removed":false}]`, }, { f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), @@ -434,8 +434,10 @@ func TestRangeLogs(t *testing.T) { t.Fatal(err) } chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {}) - var l uint64 - bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, &l) + + options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme) + options.TxLookupLimit = 0 // index all txs + bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options) if err != nil { t.Fatal(err) } diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index 8e6524446fa8..02a25bc4d822 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -30,7 +30,6 @@ import ( "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/crypto" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/event" @@ -212,7 +211,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pe }) // Construct testing chain - chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil) + chain, err := core.NewBlockChain(db, gspec, engine, &core.BlockChainConfig{NoPrefetch: true}) if err != nil { t.Fatalf("Failed to create local chain, %v", err) } diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go index 2446c5fccbb8..058a0d594990 100644 --- a/eth/handler_eth_test.go +++ b/eth/handler_eth_test.go @@ -27,7 +27,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/event" @@ -97,8 +96,8 @@ func testForkIDSplit(t *testing.T, protocol uint) { gspecNoFork = &core.Genesis{Config: configNoFork} gspecProFork = &core.Genesis{Config: configProFork} - chainNoFork, _ = core.NewBlockChain(dbNoFork, nil, gspecNoFork, nil, engine, vm.Config{}, nil) - chainProFork, _ = core.NewBlockChain(dbProFork, nil, gspecProFork, nil, engine, vm.Config{}, nil) + chainNoFork, _ = core.NewBlockChain(dbNoFork, gspecNoFork, engine, nil) + chainProFork, _ = core.NewBlockChain(dbProFork, gspecProFork, engine, nil) _, blocksNoFork, _ = core.GenerateChainWithGenesis(gspecNoFork, engine, 2, nil) _, blocksProFork, _ = core.GenerateChainWithGenesis(gspecProFork, engine, 2, nil) diff --git a/eth/handler_test.go b/eth/handler_test.go index fb3103f241ef..d0da098430b7 100644 --- a/eth/handler_test.go +++ b/eth/handler_test.go @@ -27,7 +27,6 @@ import ( "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/crypto" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/ethdb" @@ -182,7 +181,7 @@ func newTestHandlerWithBlocks(blocks int) *testHandler { Config: params.TestChainConfig, Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}}, } - chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + chain, _ := core.NewBlockChain(db, gspec, ethash.NewFaker(), nil) _, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blocks, nil) if _, err := chain.InsertChain(bs); err != nil { diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index 2fa10dfa9d3c..a3419d96ff82 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -35,7 +35,6 @@ import ( "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" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/ethdb" @@ -120,7 +119,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, cancun bool, generat Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}}, Difficulty: common.Big0, } - chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil) + chain, _ := core.NewBlockChain(db, gspec, engine, nil) _, bs, _ := core.GenerateChainWithGenesis(gspec, engine, blocks, generator) if _, err := chain.InsertChain(bs); err != nil { diff --git a/eth/protocols/snap/handler_fuzzing_test.go b/eth/protocols/snap/handler_fuzzing_test.go index 777db6387c90..4930ae9ae625 100644 --- a/eth/protocols/snap/handler_fuzzing_test.go +++ b/eth/protocols/snap/handler_fuzzing_test.go @@ -29,7 +29,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" @@ -117,16 +116,16 @@ func getChain() *core.BlockChain { Alloc: ga, } _, blocks, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *core.BlockGen) {}) - cacheConf := &core.CacheConfig{ - TrieCleanLimit: 0, - TrieDirtyLimit: 0, - TrieTimeLimit: 5 * time.Minute, - TrieCleanNoPrefetch: true, - SnapshotLimit: 100, - SnapshotWait: true, + options := &core.BlockChainConfig{ + TrieCleanLimit: 0, + TrieDirtyLimit: 0, + TrieTimeLimit: 5 * time.Minute, + NoPrefetch: true, + SnapshotLimit: 100, + SnapshotWait: true, } trieRoot = blocks[len(blocks)-1].Root() - bc, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConf, gspec, nil, ethash.NewFaker(), vm.Config{}, nil) + bc, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), gspec, ethash.NewFaker(), options) if _, err := bc.InsertChain(blocks); err != nil { panic(err) } diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 3c3e79a58417..79c91043a3c7 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -182,10 +182,11 @@ func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), erro if err == nil { return statedb, noopReleaser, nil } - // TODO historic state is not supported in path-based scheme. - // Fully archive node in pbss will be implemented by relying - // on state history, but needs more work on top. - return nil, nil, errors.New("historical state not available in path scheme yet") + statedb, err = eth.blockchain.HistoricState(block.Root()) + if err == nil { + return statedb, noopReleaser, nil + } + return nil, nil, errors.New("historical state is not available") } // stateAtBlock retrieves the state database associated with a certain block. diff --git a/eth/tracers/api.go b/eth/tracers/api.go index fe72924828e6..696202334369 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -82,7 +82,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(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) + GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) TxIndexDone() bool RPCGasCap() uint64 ChainConfig() *params.ChainConfig @@ -863,7 +863,7 @@ 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) { - found, _, blockHash, blockNumber, index := api.backend.GetTransaction(hash) + found, _, blockHash, blockNumber, index := api.backend.GetCanonicalTransaction(hash) if !found { // Warn in case tx indexer is not done. if !api.backend.TxIndexDone() { @@ -889,11 +889,11 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config * return nil, err } defer release() + msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee()) if err != nil { return nil, err } - txctx := &Context{ BlockHash: blockHash, BlockNumber: block.Number(), @@ -1041,7 +1041,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor // Call Prepare to clear out the statedb access list statedb.SetTxContext(txctx.TxHash, txctx.TxIndex) - _, err = core.ApplyTransactionWithEVM(message, new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, evm) + _, err = core.ApplyTransactionWithEVM(message, new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, vmctx.Time, tx, &usedGas, evm) if err != nil { return nil, fmt.Errorf("tracing failed: %w", err) } diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index d20d5eaff656..076e6fd8d4f9 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -77,14 +77,14 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i i _, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator) // Import the canonical chain - cacheConfig := &core.CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, - TrieDirtyDisabled: true, // Archive mode + options := &core.BlockChainConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + SnapshotLimit: 0, + ArchiveMode: true, // Archive mode } - chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil) + chain, err := core.NewBlockChain(backend.chaindb, gspec, backend.engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -117,8 +117,8 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) return b.chain.GetBlockByNumber(uint64(number)), nil } -func (b *testBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { - tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash) +func (b *testBackend) GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { + tx, hash, blockNumber, index := rawdb.ReadCanonicalTransaction(b.chaindb, txHash) return tx != nil, tx, hash, blockNumber, index } @@ -1144,14 +1144,14 @@ func newTestMergedBackend(t *testing.T, n int, gspec *core.Genesis, generator fu _, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator) // Import the canonical chain - cacheConfig := &core.CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, - TrieDirtyDisabled: true, // Archive mode + options := &core.BlockChainConfig{ + TrieCleanLimit: 256, + TrieDirtyLimit: 256, + TrieTimeLimit: 5 * time.Minute, + SnapshotLimit: 0, + ArchiveMode: true, // Archive mode } - chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil) + chain, err := core.NewBlockChain(backend.chaindb, gspec, backend.engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index b2486661e41d..70da34f4272f 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -321,7 +321,7 @@ func TestInternals(t *testing.T) { byte(vm.LOG0), }, tracer: mkTracer("prestateTracer", nil), - want: fmt.Sprintf(`{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52634000"}}`, originHex), + want: fmt.Sprintf(`{"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52634000"}}`, originHex), }, { // CREATE2 which requires padding memory by prestate tracer @@ -340,7 +340,7 @@ func TestInternals(t *testing.T) { byte(vm.LOG0), }, tracer: mkTracer("prestateTracer", nil), - want: fmt.Sprintf(`{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600160ff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52634000"}}`, originHex), + want: fmt.Sprintf(`{"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600160ff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52634000"}}`, originHex), }, } { t.Run(tc.name, func(t *testing.T) { diff --git a/eth/tracers/internal/tracetest/supply_test.go b/eth/tracers/internal/tracetest/supply_test.go index 57ba628b787b..8aedc9d5643a 100644 --- a/eth/tracers/internal/tracetest/supply_test.go +++ b/eth/tracers/internal/tracetest/supply_test.go @@ -554,7 +554,9 @@ func testSupplyTracer(t *testing.T, genesis *core.Genesis, gen func(*core.BlockG return nil, nil, fmt.Errorf("failed to create call tracer: %v", err) } - chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), core.DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, engine, vm.Config{Tracer: tracer}, nil) + options := core.DefaultConfig().WithStateScheme(rawdb.PathScheme) + options.VmConfig = vm.Config{Tracer: tracer} + chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), genesis, engine, options) if err != nil { return nil, nil, fmt.Errorf("failed to create tester chain: %v", err) } diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/7702_delegate.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/7702_delegate.json new file mode 100644 index 000000000000..14874dcc0775 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/7702_delegate.json @@ -0,0 +1,135 @@ +{ + "genesis": { + "baseFeePerGas": "0x389ef14a", + "blobGasUsed": "0x120000", + "difficulty": "0x0", + "excessBlobGas": "0x20000", + "extraData": "0x6265617665726275696c642e6f7267", + "gasLimit": "0x225da53", + "hash": "0x9c1d4eb19d30fa830e02493f5108ddfd49f2736983cecb6b3748b79e78f98d14", + "miner": "0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5", + "mixHash": "0x82bbbb55d5e4edf221aadaefe697f265210cc4afd8a0fa977769da5be8c100c0", + "nonce": "0x0000000000000000", + "number": "0x15b589d", + "parentBeaconBlockRoot": "0x64c714ee5b2d66ea6fd1f6633e41bf2863955c0b7a9e925a241f5e4e3c19f81e", + "requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "stateRoot": "0x5c700c05128ae491d83b5602fd96f0faa487562441bef96ec9474c144820ed10", + "timestamp": "0x6858a55f", + "alloc": { + "0x17816e9a858b161c3e37016d139cf618056cacd4": { + "balance": "0x0", + "code": "0xef0100b684710e6d5914ad6e64493de2a3c424cc43e970", + "nonce": 15809 + }, + "0x236501327e701692a281934230af0b6be8df3353": { + "balance": "0x0", + "code": "0x6080604052600a600c565b005b60186014601a565b605e565b565b600060597f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e808015607c573d6000f35b3d6000fdfea26469706673582212200b737106e31d6abde738d261a4c4f12fcdfac5141ebc6ab5ffe4cf6e1630aaed64736f6c63430008140033", + "nonce": 1, + "storage": { + "0x078d9cc432fb3eab476f678ef9a73d8ca570f23897c68eb99b2721ebf46e5a9e": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000bdb50eff425fb2b1b67fea21b8420eeb6d99ccc0", + "0x5555c0547520ec9521cc3134a71677625cdeb6accbb330321dcaf2cbc22c1fe9": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x84fdd52031be5dc8bcfa0ffd090a0bf85ef922e1fa9d026be0cf5716edafb4db": "0x0000000000000000000000000000000000000000007b74591c97f086c1057bee", + "0x8c854b3845c254f768d5435bc89fa04fb52bd2f72a1cf4370b962cf104ecd5fc": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xc45aef11733ee3a84cf02368a8b99ca24b1e3bfc2f5f532a1a2439aa077d2843": "0x000000000000000000000000000000000000000000000738cda8f7729a2a8a1e", + "0xda699a88dd51ba5e1d66c40fd985a4ad1511875941c3dd2936300679d596ab7b": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97": { + "balance": "0x8c2e6837fe7fb165", + "nonce": 1874580 + }, + "0xb684710e6d5914ad6e64493de2a3c424cc43e970": { + "balance": "0x0", + "code": "0x60806040525f4711156100b6575f3273ffffffffffffffffffffffffffffffffffffffff16476040516100319061048b565b5f6040518083038185875af1925050503d805f811461006b576040519150601f19603f3d011682016040523d82523d5f602084013e610070565b606091505b50509050806100b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ab906104f9565b60405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff80166001336100da9190610563565b73ffffffffffffffffffffffffffffffffffffffff161115610131576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610128906105f4565b60405180910390fd5b73b9df4a9ba45917e71d664d51462d46926e4798e873ffffffffffffffffffffffffffffffffffffffff166001336101699190610563565b73ffffffffffffffffffffffffffffffffffffffff160361045c575f8036906101929190610631565b5f1c90505f73cda6461f1a30c618373f5790a83e1569fb685cba73ffffffffffffffffffffffffffffffffffffffff16631f3a71ba306040518263ffffffff1660e01b81526004016101e491906106af565b602060405180830381865afa1580156101ff573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022391906106ff565b90508181106104595773cda6461f1a30c618373f5790a83e1569fb685cba73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb5f836040518363ffffffff1660e01b815260040161027b929190610739565b6020604051808303815f875af1158015610297573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102bb9190610795565b6102fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102f1906104f9565b60405180910390fd5b5f73236501327e701692a281934230af0b6be8df335373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161034891906106af565b602060405180830381865afa158015610363573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038791906106ff565b905073236501327e701692a281934230af0b6be8df335373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb32836040518363ffffffff1660e01b81526004016103d8929190610739565b6020604051808303815f875af11580156103f4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104189190610795565b610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044e9061080a565b60405180910390fd5b505b50505b005b5f81905092915050565b50565b5f6104765f8361045e565b915061048182610468565b5f82019050919050565b5f6104958261046b565b9150819050919050565b5f82825260208201905092915050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f6104e3600f8361049f565b91506104ee826104af565b602082019050919050565b5f6020820190508181035f830152610510816104d7565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61056d82610517565b915061057883610517565b9250828201905073ffffffffffffffffffffffffffffffffffffffff8111156105a4576105a3610536565b5b92915050565b7f50616e69632831372900000000000000000000000000000000000000000000005f82015250565b5f6105de60098361049f565b91506105e9826105aa565b602082019050919050565b5f6020820190508181035f83015261060b816105d2565b9050919050565b5f82905092915050565b5f819050919050565b5f82821b905092915050565b5f61063c8383610612565b82610647813561061c565b92506020821015610687576106827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802610625565b831692505b505092915050565b5f61069982610517565b9050919050565b6106a98161068f565b82525050565b5f6020820190506106c25f8301846106a0565b92915050565b5f80fd5b5f819050919050565b6106de816106cc565b81146106e8575f80fd5b50565b5f815190506106f9816106d5565b92915050565b5f60208284031215610714576107136106c8565b5b5f610721848285016106eb565b91505092915050565b610733816106cc565b82525050565b5f60408201905061074c5f8301856106a0565b610759602083018461072a565b9392505050565b5f8115159050919050565b61077481610760565b811461077e575f80fd5b50565b5f8151905061078f8161076b565b92915050565b5f602082840312156107aa576107a96106c8565b5b5f6107b784828501610781565b91505092915050565b7f546f6b656e207472616e73666572206661696c656400000000000000000000005f82015250565b5f6107f460158361049f565b91506107ff826107c0565b602082019050919050565b5f6020820190508181035f830152610821816107e8565b905091905056fea2646970667358221220b6a06cc7b930dc4e34352a145f3548d57ec5a60d0097c1979ef363376bf9a69164736f6c63430008140033", + "nonce": 1 + }, + "0xb9df4a9ba45917e71d664d51462d46926e4798e7": { + "balance": "0x597af049b190a724", + "code": "0xef0100000000009b1d0af20d8c6d0a44e162d11f9b8f00", + "nonce": 1887 + }, + "0xbdb50eff425fb2b1b67fea21b8420eeb6d99ccc0": { + "balance": "0x0", + "code": "0x6080604052600436106101cd5760003560e01c80637ecebe00116100f7578063a9059cbb11610095578063d505accf11610064578063d505accf146105b2578063dd62ed3e146105d2578063f1127ed814610637578063f2fde38b1461068357600080fd5b8063a9059cbb14610509578063ad3cb1cc14610529578063b119490e14610572578063c3cda5201461059257600080fd5b80638e539e8c116100d15780638e539e8c1461048857806391ddadf4146104a857806395d89b41146104d45780639ab24eb0146104e957600080fd5b80637ecebe001461040357806384b0196e146104235780638da5cb5b1461044b57600080fd5b80634bf5d7e91161016f5780635c19a95c1161013e5780635c19a95c146103795780636fcfff451461039957806370a08231146103ce578063715018a6146103ee57600080fd5b80634bf5d7e9146102dc5780634f1ef286146102f157806352d1902d14610306578063587cde1e1461031b57600080fd5b806323b872dd116101ab57806323b872dd1461026b578063313ce5671461028b5780633644e515146102a75780633a46b1a8146102bc57600080fd5b806306fdde03146101d2578063095ea7b3146101fd57806318160ddd1461022d575b600080fd5b3480156101de57600080fd5b506101e76106a3565b6040516101f49190612a81565b60405180910390f35b34801561020957600080fd5b5061021d610218366004612ab0565b61075e565b60405190151581526020016101f4565b34801561023957600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016101f4565b34801561027757600080fd5b5061021d610286366004612ada565b610778565b34801561029757600080fd5b50604051601281526020016101f4565b3480156102b357600080fd5b5061025d61079e565b3480156102c857600080fd5b5061025d6102d7366004612ab0565b6107ad565b3480156102e857600080fd5b506101e7610845565b6103046102ff366004612ba2565b6108d6565b005b34801561031257600080fd5b5061025d6108f5565b34801561032757600080fd5b50610361610336366004612c04565b6001600160a01b03908116600090815260008051602061312283398151915260205260409020541690565b6040516001600160a01b0390911681526020016101f4565b34801561038557600080fd5b50610304610394366004612c04565b610924565b3480156103a557600080fd5b506103b96103b4366004612c04565b61092f565b60405163ffffffff90911681526020016101f4565b3480156103da57600080fd5b5061025d6103e9366004612c04565b61093a565b3480156103fa57600080fd5b5061030461097f565b34801561040f57600080fd5b5061025d61041e366004612c04565b610993565b34801561042f57600080fd5b5061043861099e565b6040516101f49796959493929190612c1f565b34801561045757600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610361565b34801561049457600080fd5b5061025d6104a3366004612cd1565b610a9a565b3480156104b457600080fd5b506104bd610b16565b60405165ffffffffffff90911681526020016101f4565b3480156104e057600080fd5b506101e7610b20565b3480156104f557600080fd5b5061025d610504366004612c04565b610b71565b34801561051557600080fd5b5061021d610524366004612ab0565b610bd1565b34801561053557600080fd5b506101e76040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b34801561057e57600080fd5b5061030461058d366004612d0a565b610bdf565b34801561059e57600080fd5b506103046105ad366004612d88565b610d4b565b3480156105be57600080fd5b506103046105cd366004612de0565b610e21565b3480156105de57600080fd5b5061025d6105ed366004612e4a565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b34801561064357600080fd5b50610657610652366004612e7d565b610fac565b60408051825165ffffffffffff1681526020928301516001600160d01b031692810192909252016101f4565b34801561068f57600080fd5b5061030461069e366004612c04565b610fca565b606060007f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace005b90508060030180546106da90612ebd565b80601f016020809104026020016040519081016040528092919081815260200182805461070690612ebd565b80156107535780601f1061072857610100808354040283529160200191610753565b820191906000526020600020905b81548152906001019060200180831161073657829003601f168201915b505050505091505090565b60003361076c818585611021565b60019150505b92915050565b600033610786858285611033565b6107918585856110e9565b60019150505b9392505050565b60006107a8611161565b905090565b6000600080516020613122833981519152816107c7610b16565b90508065ffffffffffff16841061080757604051637669fc0f60e11b81526004810185905265ffffffffffff821660248201526044015b60405180910390fd5b6108336108138561116b565b6001600160a01b03871660009081526001850160205260409020906111a2565b6001600160d01b031695945050505050565b606061084f61125b565b65ffffffffffff1661085f610b16565b65ffffffffffff161461089e576040517f6ff0714000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b6108de611266565b6108e78261131d565b6108f18282611325565b5050565b60006108ff61140d565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b336108f18183611456565b600061077282611513565b6000807f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace005b6001600160a01b0390931660009081526020939093525050604090205490565b610987611564565b61099160006115d8565b565b600061077282611656565b600060608082808083817fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10080549091501580156109dd57506001810154155b610a43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a6564000000000000000000000060448201526064016107fe565b610a4b611661565b610a536116b2565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009c939b5091995046985030975095509350915050565b600060008051602061312283398151915281610ab4610b16565b90508065ffffffffffff168410610aef57604051637669fc0f60e11b81526004810185905265ffffffffffff821660248201526044016107fe565b610b05610afb8561116b565b60028401906111a2565b6001600160d01b0316949350505050565b60006107a861125b565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060917f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00916106da90612ebd565b6001600160a01b03811660009081527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d016020526040812060008051602061312283398151915290610bc1906116dc565b6001600160d01b03169392505050565b60003361076c8185856110e9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610c2a5750825b905060008267ffffffffffffffff166001148015610c475750303b155b905081158015610c55575080155b15610c8c576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610cc057845468ff00000000000000001916680100000000000000001785555b610cca8888611718565b610cd38861172a565b610cdb611771565b610ce433611779565b610cec611771565b610cf6338761178a565b8315610d4157845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b83421115610d88576040517f4683af0e000000000000000000000000000000000000000000000000000000008152600481018590526024016107fe565b604080517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60208201526001600160a01b038816918101919091526060810186905260808101859052600090610e0290610dfa9060a001604051602081830303815290604052805190602001206117c0565b858585611808565b9050610e0e8187611836565b610e188188611456565b50505050505050565b83421115610e5e576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024016107fe565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610eca8c6001600160a01b031660009081527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb006020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610f25826117c0565b90506000610f3582878787611808565b9050896001600160a01b0316816001600160a01b031614610f95576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b1660248201526044016107fe565b610fa08a8a8a611021565b50505050505050505050565b604080518082019091526000808252602082015261079783836118c1565b610fd2611564565b6001600160a01b038116611015576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024016107fe565b61101e816115d8565b50565b61102e838383600161192c565b505050565b6001600160a01b0383811660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace01602090815260408083209386168352929052205460001981146110e357818110156110d4576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260248101829052604481018390526064016107fe565b6110e38484848403600061192c565b50505050565b6001600160a01b03831661112c576040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600060048201526024016107fe565b6001600160a01b0382166111565760405163ec442f0560e01b8152600060048201526024016107fe565b61102e838383611a58565b60006107a8611a63565b600065ffffffffffff82111561119e576040516306dfcc6560e41b815260306004820152602481018390526044016107fe565b5090565b8154600090818160058111156112015760006111bd84611ad7565b6111c79085612f0d565b60008881526020902090915081015465ffffffffffff90811690871610156111f1578091506111ff565b6111fc816001612f20565b92505b505b600061120f87878585611bbf565b9050801561124d5761123487611226600184612f0d565b600091825260209091200190565b54660100000000000090046001600160d01b0316611250565b60005b979650505050505050565b60006107a84361116b565b306001600160a01b037f000000000000000000000000bdb50eff425fb2b1b67fea21b8420eeb6d99ccc01614806112ff57507f000000000000000000000000bdb50eff425fb2b1b67fea21b8420eeb6d99ccc06001600160a01b03166112f37f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156109915760405163703e46dd60e11b815260040160405180910390fd5b61101e611564565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561137f575060408051601f3d908101601f1916820190925261137c91810190612f33565b60015b6113a757604051634c9c8ce360e01b81526001600160a01b03831660048201526024016107fe565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611403576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016107fe565b61102e8383611c21565b306001600160a01b037f000000000000000000000000bdb50eff425fb2b1b67fea21b8420eeb6d99ccc016146109915760405163703e46dd60e11b815260040160405180910390fd5b6000805160206131228339815191526000611496846001600160a01b03908116600090815260008051602061312283398151915260205260409020541690565b6001600160a01b03858116600081815260208690526040808220805473ffffffffffffffffffffffffffffffffffffffff1916898616908117909155905194955093928516927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a46110e3818461150e87611c77565b611c82565b6001600160a01b03811660009081527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d0160205260408120546000805160206131228339815191529061079790611dfc565b336115967f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610991576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016107fe565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b600061077282611e2d565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100916106da90612ebd565b606060007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1006106c9565b8054600090801561170f576116f683611226600184612f0d565b54660100000000000090046001600160d01b0316610797565b60009392505050565b611720611e56565b6108f18282611ebd565b611732611e56565b61101e816040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250611f20565b610991611e56565b611781611e56565b61101e81611f93565b6001600160a01b0382166117b45760405163ec442f0560e01b8152600060048201526024016107fe565b6108f160008383611a58565b60006107726117cd611161565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b60008060008061181a88888888611f9b565b92509250925061182a828261206a565b50909695505050505050565b6001600160a01b03821660009081527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb006020526040902080546001810190915581811461102e576040517f752d88c00000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044016107fe565b604080518082018252600080825260208083018290526001600160a01b03861682527fe8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d0190529190912060008051602061312283398151915290611924908461216e565b949350505050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace006001600160a01b038516611990576040517fe602df05000000000000000000000000000000000000000000000000000000008152600060048201526024016107fe565b6001600160a01b0384166119d3576040517f94280d62000000000000000000000000000000000000000000000000000000008152600060048201526024016107fe565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611a5157836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051611a4891815260200190565b60405180910390a35b5050505050565b61102e8383836121e1565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611a8e612280565b611a966122fc565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600081600003611ae957506000919050565b60006001611af684612352565b901c6001901b90506001818481611b0f57611b0f612f4c565b048201901c90506001818481611b2757611b27612f4c565b048201901c90506001818481611b3f57611b3f612f4c565b048201901c90506001818481611b5757611b57612f4c565b048201901c90506001818481611b6f57611b6f612f4c565b048201901c90506001818481611b8757611b87612f4c565b048201901c90506001818481611b9f57611b9f612f4c565b048201901c905061079781828581611bb957611bb9612f4c565b046123e6565b60005b81831015611c19576000611bd684846123fc565b60008781526020902090915065ffffffffffff86169082015465ffffffffffff161115611c0557809250611c13565b611c10816001612f20565b93505b50611bc2565b509392505050565b611c2a82612417565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115611c6f5761102e828261249b565b6108f1612511565b60006107728261093a565b6000805160206131228339815191526001600160a01b0384811690841614801590611cad5750600082115b156110e3576001600160a01b03841615611d57576001600160a01b038416600090815260018201602052604081208190611cf290612549611ced87612555565b612589565b6001600160d01b031691506001600160d01b03169150856001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051611d4c929190918252602082015260400190565b60405180910390a250505b6001600160a01b038316156110e3576001600160a01b038316600090815260018201602052604081208190611d92906125c2611ced87612555565b6001600160d01b031691506001600160d01b03169150846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a7248383604051611dec929190918252602082015260400190565b60405180910390a2505050505050565b600063ffffffff82111561119e576040516306dfcc6560e41b815260206004820152602481018390526044016107fe565b6000807f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb0061095f565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610991576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ec5611e56565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace007f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03611f118482612fb0565b50600481016110e38382612fb0565b611f28611e56565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102611f748482612fb0565b5060038101611f838382612fb0565b5060008082556001909101555050565b610fd2611e56565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611fd65750600091506003905082612060565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561202a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661205657506000925060019150829050612060565b9250600091508190505b9450945094915050565b600082600381111561207e5761207e613070565b03612087575050565b600182600381111561209b5761209b613070565b036120d2576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028260038111156120e6576120e6613070565b03612120576040517ffce698f7000000000000000000000000000000000000000000000000000000008152600481018290526024016107fe565b600382600381111561213457612134613070565b036108f1576040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600481018290526024016107fe565b6040805180820190915260008082526020820152826000018263ffffffff168154811061219d5761219d613086565b60009182526020918290206040805180820190915291015465ffffffffffff81168252660100000000000090046001600160d01b0316918101919091529392505050565b6121ec8383836125ce565b6001600160a01b0383166122755760006122247f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025490565b90506001600160d01b0380821115612272576040517f1cb15d2600000000000000000000000000000000000000000000000000000000815260048101839052602481018290526044016107fe565b50505b61102e838383612737565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100816122ac611661565b8051909150156122c457805160209091012092915050565b815480156122d3579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100816123286116b2565b80519091501561234057805160209091012092915050565b600182015480156122d3579392505050565b600080608083901c1561236757608092831c92015b604083901c1561237957604092831c92015b602083901c1561238b57602092831c92015b601083901c1561239d57601092831c92015b600883901c156123af57600892831c92015b600483901c156123c157600492831c92015b600283901c156123d357600292831c92015b600183901c156107725760010192915050565b60008183106123f55781610797565b5090919050565b600061240b600284841861309c565b61079790848416612f20565b806001600160a01b03163b60000361244d57604051634c9c8ce360e01b81526001600160a01b03821660048201526024016107fe565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516124b891906130be565b600060405180830381855af49150503d80600081146124f3576040519150601f19603f3d011682016040523d82523d6000602084013e6124f8565b606091505b50915091506125088583836127cd565b95945050505050565b3415610991576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061079782846130da565b60006001600160d01b0382111561119e576040516306dfcc6560e41b815260d06004820152602481018390526044016107fe565b6000806125b5612597610b16565b6125ad6125a3886116dc565b868863ffffffff16565b879190612842565b915091505b935093915050565b60006107978284613101565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace006001600160a01b03841661261c57818160020160008282546126119190612f20565b909155506126a79050565b6001600160a01b03841660009081526020829052604090205482811015612688576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b038616600482015260248101829052604481018490526064016107fe565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b0383166126c55760028101805483900390556126e4565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161272991815260200190565b60405180910390a350505050565b6000805160206131228339815191526001600160a01b03841661276a57612767816002016125c2611ced85612555565b50505b6001600160a01b03831661278e5761278b81600201612549611ced85612555565b50505b6001600160a01b03848116600090815260008051602061312283398151915260205260408082205486841683529120546110e392918216911684611c82565b6060826127e2576127dd82612850565b610797565b81511580156127f957506001600160a01b0384163b155b1561283b576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016107fe565b5080610797565b6000806125b5858585612892565b8051156128605780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8254600090819080156129d35760006128b087611226600185612f0d565b60408051808201909152905465ffffffffffff80821680845266010000000000009092046001600160d01b031660208401529192509087161015612920576040517f2520601d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805165ffffffffffff80881691160361296f578461294388611226600186612f0d565b80546001600160d01b039290921666010000000000000265ffffffffffff9092169190911790556129c3565b6040805180820190915265ffffffffffff80881682526001600160d01b0380881660208085019182528b54600181018d5560008d815291909120945191519092166601000000000000029216919091179101555b6020015192508391506125ba9050565b50506040805180820190915265ffffffffffff80851682526001600160d01b0380851660208085019182528854600181018a5560008a81529182209551925190931666010000000000000291909316179201919091559050816125ba565b60005b83811015612a4c578181015183820152602001612a34565b50506000910152565b60008151808452612a6d816020860160208601612a31565b601f01601f19169290920160200192915050565b6020815260006107976020830184612a55565b80356001600160a01b0381168114612aab57600080fd5b919050565b60008060408385031215612ac357600080fd5b612acc83612a94565b946020939093013593505050565b600080600060608486031215612aef57600080fd5b612af884612a94565b9250612b0660208501612a94565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115612b4757612b47612b16565b604051601f8501601f19908116603f01168101908282118183101715612b6f57612b6f612b16565b81604052809350858152868686011115612b8857600080fd5b858560208301376000602087830101525050509392505050565b60008060408385031215612bb557600080fd5b612bbe83612a94565b9150602083013567ffffffffffffffff811115612bda57600080fd5b8301601f81018513612beb57600080fd5b612bfa85823560208401612b2c565b9150509250929050565b600060208284031215612c1657600080fd5b61079782612a94565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e081840152612c5b60e084018a612a55565b8381036040850152612c6d818a612a55565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015612cbf57835183529284019291840191600101612ca3565b50909c9b505050505050505050505050565b600060208284031215612ce357600080fd5b5035919050565b600082601f830112612cfb57600080fd5b61079783833560208501612b2c565b600080600060608486031215612d1f57600080fd5b833567ffffffffffffffff80821115612d3757600080fd5b612d4387838801612cea565b94506020860135915080821115612d5957600080fd5b50612d6686828701612cea565b925050604084013590509250925092565b803560ff81168114612aab57600080fd5b60008060008060008060c08789031215612da157600080fd5b612daa87612a94565b95506020870135945060408701359350612dc660608801612d77565b92506080870135915060a087013590509295509295509295565b600080600080600080600060e0888a031215612dfb57600080fd5b612e0488612a94565b9650612e1260208901612a94565b95506040880135945060608801359350612e2e60808901612d77565b925060a0880135915060c0880135905092959891949750929550565b60008060408385031215612e5d57600080fd5b612e6683612a94565b9150612e7460208401612a94565b90509250929050565b60008060408385031215612e9057600080fd5b612e9983612a94565b9150602083013563ffffffff81168114612eb257600080fd5b809150509250929050565b600181811c90821680612ed157607f821691505b602082108103612ef157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561077257610772612ef7565b8082018082111561077257610772612ef7565b600060208284031215612f4557600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b601f82111561102e57600081815260208120601f850160051c81016020861015612f895750805b601f850160051c820191505b81811015612fa857828155600101612f95565b505050505050565b815167ffffffffffffffff811115612fca57612fca612b16565b612fde81612fd88454612ebd565b84612f62565b602080601f8311600181146130135760008415612ffb5750858301515b600019600386901b1c1916600185901b178555612fa8565b600085815260208120601f198616915b8281101561304257888601518255948401946001909101908401613023565b50858210156130605787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000826130b957634e487b7160e01b600052601260045260246000fd5b500490565b600082516130d0818460208701612a31565b9190910192915050565b6001600160d01b038281168282160390808211156130fa576130fa612ef7565b5092915050565b6001600160d01b038181168382160190808211156130fa576130fa612ef756fee8b26c30fad74198956032a3533d903385d56dd795af560196f9c78d4af40d00a2646970667358221220c2a4c7c504a36ab9781f5fb312d81d27f781047ab9f97621c7f031a185ecb78864736f6c63430008140033", + "nonce": 1 + }, + "0xcda6461f1a30c618373f5790a83e1569fb685cba": { + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063313ce5671161008c578063a9059cbb11610066578063a9059cbb146102ab578063dd62ed3e146102be578063e6fd48bc146102d4578063fc0c546a146102fb57600080fd5b8063313ce567146101f857806370a082311461023157806395d89b411461025157600080fd5b80631514617e116100c85780631514617e146101a857806318160ddd146101cf5780631f3a71ba146101d757806323b872dd146101ea57600080fd5b80630483a7f6146100ef57806306fdde0314610122578063095ea7b314610185575b600080fd5b61010f6100fd366004610926565b60006020819052908152604090205481565b6040519081526020015b60405180910390f35b604080517f466c75656e636520546f6b656e20284c6f636b65642900000000000000000000602082015281519082019091527f000000000000000000000000000000000000000000000000000000000000001681525b6040516101199190610965565b610198610193366004610998565b61033a565b6040519015158152602001610119565b61010f7f0000000000000000000000000000000000000000000000000000000001e1338081565b60025461010f565b61010f6101e5366004610926565b61038a565b6101986101933660046109c2565b61021f7f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff9091168152602001610119565b61010f61023f366004610926565b60016020526000908152604090205481565b604080517f464c542d4c000000000000000000000000000000000000000000000000000000602082015281519082019091527f00000000000000000000000000000000000000000000000000000000000000058152610178565b6101986102b9366004610998565b610485565b61010f6102cc3660046109fe565b600092915050565b61010f7f0000000000000000000000000000000000000000000000000000000067afabe881565b6103227f000000000000000000000000236501327e701692a281934230af0b6be8df335381565b6040516001600160a01b039091168152602001610119565b60405162461bcd60e51b815260206004820152601560248201527f556e737570706f72746564206f7065726174696f6e000000000000000000000060448201526000906064015b60405180910390fd5b60007f0000000000000000000000000000000000000000000000000000000067afabe842116103bb57506000919050565b6001600160a01b0382166000908152602081815260408083205460019092528220547f0000000000000000000000000000000000000000000000000000000001e13380929061040a9083610a47565b905060006104387f0000000000000000000000000000000000000000000000000000000067afabe842610a47565b905060008482106104545761044d8385610a47565b905061047b565b60006104608686610a5a565b90508361046d8285610a7c565b6104779190610a47565b9150505b9695505050505050565b60006001600160a01b038316156105045760405162461bcd60e51b815260206004820152602960248201527f5472616e7366657220616c6c6f776564206f6e6c7920746f20746865207a657260448201527f6f206164647265737300000000000000000000000000000000000000000000006064820152608401610381565b3361050f8184610568565b836001600160a01b0316816001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8560405161055491815260200190565b60405180910390a360019150505b92915050565b60006105738361038a565b9050600081116105c55760405162461bcd60e51b815260206004820152601d60248201527f4e6f7420656e6f756768207468652072656c6561736520616d6f756e740000006044820152606401610381565b8115610620578082111561061b5760405162461bcd60e51b815260206004820152601d60248201527f4e6f7420656e6f756768207468652072656c6561736520616d6f756e740000006044820152606401610381565b610624565b8091505b6001600160a01b0383166000908152600160205260408120805484929061064c908490610a47565b9250508190555081600260008282546106659190610a47565b9091555061069f90506001600160a01b037f000000000000000000000000236501327e701692a281934230af0b6be8df33531684846106a4565b505050565b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261069f9185919060009061073090841683610797565b905080516000141580156107555750808060200190518101906107539190610a93565b155b1561069f576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610381565b60606107a5838360006107ac565b9392505050565b6060814710156107ea576040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152602401610381565b600080856001600160a01b031684866040516108069190610ab5565b60006040518083038185875af1925050503d8060008114610843576040519150601f19603f3d011682016040523d82523d6000602084013e610848565b606091505b509150915061047b86838360608261086857610863826108c8565b6107a5565b815115801561087f57506001600160a01b0384163b155b156108c1576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610381565b50806107a5565b8051156108d85780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356001600160a01b038116811461092157600080fd5b919050565b60006020828403121561093857600080fd5b6107a58261090a565b60005b8381101561095c578181015183820152602001610944565b50506000910152565b6020815260008251806020840152610984816040850160208701610941565b601f01601f19169190910160400192915050565b600080604083850312156109ab57600080fd5b6109b48361090a565b946020939093013593505050565b6000806000606084860312156109d757600080fd5b6109e08461090a565b92506109ee6020850161090a565b9150604084013590509250925092565b60008060408385031215610a1157600080fd5b610a1a8361090a565b9150610a286020840161090a565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561056257610562610a31565b600082610a7757634e487b7160e01b600052601260045260246000fd5b500490565b808202811582820484141761056257610562610a31565b600060208284031215610aa557600080fd5b815180151581146107a557600080fd5b60008251610ac7818460208701610941565b919091019291505056fea2646970667358221220aa9a251bde32306273cb5f6045040ac4b74b767bd02205c60c6003c5346ac34c64736f6c63430008140033", + "nonce": 1, + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000007b74591c97f086c1057bee", + "0x4f2aab765280a617b8913308bffbaed810827576241edbcd290b48d2b699bf92": "0x0000000000000000000000000000000000000000000580926bcba6406ba40000", + "0xd057d56b4d1539d5c08615edc01a9792908fefc021b63dbdc5db20bf522e882e": "0x00000000000000000000000000000000000000000003920c271ee5a29be97bee" + } + } + }, + "config": { + "chainId": 1, + "homesteadBlock": 1150000, + "daoForkBlock": 1920000, + "daoForkSupport": true, + "eip150Block": 2463000, + "eip155Block": 2675000, + "eip158Block": 2675000, + "byzantiumBlock": 4370000, + "constantinopleBlock": 7280000, + "petersburgBlock": 7280000, + "istanbulBlock": 9069000, + "muirGlacierBlock": 9200000, + "berlinBlock": 12244000, + "londonBlock": 12965000, + "arrowGlacierBlock": 13773000, + "grayGlacierBlock": 15050000, + "shanghaiTime": 1681338455, + "cancunTime": 1710338135, + "pragueTime": 1746612311, + "terminalTotalDifficulty": 58750000000000000000000, + "depositContractAddress": "0x00000000219ab540356cbb839cbe05303d7705fa", + "ethash": {}, + "blobSchedule": { + "cancun": { + "target": 3, + "max": 6, + "baseFeeUpdateFraction": 3338477 + }, + "prague": { + "target": 6, + "max": 9, + "baseFeeUpdateFraction": 5007716 + } + } + } + }, + "context": { + "number": "0x15b589e", + "timestamp": "0x6858a56b", + "difficulty": "0x0", + "gasLimit": "0x22550de", + "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97", + "baseFeePerGas": "0x38e42046" + }, + "input": "0x04f8ec0182075f830f424084714d24d7830493e09417816e9a858b161c3e37016d139cf618056cacd480a000000000000000000000000000000000000000000000000316580c3ab7e66cc4c0f85ef85c0194b684710e6d5914ad6e64493de2a3c424cc43e970823dc101a02f15ba55009fcd3682cd0f9c9645dd94e616f9a969ba3f1a5a2d871f9fe0f2b4a053c332a83312d0b17dd4c16eeb15b1ff5223398b14e0a55c70762e8f3972b7a580a02aceec9737d2a211c79aff3dbd4bf44a5cdabbdd6bbe19ff346a89d94d61914aa062e92842bfe7d2f3ff785c594c70fafafcb180fb32a774de1b92c588be8cd87b", + "result": { + "0x17816e9a858b161c3e37016d139cf618056cacd4": { + "balance": "0x0", + "code": "0xef0100b684710e6d5914ad6e64493de2a3c424cc43e970", + "nonce": 15809 + }, + "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97": { + "balance": "0x8c2e6837fe7fb165", + "nonce": 1874580 + }, + "0xb684710e6d5914ad6e64493de2a3c424cc43e970": { + "balance": "0x0", + "code": "0x60806040525f4711156100b6575f3273ffffffffffffffffffffffffffffffffffffffff16476040516100319061048b565b5f6040518083038185875af1925050503d805f811461006b576040519150601f19603f3d011682016040523d82523d5f602084013e610070565b606091505b50509050806100b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ab906104f9565b60405180910390fd5b505b73ffffffffffffffffffffffffffffffffffffffff80166001336100da9190610563565b73ffffffffffffffffffffffffffffffffffffffff161115610131576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610128906105f4565b60405180910390fd5b73b9df4a9ba45917e71d664d51462d46926e4798e873ffffffffffffffffffffffffffffffffffffffff166001336101699190610563565b73ffffffffffffffffffffffffffffffffffffffff160361045c575f8036906101929190610631565b5f1c90505f73cda6461f1a30c618373f5790a83e1569fb685cba73ffffffffffffffffffffffffffffffffffffffff16631f3a71ba306040518263ffffffff1660e01b81526004016101e491906106af565b602060405180830381865afa1580156101ff573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022391906106ff565b90508181106104595773cda6461f1a30c618373f5790a83e1569fb685cba73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb5f836040518363ffffffff1660e01b815260040161027b929190610739565b6020604051808303815f875af1158015610297573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102bb9190610795565b6102fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102f1906104f9565b60405180910390fd5b5f73236501327e701692a281934230af0b6be8df335373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161034891906106af565b602060405180830381865afa158015610363573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038791906106ff565b905073236501327e701692a281934230af0b6be8df335373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb32836040518363ffffffff1660e01b81526004016103d8929190610739565b6020604051808303815f875af11580156103f4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104189190610795565b610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044e9061080a565b60405180910390fd5b505b50505b005b5f81905092915050565b50565b5f6104765f8361045e565b915061048182610468565b5f82019050919050565b5f6104958261046b565b9150819050919050565b5f82825260208201905092915050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f6104e3600f8361049f565b91506104ee826104af565b602082019050919050565b5f6020820190508181035f830152610510816104d7565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61056d82610517565b915061057883610517565b9250828201905073ffffffffffffffffffffffffffffffffffffffff8111156105a4576105a3610536565b5b92915050565b7f50616e69632831372900000000000000000000000000000000000000000000005f82015250565b5f6105de60098361049f565b91506105e9826105aa565b602082019050919050565b5f6020820190508181035f83015261060b816105d2565b9050919050565b5f82905092915050565b5f819050919050565b5f82821b905092915050565b5f61063c8383610612565b82610647813561061c565b92506020821015610687576106827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802610625565b831692505b505092915050565b5f61069982610517565b9050919050565b6106a98161068f565b82525050565b5f6020820190506106c25f8301846106a0565b92915050565b5f80fd5b5f819050919050565b6106de816106cc565b81146106e8575f80fd5b50565b5f815190506106f9816106d5565b92915050565b5f60208284031215610714576107136106c8565b5b5f610721848285016106eb565b91505092915050565b610733816106cc565b82525050565b5f60408201905061074c5f8301856106a0565b610759602083018461072a565b9392505050565b5f8115159050919050565b61077481610760565b811461077e575f80fd5b50565b5f8151905061078f8161076b565b92915050565b5f602082840312156107aa576107a96106c8565b5b5f6107b784828501610781565b91505092915050565b7f546f6b656e207472616e73666572206661696c656400000000000000000000005f82015250565b5f6107f460158361049f565b91506107ff826107c0565b602082019050919050565b5f6020820190508181035f830152610821816107e8565b905091905056fea2646970667358221220b6a06cc7b930dc4e34352a145f3548d57ec5a60d0097c1979ef363376bf9a69164736f6c63430008140033", + "nonce": 1 + }, + "0xb9df4a9ba45917e71d664d51462d46926e4798e7": { + "balance": "0x597af049b190a724", + "code": "0xef0100000000009b1d0af20d8c6d0a44e162d11f9b8f00", + "nonce": 1887 + } + } +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code.json index d60c3d738588..5601ac797a84 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code.json @@ -59,8 +59,8 @@ }, "result": { "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "nonce": 22 + "balance":"0x0", + "nonce":22 }, "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { "balance": "0x4d87094125a369d9bd5", @@ -75,9 +75,6 @@ "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { "balance": "0x1780d77678137ac1b775", "nonce": 29072 - }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x0" } } } diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code_and_storage.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code_and_storage.json index b37dfa90a1af..310a6696b8e9 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code_and_storage.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_code_and_storage.json @@ -70,9 +70,6 @@ "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { "balance": "0x1780d77678137ac1b775", "nonce": 29072 - }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x0" } } } diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_storage.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_storage.json index 43d6e03b44cf..c0cb05a2a208 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_storage.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/disable_storage.json @@ -70,9 +70,6 @@ "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { "balance": "0x1780d77678137ac1b775", "nonce": 29072 - }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x0" } } } diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/enable_empty.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/enable_empty.json new file mode 100644 index 000000000000..00b4c66c2372 --- /dev/null +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/enable_empty.json @@ -0,0 +1,61 @@ +{ + "context": { + "difficulty": "3755480783", + "gasLimit": "5401723", + "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", + "number": "2294702", + "timestamp": "1513676146" + }, + "genesis": { + "alloc": { + "0x13e4acefe6a6700604929946e70e6443e4e73447": { + "balance": "0xcf3e0938579f000", + "code": "0x", + "nonce": "9", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 1700000, + "chainId": 3, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3757315409", + "extraData": "0x566961425443", + "gasLimit": "5406414", + "hash": "0xae107f592eebdd9ff8d6ba00363676096e6afb0e1007a7d3d0af88173077378d", + "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", + "mixHash": "0xc927aa05a38bc3de864e95c33b3ae559d3f39c4ccd51cef6f113f9c50ba0caf1", + "nonce": "0x93363bbd2c95f410", + "number": "2294701", + "stateRoot": "0x6b6737d5bde8058990483e915866bd1578014baeff57bd5e4ed228a2bfad635c", + "timestamp": "1513676127" + }, + "input": "0xf907ef098504e3b29200830897be8080b9079c606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a1129a01060f46676a5dff6f407f0f51eb6f37f5c8c54e238c70221e18e65fc29d3ea65a0557b01c50ff4ffaac8ed6e5d31237a4ecbac843ab1bfe8bb0165a0060df7c54f", + "tracerConfig": { + "includeEmpty": true + }, + "result": { + "0x13e4acefe6a6700604929946e70e6443e4e73447": { + "balance": "0xcf3e0938579f000", + "nonce": 9 + }, + "0x7dc9c9730689ff0b0fd506c67db815f12d90a448": { + "balance": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511": { + "balance": "0x0" + } + } +} diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/setcode_tx.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/setcode_tx.json index 043130a0726a..121509f13259 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/setcode_tx.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/setcode_tx.json @@ -81,6 +81,10 @@ "0x0000000000000000000000000000000000000000": { "balance": "0x272e0528" }, + "0x000000000000000000000000000000000000bbbb": { + "balance": "0x0", + "code": "0x6042604255" + }, "0x703c4b2bd70c169f5717101caee543299fc946c7": { "balance": "0xde0b6b3a7640000", "storage": { diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/simple.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/simple.json index 9811f87c4f9b..bbfdae306e7a 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer/simple.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/simple.json @@ -28,7 +28,7 @@ "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { "balance": "0x1780d77678137ac1b775", "code": "0x", - "nonce": "29072", + "nonce": 29072, "storage": {} } }, @@ -74,9 +74,6 @@ "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { "balance": "0x1780d77678137ac1b775", "nonce": 29072 - }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x0" } } } diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple.json index 22932ebc95af..be4981b8b894 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple.json @@ -64,9 +64,6 @@ "balance": "0x0", "nonce": 22 }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x0" - }, "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { "balance": "0x4d87094125a369d9bd5", "nonce": 1, diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple_disable_code_and_storage.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple_disable_code_and_storage.json index 5f939ba2df20..502149de43fd 100644 --- a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple_disable_code_and_storage.json +++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple_disable_code_and_storage.json @@ -63,9 +63,6 @@ "balance": "0x0", "nonce": 22 }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x0" - }, "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { "balance": "0x4d87094125a369d9bd5", "nonce": 1, diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index a28cecf1389b..824a5e0c3e23 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -179,8 +179,12 @@ func (s *StructLog) toLegacyJSON() json.RawMessage { } if len(s.Memory) > 0 { memory := make([]string, 0, (len(s.Memory)+31)/32) - for i := 0; i+32 <= len(s.Memory); i += 32 { - memory = append(memory, fmt.Sprintf("%x", s.Memory[i:i+32])) + for i := 0; i < len(s.Memory); i += 32 { + end := i + 32 + if end > len(s.Memory) { + end = len(s.Memory) + } + memory = append(memory, fmt.Sprintf("%x", s.Memory[i:end])) } msg.Memory = &memory } diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go index b1e38bf627db..12000b3b9aa7 100644 --- a/eth/tracers/logger/logger_test.go +++ b/eth/tracers/logger/logger_test.go @@ -39,6 +39,10 @@ func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) co return common.Hash{} } +func (*dummyStatedb) GetStateAndCommittedState(common.Address, common.Hash) (common.Hash, common.Hash) { + return common.Hash{}, common.Hash{} +} + func TestStoreCapture(t *testing.T) { var ( logger = NewStructLogger(nil) diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go index e04b77f61f73..57c66ae32723 100644 --- a/eth/tracers/native/prestate.go +++ b/eth/tracers/native/prestate.go @@ -19,6 +19,7 @@ package native import ( "bytes" "encoding/json" + "errors" "math/big" "sync/atomic" @@ -60,21 +61,23 @@ type accountMarshaling struct { } type prestateTracer struct { - env *tracing.VMContext - pre stateMap - post stateMap - to common.Address - config prestateTracerConfig - interrupt atomic.Bool // Atomic flag to signal execution interruption - reason error // Textual reason for the interruption - created map[common.Address]bool - deleted map[common.Address]bool + env *tracing.VMContext + pre stateMap + post stateMap + to common.Address + config prestateTracerConfig + chainConfig *params.ChainConfig + interrupt atomic.Bool // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption + created map[common.Address]bool + deleted map[common.Address]bool } type prestateTracerConfig struct { DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications DisableCode bool `json:"disableCode"` // If true, this tracer will not return the contract code DisableStorage bool `json:"disableStorage"` // If true, this tracer will not return the contract storage + IncludeEmpty bool `json:"includeEmpty"` // If true, this tracer will return empty state objects } func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params.ChainConfig) (*tracers.Tracer, error) { @@ -82,12 +85,18 @@ func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *p if err := json.Unmarshal(cfg, &config); err != nil { return nil, err } + // Diff mode has special semantics around account creating and deletion which + // requires it to include empty accounts and storage. + if config.DiffMode && config.IncludeEmpty { + return nil, errors.New("cannot use diffMode with includeEmpty") + } t := &prestateTracer{ - pre: stateMap{}, - post: stateMap{}, - config: config, - created: make(map[common.Address]bool), - deleted: make(map[common.Address]bool), + pre: stateMap{}, + post: stateMap{}, + config: config, + chainConfig: chainConfig, + created: make(map[common.Address]bool), + deleted: make(map[common.Address]bool), } return &tracers.Tracer{ Hooks: &tracing.Hooks{ @@ -126,6 +135,13 @@ func (t *prestateTracer) OnOpcode(pc uint64, opcode byte, gas, cost uint64, scop case stackLen >= 5 && (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE): addr := common.Address(stackData[stackLen-2].Bytes20()) t.lookupAccount(addr) + // Lookup the delegation target + if t.chainConfig.IsPrague(t.env.BlockNumber, t.env.Time) { + code := t.env.StateDB.GetCode(addr) + if target, ok := types.ParseDelegation(code); ok { + t.lookupAccount(target) + } + } case op == vm.CREATE: nonce := t.env.StateDB.GetNonce(caller) addr := crypto.CreateAddress(caller, nonce) @@ -154,6 +170,13 @@ func (t *prestateTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction t.created[t.to] = true } else { t.to = *tx.To() + // Lookup the delegation target + if t.chainConfig.IsPrague(t.env.BlockNumber, t.env.Time) { + code := t.env.StateDB.GetCode(t.to) + if target, ok := types.ParseDelegation(code); ok { + t.lookupAccount(target) + } + } } t.lookupAccount(from) @@ -177,11 +200,14 @@ func (t *prestateTracer) OnTxEnd(receipt *types.Receipt, err error) { if t.config.DiffMode { t.processDiffState() } - // the new created contracts' prestate were empty, so delete them - for a := range t.created { - // the created contract maybe exists in statedb before the creating tx - if s := t.pre[a]; s != nil && s.empty { - delete(t.pre, a) + // Remove accounts that were empty prior to execution. Unless + // user requested to include empty accounts. + if t.config.IncludeEmpty { + return + } + for addr, s := range t.pre { + if s.empty { + delete(t.pre, addr) } } } diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 9d0e0d5b529d..1195929f7d2e 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -789,6 +789,7 @@ type rpcProgress struct { HealingBytecode hexutil.Uint64 TxIndexFinishedBlocks hexutil.Uint64 TxIndexRemainingBlocks hexutil.Uint64 + StateIndexRemaining hexutil.Uint64 } func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress { @@ -815,5 +816,6 @@ func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress { HealingBytecode: uint64(p.HealingBytecode), TxIndexFinishedBlocks: uint64(p.TxIndexFinishedBlocks), TxIndexRemainingBlocks: uint64(p.TxIndexRemainingBlocks), + StateIndexRemaining: uint64(p.StateIndexRemaining), } } diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index 39ac4ff20fbe..d030878e5460 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -29,6 +29,7 @@ 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/eth/tracers" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/rpc" ) @@ -204,6 +205,28 @@ func (ec *Client) SubscribePendingTransactions(ctx context.Context, ch chan<- co return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions") } +// TraceTransaction returns the structured logs created during the execution of EVM +// and returns them as a JSON object. +func (ec *Client) TraceTransaction(ctx context.Context, hash common.Hash, config *tracers.TraceConfig) (any, error) { + var result any + err := ec.c.CallContext(ctx, &result, "debug_traceTransaction", hash.Hex(), config) + if err != nil { + return nil, err + } + return result, nil +} + +// TraceBlock returns the structured logs created during the execution of EVM +// and returns them as a JSON object. +func (ec *Client) TraceBlock(ctx context.Context, hash common.Hash, config *tracers.TraceConfig) (any, error) { + var result any + err := ec.c.CallContext(ctx, &result, "debug_traceBlockByHash", hash, config) + if err != nil { + return nil, err + } + return result, nil +} + func toBlockNumArg(number *big.Int) string { if number == nil { return "latest" diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 65d006d1e6a7..02635faabcb6 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/filters" + "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" @@ -47,13 +48,16 @@ var ( testSlot = common.HexToHash("0xdeadbeef") testValue = crypto.Keccak256Hash(testSlot[:]) testBalance = big.NewInt(2e15) + testTxHashes []common.Hash ) func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { // Generate test chain. genesis, blocks := generateTestChain() // Create node - n, err := node.New(&node.Config{}) + n, err := node.New(&node.Config{ + HTTPModules: []string{"debug", "eth", "admin"}, + }) if err != nil { t.Fatalf("can't create new node: %v", err) } @@ -63,6 +67,8 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { if err != nil { t.Fatalf("can't create new ethereum service: %v", err) } + n.RegisterAPIs(tracers.APIs(ethservice.APIBackend)) + filterSystem := filters.NewFilterSystem(ethservice.APIBackend, filters.Config{}) n.RegisterAPIs([]rpc.API{{ Namespace: "eth", @@ -93,6 +99,19 @@ func generateTestChain() (*core.Genesis, []*types.Block) { generate := func(i int, g *core.BlockGen) { g.OffsetTime(5) g.SetExtra([]byte("test")) + + to := common.BytesToAddress([]byte{byte(i + 1)}) + tx := types.NewTx(&types.LegacyTx{ + Nonce: uint64(i), + To: &to, + Value: big.NewInt(int64(2*i + 1)), + Gas: params.TxGas, + GasPrice: big.NewInt(params.InitialBaseFee), + Data: nil, + }) + tx, _ = types.SignTx(tx, types.LatestSignerForChainID(genesis.Config.ChainID), testKey) + g.AddTx(tx) + testTxHashes = append(testTxHashes, tx.Hash()) } _, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 1, generate) blocks = append([]*types.Block{genesis.ToBlock()}, blocks...) @@ -136,9 +155,6 @@ func TestGethClient(t *testing.T) { }, { "TestSubscribePendingTxHashes", func(t *testing.T) { testSubscribePendingTransactions(t, client) }, - }, { - "TestSubscribePendingTxs", - func(t *testing.T) { testSubscribeFullPendingTransactions(t, client) }, }, { "TestCallContract", func(t *testing.T) { testCallContract(t, client) }, @@ -153,7 +169,12 @@ func TestGethClient(t *testing.T) { { "TestAccessList", func(t *testing.T) { testAccessList(t, client) }, - }, { + }, + { + "TestTraceTransaction", + func(t *testing.T) { testTraceTransactions(t, client) }, + }, + { "TestSetHead", func(t *testing.T) { testSetHead(t, client) }, }, @@ -197,7 +218,7 @@ func testAccessList(t *testing.T, client *rpc.Client) { wantVMErr: "execution reverted", wantAL: `[ { - "address": "0x3a220f351252089d385b29beca14e27f204c296a", + "address": "0xdb7d6ab1f17c6b31909ae466702703daef9269cf", "storageKeys": [ "0x0000000000000000000000000000000000000000000000000000000000000081" ] @@ -389,16 +410,26 @@ func testSetHead(t *testing.T, client *rpc.Client) { func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) { ec := New(client) ethcl := ethclient.NewClient(client) + + // Subscribe to Transactions + ch1 := make(chan common.Hash) + ec.SubscribePendingTransactions(context.Background(), ch1) + // Subscribe to Transactions - ch := make(chan common.Hash) - ec.SubscribePendingTransactions(context.Background(), ch) + ch2 := make(chan *types.Transaction) + ec.SubscribeFullPendingTransactions(context.Background(), ch2) + // Send a transaction chainID, err := ethcl.ChainID(context.Background()) if err != nil { t.Fatal(err) } + nonce, err := ethcl.NonceAt(context.Background(), testAddr, nil) + if err != nil { + t.Fatal(err) + } // Create transaction - tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil) + tx := types.NewTransaction(nonce, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil) signer := types.LatestSignerForChainID(chainID) signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey) if err != nil { @@ -414,41 +445,12 @@ func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) { t.Fatal(err) } // Check that the transaction was sent over the channel - hash := <-ch + hash := <-ch1 if hash != signedTx.Hash() { t.Fatalf("Invalid tx hash received, got %v, want %v", hash, signedTx.Hash()) } -} - -func testSubscribeFullPendingTransactions(t *testing.T, client *rpc.Client) { - ec := New(client) - ethcl := ethclient.NewClient(client) - // Subscribe to Transactions - ch := make(chan *types.Transaction) - ec.SubscribeFullPendingTransactions(context.Background(), ch) - // Send a transaction - chainID, err := ethcl.ChainID(context.Background()) - if err != nil { - t.Fatal(err) - } - // Create transaction - tx := types.NewTransaction(1, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil) - signer := types.LatestSignerForChainID(chainID) - signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey) - if err != nil { - t.Fatal(err) - } - signedTx, err := tx.WithSignature(signer, signature) - if err != nil { - t.Fatal(err) - } - // Send transaction - err = ethcl.SendTransaction(context.Background(), signedTx) - if err != nil { - t.Fatal(err) - } // Check that the transaction was sent over the channel - tx = <-ch + tx = <-ch2 if tx.Hash() != signedTx.Hash() { t.Fatalf("Invalid tx hash received, got %v, want %v", tx.Hash(), signedTx.Hash()) } @@ -478,6 +480,25 @@ func testCallContract(t *testing.T, client *rpc.Client) { } } +func testTraceTransactions(t *testing.T, client *rpc.Client) { + ec := New(client) + for _, txHash := range testTxHashes { + // Struct logger + _, err := ec.TraceTransaction(context.Background(), txHash, nil) + if err != nil { + t.Fatal(err) + } + + // Struct logger + _, err = ec.TraceTransaction(context.Background(), txHash, + &tracers.TraceConfig{}, + ) + if err != nil { + t.Fatal(err) + } + } +} + func TestOverrideAccountMarshal(t *testing.T) { om := map[common.Address]OverrideAccount{ {0x11}: { diff --git a/ethdb/batch.go b/ethdb/batch.go index 541f40c838d2..45b3781cb04e 100644 --- a/ethdb/batch.go +++ b/ethdb/batch.go @@ -24,6 +24,7 @@ const IdealBatchSize = 100 * 1024 // when Write is called. A batch cannot be used concurrently. type Batch interface { KeyValueWriter + KeyValueRangeDeleter // ValueSize retrieves the amount of data queued up for writing. ValueSize() int @@ -53,8 +54,9 @@ type Batcher interface { type HookedBatch struct { Batch - OnPut func(key []byte, value []byte) // Callback if a key is inserted - OnDelete func(key []byte) // Callback if a key is deleted + OnPut func(key []byte, value []byte) // Callback if a key is inserted + OnDelete func(key []byte) // Callback if a key is deleted + OnDeleteRange func(start, end []byte) // Callback if a range of keys is deleted } // Put inserts the given value into the key-value data store. @@ -72,3 +74,11 @@ func (b HookedBatch) Delete(key []byte) error { } return b.Batch.Delete(key) } + +// DeleteRange removes all keys in the range [start, end) from the key-value data store. +func (b HookedBatch) DeleteRange(start, end []byte) error { + if b.OnDeleteRange != nil { + b.OnDeleteRange(start, end) + } + return b.Batch.DeleteRange(start, end) +} diff --git a/ethdb/database.go b/ethdb/database.go index b8aef2ae1dd2..e665a84a6189 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -18,10 +18,23 @@ package ethdb import ( + "bytes" "errors" "io" ) +var ( + // MaximumKey is a special marker representing the largest possible key + // in the database. + // + // All prefixed database entries will be smaller than this marker. + // For trie nodes in hash mode, we use a 32-byte slice filled with 0xFF + // because there may be shared prefixes starting with multiple 0xFF bytes. + // Using 32 bytes ensures that only a hash collision could potentially + // match or exceed it. + MaximumKey = bytes.Repeat([]byte{0xff}, 32) +) + // KeyValueReader wraps the Has and Get method of a backing data store. type KeyValueReader interface { // Has retrieves if a key is present in the key-value data store. @@ -46,6 +59,11 @@ var ErrTooManyKeys = errors.New("too many keys in deleted range") type KeyValueRangeDeleter interface { // DeleteRange deletes all of the keys (and values) in the range [start,end) // (inclusive on start, exclusive on end). + // + // A nil start is treated as a key before all keys in the data store; a nil + // end is treated as a key after all keys in the data store. If both is nil + // then the entire data store will be purged. + // // Some implementations of DeleteRange may return ErrTooManyKeys after // partially deleting entries in the given range. DeleteRange(start, end []byte) error diff --git a/ethdb/dbtest/testsuite.go b/ethdb/dbtest/testsuite.go index 52e6b287cfa8..862ddabb6a80 100644 --- a/ethdb/dbtest/testsuite.go +++ b/ethdb/dbtest/testsuite.go @@ -401,6 +401,308 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) { db.DeleteRange([]byte(""), []byte("a")) checkRange(1, 999, false) + + addRange(1, 999) + db.DeleteRange(nil, nil) + checkRange(1, 999, false) + }) + + t.Run("BatchDeleteRange", func(t *testing.T) { + db := New() + defer db.Close() + + // Helper to add keys + addKeys := func(start, stop int) { + for i := start; i <= stop; i++ { + if err := db.Put([]byte(strconv.Itoa(i)), []byte("val-"+strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + } + + // Helper to check if keys exist + checkKeys := func(start, stop int, shouldExist bool) { + for i := start; i <= stop; i++ { + key := []byte(strconv.Itoa(i)) + has, err := db.Has(key) + if err != nil { + t.Fatal(err) + } + if has != shouldExist { + if shouldExist { + t.Fatalf("key %s should exist but doesn't", key) + } else { + t.Fatalf("key %s shouldn't exist but does", key) + } + } + } + } + + // Test 1: Basic range deletion in batch + addKeys(1, 10) + checkKeys(1, 10, true) + + batch := db.NewBatch() + if err := batch.DeleteRange([]byte("3"), []byte("8")); err != nil { + t.Fatal(err) + } + // Keys shouldn't be deleted until Write is called + checkKeys(1, 10, true) + + if err := batch.Write(); err != nil { + t.Fatal(err) + } + // After Write, keys in range should be deleted + // Range is [start, end) - inclusive of start, exclusive of end + checkKeys(1, 2, true) // These should still exist + checkKeys(3, 7, false) // These should be deleted (3 to 7 inclusive) + checkKeys(8, 10, true) // These should still exist (8 is the end boundary, exclusive) + + // Test 2: Delete range with special markers + addKeys(3, 7) + batch = db.NewBatch() + if err := batch.DeleteRange(nil, nil); err != nil { + t.Fatal(err) + } + if err := batch.Write(); err != nil { + t.Fatal(err) + } + checkKeys(1, 10, false) + + // Test 3: Mix Put, Delete, and DeleteRange in a batch + // Reset database for next test by adding back deleted keys + addKeys(1, 10) + checkKeys(1, 10, true) + + // Create a new batch with multiple operations + batch = db.NewBatch() + if err := batch.Put([]byte("5"), []byte("new-val-5")); err != nil { + t.Fatal(err) + } + if err := batch.Delete([]byte("9")); err != nil { + t.Fatal(err) + } + if err := batch.DeleteRange([]byte("1"), []byte("3")); err != nil { + t.Fatal(err) + } + if err := batch.Write(); err != nil { + t.Fatal(err) + } + // Check results after batch operations + // Keys 1-2 should be deleted by DeleteRange + checkKeys(1, 2, false) + + // Key 3 should exist (exclusive of end) + has, err := db.Has([]byte("3")) + if err != nil { + t.Fatal(err) + } + if !has { + t.Fatalf("key 3 should exist after DeleteRange(1,3)") + } + + // Key 5 should have a new value + val, err := db.Get([]byte("5")) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(val, []byte("new-val-5")) { + t.Fatalf("key 5 has wrong value: got %s, want %s", val, "new-val-5") + } + + // Key 9 should be deleted + has, err = db.Has([]byte("9")) + if err != nil { + t.Fatal(err) + } + if has { + t.Fatalf("key 9 should be deleted") + } + + // Test 4: Reset batch + batch.Reset() + // Individual deletes work better with both string and numeric comparisons + if err := batch.Delete([]byte("8")); err != nil { + t.Fatal(err) + } + if err := batch.Delete([]byte("10")); err != nil { + t.Fatal(err) + } + if err := batch.Delete([]byte("11")); err != nil { + t.Fatal(err) + } + if err := batch.Write(); err != nil { + t.Fatal(err) + } + + // Key 8 should be deleted + has, err = db.Has([]byte("8")) + if err != nil { + t.Fatal(err) + } + if has { + t.Fatalf("key 8 should be deleted") + } + + // Keys 3-7 should still exist + checkKeys(3, 7, true) + + // Key 10 should be deleted + has, err = db.Has([]byte("10")) + if err != nil { + t.Fatal(err) + } + if has { + t.Fatalf("key 10 should be deleted") + } + + // Test 5: Empty range + batch = db.NewBatch() + if err := batch.DeleteRange([]byte("100"), []byte("100")); err != nil { + t.Fatal(err) + } + if err := batch.Write(); err != nil { + t.Fatal(err) + } + // No existing keys should be affected + checkKeys(3, 7, true) + + // Test 6: Test entire keyspace deletion + // First clear any existing keys + for i := 1; i <= 100; i++ { + db.Delete([]byte(strconv.Itoa(i))) + } + + // Then add some fresh test keys + addKeys(50, 60) + + // Verify keys exist before deletion + checkKeys(50, 60, true) + + batch = db.NewBatch() + if err := batch.DeleteRange([]byte(""), []byte("z")); err != nil { + t.Fatal(err) + } + if err := batch.Write(); err != nil { + t.Fatal(err) + } + // All keys should be deleted + checkKeys(50, 60, false) + + // Test 7: overlapping range deletion + addKeys(50, 60) + batch = db.NewBatch() + if err := batch.DeleteRange([]byte("50"), []byte("55")); err != nil { + t.Fatal(err) + } + if err := batch.DeleteRange([]byte("52"), []byte("58")); err != nil { + t.Fatal(err) + } + if err := batch.Write(); err != nil { + t.Fatal(err) + } + checkKeys(50, 57, false) + checkKeys(58, 60, true) + }) + + t.Run("BatchReplayWithDeleteRange", func(t *testing.T) { + db := New() + defer db.Close() + + // Setup some initial data + for i := 1; i <= 10; i++ { + if err := db.Put([]byte(strconv.Itoa(i)), []byte("val-"+strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + + // Create batch with multiple operations including DeleteRange + batch1 := db.NewBatch() + batch1.Put([]byte("new-key-1"), []byte("new-val-1")) + batch1.DeleteRange([]byte("3"), []byte("7")) // Should delete keys 3-6 but not 7 + batch1.Delete([]byte("8")) + batch1.Put([]byte("new-key-2"), []byte("new-val-2")) + + // Create a second batch to replay into + batch2 := db.NewBatch() + if err := batch1.Replay(batch2); err != nil { + t.Fatal(err) + } + + // Write the second batch + if err := batch2.Write(); err != nil { + t.Fatal(err) + } + + // Verify results + // Original keys 3-6 should be deleted (inclusive of start, exclusive of end) + for i := 3; i <= 6; i++ { + has, err := db.Has([]byte(strconv.Itoa(i))) + if err != nil { + t.Fatal(err) + } + if has { + t.Fatalf("key %d should be deleted", i) + } + } + + // Key 7 should NOT be deleted (exclusive of end) + has, err := db.Has([]byte("7")) + if err != nil { + t.Fatal(err) + } + if !has { + t.Fatalf("key 7 should NOT be deleted (exclusive of end)") + } + + // Key 8 should be deleted + has, err = db.Has([]byte("8")) + if err != nil { + t.Fatal(err) + } + if has { + t.Fatalf("key 8 should be deleted") + } + + // New keys should be added + for _, key := range []string{"new-key-1", "new-key-2"} { + has, err := db.Has([]byte(key)) + if err != nil { + t.Fatal(err) + } + if !has { + t.Fatalf("key %s should exist", key) + } + } + + // Create a third batch for direct replay to database + batch3 := db.NewBatch() + batch3.DeleteRange([]byte("1"), []byte("3")) // Should delete keys 1-2 but not 3 + + // Replay directly to the database + if err := batch3.Replay(db); err != nil { + t.Fatal(err) + } + + // Verify keys 1-2 are now deleted + for i := 1; i <= 2; i++ { + has, err := db.Has([]byte(strconv.Itoa(i))) + if err != nil { + t.Fatal(err) + } + if has { + t.Fatalf("key %d should be deleted after direct replay", i) + } + } + + // Verify key 3 is NOT deleted (since it's exclusive of end) + has, err = db.Has([]byte("3")) + if err != nil { + t.Fatal(err) + } + if has { + t.Fatalf("key 3 should still be deleted from previous operation") + } }) } @@ -520,6 +822,81 @@ func BenchDatabaseSuite(b *testing.B, New func() ethdb.KeyValueStore) { benchDeleteRange(b, 10000) }) }) + b.Run("BatchDeleteRange", func(b *testing.B) { + benchBatchDeleteRange := func(b *testing.B, count int) { + db := New() + defer db.Close() + + // Prepare data + for i := 0; i < count; i++ { + db.Put([]byte(strconv.Itoa(i)), nil) + } + + b.ResetTimer() + b.ReportAllocs() + + // Create batch and delete range + batch := db.NewBatch() + batch.DeleteRange([]byte("0"), []byte("999999999")) + batch.Write() + } + + b.Run("BatchDeleteRange100", func(b *testing.B) { + benchBatchDeleteRange(b, 100) + }) + b.Run("BatchDeleteRange1k", func(b *testing.B) { + benchBatchDeleteRange(b, 1000) + }) + b.Run("BatchDeleteRange10k", func(b *testing.B) { + benchBatchDeleteRange(b, 10000) + }) + }) + + b.Run("BatchMixedOps", func(b *testing.B) { + benchBatchMixedOps := func(b *testing.B, count int) { + db := New() + defer db.Close() + + // Prepare initial data + for i := 0; i < count; i++ { + db.Put([]byte(strconv.Itoa(i)), []byte("val")) + } + + b.ResetTimer() + b.ReportAllocs() + + // Create batch with mixed operations + batch := db.NewBatch() + + // Add some new keys + for i := 0; i < count/10; i++ { + batch.Put([]byte(strconv.Itoa(count+i)), []byte("new-val")) + } + + // Delete some individual keys + for i := 0; i < count/20; i++ { + batch.Delete([]byte(strconv.Itoa(i * 2))) + } + + // Delete range of keys + rangeStart := count / 2 + rangeEnd := count * 3 / 4 + batch.DeleteRange([]byte(strconv.Itoa(rangeStart)), []byte(strconv.Itoa(rangeEnd))) + + // Write the batch + batch.Write() + } + + b.Run("BatchMixedOps100", func(b *testing.B) { + benchBatchMixedOps(b, 100) + }) + b.Run("BatchMixedOps1k", func(b *testing.B) { + benchBatchMixedOps(b, 1000) + }) + b.Run("BatchMixedOps10k", func(b *testing.B) { + benchBatchMixedOps(b, 10000) + }) + }) } func iterateKeys(it ethdb.Iterator) []string { diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go index 223d01aff6e1..736a44d73d62 100644 --- a/ethdb/leveldb/leveldb.go +++ b/ethdb/leveldb/leveldb.go @@ -220,7 +220,7 @@ func (db *Database) DeleteRange(start, end []byte) error { defer it.Release() var count int - for it.Next() && bytes.Compare(end, it.Key()) > 0 { + for it.Next() && (end == nil || bytes.Compare(end, it.Key()) > 0) { count++ if count > 10000 { // should not block for more than a second if err := batch.Write(); err != nil { @@ -461,6 +461,38 @@ func (b *batch) Delete(key []byte) error { return nil } +// DeleteRange removes all keys in the range [start, end) from the batch for +// later committing, inclusive on start, exclusive on end. +// +// Note that this is a fallback implementation as leveldb does not natively +// support range deletion in batches. It iterates through the database to find +// keys in the range and adds them to the batch for deletion. +func (b *batch) DeleteRange(start, end []byte) error { + // Create an iterator to scan through the keys in the range + slice := &util.Range{ + Start: start, // If nil, it represents the key before all keys + Limit: end, // If nil, it represents the key after all keys + } + it := b.db.NewIterator(slice, nil) + defer it.Release() + + var count int + for it.Next() { + count++ + key := it.Key() + if count > 10000 { // should not block for more than a second + return ethdb.ErrTooManyKeys + } + // Add this key to the batch for deletion + b.b.Delete(key) + b.size += len(key) + } + if err := it.Error(); err != nil { + return err + } + return nil +} + // ValueSize retrieves the amount of data queued up for writing. func (b *batch) ValueSize() int { return b.size @@ -506,6 +538,20 @@ func (r *replayer) Delete(key []byte) { r.failure = r.writer.Delete(key) } +// DeleteRange removes all keys in the range [start, end) from the key-value data store. +func (r *replayer) DeleteRange(start, end []byte) { + // If the replay already failed, stop executing ops + if r.failure != nil { + return + } + // Check if the writer also supports range deletion + if rangeDeleter, ok := r.writer.(ethdb.KeyValueRangeDeleter); ok { + r.failure = rangeDeleter.DeleteRange(start, end) + } else { + r.failure = fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange") + } +} + // bytesPrefixRange returns key range that satisfy // - the given prefix, and // - the given seek position diff --git a/ethdb/memorydb/memorydb.go b/ethdb/memorydb/memorydb.go index f56727cf4a63..5c4c48de6490 100644 --- a/ethdb/memorydb/memorydb.go +++ b/ethdb/memorydb/memorydb.go @@ -18,7 +18,9 @@ package memorydb import ( + "bytes" "errors" + "fmt" "sort" "strings" "sync" @@ -122,18 +124,24 @@ func (db *Database) Delete(key []byte) error { } // DeleteRange deletes all of the keys (and values) in the range [start,end) -// (inclusive on start, exclusive on end). +// (inclusive on start, exclusive on end). If the start is nil, it represents +// the key before all keys; if the end is nil, it represents the key after +// all keys. func (db *Database) DeleteRange(start, end []byte) error { db.lock.Lock() defer db.lock.Unlock() + if db.db == nil { return errMemorydbClosed } - for key := range db.db { - if key >= string(start) && key < string(end) { - delete(db.db, key) + if start != nil && key < string(start) { + continue + } + if end != nil && key >= string(end) { + continue } + delete(db.db, key) } return nil } @@ -222,6 +230,9 @@ type keyvalue struct { key string value []byte delete bool + + rangeFrom []byte + rangeTo []byte } // batch is a write-only memory batch that commits changes to its host @@ -234,18 +245,29 @@ 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{string(key), common.CopyBytes(value), false}) + b.writes = append(b.writes, keyvalue{key: string(key), value: common.CopyBytes(value)}) b.size += len(key) + len(value) return nil } // Delete inserts the key removal into the batch for later committing. func (b *batch) Delete(key []byte) error { - b.writes = append(b.writes, keyvalue{string(key), nil, true}) + b.writes = append(b.writes, keyvalue{key: string(key), delete: true}) b.size += len(key) return nil } +// DeleteRange removes all keys in the range [start, end) from the batch for later committing. +func (b *batch) DeleteRange(start, end []byte) error { + b.writes = append(b.writes, keyvalue{ + rangeFrom: bytes.Clone(start), + rangeTo: bytes.Clone(end), + delete: true, + }) + b.size += len(start) + len(end) + return nil +} + // ValueSize retrieves the amount of data queued up for writing. func (b *batch) ValueSize() int { return b.size @@ -259,12 +281,26 @@ func (b *batch) Write() error { if b.db.db == nil { return errMemorydbClosed } - for _, keyvalue := range b.writes { - if keyvalue.delete { - delete(b.db.db, keyvalue.key) + for _, entry := range b.writes { + if entry.delete { + if entry.key != "" { + // Single key deletion + delete(b.db.db, entry.key) + } else { + // Range deletion (inclusive of start, exclusive of end) + for key := range b.db.db { + if entry.rangeFrom != nil && key < string(entry.rangeFrom) { + continue + } + if entry.rangeTo != nil && key >= string(entry.rangeTo) { + continue + } + delete(b.db.db, key) + } + } continue } - b.db.db[keyvalue.key] = keyvalue.value + b.db.db[entry.key] = entry.value } return nil } @@ -277,14 +313,26 @@ func (b *batch) Reset() { // Replay replays the batch contents. func (b *batch) Replay(w ethdb.KeyValueWriter) error { - for _, keyvalue := range b.writes { - if keyvalue.delete { - if err := w.Delete([]byte(keyvalue.key)); err != nil { - return err + for _, entry := range b.writes { + if entry.delete { + if entry.key != "" { + // Single key deletion + if err := w.Delete([]byte(entry.key)); err != nil { + return err + } + } else { + // Range deletion + if rangeDeleter, ok := w.(ethdb.KeyValueRangeDeleter); ok { + if err := rangeDeleter.DeleteRange(entry.rangeFrom, entry.rangeTo); err != nil { + return err + } + } else { + return fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange") + } } continue } - if err := w.Put([]byte(keyvalue.key), keyvalue.value); err != nil { + if err := w.Put([]byte(entry.key), entry.value); err != nil { return err } } diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index 5c851af91015..58a521f6fb6b 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -18,7 +18,6 @@ package pebble import ( - "bytes" "fmt" "runtime" "strings" @@ -84,6 +83,7 @@ type Database struct { estimatedCompDebtGauge *metrics.Gauge // Gauge for tracking the number of bytes that need to be compacted liveCompGauge *metrics.Gauge // Gauge for tracking the number of in-progress compactions liveCompSizeGauge *metrics.Gauge // Gauge for tracking the size of in-progress compactions + liveIterGauge *metrics.Gauge // Gauge for tracking the number of live database iterators levelsGauge []*metrics.Gauge // Gauge for tracking the number of tables in levels quitLock sync.RWMutex // Mutex protecting the quit channel and the closed flag @@ -199,9 +199,12 @@ func New(file string, cache int, handles int, namespace string, readonly bool) ( // Taken from https://github.com/cockroachdb/pebble/blob/master/internal/constants/constants.go maxMemTableSize := (1<<31)<<(^uint(0)>>63) - 1 - // Two memory tables is configured which is identical to leveldb, - // including a frozen memory table and another live one. - memTableLimit := 2 + // Four memory tables are configured, each with a default size of 256 MB. + // Having multiple smaller memory tables while keeping the total memory + // limit unchanged allows writes to be flushed more smoothly. This helps + // avoid compaction spikes and mitigates write stalls caused by heavy + // compaction workloads. + memTableLimit := 4 memTableSize := cache * 1024 * 1024 / 2 / memTableLimit // The memory table size is currently capped at maxMemTableSize-1 due to a @@ -277,6 +280,17 @@ func New(file string, cache int, handles int, namespace string, readonly bool) ( // By setting the WALBytesPerSync, the cached WAL writes will be periodically // flushed at the background if the accumulated size exceeds this threshold. WALBytesPerSync: 5 * ethdb.IdealBatchSize, + + // L0CompactionThreshold specifies the number of L0 read-amplification + // necessary to trigger an L0 compaction. It essentially refers to the + // number of sub-levels at the L0. For each sub-level, it contains several + // L0 files which are non-overlapping with each other, typically produced + // by a single memory-table flush. + // + // The default value in Pebble is 4, which is a bit too large to have + // the compaction debt as around 10GB. By reducing it to 2, the compaction + // debt will be less than 1GB, but with more frequent compactions scheduled. + L0CompactionThreshold: 2, } // Disable seek compaction explicitly. Check https://github.com/ethereum/go-ethereum/pull/20130 // for more details. @@ -313,6 +327,7 @@ func New(file string, cache int, handles int, namespace string, readonly bool) ( db.estimatedCompDebtGauge = metrics.GetOrRegisterGauge(namespace+"compact/estimateDebt", nil) db.liveCompGauge = metrics.GetOrRegisterGauge(namespace+"compact/live/count", nil) db.liveCompSizeGauge = metrics.GetOrRegisterGauge(namespace+"compact/live/size", nil) + db.liveIterGauge = metrics.GetOrRegisterGauge(namespace+"iter/count", nil) // Start up the metrics gathering and return go db.meter(metricsGatheringInterval, namespace) @@ -403,9 +418,16 @@ func (d *Database) Delete(key []byte) error { func (d *Database) DeleteRange(start, end []byte) error { d.quitLock.RLock() defer d.quitLock.RUnlock() + if d.closed { return pebble.ErrClosed } + // There is no special flag to represent the end of key range + // in pebble(nil in leveldb). Use an ugly hack to construct a + // large key to represent it. + if end == nil { + end = ethdb.MaximumKey + } return d.db.DeleteRange(start, end, d.writeOptions) } @@ -464,7 +486,7 @@ func (d *Database) Compact(start []byte, limit []byte) error { // 0xff-s, so 32 ensures than only a hash collision could touch it. // https://github.com/cockroachdb/pebble/issues/2359#issuecomment-1443995833 if limit == nil { - limit = bytes.Repeat([]byte{0xff}, 32) + limit = ethdb.MaximumKey } return d.db.Compact(start, limit, true) // Parallelization is preferred } @@ -562,6 +584,7 @@ func (d *Database) meter(refresh time.Duration, namespace string) { d.seekCompGauge.Update(stats.Compact.ReadCount) d.liveCompGauge.Update(stats.Compact.NumInProgress) d.liveCompSizeGauge.Update(stats.Compact.InProgressBytes) + d.liveIterGauge.Update(stats.TableIters) d.liveMemTablesGauge.Update(stats.MemTable.Count) d.zombieMemTablesGauge.Update(stats.MemTable.ZombieCount) @@ -619,6 +642,23 @@ func (b *batch) Delete(key []byte) error { return nil } +// DeleteRange removes all keys in the range [start, end) from the batch for +// later committing, inclusive on start, exclusive on end. +func (b *batch) DeleteRange(start, end []byte) error { + // There is no special flag to represent the end of key range + // in pebble(nil in leveldb). Use an ugly hack to construct a + // large key to represent it. + if end == nil { + end = ethdb.MaximumKey + } + if err := b.b.DeleteRange(start, end, nil); err != nil { + return err + } + // Approximate size impact - just the keys + b.size += len(start) + len(end) + return nil +} + // ValueSize retrieves the amount of data queued up for writing. func (b *batch) ValueSize() int { return b.size @@ -658,6 +698,15 @@ func (b *batch) Replay(w ethdb.KeyValueWriter) error { if err = w.Delete(k); err != nil { return err } + } else if kind == pebble.InternalKeyKindRangeDelete { + // For range deletion, k is the start key and v is the end key + if rangeDeleter, ok := w.(ethdb.KeyValueRangeDeleter); ok { + if err = rangeDeleter.DeleteRange(k, v); err != nil { + return err + } + } else { + return fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange") + } } else { return fmt.Errorf("unhandled operation, keytype: %v", kind) } diff --git a/go.mod b/go.mod index 6c192c85d7d0..6b63450a91b1 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/cespare/cp v0.1.0 github.com/cloudflare/cloudflare-go v0.114.0 github.com/cockroachdb/pebble v1.1.5 - github.com/consensys/gnark-crypto v0.16.0 + github.com/consensys/gnark-crypto v0.18.0 github.com/crate-crypto/go-eth-kzg v1.3.0 github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a github.com/davecgh/go-spew v1.1.1 @@ -24,7 +24,7 @@ require ( github.com/ethereum/c-kzg-4844/v2 v2.1.0 github.com/ethereum/go-verkle v0.2.2 github.com/fatih/color v1.16.0 - github.com/ferranbt/fastssz v0.1.2 + github.com/ferranbt/fastssz v0.1.4 github.com/fjl/gencodec v0.1.0 github.com/fsnotify/fsnotify v1.6.0 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff @@ -64,11 +64,11 @@ require ( github.com/urfave/cli/v2 v2.27.5 go.uber.org/automaxprocs v1.5.2 go.uber.org/goleak v1.3.0 - golang.org/x/crypto v0.35.0 + golang.org/x/crypto v0.36.0 golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df - golang.org/x/sync v0.11.0 - golang.org/x/sys v0.30.0 - golang.org/x/text v0.22.0 + golang.org/x/sync v0.12.0 + golang.org/x/sys v0.31.0 + golang.org/x/text v0.23.0 golang.org/x/time v0.9.0 golang.org/x/tools v0.29.0 google.golang.org/protobuf v1.34.2 @@ -98,10 +98,10 @@ require ( github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/consensys/bavard v0.1.27 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/deepmap/oapi-codegen v1.6.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/emicklei/dot v1.6.2 // indirect github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect @@ -123,7 +123,6 @@ require ( github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/naoina/go-stringutil v0.1.0 // indirect github.com/opentracing/opentracing-go v1.1.0 // indirect github.com/pion/dtls/v2 v2.2.7 // indirect @@ -143,7 +142,6 @@ require ( github.com/tklauser/numcpus v0.6.1 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect golang.org/x/mod v0.22.0 // indirect - golang.org/x/net v0.36.0 // indirect + golang.org/x/net v0.38.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index c91e34965654..db59c742299d 100644 --- a/go.sum +++ b/go.sum @@ -74,10 +74,8 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/consensys/bavard v0.1.27 h1:j6hKUrGAy/H+gpNrpLU3I26n1yc+VMGmd6ID5+gAhOs= -github.com/consensys/bavard v0.1.27/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= -github.com/consensys/gnark-crypto v0.16.0 h1:8Dl4eYmUWK9WmlP1Bj6je688gBRJCJbT8Mw4KoTAawo= -github.com/consensys/gnark-crypto v0.16.0/go.mod h1:Ke3j06ndtPTVvo++PhGNgvm+lgpLvzbcE2MqljY7diU= +github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= +github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI= @@ -110,14 +108,16 @@ github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjU github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w= github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E= github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk= -github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= +github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= +github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= github.com/fjl/gencodec v0.1.0 h1:B3K0xPfc52cw52BBgUbSPxYo+HlLfAgWMVKRWXUXBcs= github.com/fjl/gencodec v0.1.0/go.mod h1:Um1dFHPONZGTHog1qD1NaWjXJW/SPB38wPv0O8uZ2fI= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -177,7 +177,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -264,9 +263,6 @@ github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxd github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= -github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= @@ -322,8 +318,8 @@ github.com/protolambda/zrnt v0.34.1 h1:qW55rnhZJDnOb3TwFiFRJZi3yTXFrJdGOFQM7vCwY github.com/protolambda/zrnt v0.34.1/go.mod h1:A0fezkp9Tt3GBLATSPIbuY4ywYESyAuc/FFmPKg8Lqs= github.com/protolambda/ztyp v0.2.2 h1:rVcL3vBu9W/aV646zF6caLS/dyn9BN8NYiuJzicLNyY= github.com/protolambda/ztyp v0.2.2/go.mod h1:9bYgKGqg3wJqT9ac1gI2hnVb0STQq7p/1lapqrqY1dU= -github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48 h1:cSo6/vk8YpvkLbk9v3FO97cakNmUoxwi2KMP8hd5WIw= -github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk= +github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4= +github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -381,8 +377,8 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -406,8 +402,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= -golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -416,8 +412,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ 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.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -451,8 +447,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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= @@ -470,8 +466,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= @@ -517,5 +513,3 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/graphql/graphql.go b/graphql/graphql.go index e23e6fcb0e6e..0b2a77a3c4c7 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -229,7 +229,7 @@ func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, *Block) return t.tx, t.block } // Try to return an already finalized transaction - found, tx, blockHash, _, index := t.r.backend.GetTransaction(t.hash) + found, tx, blockHash, _, index := t.r.backend.GetCanonicalTransaction(t.hash) if found { t.tx = tx blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false) @@ -1510,6 +1510,9 @@ func (s *SyncState) TxIndexFinishedBlocks() hexutil.Uint64 { func (s *SyncState) TxIndexRemainingBlocks() hexutil.Uint64 { return hexutil.Uint64(s.progress.TxIndexRemainingBlocks) } +func (s *SyncState) StateIndexRemaining() hexutil.Uint64 { + return hexutil.Uint64(s.progress.StateIndexRemaining) +} // 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 peers. In case it is synchronizing: diff --git a/interfaces.go b/interfaces.go index 54a215d6e782..be5b97085155 100644 --- a/interfaces.go +++ b/interfaces.go @@ -124,6 +124,9 @@ type SyncProgress struct { // "transaction indexing" fields TxIndexFinishedBlocks uint64 // Number of blocks whose transactions are already indexed TxIndexRemainingBlocks uint64 // Number of blocks whose transactions are not indexed yet + + // "historical state indexing" fields + StateIndexRemaining uint64 // Number of states remain unindexed } // Done returns the indicator if the initial sync is finished or not. @@ -131,7 +134,7 @@ func (prog SyncProgress) Done() bool { if prog.CurrentBlock < prog.HighestBlock { return false } - return prog.TxIndexRemainingBlocks == 0 + return prog.TxIndexRemainingBlocks == 0 && prog.StateIndexRemaining == 0 } // ChainSyncReader wraps access to the node's current sync status. If there's no diff --git a/internal/debug/flags.go b/internal/debug/flags.go index adb652d59b3d..30b0ddb3be22 100644 --- a/internal/debug/flags.go +++ b/internal/debug/flags.go @@ -55,13 +55,13 @@ var ( Usage: "Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4)", Value: "", Hidden: true, - Category: flags.LoggingCategory, + Category: flags.DeprecatedCategory, } logjsonFlag = &cli.BoolFlag{ Name: "log.json", Usage: "Format logs with JSON", Hidden: true, - Category: flags.LoggingCategory, + Category: flags.DeprecatedCategory, } logFormatFlag = &cli.StringFlag{ Name: "log.format", diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8f736226c71b..21c35b76650a 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -170,6 +170,7 @@ func (api *EthereumAPI) Syncing(ctx context.Context) (interface{}, error) { "healingBytecode": hexutil.Uint64(progress.HealingBytecode), "txIndexFinishedBlocks": hexutil.Uint64(progress.TxIndexFinishedBlocks), "txIndexRemainingBlocks": hexutil.Uint64(progress.TxIndexRemainingBlocks), + "stateIndexRemaining": hexutil.Uint64(progress.StateIndexRemaining), }, nil } @@ -185,15 +186,15 @@ func NewTxPoolAPI(b Backend) *TxPoolAPI { // Content returns the transactions contained within the transaction pool. func (api *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction { + pending, queue := api.b.TxPoolContent() content := map[string]map[string]map[string]*RPCTransaction{ - "pending": make(map[string]map[string]*RPCTransaction), - "queued": make(map[string]map[string]*RPCTransaction), + "pending": make(map[string]map[string]*RPCTransaction, len(pending)), + "queued": make(map[string]map[string]*RPCTransaction, len(queue)), } - pending, queue := api.b.TxPoolContent() curHeader := api.b.CurrentHeader() // Flatten the pending transactions for account, txs := range pending { - dump := make(map[string]*RPCTransaction) + dump := make(map[string]*RPCTransaction, len(txs)) for _, tx := range txs { dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, api.b.ChainConfig()) } @@ -201,7 +202,7 @@ func (api *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction } // Flatten the queued transactions for account, txs := range queue { - dump := make(map[string]*RPCTransaction) + dump := make(map[string]*RPCTransaction, len(txs)) for _, tx := range txs { dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, api.b.ChainConfig()) } @@ -245,11 +246,11 @@ func (api *TxPoolAPI) Status() map[string]hexutil.Uint { // Inspect retrieves the content of the transaction pool and flattens it into an // easily inspectable list. func (api *TxPoolAPI) Inspect() map[string]map[string]map[string]string { + pending, queue := api.b.TxPoolContent() content := map[string]map[string]map[string]string{ - "pending": make(map[string]map[string]string), - "queued": make(map[string]map[string]string), + "pending": make(map[string]map[string]string, len(pending)), + "queued": make(map[string]map[string]string, len(queue)), } - pending, queue := api.b.TxPoolContent() // Define a formatter to flatten a transaction into a string format := func(tx *types.Transaction) string { @@ -260,7 +261,7 @@ func (api *TxPoolAPI) Inspect() map[string]map[string]map[string]string { } // Flatten the pending transactions for account, txs := range pending { - dump := make(map[string]string) + dump := make(map[string]string, len(txs)) for _, tx := range txs { dump[fmt.Sprintf("%d", tx.Nonce())] = format(tx) } @@ -268,7 +269,7 @@ func (api *TxPoolAPI) Inspect() map[string]map[string]map[string]string { } // Flatten the queued transactions for account, txs := range queue { - dump := make(map[string]string) + dump := make(map[string]string, len(txs)) for _, tx := range txs { dump[fmt.Sprintf("%d", tx.Nonce())] = format(tx) } @@ -1333,7 +1334,7 @@ func (api *TransactionAPI) GetTransactionCount(ctx context.Context, address comm // GetTransactionByHash returns the transaction for the given hash func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) { // Try to return an already finalized transaction - found, tx, blockHash, blockNumber, index := api.b.GetTransaction(hash) + found, tx, blockHash, blockNumber, index := api.b.GetCanonicalTransaction(hash) if !found { // No finalized transaction, try to retrieve it from the pool if tx := api.b.GetPoolTransaction(hash); tx != nil { @@ -1356,7 +1357,7 @@ func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common // GetRawTransactionByHash returns the bytes of the transaction for the given hash. func (api *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) { // Retrieve a finalized transaction, or a pooled otherwise - found, tx, _, _, _ := api.b.GetTransaction(hash) + found, tx, _, _, _ := api.b.GetCanonicalTransaction(hash) if !found { if tx = api.b.GetPoolTransaction(hash); tx != nil { return tx.MarshalBinary() @@ -1373,7 +1374,7 @@ func (api *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash com // GetTransactionReceipt returns the transaction receipt for the given transaction hash. func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) { - found, tx, blockHash, blockNumber, index := api.b.GetTransaction(hash) + found, tx, blockHash, blockNumber, index := api.b.GetCanonicalTransaction(hash) if !found { // Make sure indexer is done. if !api.b.TxIndexDone() { @@ -1382,22 +1383,12 @@ func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash commo // No such tx. return nil, nil } - header, err := api.b.HeaderByHash(ctx, blockHash) - if err != nil { - return nil, err - } - receipts, err := api.b.GetReceipts(ctx, blockHash) + receipt, err := api.b.GetCanonicalReceipt(tx, blockHash, blockNumber, index) if err != nil { return nil, err } - if uint64(len(receipts)) <= index { - return nil, nil - } - receipt := receipts[index] - // Derive the sender. - signer := types.MakeSigner(api.b.ChainConfig(), header.Number, header.Time) - return marshalReceipt(receipt, blockHash, blockNumber, signer, tx, int(index)), nil + return marshalReceipt(receipt, blockHash, blockNumber, api.signer, tx, int(index)), nil } // marshalReceipt marshals a transaction receipt into a JSON object. @@ -1780,7 +1771,7 @@ func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.Block // GetRawTransaction returns the bytes of the transaction for the given hash. func (api *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) { // Retrieve a finalized transaction, or a pooled otherwise - found, tx, _, _, _ := api.b.GetTransaction(hash) + found, tx, _, _, _ := api.b.GetCanonicalTransaction(hash) if !found { if tx = api.b.GetPoolTransaction(hash); tx != nil { return tx.MarshalBinary() @@ -1831,8 +1822,16 @@ func (api *DebugAPI) ChaindbCompact() error { } // SetHead rewinds the head of the blockchain to a previous block. -func (api *DebugAPI) SetHead(number hexutil.Uint64) { +func (api *DebugAPI) SetHead(number hexutil.Uint64) error { + header := api.b.CurrentHeader() + if header == nil { + return errors.New("current header is not available") + } + if header.Number.Uint64() <= uint64(number) { + return errors.New("not allowed to rewind to a future block") + } api.b.SetHead(uint64(number)) + return nil } // NetAPI offers network related RPC methods diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 0a157dce795f..1c9be836fc08 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -442,21 +442,16 @@ type testBackend struct { } func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend { - var ( - cacheConfig = &core.CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, - TrieDirtyDisabled: true, // Archive mode - } - ) + options := core.DefaultConfig().WithArchive(true) + options.TxLookupLimit = 0 // index all txs + accman, acc := newTestAccountManager(t) gspec.Alloc[acc.Address] = types.Account{Balance: big.NewInt(params.Ether)} + // Generate blocks for testing db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator) - txlookupLimit := uint64(0) - chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, &txlookupLimit) + + chain, err := core.NewBlockChain(db, gspec, engine, options) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -591,9 +586,12 @@ func (b testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) even func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { panic("implement me") } -func (b testBackend) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { - tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash) - return true, tx, blockHash, blockNumber, index +func (b testBackend) GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { + tx, blockHash, blockNumber, index := rawdb.ReadCanonicalTransaction(b.db, txHash) + return tx != nil, tx, blockHash, blockNumber, index +} +func (b testBackend) GetCanonicalReceipt(tx *types.Transaction, blockHash common.Hash, blockNumber, blockIndex uint64) (*types.Receipt, error) { + return b.chain.GetCanonicalReceipt(tx, blockHash, blockNumber, blockIndex) } func (b testBackend) TxIndexDone() bool { return true diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 49c3a37560ff..f709a1fcdcc8 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -68,13 +68,14 @@ type Backend interface { StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) Pending() (*types.Block, types.Receipts, *state.StateDB) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) + GetCanonicalReceipt(tx *types.Transaction, blockHash common.Hash, blockNumber, blockIndex uint64) (*types.Receipt, error) GetEVM(ctx context.Context, 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 // Transaction pool API SendTx(ctx context.Context, signedTx *types.Transaction) error - GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) + GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) TxIndexDone() bool GetPoolTransactions() (types.Transactions, error) GetPoolTransaction(txHash common.Hash) *types.Transaction diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index b997cf297b83..362536bcb564 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -301,7 +301,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes() } gasUsed += result.UsedGas - receipts[i] = core.MakeReceipt(evm, result, sim.state, blockContext.BlockNumber, common.Hash{}, tx, gasUsed, root) + receipts[i] = core.MakeReceipt(evm, result, sim.state, blockContext.BlockNumber, common.Hash{}, blockContext.Time, tx, gasUsed, root) blobGasUsed += receipts[i].BlobGasUsed logs := tracer.Logs() callRes := simCallResult{ReturnValue: result.Return(), Logs: logs, GasUsed: hexutil.Uint64(result.UsedGas)} diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json index 5853724cd6fe..f05cdb1cfd48 100644 --- a/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json +++ b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json @@ -17,4 +17,4 @@ "transactionIndex": "0x0", "type": "0x3" } -] +] \ 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 index 602b25e21fea..2595e38b2078 100644 --- a/internal/ethapi/testdata/eth_getBlockReceipts-block-with-dynamic-fee-tx.json +++ b/internal/ethapi/testdata/eth_getBlockReceipts-block-with-dynamic-fee-tx.json @@ -15,4 +15,4 @@ "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 index ae964b3d3b46..d3ba5aca9b0f 100644 --- 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 @@ -20,6 +20,7 @@ "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287", "transactionIndex": "0x0", "blockHash": "0xcc6225bf39327429a3d869af71182d619a354155187d0b5a8ecd6a9309cffcaa", + "blockTimestamp": "0x1e", "logIndex": "0x0", "removed": false } diff --git a/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json b/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json index 5853724cd6fe..f05cdb1cfd48 100644 --- a/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json +++ b/internal/ethapi/testdata/eth_getBlockReceipts-tag-latest.json @@ -17,4 +17,4 @@ "transactionIndex": "0x0", "type": "0x3" } -] +] \ 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 index 386f1225e6ac..d450e7c0d991 100644 --- a/internal/ethapi/testdata/eth_getTransactionReceipt-blob-tx.json +++ b/internal/ethapi/testdata/eth_getTransactionReceipt-blob-tx.json @@ -15,4 +15,4 @@ "transactionHash": "0x80348f994fb5f3b05bd2e5f58bbdc73485e449c028612a2c0680f9ac6ff70add", "transactionIndex": "0x0", "type": "0x3" -} +} \ 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 index 0519ae1da4b7..477c45c27457 100644 --- a/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-with-access-list.json +++ b/internal/ethapi/testdata/eth_getTransactionReceipt-create-contract-with-access-list.json @@ -13,4 +13,4 @@ "transactionHash": "0x173dffc76966c72542560c376ce512a871e31b86988f9169bf021da0937640f9", "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 index 4601273a5159..a0c93a962f7b 100644 --- a/internal/ethapi/testdata/eth_getTransactionReceipt-dynamic-tx-with-logs.json +++ b/internal/ethapi/testdata/eth_getTransactionReceipt-dynamic-tx-with-logs.json @@ -13,4 +13,4 @@ "transactionHash": "0xdcde2574628c9d7dff22b9afa19f235959a924ceec65a9df903a517ae91f5c84", "transactionIndex": "0x0", "type": "0x2" -} +} \ 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 index 1a1edb7887b2..7bd436066610 100644 --- a/internal/ethapi/testdata/eth_getTransactionReceipt-with-logs.json +++ b/internal/ethapi/testdata/eth_getTransactionReceipt-with-logs.json @@ -19,6 +19,7 @@ "transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287", "transactionIndex": "0x0", "blockHash": "0xcc6225bf39327429a3d869af71182d619a354155187d0b5a8ecd6a9309cffcaa", + "blockTimestamp": "0x1e", "logIndex": "0x0", "removed": false } diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 9b86e452a5be..30791f32b5eb 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -369,6 +369,9 @@ func (b *backendMock) Pending() (*types.Block, types.Receipts, *state.StateDB) { func (b *backendMock) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { return nil, nil } +func (b *backendMock) GetCanonicalReceipt(tx *types.Transaction, blockHash common.Hash, blockNumber, blockIndex uint64) (*types.Receipt, error) { + return nil, nil +} func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) { return nil, nil } @@ -380,7 +383,7 @@ func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) eve return nil } func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil } -func (b *backendMock) GetTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { +func (b *backendMock) GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { return false, nil, [32]byte{}, 0, 0 } func (b *backendMock) TxIndexDone() bool { return true } diff --git a/internal/flags/flags_test.go b/internal/flags/flags_test.go index 82e23fb4d2ff..9832f67d0957 100644 --- a/internal/flags/flags_test.go +++ b/internal/flags/flags_test.go @@ -17,19 +17,18 @@ package flags import ( - "os/user" "runtime" "testing" ) func TestPathExpansion(t *testing.T) { - user, _ := user.Current() + home := HomeDir() var tests map[string]string if runtime.GOOS == "windows" { tests = map[string]string{ `/home/someuser/tmp`: `\home\someuser\tmp`, - `~/tmp`: user.HomeDir + `\tmp`, + `~/tmp`: home + `\tmp`, `~thisOtherUser/b/`: `~thisOtherUser\b`, `$DDDXXX/a/b`: `\tmp\a\b`, `/a/b/`: `\a\b`, @@ -40,7 +39,7 @@ func TestPathExpansion(t *testing.T) { } else { tests = map[string]string{ `/home/someuser/tmp`: `/home/someuser/tmp`, - `~/tmp`: user.HomeDir + `/tmp`, + `~/tmp`: home + `/tmp`, `~thisOtherUser/b/`: `~thisOtherUser/b`, `$DDDXXX/a/b`: `/tmp/a/b`, `/a/b/`: `/a/b`, diff --git a/internal/jsre/deps/web3.js b/internal/jsre/deps/web3.js index 0aa738a2af46..3a19dce06c24 100644 --- a/internal/jsre/deps/web3.js +++ b/internal/jsre/deps/web3.js @@ -2510,10 +2510,8 @@ var RequestManager = require('./web3/requestmanager'); var Iban = require('./web3/iban'); var Eth = require('./web3/methods/eth'); var DB = require('./web3/methods/db'); -var Shh = require('./web3/methods/shh'); var Net = require('./web3/methods/net'); var Personal = require('./web3/methods/personal'); -var Swarm = require('./web3/methods/swarm'); var Settings = require('./web3/settings'); var version = require('./version.json'); var utils = require('./utils/utils'); @@ -2532,10 +2530,8 @@ function Web3 (provider) { this.currentProvider = provider; this.eth = new Eth(this); this.db = new DB(this); - this.shh = new Shh(this); this.net = new Net(this); this.personal = new Personal(this); - this.bzz = new Swarm(this); this.settings = new Settings(); this.version = { api: version.version @@ -2612,11 +2608,6 @@ var properties = function () { name: 'version.ethereum', getter: 'eth_protocolVersion', inputFormatter: utils.toDecimal - }), - new Property({ - name: 'version.whisper', - getter: 'shh_version', - inputFormatter: utils.toDecimal }) ]; }; @@ -2632,7 +2623,7 @@ Web3.prototype.createBatch = function () { module.exports = Web3; -},{"./utils/sha3":19,"./utils/utils":20,"./version.json":21,"./web3/batch":24,"./web3/extend":28,"./web3/httpprovider":32,"./web3/iban":33,"./web3/ipcprovider":34,"./web3/methods/db":37,"./web3/methods/eth":38,"./web3/methods/net":39,"./web3/methods/personal":40,"./web3/methods/shh":41,"./web3/methods/swarm":42,"./web3/property":45,"./web3/requestmanager":46,"./web3/settings":47,"bignumber.js":"bignumber.js"}],23:[function(require,module,exports){ +},{"./utils/sha3":19,"./utils/utils":20,"./version.json":21,"./web3/batch":24,"./web3/extend":28,"./web3/httpprovider":32,"./web3/iban":33,"./web3/ipcprovider":34,"./web3/methods/db":37,"./web3/methods/eth":38,"./web3/methods/net":39,"./web3/methods/personal":40,"./web3/property":45,"./web3/requestmanager":46,"./web3/settings":47,"bignumber.js":"bignumber.js"}],23:[function(require,module,exports){ /* This file is part of web3.js. @@ -3486,8 +3477,6 @@ var getOptions = function (options, type) { fromBlock: formatters.inputBlockNumberFormatter(options.fromBlock), toBlock: formatters.inputBlockNumberFormatter(options.toBlock) }; - case 'shh': - return options; } }; @@ -3977,6 +3966,7 @@ var outputSyncingFormatter = function(result) { result.healingBytecode = utils.toDecimal(result.healingBytecode); result.txIndexFinishedBlocks = utils.toDecimal(result.txIndexFinishedBlocks); result.txIndexRemainingBlocks = utils.toDecimal(result.txIndexRemainingBlocks); + result.stateIndexRemaining = utils.toDecimal(result.stateIndexRemaining) return result; }; @@ -5698,300 +5688,7 @@ var properties = function () { module.exports = Personal; -},{"../formatters":30,"../method":36,"../property":45}],41:[function(require,module,exports){ -/* - This file is part of web3.js. - - web3.js 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. - - web3.js 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 web3.js. If not, see . -*/ -/** @file shh.js - * @authors: - * Fabian Vogelsteller - * Marek Kotewicz - * @date 2017 - */ - -var Method = require('../method'); -var Filter = require('../filter'); -var watches = require('./watches'); - -var Shh = function (web3) { - this._requestManager = web3._requestManager; - - var self = this; - - methods().forEach(function(method) { - method.attachToObject(self); - method.setRequestManager(self._requestManager); - }); -}; - -Shh.prototype.newMessageFilter = function (options, callback, filterCreationErrorCallback) { - return new Filter(options, 'shh', this._requestManager, watches.shh(), null, callback, filterCreationErrorCallback); -}; - -var methods = function () { - - return [ - new Method({ - name: 'version', - call: 'shh_version', - params: 0 - }), - new Method({ - name: 'info', - call: 'shh_info', - params: 0 - }), - new Method({ - name: 'setMaxMessageSize', - call: 'shh_setMaxMessageSize', - params: 1 - }), - new Method({ - name: 'setMinPoW', - call: 'shh_setMinPoW', - params: 1 - }), - new Method({ - name: 'markTrustedPeer', - call: 'shh_markTrustedPeer', - params: 1 - }), - new Method({ - name: 'newKeyPair', - call: 'shh_newKeyPair', - params: 0 - }), - new Method({ - name: 'addPrivateKey', - call: 'shh_addPrivateKey', - params: 1 - }), - new Method({ - name: 'deleteKeyPair', - call: 'shh_deleteKeyPair', - params: 1 - }), - new Method({ - name: 'hasKeyPair', - call: 'shh_hasKeyPair', - params: 1 - }), - new Method({ - name: 'getPublicKey', - call: 'shh_getPublicKey', - params: 1 - }), - new Method({ - name: 'getPrivateKey', - call: 'shh_getPrivateKey', - params: 1 - }), - new Method({ - name: 'newSymKey', - call: 'shh_newSymKey', - params: 0 - }), - new Method({ - name: 'addSymKey', - call: 'shh_addSymKey', - params: 1 - }), - new Method({ - name: 'generateSymKeyFromPassword', - call: 'shh_generateSymKeyFromPassword', - params: 1 - }), - new Method({ - name: 'hasSymKey', - call: 'shh_hasSymKey', - params: 1 - }), - new Method({ - name: 'getSymKey', - call: 'shh_getSymKey', - params: 1 - }), - new Method({ - name: 'deleteSymKey', - call: 'shh_deleteSymKey', - params: 1 - }), - - // subscribe and unsubscribe missing - - new Method({ - name: 'post', - call: 'shh_post', - params: 1, - inputFormatter: [null] - }) - ]; -}; - -module.exports = Shh; - - -},{"../filter":29,"../method":36,"./watches":43}],42:[function(require,module,exports){ -/* - This file is part of web3.js. - - web3.js 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. - - web3.js 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 web3.js. If not, see . -*/ -/** - * @file bzz.js - * @author Alex Beregszaszi - * @date 2016 - * - * Reference: https://github.com/ethereum/go-ethereum/blob/swarm/internal/web3ext/web3ext.go#L33 - */ - -"use strict"; - -var Method = require('../method'); -var Property = require('../property'); - -function Swarm(web3) { - this._requestManager = web3._requestManager; - - var self = this; - - methods().forEach(function(method) { - method.attachToObject(self); - method.setRequestManager(self._requestManager); - }); - - properties().forEach(function(p) { - p.attachToObject(self); - p.setRequestManager(self._requestManager); - }); -} - -var methods = function () { - var blockNetworkRead = new Method({ - name: 'blockNetworkRead', - call: 'bzz_blockNetworkRead', - params: 1, - inputFormatter: [null] - }); - - var syncEnabled = new Method({ - name: 'syncEnabled', - call: 'bzz_syncEnabled', - params: 1, - inputFormatter: [null] - }); - - var swapEnabled = new Method({ - name: 'swapEnabled', - call: 'bzz_swapEnabled', - params: 1, - inputFormatter: [null] - }); - - var download = new Method({ - name: 'download', - call: 'bzz_download', - params: 2, - inputFormatter: [null, null] - }); - - var upload = new Method({ - name: 'upload', - call: 'bzz_upload', - params: 2, - inputFormatter: [null, null] - }); - - var retrieve = new Method({ - name: 'retrieve', - call: 'bzz_retrieve', - params: 1, - inputFormatter: [null] - }); - - var store = new Method({ - name: 'store', - call: 'bzz_store', - params: 2, - inputFormatter: [null, null] - }); - - var get = new Method({ - name: 'get', - call: 'bzz_get', - params: 1, - inputFormatter: [null] - }); - - var put = new Method({ - name: 'put', - call: 'bzz_put', - params: 2, - inputFormatter: [null, null] - }); - - var modify = new Method({ - name: 'modify', - call: 'bzz_modify', - params: 4, - inputFormatter: [null, null, null, null] - }); - - return [ - blockNetworkRead, - syncEnabled, - swapEnabled, - download, - upload, - retrieve, - store, - get, - put, - modify - ]; -}; - -var properties = function () { - return [ - new Property({ - name: 'hive', - getter: 'bzz_hive' - }), - new Property({ - name: 'info', - getter: 'bzz_info' - }) - ]; -}; - - -module.exports = Swarm; - -},{"../method":36,"../property":45}],43:[function(require,module,exports){ +},{"../formatters":30,"../method":36,"../property":45}],43:[function(require,module,exports){ /* This file is part of web3.js. @@ -6067,36 +5764,8 @@ var eth = function () { ]; }; -/// @returns an array of objects describing web3.shh.watch api methods -var shh = function () { - - return [ - new Method({ - name: 'newFilter', - call: 'shh_newMessageFilter', - params: 1 - }), - new Method({ - name: 'uninstallFilter', - call: 'shh_deleteMessageFilter', - params: 1 - }), - new Method({ - name: 'getLogs', - call: 'shh_getFilterMessages', - params: 1 - }), - new Method({ - name: 'poll', - call: 'shh_getFilterMessages', - params: 1 - }) - ]; -}; - module.exports = { - eth: eth, - shh: shh + eth: eth }; diff --git a/metrics/counter.go b/metrics/counter.go index 0f373b0d9289..c884e9a17845 100644 --- a/metrics/counter.go +++ b/metrics/counter.go @@ -7,10 +7,7 @@ import ( // GetOrRegisterCounter returns an existing Counter or constructs and registers // a new Counter. func GetOrRegisterCounter(name string, r Registry) *Counter { - if r == nil { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewCounter).(*Counter) + return getOrRegister(name, NewCounter, r) } // NewCounter constructs a new Counter. diff --git a/metrics/counter_float64.go b/metrics/counter_float64.go index 91c4215c4df6..6cc73d89a292 100644 --- a/metrics/counter_float64.go +++ b/metrics/counter_float64.go @@ -8,10 +8,7 @@ import ( // GetOrRegisterCounterFloat64 returns an existing *CounterFloat64 or constructs and registers // a new CounterFloat64. func GetOrRegisterCounterFloat64(name string, r Registry) *CounterFloat64 { - if nil == r { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewCounterFloat64).(*CounterFloat64) + return getOrRegister(name, NewCounterFloat64, r) } // NewCounterFloat64 constructs a new CounterFloat64. diff --git a/metrics/gauge.go b/metrics/gauge.go index ba7843e03b27..20de95255bdd 100644 --- a/metrics/gauge.go +++ b/metrics/gauge.go @@ -11,10 +11,7 @@ func (g GaugeSnapshot) Value() int64 { return int64(g) } // GetOrRegisterGauge returns an existing Gauge or constructs and registers a // new Gauge. func GetOrRegisterGauge(name string, r Registry) *Gauge { - if r == nil { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewGauge).(*Gauge) + return getOrRegister(name, NewGauge, r) } // NewGauge constructs a new Gauge. diff --git a/metrics/gauge_float64.go b/metrics/gauge_float64.go index 05b401ef9cb7..48524e4c3f70 100644 --- a/metrics/gauge_float64.go +++ b/metrics/gauge_float64.go @@ -8,10 +8,7 @@ import ( // GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a // new GaugeFloat64. func GetOrRegisterGaugeFloat64(name string, r Registry) *GaugeFloat64 { - if nil == r { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewGaugeFloat64()).(*GaugeFloat64) + return getOrRegister(name, NewGaugeFloat64, r) } // GaugeFloat64Snapshot is a read-only copy of a GaugeFloat64. diff --git a/metrics/gauge_info.go b/metrics/gauge_info.go index 1862ed55c564..34ac91791949 100644 --- a/metrics/gauge_info.go +++ b/metrics/gauge_info.go @@ -16,10 +16,7 @@ func (val GaugeInfoValue) String() string { // GetOrRegisterGaugeInfo returns an existing GaugeInfo or constructs and registers a // new GaugeInfo. func GetOrRegisterGaugeInfo(name string, r Registry) *GaugeInfo { - if nil == r { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewGaugeInfo()).(*GaugeInfo) + return getOrRegister(name, NewGaugeInfo, r) } // NewGaugeInfo constructs a new GaugeInfo. diff --git a/metrics/histogram.go b/metrics/histogram.go index 7c27bcc92880..18bf6e3d2b7f 100644 --- a/metrics/histogram.go +++ b/metrics/histogram.go @@ -23,19 +23,13 @@ type Histogram interface { // GetOrRegisterHistogram returns an existing Histogram or constructs and // registers a new StandardHistogram. func GetOrRegisterHistogram(name string, r Registry, s Sample) Histogram { - if nil == r { - r = DefaultRegistry - } - return r.GetOrRegister(name, func() Histogram { return NewHistogram(s) }).(Histogram) + return getOrRegister(name, func() Histogram { return NewHistogram(s) }, r) } // GetOrRegisterHistogramLazy returns an existing Histogram or constructs and // registers a new StandardHistogram. func GetOrRegisterHistogramLazy(name string, r Registry, s func() Sample) Histogram { - if nil == r { - r = DefaultRegistry - } - return r.GetOrRegister(name, func() Histogram { return NewHistogram(s()) }).(Histogram) + return getOrRegister(name, func() Histogram { return NewHistogram(s()) }, r) } // NewHistogram constructs a new StandardHistogram from a Sample. diff --git a/metrics/meter.go b/metrics/meter.go index 197e5abbed4a..ee23af10ebe3 100644 --- a/metrics/meter.go +++ b/metrics/meter.go @@ -12,10 +12,7 @@ import ( // Be sure to unregister the meter from the registry once it is of no use to // allow for garbage collection. func GetOrRegisterMeter(name string, r Registry) *Meter { - if r == nil { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewMeter).(*Meter) + return getOrRegister(name, NewMeter, r) } // NewMeter constructs a new Meter and launches a goroutine. diff --git a/metrics/registry.go b/metrics/registry.go index 527da6238de7..6070f3d0e9eb 100644 --- a/metrics/registry.go +++ b/metrics/registry.go @@ -3,7 +3,6 @@ package metrics import ( "errors" "fmt" - "reflect" "sort" "strings" "sync" @@ -30,10 +29,9 @@ type Registry interface { // GetAll metrics in the Registry. GetAll() map[string]map[string]interface{} - // GetOrRegister gets an existing metric or registers the given one. - // The interface can be the metric to register if not found in registry, - // or a function returning the metric for lazy instantiation. - GetOrRegister(string, interface{}) interface{} + // GetOrRegister returns an existing metric or registers the one returned + // by the given constructor. + GetOrRegister(string, func() interface{}) interface{} // Register the given metric under the given name. Register(string, interface{}) error @@ -95,19 +93,13 @@ func (r *StandardRegistry) Get(name string) interface{} { // alternative to calling Get and Register on failure. // The interface can be the metric to register if not found in registry, // or a function returning the metric for lazy instantiation. -func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { +func (r *StandardRegistry) GetOrRegister(name string, ctor func() interface{}) interface{} { // fast path cached, ok := r.metrics.Load(name) if ok { return cached } - if v := reflect.ValueOf(i); v.Kind() == reflect.Func { - i = v.Call(nil)[0].Interface() - } - item, _, ok := r.loadOrRegister(name, i) - if !ok { - return i - } + item, _, _ := r.loadOrRegister(name, ctor()) return item } @@ -120,9 +112,6 @@ func (r *StandardRegistry) Register(name string, i interface{}) error { return fmt.Errorf("%w: %v", ErrDuplicateMetric, name) } - if v := reflect.ValueOf(i); v.Kind() == reflect.Func { - i = v.Call(nil)[0].Interface() - } _, loaded, _ := r.loadOrRegister(name, i) if loaded { return fmt.Errorf("%w: %v", ErrDuplicateMetric, name) @@ -295,9 +284,9 @@ func (r *PrefixedRegistry) Get(name string) interface{} { // GetOrRegister gets an existing metric or registers the given one. // The interface can be the metric to register if not found in registry, // or a function returning the metric for lazy instantiation. -func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} { +func (r *PrefixedRegistry) GetOrRegister(name string, ctor func() interface{}) interface{} { realName := r.prefix + name - return r.underlying.GetOrRegister(realName, metric) + return r.underlying.GetOrRegister(realName, ctor) } // Register the given metric under the given name. The name will be prefixed. @@ -338,10 +327,17 @@ func Get(name string) interface{} { // GetOrRegister gets an existing metric or creates and registers a new one. Threadsafe // alternative to calling Get and Register on failure. -func GetOrRegister(name string, i interface{}) interface{} { +func GetOrRegister(name string, i func() interface{}) interface{} { return DefaultRegistry.GetOrRegister(name, i) } +func getOrRegister[T any](name string, ctor func() T, r Registry) T { + if r == nil { + r = DefaultRegistry + } + return r.GetOrRegister(name, func() any { return ctor() }).(T) +} + // Register the given metric under the given name. Returns a ErrDuplicateMetric // if a metric by the given name is already registered. func Register(name string, i interface{}) error { diff --git a/metrics/registry_test.go b/metrics/registry_test.go index bdc58fee6c74..6af0796da951 100644 --- a/metrics/registry_test.go +++ b/metrics/registry_test.go @@ -30,7 +30,7 @@ func benchmarkRegistryGetOrRegisterParallel(b *testing.B, amount int) { wg.Add(1) go func() { for i := 0; i < b.N; i++ { - r.GetOrRegister("foo", NewMeter) + GetOrRegisterMeter("foo", r) } wg.Done() }() @@ -98,10 +98,10 @@ func TestRegistryGetOrRegister(t *testing.T) { r := NewRegistry() // First metric wins with GetOrRegister - _ = r.GetOrRegister("foo", NewCounter()) - m := r.GetOrRegister("foo", NewGauge()) - if _, ok := m.(*Counter); !ok { - t.Fatal(m) + c1 := GetOrRegisterCounter("foo", r) + c2 := GetOrRegisterCounter("foo", r) + if c1 != c2 { + t.Fatal("counters should've matched") } i := 0 @@ -123,10 +123,10 @@ func TestRegistryGetOrRegisterWithLazyInstantiation(t *testing.T) { r := NewRegistry() // First metric wins with GetOrRegister - _ = r.GetOrRegister("foo", NewCounter) - m := r.GetOrRegister("foo", NewGauge) - if _, ok := m.(*Counter); !ok { - t.Fatal(m) + c1 := GetOrRegisterCounter("foo", r) + c2 := GetOrRegisterCounter("foo", r) + if c1 != c2 { + t.Fatal("counters should've matched") } i := 0 @@ -165,7 +165,7 @@ func TestPrefixedChildRegistryGetOrRegister(t *testing.T) { r := NewRegistry() pr := NewPrefixedChildRegistry(r, "prefix.") - _ = pr.GetOrRegister("foo", NewCounter()) + _ = GetOrRegisterCounter("foo", pr) i := 0 r.Each(func(name string, m interface{}) { @@ -182,7 +182,7 @@ func TestPrefixedChildRegistryGetOrRegister(t *testing.T) { func TestPrefixedRegistryGetOrRegister(t *testing.T) { r := NewPrefixedRegistry("prefix.") - _ = r.GetOrRegister("foo", NewCounter()) + _ = GetOrRegisterCounter("foo", r) i := 0 r.Each(func(name string, m interface{}) { diff --git a/metrics/resetting_timer.go b/metrics/resetting_timer.go index 66458bdb91fa..8aa7dc1488f8 100644 --- a/metrics/resetting_timer.go +++ b/metrics/resetting_timer.go @@ -8,10 +8,7 @@ import ( // GetOrRegisterResettingTimer returns an existing ResettingTimer or constructs and registers a // new ResettingTimer. func GetOrRegisterResettingTimer(name string, r Registry) *ResettingTimer { - if nil == r { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewResettingTimer).(*ResettingTimer) + return getOrRegister(name, NewResettingTimer, r) } // NewRegisteredResettingTimer constructs and registers a new ResettingTimer. diff --git a/metrics/runtimehistogram.go b/metrics/runtimehistogram.go index 92fcbcc2814c..53904b2b2866 100644 --- a/metrics/runtimehistogram.go +++ b/metrics/runtimehistogram.go @@ -8,11 +8,8 @@ import ( ) func getOrRegisterRuntimeHistogram(name string, scale float64, r Registry) *runtimeHistogram { - if r == nil { - r = DefaultRegistry - } constructor := func() Histogram { return newRuntimeHistogram(scale) } - return r.GetOrRegister(name, constructor).(*runtimeHistogram) + return getOrRegister(name, constructor, r).(*runtimeHistogram) } // runtimeHistogram wraps a runtime/metrics histogram. diff --git a/metrics/timer.go b/metrics/timer.go index 9df15c967aba..894bdfc32732 100644 --- a/metrics/timer.go +++ b/metrics/timer.go @@ -10,10 +10,7 @@ import ( // Be sure to unregister the meter from the registry once it is of no use to // allow for garbage collection. func GetOrRegisterTimer(name string, r Registry) *Timer { - if nil == r { - r = DefaultRegistry - } - return r.GetOrRegister(name, NewTimer).(*Timer) + return getOrRegister(name, NewTimer, r) } // NewCustomTimer constructs a new Timer from a Histogram and a Meter. diff --git a/miner/miner.go b/miner/miner.go index 3cec054d198f..ddfe0dcf26c8 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -52,7 +52,7 @@ type Config struct { // DefaultConfig contains default settings for miner. var DefaultConfig = Config{ - GasCeil: 36_000_000, + GasCeil: 45_000_000, GasPrice: big.NewInt(params.GWei / 1000), // The default recommit time is chosen as two seconds since diff --git a/miner/miner_test.go b/miner/miner_test.go index 04d84e2e1dc2..575ee4d0fd59 100644 --- a/miner/miner_test.go +++ b/miner/miner_test.go @@ -30,7 +30,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" @@ -152,7 +151,7 @@ func createMiner(t *testing.T) *Miner { // Create consensus engine engine := clique.New(chainConfig.Clique, chainDB) // Create Ethereum backend - bc, err := core.NewBlockChain(chainDB, nil, genesis, nil, engine, vm.Config{}, nil) + bc, err := core.NewBlockChain(chainDB, genesis, engine, nil) if err != nil { t.Fatalf("can't create new chain %v", err) } diff --git a/miner/payload_building_test.go b/miner/payload_building_test.go index e0791921d6eb..295962d7ef43 100644 --- a/miner/payload_building_test.go +++ b/miner/payload_building_test.go @@ -32,7 +32,6 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" @@ -118,7 +117,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine default: t.Fatalf("unexpected consensus engine type: %T", engine) } - chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil) + chain, err := core.NewBlockChain(db, gspec, engine, &core.BlockChainConfig{ArchiveMode: true}) if err != nil { t.Fatalf("core.NewBlockChain failed: %v", err) } diff --git a/miner/worker.go b/miner/worker.go index d80cb8913baf..799107f3bf42 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -32,6 +32,7 @@ import ( "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/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" @@ -49,6 +50,7 @@ type environment struct { signer types.Signer state *state.StateDB // apply state changes here tcount int // tx count in cycle + size uint64 // size of the block we are building gasPool *core.GasPool // available gas used to pack transactions coinbase common.Address evm *vm.EVM @@ -62,6 +64,11 @@ type environment struct { witness *stateless.Witness } +// txFits reports whether the transaction fits into the block size limit. +func (env *environment) txFitsSize(tx *types.Transaction) bool { + return env.size+tx.Size() < params.MaxBlockSize-maxBlockSizeBufferZone +} + const ( commitInterruptNone int32 = iota commitInterruptNewHead @@ -69,6 +76,11 @@ const ( commitInterruptTimeout ) +// Block size is capped by the protocol at params.MaxBlockSize. When producing blocks, we +// try to say below the size including a buffer zone, this is to avoid going over the +// maximum size with auxiliary data added into the block. +const maxBlockSizeBufferZone = 1_000_000 + // newPayloadResult is the result of payload generation. type newPayloadResult struct { err error @@ -94,12 +106,23 @@ type generateParams struct { } // generateWork generates a sealing block based on the given parameters. -func (miner *Miner) generateWork(params *generateParams, witness bool) *newPayloadResult { - work, err := miner.prepareWork(params, witness) +func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPayloadResult { + work, err := miner.prepareWork(genParam, witness) if err != nil { return &newPayloadResult{err: err} } - if !params.noTxs { + + // Check withdrawals fit max block size. + // Due to the cap on withdrawal count, this can actually never happen, but we still need to + // check to ensure the CL notices there's a problem if the withdrawal cap is ever lifted. + maxBlockSize := params.MaxBlockSize - maxBlockSizeBufferZone + if genParam.withdrawals.Size() > maxBlockSize { + return &newPayloadResult{err: errors.New("withdrawals exceed max block size")} + } + // Also add size of withdrawals to work block size. + work.size += uint64(genParam.withdrawals.Size()) + + if !genParam.noTxs { interrupt := new(atomic.Int32) timer := time.AfterFunc(miner.config.Recommit, func() { interrupt.Store(commitInterruptTimeout) @@ -111,8 +134,8 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(miner.config.Recommit)) } } + body := types.Body{Transactions: work.txs, Withdrawals: genParam.withdrawals} - body := types.Body{Transactions: work.txs, Withdrawals: params.withdrawals} allLogs := make([]*types.Log, 0) for _, r := range work.receipts { allLogs = append(allLogs, r.Logs...) @@ -255,6 +278,7 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase return &environment{ signer: types.MakeSigner(miner.chainConfig, header.Number, header.Time), state: state, + size: uint64(header.Size()), coinbase: coinbase, header: header, witness: state.Witness(), @@ -272,6 +296,7 @@ func (miner *Miner) commitTransaction(env *environment, tx *types.Transaction) e } env.txs = append(env.txs, tx) env.receipts = append(env.receipts, receipt) + env.size += tx.Size() env.tcount++ return nil } @@ -293,10 +318,12 @@ func (miner *Miner) commitBlobTransaction(env *environment, tx *types.Transactio if err != nil { return err } - env.txs = append(env.txs, tx.WithoutBlobTxSidecar()) + txNoBlob := tx.WithoutBlobTxSidecar() + env.txs = append(env.txs, txNoBlob) env.receipts = append(env.receipts, receipt) env.sidecars = append(env.sidecars, sc) env.blobs += len(sc.Blobs) + env.size += txNoBlob.Size() *env.header.BlobGasUsed += receipt.BlobGasUsed env.tcount++ return nil @@ -317,7 +344,11 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (* } func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *transactionsByPriceAndNonce, interrupt *atomic.Int32) error { - gasLimit := env.header.GasLimit + var ( + isOsaka = miner.chainConfig.IsOsaka(env.header.Number, env.header.Time) + isCancun = miner.chainConfig.IsCancun(env.header.Number, env.header.Time) + gasLimit = env.header.GasLimit + ) if env.gasPool == nil { env.gasPool = new(core.GasPool).AddGas(gasLimit) } @@ -373,7 +404,7 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran // Most of the blob gas logic here is agnostic as to if the chain supports // blobs or not, however the max check panics when called on a chain without // a defined schedule, so we need to verify it's safe to call. - if miner.chainConfig.IsCancun(env.header.Number, env.header.Time) { + if isCancun { left := eip4844.MaxBlobsPerBlock(miner.chainConfig, env.header.Time) - env.blobs if left < int(ltx.BlobGas/params.BlobTxBlobGasPerBlob) { log.Trace("Not enough blob space left for transaction", "hash", ltx.Hash, "left", left, "needed", ltx.BlobGas/params.BlobTxBlobGasPerBlob) @@ -390,6 +421,29 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran continue } + // if inclusion of the transaction would put the block size over the + // maximum we allow, don't add any more txs to the payload. + if !env.txFitsSize(tx) { + break + } + + // Make sure all transactions after osaka have cell proofs + if isOsaka { + if sidecar := tx.BlobTxSidecar(); sidecar != nil { + if sidecar.Version == 0 { + log.Info("Including blob tx with v0 sidecar, recomputing proofs", "hash", ltx.Hash) + sidecar.Proofs = make([]kzg4844.Proof, 0, len(sidecar.Blobs)*kzg4844.CellProofsPerBlob) + for _, blob := range sidecar.Blobs { + cellProofs, err := kzg4844.ComputeCellProofs(&blob) + if err != nil { + panic(err) + } + sidecar.Proofs = append(sidecar.Proofs, cellProofs...) + } + } + } + } + // Error may be ignored here. The error has already been checked // during transaction acceptance in the transaction pool. from, _ := types.Sender(env.signer, tx) @@ -444,6 +498,9 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment) if env.header.ExcessBlobGas != nil { filter.BlobFee = uint256.MustFromBig(eip4844.CalcBlobFee(miner.chainConfig, env.header)) } + if miner.chainConfig.IsOsaka(env.header.Number, env.header.Time) { + filter.GasLimitCap = params.MaxTxGas + } filter.OnlyPlainTxs, filter.OnlyBlobTxs = true, false pendingPlainTxs := miner.txpool.Pending(filter) diff --git a/node/database.go b/node/database.go index 44bea10307a2..274ccbfa7e7e 100644 --- a/node/database.go +++ b/node/database.go @@ -109,7 +109,7 @@ func newLevelDBDatabase(file string, cache int, handles int, namespace string, r return nil, err } log.Info("Using LevelDB as the backing database") - return rawdb.NewDatabase(db), nil + return db, nil } // newPebbleDBDatabase creates a persistent key-value database without a freezer @@ -119,5 +119,5 @@ func newPebbleDBDatabase(file string, cache int, handles int, namespace string, if err != nil { return nil, err } - return rawdb.NewDatabase(db), nil + return db, nil } diff --git a/node/rpcstack.go b/node/rpcstack.go index 6d3828ec2b0c..655f7db9e4f3 100644 --- a/node/rpcstack.go +++ b/node/rpcstack.go @@ -62,6 +62,7 @@ type rpcEndpointConfig struct { type rpcHandler struct { http.Handler + prefix string server *rpc.Server } @@ -77,11 +78,11 @@ type httpServer struct { // HTTP RPC handler things. httpConfig httpConfig - httpHandler atomic.Value // *rpcHandler + httpHandler atomic.Pointer[rpcHandler] // WebSocket handler things. wsConfig wsConfig - wsHandler atomic.Value // *rpcHandler + wsHandler atomic.Pointer[rpcHandler] // These are set by setListenAddr. endpoint string @@ -97,9 +98,6 @@ const ( func newHTTPServer(log log.Logger, timeouts rpc.HTTPTimeouts) *httpServer { h := &httpServer{log: log, timeouts: timeouts, handlerNames: make(map[string]string)} - - h.httpHandler.Store((*rpcHandler)(nil)) - h.wsHandler.Store((*rpcHandler)(nil)) return h } @@ -173,7 +171,7 @@ func (h *httpServer) start() error { } // Log http endpoint. h.log.Info("HTTP server started", - "endpoint", listener.Addr(), "auth", (h.httpConfig.jwtSecret != nil), + "endpoint", listener.Addr(), "auth", h.httpConfig.jwtSecret != nil, "prefix", h.httpConfig.prefix, "cors", strings.Join(h.httpConfig.CorsAllowedOrigins, ","), "vhosts", strings.Join(h.httpConfig.Vhosts, ","), @@ -198,16 +196,16 @@ func (h *httpServer) start() error { func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { // check if ws request and serve if ws enabled - ws := h.wsHandler.Load().(*rpcHandler) + ws := h.wsHandler.Load() if ws != nil && isWebsocket(r) { - if checkPath(r, h.wsConfig.prefix) { + if checkPath(r, ws.prefix) { ws.ServeHTTP(w, r) } return } // if http-rpc is enabled, try to serve request - rpc := h.httpHandler.Load().(*rpcHandler) + rpc := h.httpHandler.Load() if rpc != nil { // First try to route in the mux. // Requests to a path below root are handled by the mux, @@ -219,7 +217,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - if checkPath(r, h.httpConfig.prefix) { + if checkPath(r, rpc.prefix) { rpc.ServeHTTP(w, r) return } @@ -267,14 +265,14 @@ func (h *httpServer) doStop() { } // Shut down the server. - httpHandler := h.httpHandler.Load().(*rpcHandler) - wsHandler := h.wsHandler.Load().(*rpcHandler) + httpHandler := h.httpHandler.Load() + wsHandler := h.wsHandler.Load() if httpHandler != nil { - h.httpHandler.Store((*rpcHandler)(nil)) + h.httpHandler.Store(nil) httpHandler.server.Stop() } if wsHandler != nil { - h.wsHandler.Store((*rpcHandler)(nil)) + h.wsHandler.Store(nil) wsHandler.server.Stop() } @@ -315,6 +313,7 @@ func (h *httpServer) enableRPC(apis []rpc.API, config httpConfig) error { h.httpConfig = config h.httpHandler.Store(&rpcHandler{ Handler: NewHTTPHandlerStack(srv, config.CorsAllowedOrigins, config.Vhosts, config.jwtSecret), + prefix: config.prefix, server: srv, }) return nil @@ -322,9 +321,9 @@ func (h *httpServer) enableRPC(apis []rpc.API, config httpConfig) error { // disableRPC stops the HTTP RPC handler. This is internal, the caller must hold h.mu. func (h *httpServer) disableRPC() bool { - handler := h.httpHandler.Load().(*rpcHandler) + handler := h.httpHandler.Load() if handler != nil { - h.httpHandler.Store((*rpcHandler)(nil)) + h.httpHandler.Store(nil) handler.server.Stop() } return handler != nil @@ -350,6 +349,7 @@ func (h *httpServer) enableWS(apis []rpc.API, config wsConfig) error { h.wsConfig = config h.wsHandler.Store(&rpcHandler{ Handler: NewWSHandlerStack(srv.WebsocketHandler(config.Origins), config.jwtSecret), + prefix: config.prefix, server: srv, }) return nil @@ -369,9 +369,9 @@ func (h *httpServer) stopWS() { // disableWS disables the WebSocket handler. This is internal, the caller must hold h.mu. func (h *httpServer) disableWS() bool { - ws := h.wsHandler.Load().(*rpcHandler) + ws := h.wsHandler.Load() if ws != nil { - h.wsHandler.Store((*rpcHandler)(nil)) + h.wsHandler.Store(nil) ws.server.Stop() } return ws != nil @@ -379,12 +379,12 @@ func (h *httpServer) disableWS() bool { // rpcAllowed returns true when JSON-RPC over HTTP is enabled. func (h *httpServer) rpcAllowed() bool { - return h.httpHandler.Load().(*rpcHandler) != nil + return h.httpHandler.Load() != nil } // wsAllowed returns true when JSON-RPC over WebSocket is enabled. func (h *httpServer) wsAllowed() bool { - return h.wsHandler.Load().(*rpcHandler) != nil + return h.wsHandler.Load() != nil } // isWebsocket checks the header of an http request for a websocket upgrade request. diff --git a/oss-fuzz.sh b/oss-fuzz.sh index 4db245a78177..020b6fee273b 100644 --- a/oss-fuzz.sh +++ b/oss-fuzz.sh @@ -152,6 +152,14 @@ 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/bn256 \ + FuzzUnmarshalG1 fuzzBn256UnmarshalG1 \ + $repo/tests/fuzzers/bn256/bn256_test.go + +compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bn256 \ + FuzzUnmarshalG2 fuzzBn256UnmarshalG2 \ + $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 diff --git a/params/config.go b/params/config.go index 2e825ffcd56c..85619bbe222a 100644 --- a/params/config.go +++ b/params/config.go @@ -296,7 +296,7 @@ var ( ShanghaiTime: newUint64(0), CancunTime: newUint64(0), PragueTime: newUint64(0), - OsakaTime: nil, + OsakaTime: newUint64(0), VerkleTime: nil, TerminalTotalDifficulty: big.NewInt(0), Ethash: new(EthashConfig), @@ -304,6 +304,7 @@ var ( BlobScheduleConfig: &BlobScheduleConfig{ Cancun: DefaultCancunBlobConfig, Prague: DefaultPragueBlobConfig, + Osaka: DefaultOsakaBlobConfig, }, } @@ -410,6 +411,11 @@ type ChainConfig struct { PragueTime *uint64 `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague) OsakaTime *uint64 `json:"osakaTime,omitempty"` // Osaka switch time (nil = no fork, 0 = already on osaka) VerkleTime *uint64 `json:"verkleTime,omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle) + BPO1Time *uint64 `json:"bpo1Time,omitempty"` // BPO1 switch time (nil = no fork, 0 = already on bpo1) + BPO2Time *uint64 `json:"bpo2Time,omitempty"` // BPO2 switch time (nil = no fork, 0 = already on bpo2) + BPO3Time *uint64 `json:"bpo3Time,omitempty"` // BPO3 switch time (nil = no fork, 0 = already on bpo3) + BPO4Time *uint64 `json:"bpo4Time,omitempty"` // BPO4 switch time (nil = no fork, 0 = already on bpo4) + BPO5Time *uint64 `json:"bpo5Time,omitempty"` // BPO5 switch time (nil = no fork, 0 = already on bpo5) // TerminalTotalDifficulty is the amount of total difficulty reached by // the network that triggers the consensus upgrade. @@ -530,6 +536,21 @@ func (c *ChainConfig) Description() string { if c.VerkleTime != nil { banner += fmt.Sprintf(" - Verkle: @%-10v\n", *c.VerkleTime) } + if c.BPO1Time != nil { + banner += fmt.Sprintf(" - BPO1: @%-10v\n", *c.BPO1Time) + } + if c.BPO2Time != nil { + banner += fmt.Sprintf(" - BPO2: @%-10v\n", *c.BPO2Time) + } + if c.BPO3Time != nil { + banner += fmt.Sprintf(" - BPO3: @%-10v\n", *c.BPO3Time) + } + if c.BPO4Time != nil { + banner += fmt.Sprintf(" - BPO4: @%-10v\n", *c.BPO4Time) + } + if c.BPO5Time != nil { + banner += fmt.Sprintf(" - BPO5: @%-10v\n", *c.BPO5Time) + } return banner } @@ -546,6 +567,11 @@ type BlobScheduleConfig struct { Prague *BlobConfig `json:"prague,omitempty"` Osaka *BlobConfig `json:"osaka,omitempty"` Verkle *BlobConfig `json:"verkle,omitempty"` + BPO1 *BlobConfig `json:"bpo1,omitempty"` + BPO2 *BlobConfig `json:"bpo2,omitempty"` + BPO3 *BlobConfig `json:"bpo3,omitempty"` + BPO4 *BlobConfig `json:"bpo4,omitempty"` + BPO5 *BlobConfig `json:"bpo5,omitempty"` } // IsHomestead returns whether num is either equal to the homestead block or greater. @@ -653,6 +679,31 @@ func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool { return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time) } +// IsBPO1 returns whether time is either equal to the BPO1 fork time or greater. +func (c *ChainConfig) IsBPO1(num *big.Int, time uint64) bool { + return c.IsLondon(num) && isTimestampForked(c.BPO1Time, time) +} + +// IsBPO2 returns whether time is either equal to the BPO2 fork time or greater. +func (c *ChainConfig) IsBPO2(num *big.Int, time uint64) bool { + return c.IsLondon(num) && isTimestampForked(c.BPO2Time, time) +} + +// IsBPO3 returns whether time is either equal to the BPO3 fork time or greater. +func (c *ChainConfig) IsBPO3(num *big.Int, time uint64) bool { + return c.IsLondon(num) && isTimestampForked(c.BPO3Time, time) +} + +// IsBPO4 returns whether time is either equal to the BPO4 fork time or greater. +func (c *ChainConfig) IsBPO4(num *big.Int, time uint64) bool { + return c.IsLondon(num) && isTimestampForked(c.BPO4Time, time) +} + +// IsBPO5 returns whether time is either equal to the BPO5 fork time or greater. +func (c *ChainConfig) IsBPO5(num *big.Int, time uint64) bool { + return c.IsLondon(num) && isTimestampForked(c.BPO5Time, time) +} + // IsVerkleGenesis checks whether the verkle fork is activated at the genesis block. // // Verkle mode is considered enabled if the verkle fork time is configured, @@ -728,6 +779,11 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "pragueTime", timestamp: c.PragueTime, optional: true}, {name: "osakaTime", timestamp: c.OsakaTime, optional: true}, {name: "verkleTime", timestamp: c.VerkleTime, optional: true}, + {name: "bpo1", timestamp: c.BPO1Time, optional: true}, + {name: "bpo2", timestamp: c.BPO2Time, optional: true}, + {name: "bpo3", timestamp: c.BPO3Time, optional: true}, + {name: "bpo4", timestamp: c.BPO4Time, optional: true}, + {name: "bpo5", timestamp: c.BPO5Time, optional: true}, } { if lastFork.name != "" { switch { @@ -777,6 +833,11 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "cancun", timestamp: c.CancunTime, config: bsc.Cancun}, {name: "prague", timestamp: c.PragueTime, config: bsc.Prague}, {name: "osaka", timestamp: c.OsakaTime, config: bsc.Osaka}, + {name: "bpo1", timestamp: c.BPO1Time, config: bsc.BPO1}, + {name: "bpo2", timestamp: c.BPO2Time, config: bsc.BPO2}, + {name: "bpo3", timestamp: c.BPO3Time, config: bsc.BPO3}, + {name: "bpo4", timestamp: c.BPO4Time, config: bsc.BPO4}, + {name: "bpo5", timestamp: c.BPO5Time, config: bsc.BPO5}, } { if cur.config != nil { if err := cur.config.validate(); err != nil { @@ -877,6 +938,21 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, if isForkTimestampIncompatible(c.VerkleTime, newcfg.VerkleTime, headTimestamp) { return newTimestampCompatError("Verkle fork timestamp", c.VerkleTime, newcfg.VerkleTime) } + if isForkTimestampIncompatible(c.BPO1Time, newcfg.BPO1Time, headTimestamp) { + return newTimestampCompatError("BPO1 fork timestamp", c.BPO1Time, newcfg.BPO1Time) + } + if isForkTimestampIncompatible(c.BPO2Time, newcfg.BPO2Time, headTimestamp) { + return newTimestampCompatError("BPO2 fork timestamp", c.BPO2Time, newcfg.BPO2Time) + } + if isForkTimestampIncompatible(c.BPO3Time, newcfg.BPO3Time, headTimestamp) { + return newTimestampCompatError("BPO3 fork timestamp", c.BPO3Time, newcfg.BPO3Time) + } + if isForkTimestampIncompatible(c.BPO4Time, newcfg.BPO4Time, headTimestamp) { + return newTimestampCompatError("BPO4 fork timestamp", c.BPO4Time, newcfg.BPO4Time) + } + if isForkTimestampIncompatible(c.BPO5Time, newcfg.BPO5Time, headTimestamp) { + return newTimestampCompatError("BPO5 fork timestamp", c.BPO5Time, newcfg.BPO5Time) + } return nil } diff --git a/params/protocol_params.go b/params/protocol_params.go index 6b06dadaef17..f52bb27380d6 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -28,6 +28,8 @@ const ( MaxGasLimit uint64 = 0x7fffffffffffffff // Maximum the gas limit (2^63-1). GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. + MaxTxGas uint64 = 30_000_000 // Maximum transaction gas limit after eip-7825. + MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. 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. @@ -163,6 +165,8 @@ const ( Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation Bls12381MapG2Gas uint64 = 23800 // Gas price for BLS12-381 mapping field element to G2 operation + P256VerifyGas uint64 = 6900 // secp256r1 elliptic curve signature verifier gas price + // The Refund Quotient is the cap on how much of the used gas can be refunded. Before EIP-3529, // up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529 RefundQuotient uint64 = 2 @@ -173,8 +177,11 @@ const ( BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size) BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs BlobTxPointEvaluationPrecompileGas = 50000 // Gas price for the point evaluation precompile. + BlobBaseCost = 1 << 13 // Base execution gas cost for a blob. HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935. + + MaxBlockSize = 8_388_608 // maximum size of an RLP-encoded block ) // Bls12381G1MultiExpDiscountTable is the gas discount table for BLS12-381 G1 multi exponentiation operation diff --git a/rpc/client.go b/rpc/client.go index f9a8f1116b2b..ba7e43eb5c4e 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -487,12 +487,6 @@ func (c *Client) EthSubscribe(ctx context.Context, channel interface{}, args ... return c.Subscribe(ctx, "eth", channel, args...) } -// ShhSubscribe registers a subscription under the "shh" namespace. -// Deprecated: use Subscribe(ctx, "shh", ...). -func (c *Client) ShhSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error) { - return c.Subscribe(ctx, "shh", channel, args...) -} - // Subscribe calls the "_subscribe" method with the given arguments, // registering a subscription. Server notifications for the subscription are // sent to the given channel. The element type of the channel must match the diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go index e52f390adb94..cd44d219de1e 100644 --- a/rpc/subscription_test.go +++ b/rpc/subscription_test.go @@ -59,7 +59,7 @@ func TestSubscriptions(t *testing.T) { t.Parallel() var ( - namespaces = []string{"eth", "bzz"} + namespaces = []string{"eth"} service = ¬ificationTestService{} subCount = len(namespaces) notificationCount = 3 diff --git a/tests/block_test_util.go b/tests/block_test_util.go index f029fa7f414e..a76037405b95 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -151,15 +151,21 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t // Wrap the original engine within the beacon-engine engine := beacon.New(ethash.NewFaker()) - cache := &core.CacheConfig{TrieCleanLimit: 0, StateScheme: scheme, Preimages: true} + options := &core.BlockChainConfig{ + TrieCleanLimit: 0, + StateScheme: scheme, + Preimages: true, + TxLookupLimit: -1, // disable tx indexing + VmConfig: vm.Config{ + Tracer: tracer, + StatelessSelfValidation: witness, + }, + } if snapshotter { - cache.SnapshotLimit = 1 - cache.SnapshotWait = true + options.SnapshotLimit = 1 + options.SnapshotWait = true } - chain, err := core.NewBlockChain(db, cache, gspec, nil, engine, vm.Config{ - Tracer: tracer, - StatelessSelfValidation: witness, - }, nil) + chain, err := core.NewBlockChain(db, gspec, engine, options) if err != nil { return err } diff --git a/tests/fuzzers/bn256/bn256_fuzz.go b/tests/fuzzers/bn256/bn256_fuzz.go index 4521f6b0dbca..d53bdbb4b9ad 100644 --- a/tests/fuzzers/bn256/bn256_fuzz.go +++ b/tests/fuzzers/bn256/bn256_fuzz.go @@ -161,6 +161,60 @@ func fuzzPair(data []byte) int { return 1 } +func fuzzUnmarshalG1(input []byte) int { + rc := new(cloudflare.G1) + _, errC := rc.Unmarshal(input) + + rg := new(google.G1) + _, errG := rg.Unmarshal(input) + + rs := new(gnark.G1) + _, errS := rs.Unmarshal(input) + + if errC != nil && errG != nil && errS != nil { + return 0 // bad input + } + if errC == nil && errG == nil && errS == nil { + //make sure we unmarshalled the same points: + if !bytes.Equal(rc.Marshal(), rg.Marshal()) { + panic("marshaling mismatch: cloudflare/google") + } + if !bytes.Equal(rc.Marshal(), rs.Marshal()) { + panic("marshaling mismatch: cloudflare/gnark") + } + return 1 + } else { + panic(fmt.Sprintf("error missmatch: cf: %v g: %v gn: %v", errC, errG, errS)) + } +} + +func fuzzUnmarshalG2(input []byte) int { + rc := new(cloudflare.G2) + _, errC := rc.Unmarshal(input) + + rg := new(google.G2) + _, errG := rg.Unmarshal(input) + + rs := new(gnark.G2) + _, errS := rs.Unmarshal(input) + + if errC != nil && errG != nil && errS != nil { + return 0 // bad input + } + if errC == nil && errG == nil && errS == nil { + //make sure we unmarshalled the same points: + if !bytes.Equal(rc.Marshal(), rg.Marshal()) { + panic("marshaling mismatch: cloudflare/google") + } + if !bytes.Equal(rc.Marshal(), rs.Marshal()) { + panic("marshaling mismatch: cloudflare/gnark") + } + return 1 + } else { + panic(fmt.Sprintf("error missmatch: cf: %v g: %v gn: %v", errC, errG, errS)) + } +} + // normalizeGTToGnark scales a Cloudflare/Google GT element by `s` // so that it can be compared with a gnark GT point. // diff --git a/tests/fuzzers/bn256/bn256_test.go b/tests/fuzzers/bn256/bn256_test.go index 8b2f962284cf..80fb850103a2 100644 --- a/tests/fuzzers/bn256/bn256_test.go +++ b/tests/fuzzers/bn256/bn256_test.go @@ -35,3 +35,15 @@ func FuzzPair(f *testing.F) { fuzzPair(data) }) } + +func FuzzUnmarshalG1(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + fuzzUnmarshalG1(data) + }) +} + +func FuzzUnmarshalG2(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + fuzzUnmarshalG2(data) + }) +} diff --git a/trie/database_test.go b/trie/database_test.go index 535f0d61b208..98fd2372ef75 100644 --- a/trie/database_test.go +++ b/trie/database_test.go @@ -86,6 +86,10 @@ func (db *testDb) InsertPreimage(preimages map[common.Hash][]byte) { rawdb.WritePreimages(db.disk, preimages) } +func (db *testDb) PreimageEnabled() bool { + return true +} + func (db *testDb) Scheme() string { return db.scheme } func (db *testDb) Update(root common.Hash, parent common.Hash, nodes *trienode.MergedNodeSet) error { diff --git a/trie/secure_trie.go b/trie/secure_trie.go index 7852e16619c1..0424ecb6e515 100644 --- a/trie/secure_trie.go +++ b/trie/secure_trie.go @@ -33,6 +33,9 @@ type preimageStore interface { // InsertPreimage commits a set of preimages along with their hashes. InsertPreimage(preimages map[common.Hash][]byte) + + // PreimageEnabled returns true if the preimage store is enabled. + PreimageEnabled() bool } // SecureTrie is the old name of StateTrie. @@ -61,11 +64,10 @@ func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db da // // StateTrie is not safe for concurrent use. type StateTrie struct { - trie Trie - db database.NodeDatabase - preimages preimageStore - secKeyCache map[common.Hash][]byte - secKeyCacheOwner *StateTrie // Pointer to self, replace the key cache on mismatch + trie Trie + db database.NodeDatabase + preimages preimageStore + secKeyCache map[common.Hash][]byte } // NewStateTrie creates a trie with an existing root node from a backing database. @@ -81,11 +83,14 @@ func NewStateTrie(id *ID, db database.NodeDatabase) (*StateTrie, error) { if err != nil { return nil, err } - tr := &StateTrie{trie: *trie, db: db} + tr := &StateTrie{ + trie: *trie, + db: db, + secKeyCache: make(map[common.Hash][]byte), + } // link the preimage store if it's supported - preimages, ok := db.(preimageStore) - if ok { + if preimages, ok := db.(preimageStore); ok && preimages.PreimageEnabled() { tr.preimages = preimages } return tr, nil @@ -159,7 +164,9 @@ func (t *StateTrie) GetNode(path []byte) ([]byte, int, error) { func (t *StateTrie) MustUpdate(key, value []byte) { hk := crypto.Keccak256(key) t.trie.MustUpdate(hk, value) - t.getSecKeyCache()[common.Hash(hk)] = common.CopyBytes(key) + if t.preimages != nil { + t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key) + } } // UpdateStorage associates key with value in the trie. Subsequent calls to @@ -177,7 +184,9 @@ func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error { if err != nil { return err } - t.getSecKeyCache()[common.Hash(hk)] = common.CopyBytes(key) + if t.preimages != nil { + t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key) + } return nil } @@ -191,7 +200,9 @@ func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccoun if err := t.trie.Update(hk, data); err != nil { return err } - t.getSecKeyCache()[common.Hash(hk)] = address.Bytes() + if t.preimages != nil { + t.secKeyCache[common.Hash(hk)] = address.Bytes() + } return nil } @@ -203,7 +214,9 @@ func (t *StateTrie) UpdateContractCode(_ common.Address, _ common.Hash, _ []byte // will omit any encountered error but just print out an error message. func (t *StateTrie) MustDelete(key []byte) { hk := crypto.Keccak256(key) - delete(t.getSecKeyCache(), common.Hash(hk)) + if t.preimages != nil { + delete(t.secKeyCache, common.Hash(hk)) + } t.trie.MustDelete(hk) } @@ -212,26 +225,30 @@ func (t *StateTrie) MustDelete(key []byte) { // If a node is not found in the database, a MissingNodeError is returned. func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error { hk := crypto.Keccak256(key) - delete(t.getSecKeyCache(), common.Hash(hk)) + if t.preimages != nil { + delete(t.secKeyCache, common.Hash(hk)) + } return t.trie.Delete(hk) } // DeleteAccount abstracts an account deletion from the trie. func (t *StateTrie) DeleteAccount(address common.Address) error { hk := crypto.Keccak256(address.Bytes()) - delete(t.getSecKeyCache(), common.Hash(hk)) + if t.preimages != nil { + delete(t.secKeyCache, common.Hash(hk)) + } return t.trie.Delete(hk) } // GetKey returns the sha3 preimage of a hashed key that was // previously used to store a value. func (t *StateTrie) GetKey(shaKey []byte) []byte { - if key, ok := t.getSecKeyCache()[common.BytesToHash(shaKey)]; ok { - return key - } if t.preimages == nil { return nil } + if key, ok := t.secKeyCache[common.BytesToHash(shaKey)]; ok { + return key + } return t.preimages.Preimage(common.BytesToHash(shaKey)) } @@ -249,11 +266,11 @@ func (t *StateTrie) Witness() map[string]struct{} { // be created with new root and updated trie database for following usage func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) { // Write all the pre-images to the actual disk database - if len(t.getSecKeyCache()) > 0 { + if len(t.secKeyCache) > 0 { if t.preimages != nil { t.preimages.InsertPreimage(t.secKeyCache) } - t.secKeyCache = make(map[common.Hash][]byte) + clear(t.secKeyCache) } // Commit the trie and return its modified nodeset. return t.trie.Commit(collectLeaf) @@ -270,7 +287,7 @@ func (t *StateTrie) Copy() *StateTrie { return &StateTrie{ trie: *t.trie.Copy(), db: t.db, - secKeyCache: t.secKeyCache, + secKeyCache: make(map[common.Hash][]byte), preimages: t.preimages, } } @@ -287,17 +304,6 @@ func (t *StateTrie) MustNodeIterator(start []byte) NodeIterator { return t.trie.MustNodeIterator(start) } -// getSecKeyCache returns the current secure key cache, creating a new one if -// ownership changed (i.e. the current secure trie is a copy of another owning -// the actual cache). -func (t *StateTrie) getSecKeyCache() map[common.Hash][]byte { - if t != t.secKeyCacheOwner { - t.secKeyCacheOwner = t - t.secKeyCache = make(map[common.Hash][]byte) - } - return t.secKeyCache -} - func (t *StateTrie) IsVerkle() bool { return false } diff --git a/trie/trie_test.go b/trie/trie_test.go index 91fde6dbf260..b806ae6b0ce6 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -876,6 +876,7 @@ func (b *spongeBatch) Put(key, value []byte) error { return nil } func (b *spongeBatch) Delete(key []byte) error { panic("implement me") } +func (b *spongeBatch) DeleteRange(start, end []byte) error { panic("implement me") } func (b *spongeBatch) ValueSize() int { return 100 } func (b *spongeBatch) Write() error { return nil } func (b *spongeBatch) Reset() {} diff --git a/triedb/database.go b/triedb/database.go index 18e24cd176d5..e2f4334d6e07 100644 --- a/triedb/database.go +++ b/triedb/database.go @@ -129,6 +129,15 @@ func (db *Database) StateReader(blockRoot common.Hash) (database.StateReader, er return db.backend.StateReader(blockRoot) } +// HistoricReader constructs a reader for accessing the requested historic state. +func (db *Database) HistoricReader(root common.Hash) (*pathdb.HistoricalStateReader, error) { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return nil, errors.New("not supported") + } + return pdb.HistoricReader(root) +} + // Update performs a state transition by committing dirty nodes contained in the // given set in order to update state from the specified parent to the specified // root. The held pre-images accumulated up to this point will be flushed in case @@ -213,6 +222,11 @@ func (db *Database) InsertPreimage(preimages map[common.Hash][]byte) { db.preimages.insertPreimage(preimages) } +// PreimageEnabled returns the indicator if the pre-image store is enabled. +func (db *Database) PreimageEnabled() bool { + return db.preimages != nil +} + // 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. @@ -312,6 +326,16 @@ func (db *Database) Journal(root common.Hash) error { return pdb.Journal(root) } +// VerifyState traverses the flat states specified by the given state root and +// ensures they are matched with each other. +func (db *Database) VerifyState(root common.Hash) error { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return errors.New("not supported") + } + return pdb.VerifyState(root) +} + // AccountIterator creates a new account iterator for the specified root hash and // seeks to a starting account hash. func (db *Database) AccountIterator(root common.Hash, seek common.Hash) (pathdb.AccountIterator, error) { @@ -332,6 +356,16 @@ func (db *Database) StorageIterator(root common.Hash, account common.Hash, seek return pdb.StorageIterator(root, account, seek) } +// IndexProgress returns the indexing progress made so far. It provides the +// number of states that remain unindexed. +func (db *Database) IndexProgress() (uint64, error) { + pdb, ok := db.backend.(*pathdb.Database) + if !ok { + return 0, errors.New("not supported") + } + return pdb.IndexProgress() +} + // IsVerkle returns the indicator if the database is holding a verkle tree. func (db *Database) IsVerkle() bool { return db.config.IsVerkle diff --git a/triedb/pathdb/buffer.go b/triedb/pathdb/buffer.go index e639a43835de..138962110f08 100644 --- a/triedb/pathdb/buffer.go +++ b/triedb/pathdb/buffer.go @@ -17,6 +17,7 @@ package pathdb import ( + "errors" "fmt" "time" @@ -37,6 +38,13 @@ type buffer struct { limit uint64 // The maximum memory allowance in bytes nodes *nodeSet // Aggregated trie node set states *stateSet // Aggregated state set + + // done is the notifier whether the content in buffer has been flushed or not. + // This channel is nil if the buffer is not frozen. + done chan struct{} + + // flushErr memorizes the error if any exception occurs during flushing + flushErr error } // newBuffer initializes the buffer with the provided states and trie nodes. @@ -61,7 +69,7 @@ func (b *buffer) account(hash common.Hash) ([]byte, bool) { return b.states.account(hash) } -// storage retrieves the storage slot with account address hash and slot key. +// storage retrieves the storage slot with account address hash and slot key hash. func (b *buffer) storage(addrHash common.Hash, storageHash common.Hash) ([]byte, bool) { return b.states.storage(addrHash, storageHash) } @@ -124,43 +132,78 @@ func (b *buffer) size() uint64 { // flush persists the in-memory dirty trie node into the disk if the configured // memory threshold is reached. Note, all data must be written atomically. -func (b *buffer) flush(root common.Hash, db ethdb.KeyValueStore, freezer ethdb.AncientWriter, progress []byte, nodesCache, statesCache *fastcache.Cache, id uint64) error { - // Ensure the target state id is aligned with the internal counter. - head := rawdb.ReadPersistentStateID(db) - if head+b.layers != id { - return fmt.Errorf("buffer layers (%d) cannot be applied on top of persisted state id (%d) to reach requested state id (%d)", b.layers, head, id) +func (b *buffer) flush(root common.Hash, db ethdb.KeyValueStore, freezer ethdb.AncientWriter, progress []byte, nodesCache, statesCache *fastcache.Cache, id uint64, postFlush func()) { + if b.done != nil { + panic("duplicated flush operation") } - // Terminate the state snapshot generation if it's active - var ( - start = time.Now() - batch = db.NewBatchWithSize((b.nodes.dbsize() + b.states.dbsize()) * 11 / 10) // extra 10% for potential pebble internal stuff - ) - // Explicitly sync the state freezer to ensure all written data is persisted to disk - // before updating the key-value store. - // - // This step is crucial to guarantee that the corresponding state history remains - // available for state rollback. - if freezer != nil { - if err := freezer.SyncAncient(); err != nil { - return err + b.done = make(chan struct{}) // allocate the channel for notification + + // Schedule the background thread to construct the batch, which usually + // take a few seconds. + go func() { + defer func() { + if postFlush != nil { + postFlush() + } + close(b.done) + }() + + // Ensure the target state id is aligned with the internal counter. + head := rawdb.ReadPersistentStateID(db) + if head+b.layers != id { + b.flushErr = fmt.Errorf("buffer layers (%d) cannot be applied on top of persisted state id (%d) to reach requested state id (%d)", b.layers, head, id) + return } + + // Terminate the state snapshot generation if it's active + var ( + start = time.Now() + batch = db.NewBatchWithSize((b.nodes.dbsize() + b.states.dbsize()) * 11 / 10) // extra 10% for potential pebble internal stuff + ) + // Explicitly sync the state freezer to ensure all written data is persisted to disk + // before updating the key-value store. + // + // This step is crucial to guarantee that the corresponding state history remains + // available for state rollback. + if freezer != nil { + if err := freezer.SyncAncient(); err != nil { + b.flushErr = err + return + } + } + nodes := b.nodes.write(batch, nodesCache) + accounts, slots := b.states.write(batch, progress, statesCache) + rawdb.WritePersistentStateID(batch, id) + rawdb.WriteSnapshotRoot(batch, root) + + // Flush all mutations in a single batch + size := batch.ValueSize() + if err := batch.Write(); err != nil { + b.flushErr = err + return + } + commitBytesMeter.Mark(int64(size)) + commitNodesMeter.Mark(int64(nodes)) + commitAccountsMeter.Mark(int64(accounts)) + commitStoragesMeter.Mark(int64(slots)) + commitTimeTimer.UpdateSince(start) + + // The content in the frozen buffer is kept for consequent state access, + // TODO (rjl493456442) measure the gc overhead for holding this struct. + // TODO (rjl493456442) can we somehow get rid of it after flushing?? + // TODO (rjl493456442) buffer itself is not thread-safe, add the lock + // protection if try to reset the buffer here. + // b.reset() + log.Debug("Persisted buffer content", "nodes", nodes, "accounts", accounts, "slots", slots, "bytes", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start))) + }() +} + +// waitFlush blocks until the buffer has been fully flushed and returns any +// stored errors that occurred during the process. +func (b *buffer) waitFlush() error { + if b.done == nil { + return errors.New("the buffer is not frozen") } - nodes := b.nodes.write(batch, nodesCache) - accounts, slots := b.states.write(batch, progress, statesCache) - rawdb.WritePersistentStateID(batch, id) - rawdb.WriteSnapshotRoot(batch, root) - - // Flush all mutations in a single batch - size := batch.ValueSize() - if err := batch.Write(); err != nil { - return err - } - commitBytesMeter.Mark(int64(size)) - commitNodesMeter.Mark(int64(nodes)) - commitAccountsMeter.Mark(int64(accounts)) - commitStoragesMeter.Mark(int64(slots)) - commitTimeTimer.UpdateSince(start) - b.reset() - log.Debug("Persisted buffer content", "nodes", nodes, "accounts", accounts, "slots", slots, "bytes", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start))) - return nil + <-b.done + return b.flushErr } diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go index 3174a7c964b3..23a7d383b583 100644 --- a/triedb/pathdb/database.go +++ b/triedb/pathdb/database.go @@ -114,12 +114,17 @@ type layer interface { // Config contains the settings for database. type Config struct { - StateHistory uint64 // Number of recent blocks to maintain state history for - TrieCleanSize int // Maximum memory allowance (in bytes) for caching clean trie nodes - StateCleanSize int // Maximum memory allowance (in bytes) for caching clean state data - WriteBufferSize int // Maximum memory allowance (in bytes) for write buffer - ReadOnly bool // Flag whether the database is opened in read only mode - SnapshotNoBuild bool // Flag Whether the background generation is allowed + StateHistory uint64 // Number of recent blocks to maintain state history for + EnableStateIndexing bool // Whether to enable state history indexing for external state access + TrieCleanSize int // Maximum memory allowance (in bytes) for caching clean trie nodes + StateCleanSize int // Maximum memory allowance (in bytes) for caching clean state data + WriteBufferSize int // Maximum memory allowance (in bytes) for write buffer + ReadOnly bool // Flag whether the database is opened in read only mode + + // Testing configurations + SnapshotNoBuild bool // Flag Whether the state generation is allowed + NoAsyncFlush bool // Flag whether the background buffer flushing is allowed + NoAsyncGeneration bool // Flag whether the background generation is allowed } // sanitize checks the provided user configurations and changes anything that's @@ -145,7 +150,12 @@ func (c *Config) fields() []interface{} { list = append(list, "triecache", common.StorageSize(c.TrieCleanSize)) list = append(list, "statecache", common.StorageSize(c.StateCleanSize)) list = append(list, "buffer", common.StorageSize(c.WriteBufferSize)) - list = append(list, "history", c.StateHistory) + + if c.StateHistory == 0 { + list = append(list, "history", "entire chain") + } else { + list = append(list, "history", fmt.Sprintf("last %d blocks", c.StateHistory)) + } return list } @@ -209,6 +219,7 @@ type Database struct { tree *layerTree // The group for all known layers freezer ethdb.ResettableAncientStore // Freezer for storing trie histories, nil possible in tests lock sync.RWMutex // Lock to prevent mutations from happening at the same time + indexer *historyIndexer // History indexer } // New attempts to load an already existing layer from a persistent key-value @@ -258,6 +269,11 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database { if err := db.setStateGenerator(); err != nil { log.Crit("Failed to setup the generator", "err", err) } + // TODO (rjl493456442) disable the background indexing in read-only mode + if db.freezer != nil && db.config.EnableStateIndexing { + db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID()) + log.Info("Enabled state history indexing") + } fields := config.fields() if db.isVerkle { fields = append(fields, "verkle", true) @@ -295,6 +311,11 @@ func (db *Database) repairHistory() error { log.Crit("Failed to retrieve head of state history", "err", err) } if frozen != 0 { + // TODO(rjl493456442) would be better to group them into a batch. + // + // Purge all state history indexing data first + rawdb.DeleteStateHistoryIndexMetadata(db.diskdb) + rawdb.DeleteStateHistoryIndex(db.diskdb) err := db.freezer.Reset() if err != nil { log.Crit("Failed to reset state histories", "err", err) @@ -366,6 +387,12 @@ func (db *Database) setStateGenerator() error { } stats.log("Starting snapshot generation", root, generator.Marker) dl.generator.run(root) + + // Block until the generation completes. It's the feature used in + // unit tests. + if db.config.NoAsyncGeneration { + <-dl.generator.done + } return nil } @@ -434,8 +461,8 @@ func (db *Database) Disable() error { // Terminate the state generator if it's active and mark the disk layer // as stale to prevent access to persistent state. disk := db.tree.bottom() - if disk.generator != nil { - disk.generator.stop() + if err := disk.terminate(); err != nil { + return err } disk.markStale() @@ -477,6 +504,11 @@ func (db *Database) Enable(root common.Hash) error { // mappings can be huge and might take a while to clear // them, just leave them in disk and wait for overwriting. if db.freezer != nil { + // TODO(rjl493456442) would be better to group them into a batch. + // + // Purge all state history indexing data first + rawdb.DeleteStateHistoryIndexMetadata(db.diskdb) + rawdb.DeleteStateHistoryIndex(db.diskdb) if err := db.freezer.Reset(); err != nil { return err } @@ -488,6 +520,16 @@ func (db *Database) Enable(root common.Hash) error { // Re-construct a new disk layer backed by persistent state // and schedule the state snapshot generation if it's permitted. db.tree.init(generateSnapshot(db, root, db.isVerkle || db.config.SnapshotNoBuild)) + + // After snap sync, the state of the database may have changed completely. + // To ensure the history indexer always matches the current state, we must: + // 1. Close any existing indexer + // 2. Re-initialize the indexer so it starts indexing from the new state root. + if db.indexer != nil && db.freezer != nil && db.config.EnableStateIndexing { + db.indexer.close() + db.indexer = newHistoryIndexer(db.diskdb, db.freezer, db.tree.bottom().stateID()) + log.Info("Re-enabled state history indexing") + } log.Info("Rebuilt trie database", "root", root) return nil } @@ -592,13 +634,19 @@ func (db *Database) Close() error { // following mutations. db.readOnly = true - // Terminate the background generation if it's active - disk := db.tree.bottom() - if disk.generator != nil { - disk.generator.stop() + // Block until the background flushing is finished. It must + // be done before terminating the potential background snapshot + // generator. + dl := db.tree.bottom() + if err := dl.terminate(); err != nil { + return err } - disk.resetCache() // release the memory held by clean cache + dl.resetCache() // release the memory held by clean cache + // Terminate the background state history indexer + if db.indexer != nil { + db.indexer.close() + } // Close the attached state history freezer. if db.freezer == nil { return nil @@ -662,14 +710,13 @@ func (db *Database) HistoryRange() (uint64, uint64, error) { return historyRange(db.freezer) } -// waitGeneration waits until the background generation is finished. It assumes -// that the generation is permitted; otherwise, it will block indefinitely. -func (db *Database) waitGeneration() { - gen := db.tree.bottom().generator - if gen == nil || gen.completed() { - return +// IndexProgress returns the indexing progress made so far. It provides the +// number of states that remain unindexed. +func (db *Database) IndexProgress() (uint64, error) { + if db.indexer == nil { + return 0, nil } - <-gen.done + return db.indexer.progress() } // AccountIterator creates a new account iterator for the specified root hash and @@ -681,7 +728,7 @@ func (db *Database) AccountIterator(root common.Hash, seek common.Hash) (Account if wait { return nil, errDatabaseWaitSync } - if gen := db.tree.bottom().generator; gen != nil && !gen.completed() { + if !db.tree.bottom().genComplete() { return nil, errNotConstructed } return newFastAccountIterator(db, root, seek) @@ -696,7 +743,7 @@ func (db *Database) StorageIterator(root common.Hash, account common.Hash, seek if wait { return nil, errDatabaseWaitSync } - if gen := db.tree.bottom().generator; gen != nil && !gen.completed() { + if !db.tree.bottom().genComplete() { return nil, errNotConstructed } return newFastStorageIterator(db, root, account, seek) diff --git a/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go index ca106cc27cf8..2982202009f0 100644 --- a/triedb/pathdb/database_test.go +++ b/triedb/pathdb/database_test.go @@ -121,14 +121,16 @@ type tester struct { snapStorages map[common.Hash]map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address and the hash of storage key } -func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int) *tester { +func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int, enableIndex bool) *tester { var ( disk, _ = rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{Ancient: t.TempDir()}) db = New(disk, &Config{ - StateHistory: historyLimit, - TrieCleanSize: 256 * 1024, - StateCleanSize: 256 * 1024, - WriteBufferSize: 256 * 1024, + StateHistory: historyLimit, + EnableStateIndexing: enableIndex, + TrieCleanSize: 256 * 1024, + StateCleanSize: 256 * 1024, + WriteBufferSize: 256 * 1024, + NoAsyncFlush: true, }, isVerkle) obj = &tester{ @@ -163,6 +165,20 @@ func (t *tester) hashPreimage(hash common.Hash) common.Hash { return common.BytesToHash(t.preimages[hash]) } +func (t *tester) extend(layers int) { + for i := 0; i < layers; i++ { + var parent = types.EmptyRootHash + if len(t.roots) != 0 { + parent = t.roots[len(t.roots)-1] + } + root, nodes, states := t.generate(parent, true) + if err := t.db.Update(root, parent, uint64(i), nodes, states); err != nil { + panic(fmt.Errorf("failed to update state changes, err: %w", err)) + } + t.roots = append(t.roots, root) + } +} + func (t *tester) release() { t.db.Close() t.db.diskdb.Close() @@ -450,7 +466,7 @@ func TestDatabaseRollback(t *testing.T) { }() // Verify state histories - tester := newTester(t, 0, false, 32) + tester := newTester(t, 0, false, 32, false) defer tester.release() if err := tester.verifyHistory(); err != nil { @@ -484,7 +500,7 @@ func TestDatabaseRecoverable(t *testing.T) { }() var ( - tester = newTester(t, 0, false, 12) + tester = newTester(t, 0, false, 12, false) index = tester.bottomIndex() ) defer tester.release() @@ -528,7 +544,7 @@ func TestDisable(t *testing.T) { maxDiffLayers = 128 }() - tester := newTester(t, 0, false, 32) + tester := newTester(t, 0, false, 32, false) defer tester.release() stored := crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(tester.db.diskdb, nil)) @@ -570,7 +586,7 @@ func TestCommit(t *testing.T) { maxDiffLayers = 128 }() - tester := newTester(t, 0, false, 12) + tester := newTester(t, 0, false, 12, false) defer tester.release() if err := tester.db.Commit(tester.lastHash(), false); err != nil { @@ -600,7 +616,7 @@ func TestJournal(t *testing.T) { maxDiffLayers = 128 }() - tester := newTester(t, 0, false, 12) + tester := newTester(t, 0, false, 12, false) defer tester.release() if err := tester.db.Journal(tester.lastHash()); err != nil { @@ -630,7 +646,7 @@ func TestCorruptedJournal(t *testing.T) { maxDiffLayers = 128 }() - tester := newTester(t, 0, false, 12) + tester := newTester(t, 0, false, 12, false) defer tester.release() if err := tester.db.Journal(tester.lastHash()); err != nil { @@ -678,7 +694,7 @@ func TestTailTruncateHistory(t *testing.T) { maxDiffLayers = 128 }() - tester := newTester(t, 10, false, 12) + tester := newTester(t, 10, false, 12, false) defer tester.release() tester.db.Close() diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go index 1c9efb024bd6..06f0a7285ff1 100644 --- a/triedb/pathdb/disklayer.go +++ b/triedb/pathdb/disklayer.go @@ -41,17 +41,20 @@ type diskLayer struct { nodes *fastcache.Cache // GC friendly memory cache of clean nodes states *fastcache.Cache // GC friendly memory cache of clean states - buffer *buffer // Dirty buffer to aggregate writes of nodes and states - stale bool // Signals that the layer became stale (state progressed) - lock sync.RWMutex // Lock used to protect stale flag and genMarker + buffer *buffer // Live buffer to aggregate writes + frozen *buffer // Frozen node buffer waiting for flushing + + stale bool // Signals that the layer became stale (state progressed) + lock sync.RWMutex // Lock used to protect stale flag and genMarker // The generator is set if the state snapshot was not fully completed, // regardless of whether the background generation is running or not. + // It should only be unset if the generation completes. generator *generator } // newDiskLayer creates a new disk layer based on the passing arguments. -func newDiskLayer(root common.Hash, id uint64, db *Database, nodes *fastcache.Cache, states *fastcache.Cache, buffer *buffer) *diskLayer { +func newDiskLayer(root common.Hash, id uint64, db *Database, nodes *fastcache.Cache, states *fastcache.Cache, buffer *buffer, frozen *buffer) *diskLayer { // Initialize the clean caches if the memory allowance is not zero // or reuse the provided caches if they are not nil (inherited from // the original disk layer). @@ -68,6 +71,7 @@ func newDiskLayer(root common.Hash, id uint64, db *Database, nodes *fastcache.Ca nodes: nodes, states: states, buffer: buffer, + frozen: frozen, } } @@ -114,16 +118,19 @@ func (dl *diskLayer) node(owner common.Hash, path []byte, depth int) ([]byte, co if dl.stale { return nil, common.Hash{}, nil, errSnapshotStale } - // Try to retrieve the trie node from the not-yet-written - // node buffer first. Note the buffer is lock free since - // it's impossible to mutate the buffer before tagging the - // layer as stale. - n, found := dl.buffer.node(owner, path) - if found { - dirtyNodeHitMeter.Mark(1) - dirtyNodeReadMeter.Mark(int64(len(n.Blob))) - dirtyNodeHitDepthHist.Update(int64(depth)) - return n.Blob, n.Hash, &nodeLoc{loc: locDirtyCache, depth: depth}, nil + // Try to retrieve the trie node from the not-yet-written node buffer first + // (both the live one and the frozen one). Note the buffer is lock free since + // it's impossible to mutate the buffer before tagging the layer as stale. + for _, buffer := range []*buffer{dl.buffer, dl.frozen} { + if buffer != nil { + n, found := buffer.node(owner, path) + if found { + dirtyNodeHitMeter.Mark(1) + dirtyNodeReadMeter.Mark(int64(len(n.Blob))) + dirtyNodeHitDepthHist.Update(int64(depth)) + return n.Blob, n.Hash, &nodeLoc{loc: locDirtyCache, depth: depth}, nil + } + } } dirtyNodeMissMeter.Mark(1) @@ -144,6 +151,11 @@ func (dl *diskLayer) node(owner common.Hash, path []byte, depth int) ([]byte, co } else { blob = rawdb.ReadStorageTrieNode(dl.db.diskdb, owner, path) } + // Store the resolved data in the clean cache. The background buffer flusher + // may also write to the clean cache concurrently, but two writers cannot + // write the same item with different content. If the item already exists, + // it will be found in the frozen buffer, eliminating the need to check the + // database. if dl.nodes != nil && len(blob) > 0 { dl.nodes.Set(key, blob) cleanNodeWriteMeter.Mark(int64(len(blob))) @@ -162,22 +174,25 @@ func (dl *diskLayer) account(hash common.Hash, depth int) ([]byte, error) { if dl.stale { return nil, errSnapshotStale } - // Try to retrieve the account from the not-yet-written - // node buffer first. Note the buffer is lock free since - // it's impossible to mutate the buffer before tagging the - // layer as stale. - blob, found := dl.buffer.account(hash) - if found { - dirtyStateHitMeter.Mark(1) - dirtyStateReadMeter.Mark(int64(len(blob))) - dirtyStateHitDepthHist.Update(int64(depth)) - - if len(blob) == 0 { - stateAccountInexMeter.Mark(1) - } else { - stateAccountExistMeter.Mark(1) + // Try to retrieve the trie node from the not-yet-written node buffer first + // (both the live one and the frozen one). Note the buffer is lock free since + // it's impossible to mutate the buffer before tagging the layer as stale. + for _, buffer := range []*buffer{dl.buffer, dl.frozen} { + if buffer != nil { + blob, found := buffer.account(hash) + if found { + dirtyStateHitMeter.Mark(1) + dirtyStateReadMeter.Mark(int64(len(blob))) + dirtyStateHitDepthHist.Update(int64(depth)) + + if len(blob) == 0 { + stateAccountInexMeter.Mark(1) + } else { + stateAccountExistMeter.Mark(1) + } + return blob, nil + } } - return blob, nil } dirtyStateMissMeter.Mark(1) @@ -203,7 +218,13 @@ func (dl *diskLayer) account(hash common.Hash, depth int) ([]byte, error) { cleanStateMissMeter.Mark(1) } // Try to retrieve the account from the disk. - blob = rawdb.ReadAccountSnapshot(dl.db.diskdb, hash) + blob := rawdb.ReadAccountSnapshot(dl.db.diskdb, hash) + + // Store the resolved data in the clean cache. The background buffer flusher + // may also write to the clean cache concurrently, but two writers cannot + // write the same item with different content. If the item already exists, + // it will be found in the frozen buffer, eliminating the need to check the + // database. if dl.states != nil { dl.states.Set(hash[:], blob) cleanStateWriteMeter.Mark(int64(len(blob))) @@ -231,21 +252,24 @@ func (dl *diskLayer) storage(accountHash, storageHash common.Hash, depth int) ([ if dl.stale { return nil, errSnapshotStale } - // Try to retrieve the storage slot from the not-yet-written - // node buffer first. Note the buffer is lock free since - // it's impossible to mutate the buffer before tagging the - // layer as stale. - if blob, found := dl.buffer.storage(accountHash, storageHash); found { - dirtyStateHitMeter.Mark(1) - dirtyStateReadMeter.Mark(int64(len(blob))) - dirtyStateHitDepthHist.Update(int64(depth)) - - if len(blob) == 0 { - stateStorageInexMeter.Mark(1) - } else { - stateStorageExistMeter.Mark(1) + // Try to retrieve the trie node from the not-yet-written node buffer first + // (both the live one and the frozen one). Note the buffer is lock free since + // it's impossible to mutate the buffer before tagging the layer as stale. + for _, buffer := range []*buffer{dl.buffer, dl.frozen} { + if buffer != nil { + if blob, found := buffer.storage(accountHash, storageHash); found { + dirtyStateHitMeter.Mark(1) + dirtyStateReadMeter.Mark(int64(len(blob))) + dirtyStateHitDepthHist.Update(int64(depth)) + + if len(blob) == 0 { + stateStorageInexMeter.Mark(1) + } else { + stateStorageExistMeter.Mark(1) + } + return blob, nil + } } - return blob, nil } dirtyStateMissMeter.Mark(1) @@ -273,6 +297,12 @@ func (dl *diskLayer) storage(accountHash, storageHash common.Hash, depth int) ([ } // Try to retrieve the account from the disk blob := rawdb.ReadStorageSnapshot(dl.db.diskdb, accountHash, storageHash) + + // Store the resolved data in the clean cache. The background buffer flusher + // may also write to the clean cache concurrently, but two writers cannot + // write the same item with different content. If the item already exists, + // it will be found in the frozen buffer, eliminating the need to check the + // database. if dl.states != nil { dl.states.Set(key, blob) cleanStateWriteMeter.Mark(int64(len(blob))) @@ -325,6 +355,12 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { overflow = true oldest = bottom.stateID() - limit + 1 // track the id of history **after truncation** } + // Notify the state history indexer for newly created history + if dl.db.indexer != nil { + if err := dl.db.indexer.extend(bottom.stateID()); err != nil { + return nil, err + } + } } // Mark the diskLayer as stale before applying any mutations on top. dl.stale = true @@ -341,7 +377,8 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { // truncation) surpasses the persisted state ID, we take the necessary action // of forcibly committing the cached dirty states to ensure that the persisted // state ID remains higher. - if !force && rawdb.ReadPersistentStateID(dl.db.diskdb) < oldest { + persistedID := rawdb.ReadPersistentStateID(dl.db.diskdb) + if !force && persistedID < oldest { force = true } // Merge the trie nodes and flat states of the bottom-most diff layer into the @@ -351,12 +388,25 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { // Terminate the background state snapshot generation before mutating the // persistent state. if combined.full() || force { + // Wait until the previous frozen buffer is fully flushed + if dl.frozen != nil { + if err := dl.frozen.waitFlush(); err != nil { + return nil, err + } + } + // Release the frozen buffer and the internally referenced maps will + // be reclaimed by GC. + dl.frozen = nil + // Terminate the background state snapshot generator before flushing // to prevent data race. - var progress []byte - if dl.generator != nil { - dl.generator.stop() - progress = dl.generator.progressMarker() + var ( + progress []byte + gen = dl.generator + ) + if gen != nil { + gen.stop() + progress = gen.progressMarker() // If the snapshot has been fully generated, unset the generator if progress == nil { @@ -365,18 +415,33 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { log.Info("Paused snapshot generation") } } - // Flush the content in combined buffer. Any state data after the progress - // marker will be ignored, as the generator will pick it up later. - if err := combined.flush(bottom.root, dl.db.diskdb, dl.db.freezer, progress, dl.nodes, dl.states, bottom.stateID()); err != nil { - return nil, err - } - // Resume the background generation if it's not completed yet - if progress != nil { - dl.generator.run(bottom.root) + + // Freeze the live buffer and schedule background flushing + dl.frozen = combined + dl.frozen.flush(bottom.root, dl.db.diskdb, dl.db.freezer, progress, dl.nodes, dl.states, bottom.stateID(), func() { + // Resume the background generation if it's not completed yet. + // The generator is assumed to be available if the progress is + // not nil. + // + // Notably, the generator will be shared and linked by all the + // disk layer instances, regardless of the generation is terminated + // or not. + if progress != nil { + gen.run(bottom.root) + } + }) + // Block until the frozen buffer is fully flushed out if the async flushing + // is not allowed, or if the oldest history surpasses the persisted state ID. + if dl.db.config.NoAsyncFlush || persistedID < oldest { + if err := dl.frozen.waitFlush(); err != nil { + return nil, err + } + dl.frozen = nil } + combined = newBuffer(dl.db.config.WriteBufferSize, nil, nil, 0) } // Link the generator if snapshot is not yet completed - ndl := newDiskLayer(bottom.root, bottom.stateID(), dl.db, dl.nodes, dl.states, combined) + ndl := newDiskLayer(bottom.root, bottom.stateID(), dl.db, dl.nodes, dl.states, combined, dl.frozen) if dl.generator != nil { ndl.setGenerator(dl.generator) } @@ -418,6 +483,12 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) { dl.stale = true + // Unindex the corresponding state history + if dl.db.indexer != nil { + if err := dl.db.indexer.shorten(dl.id); err != nil { + return nil, err + } + } // State change may be applied to node buffer, or the persistent // state, depends on if node buffer is empty or not. If the node // buffer is not empty, it means that the state transition that @@ -428,7 +499,7 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) { if err != nil { return nil, err } - ndl := newDiskLayer(h.meta.parent, dl.id-1, dl.db, dl.nodes, dl.states, dl.buffer) + ndl := newDiskLayer(h.meta.parent, dl.id-1, dl.db, dl.nodes, dl.states, dl.buffer, dl.frozen) // Link the generator if it exists if dl.generator != nil { @@ -437,7 +508,19 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) { log.Debug("Reverted data in write buffer", "oldroot", h.meta.root, "newroot", h.meta.parent, "elapsed", common.PrettyDuration(time.Since(start))) return ndl, nil } - // Terminate the generation before writing any data into database + // Block until the frozen buffer is fully flushed + if dl.frozen != nil { + if err := dl.frozen.waitFlush(); err != nil { + return nil, err + } + // Unset the frozen buffer if it exists, otherwise these "reverted" + // states will still be accessible after revert in frozen buffer. + dl.frozen = nil + } + + // Terminate the generator before writing any data to the database. + // This must be done after flushing the frozen buffer, as the generator + // may be restarted at the end of the flush process. var progress []byte if dl.generator != nil { dl.generator.stop() @@ -455,7 +538,7 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) { } // Link the generator and resume generation if the snapshot is not yet // fully completed. - ndl := newDiskLayer(h.meta.parent, dl.id-1, dl.db, dl.nodes, dl.states, dl.buffer) + ndl := newDiskLayer(h.meta.parent, dl.id-1, dl.db, dl.nodes, dl.states, dl.buffer, dl.frozen) if dl.generator != nil && !dl.generator.completed() { ndl.generator = dl.generator ndl.generator.run(h.meta.parent) @@ -500,3 +583,41 @@ func (dl *diskLayer) genMarker() []byte { } return dl.generator.progressMarker() } + +// genComplete returns a flag indicating whether the state snapshot has been +// fully generated. +func (dl *diskLayer) genComplete() bool { + dl.lock.RLock() + defer dl.lock.RUnlock() + + return dl.genMarker() == nil +} + +// waitFlush blocks until the background buffer flush is completed. +func (dl *diskLayer) waitFlush() error { + dl.lock.RLock() + defer dl.lock.RUnlock() + + if dl.frozen == nil { + return nil + } + return dl.frozen.waitFlush() +} + +// terminate releases the frozen buffer if it's not nil and terminates the +// background state generator. +func (dl *diskLayer) terminate() error { + dl.lock.Lock() + defer dl.lock.Unlock() + + if dl.frozen != nil { + if err := dl.frozen.waitFlush(); err != nil { + return err + } + dl.frozen = nil + } + if dl.generator != nil { + dl.generator.stop() + } + return nil +} diff --git a/triedb/pathdb/execute.go b/triedb/pathdb/execute.go index db1e67927791..aa4bd8b44b63 100644 --- a/triedb/pathdb/execute.go +++ b/triedb/pathdb/execute.go @@ -86,9 +86,7 @@ func apply(db database.NodeDatabase, prevRoot common.Hash, postRoot common.Hash, func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) error { // The account was present in prev-state, decode it from the // 'slim-rlp' format bytes. - h := crypto.NewKeccakState() - - addrHash := crypto.HashData(h, addr.Bytes()) + addrHash := crypto.Keccak256Hash(addr.Bytes()) prev, err := types.FullAccount(ctx.accounts[addr]) if err != nil { return err @@ -113,7 +111,7 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) for key, val := range ctx.storages[addr] { tkey := key if ctx.rawStorageKey { - tkey = crypto.HashData(h, key.Bytes()) + tkey = crypto.Keccak256Hash(key.Bytes()) } var err error if len(val) == 0 { @@ -149,9 +147,7 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) // account and storage is wiped out correctly. func deleteAccount(ctx *context, db database.NodeDatabase, addr common.Address) error { // The account must be existent in post-state, load the account. - h := crypto.NewKeccakState() - - addrHash := crypto.HashData(h, addr.Bytes()) + addrHash := crypto.Keccak256Hash(addr.Bytes()) blob, err := ctx.accountTrie.Get(addrHash.Bytes()) if err != nil { return err @@ -173,7 +169,7 @@ func deleteAccount(ctx *context, db database.NodeDatabase, addr common.Address) } tkey := key if ctx.rawStorageKey { - tkey = crypto.HashData(h, key.Bytes()) + tkey = crypto.Keccak256Hash(key.Bytes()) } if err := st.Delete(tkey.Bytes()); err != nil { return err diff --git a/triedb/pathdb/generate.go b/triedb/pathdb/generate.go index f4f98c9d19f2..2efbbbb4e1ea 100644 --- a/triedb/pathdb/generate.go +++ b/triedb/pathdb/generate.go @@ -186,7 +186,7 @@ func generateSnapshot(triedb *Database, root common.Hash, noBuild bool) *diskLay stats = &generatorStats{start: time.Now()} genMarker = []byte{} // Initialized but empty! ) - dl := newDiskLayer(root, 0, triedb, nil, nil, newBuffer(triedb.config.WriteBufferSize, nil, nil, 0)) + dl := newDiskLayer(root, 0, triedb, nil, nil, newBuffer(triedb.config.WriteBufferSize, nil, nil, 0), nil) dl.setGenerator(newGenerator(triedb.diskdb, noBuild, genMarker, stats)) if !noBuild { diff --git a/triedb/pathdb/generate_test.go b/triedb/pathdb/generate_test.go index 23efb0e3c551..f38a1ed7c43a 100644 --- a/triedb/pathdb/generate_test.go +++ b/triedb/pathdb/generate_test.go @@ -49,6 +49,7 @@ func newGenTester() *genTester { disk := rawdb.NewMemoryDatabase() config := *Defaults config.SnapshotNoBuild = true // no background generation + config.NoAsyncFlush = true // no async flush db := New(disk, &config, false) tr, _ := trie.New(trie.StateTrieID(types.EmptyRootHash), db) return &genTester{ diff --git a/triedb/pathdb/history.go b/triedb/pathdb/history.go index aed0296da5bc..47f224170d7f 100644 --- a/triedb/pathdb/history.go +++ b/triedb/pathdb/history.go @@ -278,12 +278,11 @@ func newHistory(root common.Hash, parent common.Hash, block uint64, accounts map // and the hash of the storage slot key. func (h *history) stateSet() (map[common.Hash][]byte, map[common.Hash]map[common.Hash][]byte) { var ( - buff = crypto.NewKeccakState() accounts = make(map[common.Hash][]byte) storages = make(map[common.Hash]map[common.Hash][]byte) ) for addr, blob := range h.accounts { - addrHash := crypto.HashData(buff, addr.Bytes()) + addrHash := crypto.Keccak256Hash(addr.Bytes()) accounts[addrHash] = blob storage, exist := h.storages[addr] @@ -295,7 +294,7 @@ func (h *history) stateSet() (map[common.Hash][]byte, map[common.Hash]map[common } else { subset := make(map[common.Hash][]byte) for key, slot := range storage { - subset[crypto.HashData(buff, key.Bytes())] = slot + subset[crypto.Keccak256Hash(key.Bytes())] = slot } storages[addrHash] = subset } @@ -506,25 +505,41 @@ func (h *history) decode(accountData, storageData, accountIndexes, storageIndexe // readHistory reads and decodes the state history object by the given id. func readHistory(reader ethdb.AncientReader, id uint64) (*history, error) { - blob := rawdb.ReadStateHistoryMeta(reader, id) - if len(blob) == 0 { - return nil, fmt.Errorf("state history not found %d", id) + mData, accountIndexes, storageIndexes, accountData, storageData, err := rawdb.ReadStateHistory(reader, id) + if err != nil { + return nil, err } var m meta - if err := m.decode(blob); err != nil { + if err := m.decode(mData); err != nil { return nil, err } - var ( - dec = history{meta: &m} - accountData = rawdb.ReadStateAccountHistory(reader, id) - storageData = rawdb.ReadStateStorageHistory(reader, id) - accountIndexes = rawdb.ReadStateAccountIndex(reader, id) - storageIndexes = rawdb.ReadStateStorageIndex(reader, id) - ) - if err := dec.decode(accountData, storageData, accountIndexes, storageIndexes); err != nil { + h := history{meta: &m} + if err := h.decode(accountData, storageData, accountIndexes, storageIndexes); err != nil { return nil, err } - return &dec, nil + return &h, nil +} + +// readHistories reads and decodes a list of state histories with the specific +// history range. +func readHistories(freezer ethdb.AncientReader, start uint64, count uint64) ([]*history, error) { + var histories []*history + metaList, aIndexList, sIndexList, aDataList, sDataList, err := rawdb.ReadStateHistoryList(freezer, start, count) + if err != nil { + return nil, err + } + for i := 0; i < len(metaList); i++ { + var m meta + if err := m.decode(metaList[i]); err != nil { + return nil, err + } + h := history{meta: &m} + if err := h.decode(aDataList[i], sDataList[i], aIndexList[i], sIndexList[i]); err != nil { + return nil, err + } + histories = append(histories, &h) + } + return histories, nil } // writeHistory persists the state history with the provided state set. diff --git a/triedb/pathdb/history_index.go b/triedb/pathdb/history_index.go new file mode 100644 index 000000000000..f79581b38b19 --- /dev/null +++ b/triedb/pathdb/history_index.go @@ -0,0 +1,436 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see = indexBlockEntriesCap +} + +// encode packs index block descriptor into byte stream. +func (d *indexBlockDesc) encode() []byte { + var buf [indexBlockDescSize]byte + binary.BigEndian.PutUint64(buf[0:8], d.max) + binary.BigEndian.PutUint16(buf[8:10], d.entries) + binary.BigEndian.PutUint32(buf[10:14], d.id) + return buf[:] +} + +// decode unpacks index block descriptor from byte stream. +func (d *indexBlockDesc) decode(blob []byte) { + d.max = binary.BigEndian.Uint64(blob[:8]) + d.entries = binary.BigEndian.Uint16(blob[8:10]) + d.id = binary.BigEndian.Uint32(blob[10:14]) +} + +// parseIndexBlock parses the index block with the supplied byte stream. +// The index block format can be illustrated as below: +// +// +---->+------------------+ +// | | Chunk1 | +// | +------------------+ +// | | ...... | +// | +-->+------------------+ +// | | | ChunkN | +// | | +------------------+ +// +-|---| Restart1 | +// | | Restart... | 2N bytes +// +---| RestartN | +// +------------------+ +// | Restart count | 1 byte +// +------------------+ +// +// - Chunk list: A list of data chunks +// - Restart list: A list of 2-byte pointers, each pointing to the start position of a chunk +// - Restart count: The number of restarts in the block, stored at the end of the block (1 byte) +// +// Note: the pointer is encoded as a uint16, which is sufficient within a chunk. +// A uint16 can cover offsets in the range [0, 65536), which is more than enough +// to store 4096 integers. +// +// Each chunk begins with the full value of the first integer, followed by +// subsequent integers representing the differences between the current value +// and the preceding one. Integers are encoded with variable-size for best +// storage efficiency. Each chunk can be illustrated as below. +// +// Restart ---> +----------------+ +// | Full integer | +// +----------------+ +// | Diff with prev | +// +----------------+ +// | ... | +// +----------------+ +// | Diff with prev | +// +----------------+ +// +// Empty index block is regarded as invalid. +func parseIndexBlock(blob []byte) ([]uint16, []byte, error) { + if len(blob) < 1 { + return nil, nil, fmt.Errorf("corrupted index block, len: %d", len(blob)) + } + restartLen := blob[len(blob)-1] + if restartLen == 0 { + return nil, nil, errors.New("corrupted index block, no restart") + } + tailLen := int(restartLen)*2 + 1 + if len(blob) < tailLen { + return nil, nil, fmt.Errorf("truncated restarts, size: %d, restarts: %d", len(blob), restartLen) + } + restarts := make([]uint16, 0, restartLen) + for i := int(restartLen); i > 0; i-- { + restart := binary.BigEndian.Uint16(blob[len(blob)-1-2*i:]) + restarts = append(restarts, restart) + } + // Validate that restart points are strictly ordered and within the valid + // data range. + var prev uint16 + for i := 0; i < len(restarts); i++ { + if i != 0 { + if restarts[i] <= prev { + return nil, nil, fmt.Errorf("restart out of order, prev: %d, next: %d", prev, restarts[i]) + } + } + if int(restarts[i]) >= len(blob)-tailLen { + return nil, nil, fmt.Errorf("invalid restart position, restart: %d, size: %d", restarts[i], len(blob)-tailLen) + } + prev = restarts[i] + } + return restarts, blob[:len(blob)-tailLen], nil +} + +// blockReader is the reader to access the element within a block. +type blockReader struct { + restarts []uint16 + data []byte +} + +// newBlockReader constructs the block reader with the supplied block data. +func newBlockReader(blob []byte) (*blockReader, error) { + restarts, data, err := parseIndexBlock(blob) + if err != nil { + return nil, err + } + return &blockReader{ + restarts: restarts, + data: data, // safe to own the slice + }, nil +} + +// readGreaterThan locates the first element in the block that is greater than +// the specified value. If no such element is found, MaxUint64 is returned. +func (br *blockReader) readGreaterThan(id uint64) (uint64, error) { + var err error + index := sort.Search(len(br.restarts), func(i int) bool { + item, n := binary.Uvarint(br.data[br.restarts[i]:]) + if n <= 0 { + err = fmt.Errorf("failed to decode item at restart %d", br.restarts[i]) + } + return item > id + }) + if err != nil { + return 0, err + } + if index == 0 { + item, _ := binary.Uvarint(br.data[br.restarts[0]:]) + return item, nil + } + var ( + start int + limit int + result uint64 + ) + if index == len(br.restarts) { + // The element being searched falls within the last restart section, + // there is no guarantee such element can be found. + start = int(br.restarts[len(br.restarts)-1]) + limit = len(br.data) + } else { + // The element being searched falls within the non-last restart section, + // such element can be found for sure. + start = int(br.restarts[index-1]) + limit = int(br.restarts[index]) + } + pos := start + for pos < limit { + x, n := binary.Uvarint(br.data[pos:]) + if pos == start { + result = x + } else { + result += x + } + if result > id { + return result, nil + } + pos += n + } + // The element which is greater than specified id is not found. + if index == len(br.restarts) { + return math.MaxUint64, nil + } + // The element which is the first one greater than the specified id + // is exactly the one located at the restart point. + item, _ := binary.Uvarint(br.data[br.restarts[index]:]) + return item, nil +} + +type blockWriter struct { + desc *indexBlockDesc // Descriptor of the block + restarts []uint16 // Offsets into the data slice, marking the start of each section + scratch []byte // Buffer used for encoding full integers or value differences + data []byte // Aggregated encoded data slice +} + +func newBlockWriter(blob []byte, desc *indexBlockDesc) (*blockWriter, error) { + scratch := make([]byte, binary.MaxVarintLen64) + if len(blob) == 0 { + return &blockWriter{ + desc: desc, + scratch: scratch, + data: make([]byte, 0, 1024), + }, nil + } + restarts, data, err := parseIndexBlock(blob) + if err != nil { + return nil, err + } + return &blockWriter{ + desc: desc, + restarts: restarts, + scratch: scratch, + data: data, // safe to own the slice + }, nil +} + +// append adds a new element to the block. The new element must be greater than +// the previous one. The provided ID is assumed to always be greater than 0. +func (b *blockWriter) append(id uint64) error { + if id == 0 { + return errors.New("invalid zero id") + } + if id <= b.desc.max { + return fmt.Errorf("append element out of order, last: %d, this: %d", b.desc.max, id) + } + // Rotate the current restart section if it's full + if b.desc.entries%indexBlockRestartLen == 0 { + // Save the offset within the data slice as the restart point + // for the next section. + b.restarts = append(b.restarts, uint16(len(b.data))) + + // The restart point item can either be encoded in variable + // size or fixed size. Although variable-size encoding is + // slightly slower (2ns per operation), it is still relatively + // fast, therefore, it's picked for better space efficiency. + // + // The first element in a restart range is encoded using its + // full value. + n := binary.PutUvarint(b.scratch[0:], id) + b.data = append(b.data, b.scratch[:n]...) + } else { + // The current section is not full, append the element. + // The element which is not the first one in the section + // is encoded using the value difference from the preceding + // element. + n := binary.PutUvarint(b.scratch[0:], id-b.desc.max) + b.data = append(b.data, b.scratch[:n]...) + } + b.desc.entries++ + + // The state history ID must be greater than 0. + //if b.desc.min == 0 { + // b.desc.min = id + //} + b.desc.max = id + return nil +} + +// scanSection traverses the specified section and terminates if fn returns true. +func (b *blockWriter) scanSection(section int, fn func(uint64, int) bool) { + var ( + value uint64 + start = int(b.restarts[section]) + pos = start + limit int + ) + if section == len(b.restarts)-1 { + limit = len(b.data) + } else { + limit = int(b.restarts[section+1]) + } + for pos < limit { + x, n := binary.Uvarint(b.data[pos:]) + if pos == start { + value = x + } else { + value += x + } + if fn(value, pos) { + return + } + pos += n + } +} + +// sectionLast returns the last element in the specified section. +func (b *blockWriter) sectionLast(section int) uint64 { + var n uint64 + b.scanSection(section, func(v uint64, _ int) bool { + n = v + return false + }) + return n +} + +// sectionSearch looks up the specified value in the given section, +// the position and the preceding value will be returned if found. +func (b *blockWriter) sectionSearch(section int, n uint64) (found bool, prev uint64, pos int) { + b.scanSection(section, func(v uint64, p int) bool { + if n == v { + pos = p + found = true + return true // terminate iteration + } + prev = v + return false // continue iteration + }) + return found, prev, pos +} + +// pop removes the last element from the block. The assumption is held that block +// writer must be non-empty. +func (b *blockWriter) pop(id uint64) error { + if id == 0 { + return errors.New("invalid zero id") + } + if id != b.desc.max { + return fmt.Errorf("pop element out of order, last: %d, this: %d", b.desc.max, id) + } + // If there is only one entry left, the entire block should be reset + if b.desc.entries == 1 { + //b.desc.min = 0 + b.desc.max = 0 + b.desc.entries = 0 + b.restarts = nil + b.data = b.data[:0] + return nil + } + // Pop the last restart section if the section becomes empty after removing + // one element. + if b.desc.entries%indexBlockRestartLen == 1 { + b.data = b.data[:b.restarts[len(b.restarts)-1]] + b.restarts = b.restarts[:len(b.restarts)-1] + b.desc.max = b.sectionLast(len(b.restarts) - 1) + b.desc.entries -= 1 + return nil + } + // Look up the element preceding the one to be popped, in order to update + // the maximum element in the block. + found, prev, pos := b.sectionSearch(len(b.restarts)-1, id) + if !found { + return fmt.Errorf("pop element is not found, last: %d, this: %d", b.desc.max, id) + } + b.desc.max = prev + b.data = b.data[:pos] + b.desc.entries -= 1 + return nil +} + +func (b *blockWriter) empty() bool { + return b.desc.empty() +} + +func (b *blockWriter) full() bool { + return b.desc.full() +} + +// finish finalizes the index block encoding by appending the encoded restart points +// and the restart counter to the end of the block. +// +// This function is safe to be called multiple times. +func (b *blockWriter) finish() []byte { + var buf []byte + for _, number := range b.restarts { + binary.BigEndian.PutUint16(b.scratch[:2], number) + buf = append(buf, b.scratch[:2]...) + } + buf = append(buf, byte(len(b.restarts))) + return append(b.data, buf...) +} diff --git a/triedb/pathdb/history_index_block_test.go b/triedb/pathdb/history_index_block_test.go new file mode 100644 index 000000000000..173387b44781 --- /dev/null +++ b/triedb/pathdb/history_index_block_test.go @@ -0,0 +1,216 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see value + }) + got, err := br.readGreaterThan(value) + if err != nil { + t.Fatalf("Unexpected error, got %v", err) + } + if pos == len(elements) { + if got != math.MaxUint64 { + t.Fatalf("Unexpected result, got %d, wanted math.MaxUint64", got) + } + } else if got != elements[pos] { + t.Fatalf("Unexpected result, got %d, wanted %d", got, elements[pos]) + } + } +} + +func TestBlockWriterBasic(t *testing.T) { + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + if !bw.empty() { + t.Fatal("expected empty block") + } + bw.append(2) + if err := bw.append(1); err == nil { + t.Fatal("out-of-order insertion is not expected") + } + for i := 0; i < 10; i++ { + bw.append(uint64(i + 3)) + } + + bw, err := newBlockWriter(bw.finish(), newIndexBlockDesc(0)) + if err != nil { + t.Fatalf("Failed to construct the block writer, %v", err) + } + for i := 0; i < 10; i++ { + if err := bw.append(uint64(i + 100)); err != nil { + t.Fatalf("Failed to append value %d: %v", i, err) + } + } + bw.finish() +} + +func TestBlockWriterDelete(t *testing.T) { + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + for i := 0; i < 10; i++ { + bw.append(uint64(i + 1)) + } + // Pop unknown id, the request should be rejected + if err := bw.pop(100); err == nil { + t.Fatal("Expect error to occur for unknown id") + } + for i := 10; i >= 1; i-- { + if err := bw.pop(uint64(i)); err != nil { + t.Fatalf("Unexpected error for element popping, %v", err) + } + empty := i == 1 + if empty != bw.empty() { + t.Fatalf("Emptiness is not matched, want: %T, got: %T", empty, bw.empty()) + } + newMax := uint64(i - 1) + if bw.desc.max != newMax { + t.Fatalf("Maxmium element is not matched, want: %d, got: %d", newMax, bw.desc.max) + } + } +} + +func TestBlcokWriterDeleteWithData(t *testing.T) { + elements := []uint64{ + 1, 5, 10, 11, 20, + } + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + for i := 0; i < len(elements); i++ { + bw.append(elements[i]) + } + + // Re-construct the block writer with data + desc := &indexBlockDesc{ + id: 0, + max: 20, + entries: 5, + } + bw, err := newBlockWriter(bw.finish(), desc) + if err != nil { + t.Fatalf("Failed to construct block writer %v", err) + } + for i := len(elements) - 1; i > 0; i-- { + if err := bw.pop(elements[i]); err != nil { + t.Fatalf("Failed to pop element, %v", err) + } + newTail := elements[i-1] + + // Ensure the element can still be queried with no issue + br, err := newBlockReader(bw.finish()) + if err != nil { + t.Fatalf("Failed to construct the block reader, %v", err) + } + cases := []struct { + value uint64 + result uint64 + }{ + {0, 1}, + {1, 5}, + {10, 11}, + {19, 20}, + {20, math.MaxUint64}, + {21, math.MaxUint64}, + } + for _, c := range cases { + want := c.result + if c.value >= newTail { + want = math.MaxUint64 + } + got, err := br.readGreaterThan(c.value) + if err != nil { + t.Fatalf("Unexpected error, got %v", err) + } + if got != want { + t.Fatalf("Unexpected result, got %v, wanted %v", got, want) + } + } + } +} + +func TestCorruptedIndexBlock(t *testing.T) { + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + for i := 0; i < 10; i++ { + bw.append(uint64(i + 1)) + } + buf := bw.finish() + + // Mutate the buffer manually + buf[len(buf)-1]++ + _, err := newBlockWriter(buf, newIndexBlockDesc(0)) + if err == nil { + t.Fatal("Corrupted index block data is not detected") + } +} diff --git a/triedb/pathdb/history_index_test.go b/triedb/pathdb/history_index_test.go new file mode 100644 index 000000000000..7b24b86fd655 --- /dev/null +++ b/triedb/pathdb/history_index_test.go @@ -0,0 +1,292 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see value + }) + got, err := br.readGreaterThan(value) + if err != nil { + t.Fatalf("Unexpected error, got %v", err) + } + if pos == len(elements) { + if got != math.MaxUint64 { + t.Fatalf("Unexpected result, got %d, wanted math.MaxUint64", got) + } + } else if got != elements[pos] { + t.Fatalf("Unexpected result, got %d, wanted %d", got, elements[pos]) + } + } +} + +func TestEmptyIndexReader(t *testing.T) { + br, err := newIndexReader(rawdb.NewMemoryDatabase(), newAccountIdent(common.Hash{0xa})) + if err != nil { + t.Fatalf("Failed to construct the index reader, %v", err) + } + res, err := br.readGreaterThan(100) + if err != nil { + t.Fatalf("Failed to query, %v", err) + } + if res != math.MaxUint64 { + t.Fatalf("Unexpected result, got %d, wanted math.MaxUint64", res) + } +} + +func TestIndexWriterBasic(t *testing.T) { + db := rawdb.NewMemoryDatabase() + iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa})) + iw.append(2) + if err := iw.append(1); err == nil { + t.Fatal("out-of-order insertion is not expected") + } + for i := 0; i < 10; i++ { + iw.append(uint64(i + 3)) + } + batch := db.NewBatch() + iw.finish(batch) + batch.Write() + + iw, err := newIndexWriter(db, newAccountIdent(common.Hash{0xa})) + if err != nil { + t.Fatalf("Failed to construct the block writer, %v", err) + } + for i := 0; i < 10; i++ { + if err := iw.append(uint64(i + 100)); err != nil { + t.Fatalf("Failed to append item, %v", err) + } + } + iw.finish(db.NewBatch()) +} + +func TestIndexWriterDelete(t *testing.T) { + db := rawdb.NewMemoryDatabase() + iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa})) + for i := 0; i < indexBlockEntriesCap*4; i++ { + iw.append(uint64(i + 1)) + } + batch := db.NewBatch() + iw.finish(batch) + batch.Write() + + // Delete unknown id, the request should be rejected + id, _ := newIndexDeleter(db, newAccountIdent(common.Hash{0xa})) + if err := id.pop(indexBlockEntriesCap * 5); err == nil { + t.Fatal("Expect error to occur for unknown id") + } + for i := indexBlockEntriesCap * 4; i >= 1; i-- { + if err := id.pop(uint64(i)); err != nil { + t.Fatalf("Unexpected error for element popping, %v", err) + } + if id.lastID != uint64(i-1) { + t.Fatalf("Unexpected lastID, want: %d, got: %d", uint64(i-1), iw.lastID) + } + if rand.Intn(10) == 0 { + batch := db.NewBatch() + id.finish(batch) + batch.Write() + } + } +} + +func TestBatchIndexerWrite(t *testing.T) { + var ( + db = rawdb.NewMemoryDatabase() + batch = newBatchIndexer(db, false) + histories = makeHistories(10) + ) + for i, h := range histories { + if err := batch.process(h, uint64(i+1)); err != nil { + t.Fatalf("Failed to process history, %v", err) + } + } + if err := batch.finish(true); err != nil { + t.Fatalf("Failed to finish batch indexer, %v", err) + } + metadata := loadIndexMetadata(db) + if metadata == nil || metadata.Last != uint64(10) { + t.Fatal("Unexpected index position") + } + var ( + accounts = make(map[common.Hash][]uint64) + storages = make(map[common.Hash]map[common.Hash][]uint64) + ) + for i, h := range histories { + for _, addr := range h.accountList { + addrHash := crypto.Keccak256Hash(addr.Bytes()) + accounts[addrHash] = append(accounts[addrHash], uint64(i+1)) + + if _, ok := storages[addrHash]; !ok { + storages[addrHash] = make(map[common.Hash][]uint64) + } + for _, slot := range h.storageList[addr] { + storages[addrHash][slot] = append(storages[addrHash][slot], uint64(i+1)) + } + } + } + for addrHash, indexes := range accounts { + ir, _ := newIndexReader(db, newAccountIdent(addrHash)) + for i := 0; i < len(indexes)-1; i++ { + n, err := ir.readGreaterThan(indexes[i]) + if err != nil { + t.Fatalf("Failed to read index, %v", err) + } + if n != indexes[i+1] { + t.Fatalf("Unexpected result, want %d, got %d", indexes[i+1], n) + } + } + n, err := ir.readGreaterThan(indexes[len(indexes)-1]) + if err != nil { + t.Fatalf("Failed to read index, %v", err) + } + if n != math.MaxUint64 { + t.Fatalf("Unexpected result, want math.MaxUint64, got %d", n) + } + } + for addrHash, slots := range storages { + for slotHash, indexes := range slots { + ir, _ := newIndexReader(db, newStorageIdent(addrHash, slotHash)) + for i := 0; i < len(indexes)-1; i++ { + n, err := ir.readGreaterThan(indexes[i]) + if err != nil { + t.Fatalf("Failed to read index, %v", err) + } + if n != indexes[i+1] { + t.Fatalf("Unexpected result, want %d, got %d", indexes[i+1], n) + } + } + n, err := ir.readGreaterThan(indexes[len(indexes)-1]) + if err != nil { + t.Fatalf("Failed to read index, %v", err) + } + if n != math.MaxUint64 { + t.Fatalf("Unexpected result, want math.MaxUint64, got %d", n) + } + } + } +} + +func TestBatchIndexerDelete(t *testing.T) { + var ( + db = rawdb.NewMemoryDatabase() + bw = newBatchIndexer(db, false) + histories = makeHistories(10) + ) + // Index histories + for i, h := range histories { + if err := bw.process(h, uint64(i+1)); err != nil { + t.Fatalf("Failed to process history, %v", err) + } + } + if err := bw.finish(true); err != nil { + t.Fatalf("Failed to finish batch indexer, %v", err) + } + + // Unindex histories + bd := newBatchIndexer(db, true) + for i := len(histories) - 1; i >= 0; i-- { + if err := bd.process(histories[i], uint64(i+1)); err != nil { + t.Fatalf("Failed to process history, %v", err) + } + } + if err := bd.finish(true); err != nil { + t.Fatalf("Failed to finish batch indexer, %v", err) + } + + metadata := loadIndexMetadata(db) + if metadata != nil { + t.Fatal("Unexpected index position") + } + it := db.NewIterator(rawdb.StateHistoryIndexPrefix, nil) + for it.Next() { + t.Fatal("Leftover history index data") + } + it.Release() +} diff --git a/triedb/pathdb/history_indexer.go b/triedb/pathdb/history_indexer.go new file mode 100644 index 000000000000..42103fab32c9 --- /dev/null +++ b/triedb/pathdb/history_indexer.go @@ -0,0 +1,674 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see = tailID { + log.Debug("Resume state history indexing", "id", metadata.Last+1, "tail", tailID) + return metadata.Last + 1, nil + } + // History has been shortened without indexing. Discard the gapped segment + // in the history and shift to the first available element. + // + // The missing indexes corresponding to the gapped histories won't be visible. + // It's fine to leave them unindexed. + log.Info("History gap detected, discard old segment", "oldHead", metadata.Last, "newHead", tailID) + return tailID, nil +} + +func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID uint64) { + defer close(done) + + beginID, err := i.next() + if err != nil { + log.Error("Failed to find next state history for indexing", "err", err) + return + } + // All available state histories have been indexed, and the last indexed one + // exceeds the most recent available state history. This situation may occur + // when the state is reverted manually (chain.SetHead) or the deep reorg is + // encountered. In such cases, no indexing should be scheduled. + if beginID > lastID { + if lastID == 0 && beginID == 1 { + // Initialize the indexing flag if the state history is empty by + // using zero as the disk layer ID. This is a common case that + // can occur after snap sync. + // + // This step is essential to avoid spinning up indexing thread + // endlessly until a history object is produced. + storeIndexMetadata(i.disk, 0) + log.Info("Initialized history indexing flag") + } else { + log.Debug("State history is fully indexed", "last", lastID) + } + return + } + log.Info("Start history indexing", "beginID", beginID, "lastID", lastID) + + var ( + current = beginID + start = time.Now() + logged = time.Now() + batch = newBatchIndexer(i.disk, false) + ) + for current <= lastID { + count := lastID - current + 1 + if count > historyReadBatch { + count = historyReadBatch + } + histories, err := readHistories(i.freezer, current, count) + if err != nil { + // The history read might fall if the history is truncated from + // head due to revert operation. + log.Error("Failed to read history for indexing", "current", current, "count", count, "err", err) + return + } + for _, h := range histories { + if err := batch.process(h, current); err != nil { + log.Error("Failed to index history", "err", err) + return + } + current += 1 + + // Occasionally report the indexing progress + if time.Since(logged) > time.Second*8 { + logged = time.Now() + + var ( + left = lastID - current + 1 + done = current - beginID + speed = done/uint64(time.Since(start)/time.Millisecond+1) + 1 // +1s to avoid division by zero + ) + // Override the ETA if larger than the largest until now + eta := time.Duration(left/speed) * time.Millisecond + log.Info("Indexing state history", "processed", done, "left", left, "elapsed", common.PrettyDuration(time.Since(start)), "eta", common.PrettyDuration(eta)) + } + } + i.indexed.Store(current - 1) // update indexing progress + + // Check interruption signal and abort process if it's fired + if interrupt != nil { + if signal := interrupt.Load(); signal != 0 { + if err := batch.finish(true); err != nil { + log.Error("Failed to flush index", "err", err) + } + log.Info("State indexing interrupted") + return + } + } + } + if err := batch.finish(true); err != nil { + log.Error("Failed to flush index", "err", err) + } + log.Info("Indexed state history", "from", beginID, "to", lastID, "elapsed", common.PrettyDuration(time.Since(start))) +} + +// historyIndexer manages the indexing and unindexing of state histories, +// providing access to historical states. +// +// Upon initialization, historyIndexer starts a one-time background process +// to complete the indexing of any remaining state histories. Once this +// process is finished, all state histories are marked as fully indexed, +// enabling handling of requests for historical states. Thereafter, any new +// state histories must be indexed or unindexed synchronously, ensuring that +// the history index is created or removed along with the corresponding +// state history. +type historyIndexer struct { + initer *indexIniter + disk ethdb.KeyValueStore + freezer ethdb.AncientStore +} + +// checkVersion checks whether the index data in the database matches the version. +func checkVersion(disk ethdb.KeyValueStore) { + blob := rawdb.ReadStateHistoryIndexMetadata(disk) + if len(blob) == 0 { + return + } + var m indexMetadata + err := rlp.DecodeBytes(blob, &m) + if err == nil && m.Version == stateIndexVersion { + return + } + // TODO(rjl493456442) would be better to group them into a batch. + rawdb.DeleteStateHistoryIndexMetadata(disk) + rawdb.DeleteStateHistoryIndex(disk) + + version := "unknown" + if err == nil { + version = fmt.Sprintf("%d", m.Version) + } + log.Info("Cleaned up obsolete state history index", "version", version, "want", stateIndexVersion) +} + +// newHistoryIndexer constructs the history indexer and launches the background +// initer to complete the indexing of any remaining state histories. +func newHistoryIndexer(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, lastHistoryID uint64) *historyIndexer { + checkVersion(disk) + return &historyIndexer{ + initer: newIndexIniter(disk, freezer, lastHistoryID), + disk: disk, + freezer: freezer, + } +} + +func (i *historyIndexer) close() { + i.initer.close() +} + +// inited returns a flag indicating whether the existing state histories +// have been fully indexed, in other words, whether they are available +// for external access. +func (i *historyIndexer) inited() bool { + return i.initer.inited() +} + +// extend sends the notification that new state history with specified ID +// has been written into the database and is ready for indexing. +func (i *historyIndexer) extend(historyID uint64) error { + signal := &interruptSignal{ + newLastID: historyID, + result: make(chan error, 1), + } + select { + case <-i.initer.closed: + return errors.New("indexer is closed") + case <-i.initer.done: + return indexSingle(historyID, i.disk, i.freezer) + case i.initer.interrupt <- signal: + return <-signal.result + } +} + +// shorten sends the notification that state history with specified ID +// is about to be deleted from the database and should be unindexed. +func (i *historyIndexer) shorten(historyID uint64) error { + signal := &interruptSignal{ + newLastID: historyID - 1, + result: make(chan error, 1), + } + select { + case <-i.initer.closed: + return errors.New("indexer is closed") + case <-i.initer.done: + return unindexSingle(historyID, i.disk, i.freezer) + case i.initer.interrupt <- signal: + return <-signal.result + } +} + +// progress returns the indexing progress made so far. It provides the number +// of states that remain unindexed. +func (i *historyIndexer) progress() (uint64, error) { + select { + case <-i.initer.closed: + return 0, errors.New("indexer is closed") + default: + return i.initer.remain(), nil + } +} diff --git a/triedb/pathdb/history_reader.go b/triedb/pathdb/history_reader.go new file mode 100644 index 000000000000..9471ab423d75 --- /dev/null +++ b/triedb/pathdb/history_reader.go @@ -0,0 +1,375 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see lastID { + return 0, fmt.Errorf("index reader is stale, limit: %d, last-state-id: %d", r.limit, lastID) + } + // Try to find the element which is greater than the specified target + res, err := r.reader.readGreaterThan(id) + if err != nil { + return 0, err + } + // Short circuit if the element is found within the current index + if res != math.MaxUint64 { + return res, nil + } + // The element was not found, and no additional histories have been indexed. + // Return a not-found result. + if r.limit == lastID { + return res, nil + } + // Refresh the index reader and attempt again. If the latest indexed position + // is even below the ID of the disk layer, it indicates that state histories + // are being removed. In this case, it would theoretically be better to block + // the state rollback operation synchronously until all readers are released. + // Given that it's very unlikely to occur and users try to perform historical + // state queries while reverting the states at the same time. Simply returning + // an error should be sufficient for now. + metadata := loadIndexMetadata(r.db) + if metadata == nil || metadata.Last < lastID { + return 0, errors.New("state history hasn't been indexed yet") + } + if err := r.reader.refresh(); err != nil { + return 0, err + } + r.limit = metadata.Last + + return r.reader.readGreaterThan(id) +} + +// historyReader is the structure to access historic state data. +type historyReader struct { + disk ethdb.KeyValueReader + freezer ethdb.AncientReader + readers map[string]*indexReaderWithLimitTag +} + +// newHistoryReader constructs the history reader with the supplied db. +func newHistoryReader(disk ethdb.KeyValueReader, freezer ethdb.AncientReader) *historyReader { + return &historyReader{ + disk: disk, + freezer: freezer, + readers: make(map[string]*indexReaderWithLimitTag), + } +} + +// readAccountMetadata resolves the account metadata within the specified +// state history. +func (r *historyReader) readAccountMetadata(address common.Address, historyID uint64) ([]byte, error) { + blob := rawdb.ReadStateAccountIndex(r.freezer, historyID) + if len(blob) == 0 { + return nil, fmt.Errorf("account index is truncated, historyID: %d", historyID) + } + if len(blob)%accountIndexSize != 0 { + return nil, fmt.Errorf("account index is corrupted, historyID: %d, size: %d", historyID, len(blob)) + } + n := len(blob) / accountIndexSize + + pos := sort.Search(n, func(i int) bool { + h := blob[accountIndexSize*i : accountIndexSize*i+common.HashLength] + return bytes.Compare(h, address.Bytes()) >= 0 + }) + if pos == n { + return nil, fmt.Errorf("account %#x is not found", address) + } + offset := accountIndexSize * pos + if address != common.BytesToAddress(blob[offset:offset+common.AddressLength]) { + return nil, fmt.Errorf("account %#x is not found", address) + } + return blob[offset : accountIndexSize*(pos+1)], nil +} + +// readStorageMetadata resolves the storage slot metadata within the specified +// state history. +func (r *historyReader) readStorageMetadata(storageKey common.Hash, storageHash common.Hash, historyID uint64, slotOffset, slotNumber int) ([]byte, error) { + // TODO(rj493456442) optimize it with partial read + blob := rawdb.ReadStateStorageIndex(r.freezer, historyID) + if len(blob) == 0 { + return nil, fmt.Errorf("storage index is truncated, historyID: %d", historyID) + } + if len(blob)%slotIndexSize != 0 { + return nil, fmt.Errorf("storage indices is corrupted, historyID: %d, size: %d", historyID, len(blob)) + } + if slotIndexSize*(slotOffset+slotNumber) > len(blob) { + return nil, fmt.Errorf("storage indices is truncated, historyID: %d, size: %d, offset: %d, length: %d", historyID, len(blob), slotOffset, slotNumber) + } + subSlice := blob[slotIndexSize*slotOffset : slotIndexSize*(slotOffset+slotNumber)] + + // TODO(rj493456442) get rid of the metadata resolution + var ( + m meta + target common.Hash + ) + blob = rawdb.ReadStateHistoryMeta(r.freezer, historyID) + if err := m.decode(blob); err != nil { + return nil, err + } + if m.version == stateHistoryV0 { + target = storageHash + } else { + target = storageKey + } + pos := sort.Search(slotNumber, func(i int) bool { + slotID := subSlice[slotIndexSize*i : slotIndexSize*i+common.HashLength] + return bytes.Compare(slotID, target.Bytes()) >= 0 + }) + if pos == slotNumber { + return nil, fmt.Errorf("storage metadata is not found, slot key: %#x, historyID: %d", storageKey, historyID) + } + offset := slotIndexSize * pos + if target != common.BytesToHash(subSlice[offset:offset+common.HashLength]) { + return nil, fmt.Errorf("storage metadata is not found, slot key: %#x, historyID: %d", storageKey, historyID) + } + return subSlice[offset : slotIndexSize*(pos+1)], nil +} + +// readAccount retrieves the account data from the specified state history. +func (r *historyReader) readAccount(address common.Address, historyID uint64) ([]byte, error) { + metadata, err := r.readAccountMetadata(address, historyID) + if err != nil { + return nil, err + } + length := int(metadata[common.AddressLength]) // one byte for account data length + offset := int(binary.BigEndian.Uint32(metadata[common.AddressLength+1 : common.AddressLength+5])) // four bytes for the account data offset + + // TODO(rj493456442) optimize it with partial read + data := rawdb.ReadStateAccountHistory(r.freezer, historyID) + if len(data) < length+offset { + return nil, fmt.Errorf("account data is truncated, address: %#x, historyID: %d, size: %d, offset: %d, len: %d", address, historyID, len(data), offset, length) + } + return data[offset : offset+length], nil +} + +// readStorage retrieves the storage slot data from the specified state history. +func (r *historyReader) readStorage(address common.Address, storageKey common.Hash, storageHash common.Hash, historyID uint64) ([]byte, error) { + metadata, err := r.readAccountMetadata(address, historyID) + if err != nil { + return nil, err + } + // slotIndexOffset: + // The offset of storage indices associated with the specified account. + // slotIndexNumber: + // The number of storage indices associated with the specified account. + slotIndexOffset := int(binary.BigEndian.Uint32(metadata[common.AddressLength+5 : common.AddressLength+9])) + slotIndexNumber := int(binary.BigEndian.Uint32(metadata[common.AddressLength+9 : common.AddressLength+13])) + + slotMetadata, err := r.readStorageMetadata(storageKey, storageHash, historyID, slotIndexOffset, slotIndexNumber) + if err != nil { + return nil, err + } + length := int(slotMetadata[common.HashLength]) // one byte for slot data length + offset := int(binary.BigEndian.Uint32(slotMetadata[common.HashLength+1 : common.HashLength+5])) // four bytes for slot data offset + + // TODO(rj493456442) optimize it with partial read + data := rawdb.ReadStateStorageHistory(r.freezer, historyID) + if len(data) < offset+length { + return nil, fmt.Errorf("storage data is truncated, address: %#x, key: %#x, historyID: %d, size: %d, offset: %d, len: %d", address, storageKey, historyID, len(data), offset, length) + } + return data[offset : offset+length], nil +} + +// read retrieves the state element data associated with the stateID. +// stateID: represents the ID of the state of the specified version; +// lastID: represents the ID of the latest/newest state history; +// latestValue: represents the state value at the current disk layer with ID == lastID; +func (r *historyReader) read(state stateIdentQuery, stateID uint64, lastID uint64, latestValue []byte) ([]byte, error) { + tail, err := r.freezer.Tail() + if err != nil { + return nil, err + } + // stateID == tail is allowed, as the first history object preserved + // is tail+1 + if stateID < tail { + return nil, errors.New("historical state has been pruned") + } + + // To serve the request, all state histories from stateID+1 to lastID + // must be indexed. It's not supposed to happen unless system is very + // wrong. + metadata := loadIndexMetadata(r.disk) + if metadata == nil || metadata.Last < lastID { + indexed := "null" + if metadata != nil { + indexed = fmt.Sprintf("%d", metadata.Last) + } + return nil, fmt.Errorf("state history is not fully indexed, requested: %d, indexed: %s", stateID, indexed) + } + + // Construct the index reader to locate the corresponding history for + // state retrieval + ir, ok := r.readers[state.String()] + if !ok { + ir, err = newIndexReaderWithLimitTag(r.disk, state.stateIdent) + if err != nil { + return nil, err + } + r.readers[state.String()] = ir + } + historyID, err := ir.readGreaterThan(stateID, lastID) + if err != nil { + return nil, err + } + // The state was not found in the state histories, as it has not been modified + // since stateID. Use the data from the associated disk layer instead. + if historyID == math.MaxUint64 { + return latestValue, nil + } + // Resolve data from the specified state history object. Notably, since the history + // reader operates completely asynchronously with the indexer/unindexer, it's possible + // that the associated state histories are no longer available due to a rollback. + // Such truncation should be captured by the state resolver below, rather than returning + // invalid data. + if state.account { + return r.readAccount(state.address, historyID) + } + return r.readStorage(state.address, state.storageKey, state.storageHash, historyID) +} diff --git a/triedb/pathdb/history_reader_test.go b/triedb/pathdb/history_reader_test.go new file mode 100644 index 000000000000..4356490f2396 --- /dev/null +++ b/triedb/pathdb/history_reader_test.go @@ -0,0 +1,159 @@ +// Copyright 2025 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see = db.tree.bottom().stateID() { + return + } + time.Sleep(100 * time.Millisecond) + } +} + +func checkHistoricState(env *tester, root common.Hash, hr *historyReader) error { + // Short circuit if the historical state is no longer available + if rawdb.ReadStateID(env.db.diskdb, root) == nil { + return nil + } + var ( + dl = env.db.tree.bottom() + stateID = rawdb.ReadStateID(env.db.diskdb, root) + accounts = env.snapAccounts[root] + storages = env.snapStorages[root] + ) + for addrHash, accountData := range accounts { + latest, _ := dl.account(addrHash, 0) + blob, err := hr.read(newAccountIdentQuery(env.accountPreimage(addrHash), addrHash), *stateID, dl.stateID(), latest) + if err != nil { + return err + } + if !bytes.Equal(accountData, blob) { + return fmt.Errorf("wrong account data, expected %x, got %x", accountData, blob) + } + } + for i := 0; i < len(env.roots); i++ { + if env.roots[i] == root { + break + } + // Find all accounts deleted in the past, ensure the associated data is null + for addrHash := range env.snapAccounts[env.roots[i]] { + if _, ok := accounts[addrHash]; !ok { + latest, _ := dl.account(addrHash, 0) + blob, err := hr.read(newAccountIdentQuery(env.accountPreimage(addrHash), addrHash), *stateID, dl.stateID(), latest) + if err != nil { + return err + } + if len(blob) != 0 { + return fmt.Errorf("wrong account data, expected null, got %x", blob) + } + } + } + } + for addrHash, slots := range storages { + for slotHash, slotData := range slots { + latest, _ := dl.storage(addrHash, slotHash, 0) + blob, err := hr.read(newStorageIdentQuery(env.accountPreimage(addrHash), addrHash, env.hashPreimage(slotHash), slotHash), *stateID, dl.stateID(), latest) + if err != nil { + return err + } + if !bytes.Equal(slotData, blob) { + return fmt.Errorf("wrong storage data, expected %x, got %x", slotData, blob) + } + } + } + for i := 0; i < len(env.roots); i++ { + if env.roots[i] == root { + break + } + // Find all storage slots deleted in the past, ensure the associated data is null + for addrHash, slots := range env.snapStorages[env.roots[i]] { + for slotHash := range slots { + _, ok := storages[addrHash] + if ok { + _, ok = storages[addrHash][slotHash] + } + if !ok { + latest, _ := dl.storage(addrHash, slotHash, 0) + blob, err := hr.read(newStorageIdentQuery(env.accountPreimage(addrHash), addrHash, env.hashPreimage(slotHash), slotHash), *stateID, dl.stateID(), latest) + if err != nil { + return err + } + if len(blob) != 0 { + return fmt.Errorf("wrong storage data, expected null, got %x", blob) + } + } + } + } + } + return nil +} + +func TestHistoryReader(t *testing.T) { + testHistoryReader(t, 0) // with all histories reserved + testHistoryReader(t, 10) // with latest 10 histories reserved +} + +func testHistoryReader(t *testing.T, historyLimit uint64) { + maxDiffLayers = 4 + defer func() { + maxDiffLayers = 128 + }() + //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true))) + + env := newTester(t, historyLimit, false, 64, true) + defer env.release() + waitIndexing(env.db) + + var ( + roots = env.roots + dRoot = env.db.tree.bottom().rootHash() + hr = newHistoryReader(env.db.diskdb, env.db.freezer) + ) + for _, root := range roots { + if root == dRoot { + break + } + if err := checkHistoricState(env, root, hr); err != nil { + t.Fatal(err) + } + } + + // Pile up more histories on top, ensuring the historic reader is not affected + env.extend(4) + waitIndexing(env.db) + + for _, root := range roots { + if root == dRoot { + break + } + if err := checkHistoricState(env, root, hr); err != nil { + t.Fatal(err) + } + } +} diff --git a/triedb/pathdb/iterator_binary.go b/triedb/pathdb/iterator_binary.go index 0620081d0c12..97a291898960 100644 --- a/triedb/pathdb/iterator_binary.go +++ b/triedb/pathdb/iterator_binary.go @@ -45,6 +45,10 @@ type binaryIterator struct { // accounts in a slow, but easily verifiable way. Note this function is used // for initialization, use `newBinaryAccountIterator` as the API. func (dl *diskLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator { + // Block until the frozen buffer flushing is completed. + if err := dl.waitFlush(); err != nil { + panic(err) + } // The state set in the disk layer is mutable, hold the lock before obtaining // the account list to prevent concurrent map iteration and write. dl.lock.RLock() @@ -113,6 +117,10 @@ func (dl *diffLayer) initBinaryAccountIterator(seek common.Hash) *binaryIterator // storage slots in a slow, but easily verifiable way. Note this function is used // for initialization, use `newBinaryStorageIterator` as the API. func (dl *diskLayer) initBinaryStorageIterator(account common.Hash, seek common.Hash) *binaryIterator { + // Block until the frozen buffer flushing is completed. + if err := dl.waitFlush(); err != nil { + panic(err) + } // The state set in the disk layer is mutable, hold the lock before obtaining // the storage list to prevent concurrent map iteration and write. dl.lock.RLock() diff --git a/triedb/pathdb/iterator_fast.go b/triedb/pathdb/iterator_fast.go index 87b2dd567ac8..04bf89e874e3 100644 --- a/triedb/pathdb/iterator_fast.go +++ b/triedb/pathdb/iterator_fast.go @@ -76,6 +76,11 @@ func newFastIterator(db *Database, root common.Hash, account common.Hash, seek c if accountIterator { switch dl := current.(type) { case *diskLayer: + // Ensure no active background buffer flush is in progress, otherwise, + // part of the state data may become invisible. + if err := dl.waitFlush(); err != nil { + return nil, err + } // The state set in the disk layer is mutable, hold the lock before obtaining // the account list to prevent concurrent map iteration and write. dl.lock.RLock() @@ -113,6 +118,11 @@ func newFastIterator(db *Database, root common.Hash, account common.Hash, seek c } else { switch dl := current.(type) { case *diskLayer: + // Ensure no active background buffer flush is in progress, otherwise, + // part of the state data may become invisible. + if err := dl.waitFlush(); err != nil { + return nil, err + } // The state set in the disk layer is mutable, hold the lock before obtaining // the storage list to prevent concurrent map iteration and write. dl.lock.RLock() diff --git a/triedb/pathdb/iterator_test.go b/triedb/pathdb/iterator_test.go index 6517735d7e9b..adb534f47d16 100644 --- a/triedb/pathdb/iterator_test.go +++ b/triedb/pathdb/iterator_test.go @@ -254,10 +254,9 @@ func TestFastIteratorBasics(t *testing.T) { // TestAccountIteratorTraversal tests some simple multi-layer iteration. func TestAccountIteratorTraversal(t *testing.T) { config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 0, trienode.NewMergedNodeSet(), @@ -298,10 +297,9 @@ func TestAccountIteratorTraversal(t *testing.T) { func TestStorageIteratorTraversal(t *testing.T) { config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 0, trienode.NewMergedNodeSet(), @@ -311,14 +309,14 @@ func TestStorageIteratorTraversal(t *testing.T) { NewStateSetWithOrigin(randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x04", "0x05", "0x06"}}, nil), nil, nil, false)) db.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 0, trienode.NewMergedNodeSet(), - NewStateSetWithOrigin(randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil), nil, nil, false)) + NewStateSetWithOrigin(randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02"}}, nil), nil, nil, false)) // Verify the single and multi-layer iterators head := db.tree.get(common.HexToHash("0x04")) // singleLayer: 0x1, 0x2, 0x3 diffIter := newDiffStorageIterator(common.HexToHash("0xaa"), common.Hash{}, head.(*diffLayer).states.stateSet.storageList(common.HexToHash("0xaa")), nil) - verifyIterator(t, 3, diffIter, verifyNothing) + verifyIterator(t, 2, diffIter, verifyNothing) // binaryIterator: 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa"), common.Hash{}), verifyStorage) @@ -342,10 +340,9 @@ func TestStorageIteratorTraversal(t *testing.T) { // also expect the correct values to show up. func TestAccountIteratorTraversalValues(t *testing.T) { config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() // Create a batch of account sets to seed subsequent layers with var ( @@ -458,10 +455,9 @@ func TestAccountIteratorTraversalValues(t *testing.T) { func TestStorageIteratorTraversalValues(t *testing.T) { config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() wrapStorage := func(storage map[common.Hash][]byte) map[common.Hash]map[common.Hash][]byte { return map[common.Hash]map[common.Hash][]byte{ @@ -591,10 +587,9 @@ func TestAccountIteratorLargeTraversal(t *testing.T) { } // Build up a large stack of snapshots config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() for i := 1; i < 128; i++ { parent := types.EmptyRootHash @@ -630,10 +625,10 @@ func TestAccountIteratorLargeTraversal(t *testing.T) { // - continues iterating func TestAccountIteratorFlattening(t *testing.T) { config := &Config{ - WriteBufferSize: 10 * 1024, + WriteBufferSize: 10 * 1024, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() // Create a stack of diffs on top db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -662,11 +657,24 @@ func TestAccountIteratorFlattening(t *testing.T) { } func TestAccountIteratorSeek(t *testing.T) { + t.Run("fast", func(t *testing.T) { + testAccountIteratorSeek(t, func(db *Database, root, seek common.Hash) AccountIterator { + it, _ := db.AccountIterator(root, seek) + return it + }) + }) + t.Run("binary", func(t *testing.T) { + testAccountIteratorSeek(t, func(db *Database, root, seek common.Hash) AccountIterator { + return db.tree.get(root).(*diffLayer).newBinaryAccountIterator(seek) + }) + }) +} + +func testAccountIteratorSeek(t *testing.T, newIterator func(db *Database, root, seek common.Hash) AccountIterator) { config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil, nil, nil, false)) @@ -682,39 +690,39 @@ func TestAccountIteratorSeek(t *testing.T) { // 03: aa, bb, dd, ee, f0 (, f0), ff // 04: aa, bb, cc, dd, ee, f0 (, f0), ff (, ff) // Construct various iterators and ensure their traversal is correct - it, _ := db.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xdd")) + it := newIterator(db, common.HexToHash("0x02"), common.HexToHash("0xdd")) defer it.Release() verifyIterator(t, 3, it, verifyAccount) // expected: ee, f0, ff - it, _ = db.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xaa")) + it = newIterator(db, common.HexToHash("0x02"), common.HexToHash("0xaa")) defer it.Release() verifyIterator(t, 4, it, verifyAccount) // expected: aa, ee, f0, ff - it, _ = db.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xff")) + it = newIterator(db, common.HexToHash("0x02"), common.HexToHash("0xff")) defer it.Release() verifyIterator(t, 1, it, verifyAccount) // expected: ff - it, _ = db.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xff1")) + it = newIterator(db, common.HexToHash("0x02"), common.HexToHash("0xff1")) defer it.Release() verifyIterator(t, 0, it, verifyAccount) // expected: nothing - it, _ = db.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xbb")) + it = newIterator(db, common.HexToHash("0x04"), common.HexToHash("0xbb")) defer it.Release() verifyIterator(t, 6, it, verifyAccount) // expected: bb, cc, dd, ee, f0, ff - it, _ = db.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xef")) + it = newIterator(db, common.HexToHash("0x04"), common.HexToHash("0xef")) defer it.Release() verifyIterator(t, 2, it, verifyAccount) // expected: f0, ff - it, _ = db.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xf0")) + it = newIterator(db, common.HexToHash("0x04"), common.HexToHash("0xf0")) defer it.Release() verifyIterator(t, 2, it, verifyAccount) // expected: f0, ff - it, _ = db.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xff")) + it = newIterator(db, common.HexToHash("0x04"), common.HexToHash("0xff")) defer it.Release() verifyIterator(t, 1, it, verifyAccount) // expected: ff - it, _ = db.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xff1")) + it = newIterator(db, common.HexToHash("0x04"), common.HexToHash("0xff1")) defer it.Release() verifyIterator(t, 0, it, verifyAccount) // expected: nothing } @@ -735,10 +743,9 @@ func TestStorageIteratorSeek(t *testing.T) { func testStorageIteratorSeek(t *testing.T, newIterator func(db *Database, root, account, seek common.Hash) StorageIterator) { config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -807,10 +814,10 @@ func TestAccountIteratorDeletions(t *testing.T) { func testAccountIteratorDeletions(t *testing.T, newIterator func(db *Database, root, seek common.Hash) AccountIterator) { config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } - db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() + memoryDB := rawdb.NewMemoryDatabase() + db := New(memoryDB, config, false) // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -825,32 +832,55 @@ func testAccountIteratorDeletions(t *testing.T, newIterator func(db *Database, r db.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(randomAccountSet("0x33", "0x44", "0x55"), nil, nil, nil, false)) - // The output should be 11,33,44,55 - it := newIterator(db, common.HexToHash("0x04"), common.Hash{}) - // Do a quick check - verifyIterator(t, 4, it, verifyAccount) - it.Release() - - // And a more detailed verification that we indeed do not see '0x22' - it = newIterator(db, common.HexToHash("0x04"), common.Hash{}) - defer it.Release() - for it.Next() { - hash := it.Hash() - if it.Account() == nil { - t.Errorf("iterator returned nil-value for hash %x", hash) - } - if hash == deleted { - t.Errorf("expected deleted elem %x to not be returned by iterator", deleted) + verify := func() { + // The output should be 11,33,44,55 + it := newIterator(db, common.HexToHash("0x04"), common.Hash{}) + // Do a quick check + verifyIterator(t, 4, it, verifyAccount) + it.Release() + + // And a more detailed verification that we indeed do not see '0x22' + it = newIterator(db, common.HexToHash("0x04"), common.Hash{}) + defer it.Release() + for it.Next() { + hash := it.Hash() + if it.Account() == nil { + t.Errorf("iterator returned nil-value for hash %x", hash) + } + if hash == deleted { + t.Errorf("expected deleted elem %x to not be returned by iterator", deleted) + } } } + verify() + + if err := db.Journal(common.HexToHash("0x04")); err != nil { + t.Fatalf("Failed to journal the database, %v", err) + } + if err := db.Close(); err != nil { + t.Fatalf("Failed to close the database, %v", err) + } + db = New(memoryDB, config, false) + + verify() } func TestStorageIteratorDeletions(t *testing.T) { config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, + } + memoryDB := rawdb.NewMemoryDatabase() + db := New(memoryDB, config, false) + + restart := func(head common.Hash) { + if err := db.Journal(head); err != nil { + t.Fatalf("Failed to journal the database, %v", err) + } + if err := db.Close(); err != nil { + t.Fatalf("Failed to close the database, %v", err) + } + db = New(memoryDB, config, false) } - db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() // Stack three diff layers on top with various overlaps db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -869,6 +899,19 @@ func TestStorageIteratorDeletions(t *testing.T) { verifyIterator(t, 3, it, verifyStorage) it.Release() + // Ensure the iteration result aligns after the database restart + restart(common.HexToHash("0x03")) + + // The output should be 02,04,05,06 + it, _ = db.StorageIterator(common.HexToHash("0x03"), common.HexToHash("0xaa"), common.Hash{}) + verifyIterator(t, 4, it, verifyStorage) + it.Release() + + // The output should be 04,05,06 + it, _ = db.StorageIterator(common.HexToHash("0x03"), common.HexToHash("0xaa"), common.HexToHash("0x03")) + verifyIterator(t, 3, it, verifyStorage) + it.Release() + // Destruct the whole storage accounts := map[common.Hash][]byte{ common.HexToHash("0xaa"): nil, @@ -880,6 +923,12 @@ func TestStorageIteratorDeletions(t *testing.T) { verifyIterator(t, 0, it, verifyStorage) it.Release() + // Ensure the iteration result aligns after the database restart + restart(common.HexToHash("0x04")) + it, _ = db.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) + verifyIterator(t, 0, it, verifyStorage) + it.Release() + // Re-insert the slots of the same account db.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), 4, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x07", "0x08", "0x09"}}, nil), nil, nil, false)) @@ -889,6 +938,14 @@ func TestStorageIteratorDeletions(t *testing.T) { verifyIterator(t, 3, it, verifyStorage) it.Release() + // Ensure the iteration result aligns after the database restart + restart(common.HexToHash("0x05")) + + // The output should be 07,08,09 + it, _ = db.StorageIterator(common.HexToHash("0x05"), common.HexToHash("0xaa"), common.Hash{}) + verifyIterator(t, 3, it, verifyStorage) + it.Release() + // Destruct the whole storage but re-create the account in the same layer db.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), 5, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x11", "0x12"}}, [][]string{{"0x07", "0x08", "0x09"}}), nil, nil, false)) @@ -898,6 +955,13 @@ func TestStorageIteratorDeletions(t *testing.T) { it.Release() verifyIterator(t, 2, db.tree.get(common.HexToHash("0x06")).(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa"), common.Hash{}), verifyStorage) + + // Ensure the iteration result aligns after the database restart + restart(common.HexToHash("0x06")) + it, _ = db.StorageIterator(common.HexToHash("0x06"), common.HexToHash("0xaa"), common.Hash{}) + verifyIterator(t, 2, it, verifyStorage) // The output should be 11,12 + it.Release() + verifyIterator(t, 2, db.tree.get(common.HexToHash("0x06")).(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa"), common.Hash{}), verifyStorage) } // TestStaleIterator tests if the iterator could correctly terminate the iteration @@ -915,10 +979,10 @@ func TestStaleIterator(t *testing.T) { func testStaleIterator(t *testing.T, newIter func(db *Database, hash common.Hash) Iterator) { config := &Config{ - WriteBufferSize: 16 * 1024 * 1024, + WriteBufferSize: 16 * 1024 * 1024, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() // [02 (disk), 03] db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), @@ -970,10 +1034,9 @@ func BenchmarkAccountIteratorTraversal(b *testing.B) { return accounts } config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() for i := 1; i <= 100; i++ { parent := types.EmptyRootHash @@ -1065,10 +1128,9 @@ func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) { return accounts } config := &Config{ - WriteBufferSize: 0, + NoAsyncGeneration: true, } db := New(rawdb.NewMemoryDatabase(), config, false) - db.waitGeneration() db.Update(common.HexToHash("0x02"), types.EmptyRootHash, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(makeAccounts(2000), nil, nil, nil, false)) for i := 2; i <= 100; i++ { diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go index 5dc6da92b85b..e88b3e062fd5 100644 --- a/triedb/pathdb/journal.go +++ b/triedb/pathdb/journal.go @@ -160,7 +160,7 @@ func (db *Database) loadLayers() layer { log.Info("Failed to load journal, discard it", "err", err) } // Return single layer with persistent state. - return newDiskLayer(root, rawdb.ReadPersistentStateID(db.diskdb), db, nil, nil, newBuffer(db.config.WriteBufferSize, nil, nil, 0)) + return newDiskLayer(root, rawdb.ReadPersistentStateID(db.diskdb), db, nil, nil, newBuffer(db.config.WriteBufferSize, nil, nil, 0), nil) } // loadDiskLayer reads the binary blob from the layer journal, reconstructing @@ -192,7 +192,7 @@ func (db *Database) loadDiskLayer(r *rlp.Stream) (layer, error) { if err := states.decode(r); err != nil { return nil, err } - return newDiskLayer(root, id, db, nil, nil, newBuffer(db.config.WriteBufferSize, &nodes, &states, id-stored)), nil + return newDiskLayer(root, id, db, nil, nil, newBuffer(db.config.WriteBufferSize, &nodes, &states, id-stored), nil), nil } // loadDiffLayer reads the next sections of a layer journal, reconstructing a new @@ -301,9 +301,10 @@ func (db *Database) Journal(root common.Hash) error { } else { // disk layer only on noop runs (likely) or deep reorgs (unlikely) log.Info("Persisting dirty state to disk", "root", root, "layers", disk.buffer.layers) } - // Terminate the background state generation if it's active - if disk.generator != nil { - disk.generator.stop() + // Block until the background flushing is finished and terminate + // the potential active state generator. + if err := disk.terminate(); err != nil { + return err } start := time.Now() diff --git a/triedb/pathdb/layertree_test.go b/triedb/pathdb/layertree_test.go index a72ff5899eed..a76d60ba5b24 100644 --- a/triedb/pathdb/layertree_test.go +++ b/triedb/pathdb/layertree_test.go @@ -27,7 +27,7 @@ import ( func newTestLayerTree() *layerTree { db := New(rawdb.NewMemoryDatabase(), nil, false) - l := newDiskLayer(common.Hash{0x1}, 0, db, nil, nil, newBuffer(0, nil, nil, 0)) + l := newDiskLayer(common.Hash{0x1}, 0, db, nil, nil, newBuffer(0, nil, nil, 0), nil) t := newLayerTree(l) return t } diff --git a/triedb/pathdb/metrics.go b/triedb/pathdb/metrics.go index 6d40c5713b4f..779f9d813ffe 100644 --- a/triedb/pathdb/metrics.go +++ b/triedb/pathdb/metrics.go @@ -73,8 +73,14 @@ var ( historyDataBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/data", nil) historyIndexBytesMeter = metrics.NewRegisteredMeter("pathdb/history/bytes/index", nil) + indexHistoryTimer = metrics.NewRegisteredResettingTimer("pathdb/history/index/time", nil) + unindexHistoryTimer = metrics.NewRegisteredResettingTimer("pathdb/history/unindex/time", nil) + lookupAddLayerTimer = metrics.NewRegisteredResettingTimer("pathdb/lookup/add/time", nil) lookupRemoveLayerTimer = metrics.NewRegisteredResettingTimer("pathdb/lookup/remove/time", nil) + + historicalAccountReadTimer = metrics.NewRegisteredResettingTimer("pathdb/history/account/reads", nil) + historicalStorageReadTimer = metrics.NewRegisteredResettingTimer("pathdb/history/storage/reads", nil) ) // Metrics in generation diff --git a/triedb/pathdb/reader.go b/triedb/pathdb/reader.go index bc72db34e34c..b7b18f13f9ef 100644 --- a/triedb/pathdb/reader.go +++ b/triedb/pathdb/reader.go @@ -19,10 +19,13 @@ package pathdb import ( "errors" "fmt" + "time" "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/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/triedb/database" @@ -192,3 +195,122 @@ func (db *Database) StateReader(root common.Hash) (database.StateReader, error) layer: layer, }, nil } + +// HistoricalStateReader is a wrapper over history reader, providing access to +// historical state. +type HistoricalStateReader struct { + db *Database + reader *historyReader + id uint64 +} + +// HistoricReader constructs a reader for accessing the requested historic state. +func (db *Database) HistoricReader(root common.Hash) (*HistoricalStateReader, error) { + // Bail out if the state history hasn't been fully indexed + if db.indexer == nil || !db.indexer.inited() { + return nil, errors.New("state histories haven't been fully indexed yet") + } + if db.freezer == nil { + return nil, errors.New("state histories are not available") + } + // States at the current disk layer or above are directly accessible via + // db.StateReader. + // + // States older than the current disk layer (including the disk layer + // itself) are available through historic state access. + // + // Note: the requested state may refer to a stale historic state that has + // already been pruned. This function does not validate availability, as + // underlying states may be pruned dynamically. Validity is checked during + // each actual state retrieval. + id := rawdb.ReadStateID(db.diskdb, root) + if id == nil { + return nil, fmt.Errorf("state %#x is not available", root) + } + return &HistoricalStateReader{ + id: *id, + db: db, + reader: newHistoryReader(db.diskdb, db.freezer), + }, nil +} + +// AccountRLP directly retrieves the account RLP associated with a particular +// address in the slim data format. An error will be returned if the read +// operation exits abnormally. Specifically, if the layer is already stale. +// +// Note: +// - the returned account is not a copy, please don't modify it. +// - no error will be returned if the requested account is not found in database. +func (r *HistoricalStateReader) AccountRLP(address common.Address) ([]byte, error) { + defer func(start time.Time) { + historicalAccountReadTimer.UpdateSince(start) + }(time.Now()) + + // TODO(rjl493456442): Theoretically, the obtained disk layer could become stale + // within a very short time window. + // + // While reading the account data while holding `db.tree.lock` can resolve + // this issue, but it will introduce a heavy contention over the lock. + // + // Let's optimistically assume the situation is very unlikely to happen, + // and try to define a low granularity lock if the current approach doesn't + // work later. + dl := r.db.tree.bottom() + hash := crypto.Keccak256Hash(address.Bytes()) + latest, err := dl.account(hash, 0) + if err != nil { + return nil, err + } + return r.reader.read(newAccountIdentQuery(address, hash), r.id, dl.stateID(), latest) +} + +// Account directly retrieves the account associated with a particular address in +// the slim data format. An error will be returned if the read operation exits +// abnormally. Specifically, if the layer is already stale. +// +// No error will be returned if the requested account is not found in database +func (r *HistoricalStateReader) Account(address common.Address) (*types.SlimAccount, error) { + blob, err := r.AccountRLP(address) + if err != nil { + return nil, err + } + if len(blob) == 0 { + return nil, nil + } + account := new(types.SlimAccount) + if err := rlp.DecodeBytes(blob, account); err != nil { + panic(err) + } + return account, nil +} + +// Storage directly retrieves the storage data associated with a particular key, +// within a particular account. An error will be returned if the read operation +// exits abnormally. Specifically, if the layer is already stale. +// +// Note: +// - the returned storage data is not a copy, please don't modify it. +// - no error will be returned if the requested slot is not found in database. +func (r *HistoricalStateReader) Storage(address common.Address, key common.Hash) ([]byte, error) { + defer func(start time.Time) { + historicalStorageReadTimer.UpdateSince(start) + }(time.Now()) + + // TODO(rjl493456442): Theoretically, the obtained disk layer could become stale + // within a very short time window. + // + // While reading the account data while holding `db.tree.lock` can resolve + // this issue, but it will introduce a heavy contention over the lock. + // + // Let's optimistically assume the situation is very unlikely to happen, + // and try to define a low granularity lock if the current approach doesn't + // work later. + dl := r.db.tree.bottom() + addrHash := crypto.Keccak256Hash(address.Bytes()) + keyHash := crypto.Keccak256Hash(key.Bytes()) + latest, err := dl.storage(addrHash, keyHash, 0) + if err != nil { + return nil, err + } + return r.reader.read(newStorageIdentQuery(address, addrHash, key, keyHash), r.id, dl.stateID(), latest) +} diff --git a/triedb/pathdb/states.go b/triedb/pathdb/states.go index 2a88d74f5f64..bc638a569efa 100644 --- a/triedb/pathdb/states.go +++ b/triedb/pathdb/states.go @@ -387,8 +387,8 @@ func (s *stateSet) decode(r *rlp.Stream) error { if err := r.Decode(&dec); err != nil { return fmt.Errorf("load diff accounts: %v", err) } - for i := 0; i < len(dec.AddrHashes); i++ { - accountSet[dec.AddrHashes[i]] = dec.Accounts[i] + for i := range dec.AddrHashes { + accountSet[dec.AddrHashes[i]] = empty2nil(dec.Accounts[i]) } s.accountData = accountSet @@ -407,8 +407,8 @@ func (s *stateSet) decode(r *rlp.Stream) error { } for _, entry := range storages { storageSet[entry.AddrHash] = make(map[common.Hash][]byte, len(entry.Keys)) - for i := 0; i < len(entry.Keys); i++ { - storageSet[entry.AddrHash][entry.Keys[i]] = entry.Vals[i] + for i := range entry.Keys { + storageSet[entry.AddrHash][entry.Keys[i]] = empty2nil(entry.Vals[i]) } } s.storageData = storageSet @@ -550,8 +550,8 @@ func (s *StateSetWithOrigin) decode(r *rlp.Stream) error { if err := r.Decode(&accounts); err != nil { return fmt.Errorf("load diff account origin set: %v", err) } - for i := 0; i < len(accounts.Accounts); i++ { - accountSet[accounts.Addresses[i]] = accounts.Accounts[i] + for i := range accounts.Accounts { + accountSet[accounts.Addresses[i]] = empty2nil(accounts.Accounts[i]) } s.accountOrigin = accountSet @@ -570,10 +570,17 @@ func (s *StateSetWithOrigin) decode(r *rlp.Stream) error { } for _, storage := range storages { storageSet[storage.Address] = make(map[common.Hash][]byte) - for i := 0; i < len(storage.Keys); i++ { - storageSet[storage.Address][storage.Keys[i]] = storage.Vals[i] + for i := range storage.Keys { + storageSet[storage.Address][storage.Keys[i]] = empty2nil(storage.Vals[i]) } } s.storageOrigin = storageSet return nil } + +func empty2nil(b []byte) []byte { + if len(b) == 0 { + return nil + } + return b +} diff --git a/triedb/pathdb/verifier.go b/triedb/pathdb/verifier.go new file mode 100644 index 000000000000..2d6f72925b6e --- /dev/null +++ b/triedb/pathdb/verifier.go @@ -0,0 +1,355 @@ +// 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 pathdb + +import ( + "encoding/binary" + "errors" + "fmt" + "math" + "runtime" + "sync" + "time" + + "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/log" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +// trieKV represents a trie key-value pair +type trieKV struct { + key common.Hash + value []byte +} + +type ( + // trieHasherFn is the interface of trie hasher which can be implemented + // by different trie algorithm. + trieHasherFn func(in chan trieKV, out chan common.Hash) + + // leafCallbackFn is the callback invoked at the leaves of the trie, + // returns the subtrie root with the specified subtrie identifier. + leafCallbackFn func(accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) +) + +// VerifyState traverses the flat states specified by the given state root and +// ensures they are matched with each other. +func (db *Database) VerifyState(root common.Hash) error { + acctIt, err := db.AccountIterator(root, common.Hash{}) + if err != nil { + return err // The required snapshot might not exist. + } + defer acctIt.Release() + + got, err := generateTrieRoot(acctIt, common.Hash{}, stackTrieHasher, func(accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) { + // Migrate the code first, commit the contract code into the tmp db. + if codeHash != types.EmptyCodeHash { + code := rawdb.ReadCode(db.diskdb, codeHash) + if len(code) == 0 { + return common.Hash{}, errors.New("failed to read contract code") + } + } + // Then migrate all storage trie nodes into the tmp db. + storageIt, err := db.StorageIterator(root, accountHash, common.Hash{}) + if err != nil { + return common.Hash{}, err + } + defer storageIt.Release() + + hash, err := generateTrieRoot(storageIt, accountHash, stackTrieHasher, nil, stat, false) + if err != nil { + return common.Hash{}, err + } + return hash, nil + }, newGenerateStats(), true) + + if err != nil { + return err + } + if got != root { + return fmt.Errorf("state root hash mismatch: got %x, want %x", got, root) + } + return nil +} + +// generateStats is a collection of statistics gathered by the trie generator +// for logging purposes. +type generateStats struct { + head common.Hash + start time.Time + + accounts uint64 // Number of accounts done (including those being crawled) + slots uint64 // Number of storage slots done (including those being crawled) + + slotsStart map[common.Hash]time.Time // Start time for account slot crawling + slotsHead map[common.Hash]common.Hash // Slot head for accounts being crawled + + lock sync.RWMutex +} + +// newGenerateStats creates a new generator stats. +func newGenerateStats() *generateStats { + return &generateStats{ + slotsStart: make(map[common.Hash]time.Time), + slotsHead: make(map[common.Hash]common.Hash), + start: time.Now(), + } +} + +// progressAccounts updates the generator stats for the account range. +func (stat *generateStats) progressAccounts(account common.Hash, done uint64) { + stat.lock.Lock() + defer stat.lock.Unlock() + + stat.accounts += done + stat.head = account +} + +// finishAccounts updates the generator stats for the finished account range. +func (stat *generateStats) finishAccounts(done uint64) { + stat.lock.Lock() + defer stat.lock.Unlock() + + stat.accounts += done +} + +// progressContract updates the generator stats for a specific in-progress contract. +func (stat *generateStats) progressContract(account common.Hash, slot common.Hash, done uint64) { + stat.lock.Lock() + defer stat.lock.Unlock() + + stat.slots += done + stat.slotsHead[account] = slot + if _, ok := stat.slotsStart[account]; !ok { + stat.slotsStart[account] = time.Now() + } +} + +// finishContract updates the generator stats for a specific just-finished contract. +func (stat *generateStats) finishContract(account common.Hash, done uint64) { + stat.lock.Lock() + defer stat.lock.Unlock() + + stat.slots += done + delete(stat.slotsHead, account) + delete(stat.slotsStart, account) +} + +// report prints the cumulative progress statistic smartly. +func (stat *generateStats) report() { + stat.lock.RLock() + defer stat.lock.RUnlock() + + ctx := []interface{}{ + "accounts", stat.accounts, + "slots", stat.slots, + "elapsed", common.PrettyDuration(time.Since(stat.start)), + } + if stat.accounts > 0 { + // If there's progress on the account trie, estimate the time to finish crawling it + if done := binary.BigEndian.Uint64(stat.head[:8]) / stat.accounts; done > 0 { + var ( + left = (math.MaxUint64 - binary.BigEndian.Uint64(stat.head[:8])) / stat.accounts + speed = done/uint64(time.Since(stat.start)/time.Millisecond+1) + 1 // +1s to avoid division by zero + eta = time.Duration(left/speed) * time.Millisecond + ) + // If there are large contract crawls in progress, estimate their finish time + for acc, head := range stat.slotsHead { + start := stat.slotsStart[acc] + if done := binary.BigEndian.Uint64(head[:8]); done > 0 { + var ( + left = math.MaxUint64 - binary.BigEndian.Uint64(head[:8]) + speed = done/uint64(time.Since(start)/time.Millisecond+1) + 1 // +1s to avoid division by zero + ) + // Override the ETA if larger than the largest until now + if slotETA := time.Duration(left/speed) * time.Millisecond; eta < slotETA { + eta = slotETA + } + } + } + ctx = append(ctx, []interface{}{ + "eta", common.PrettyDuration(eta), + }...) + } + } + log.Info("Iterating state snapshot", ctx...) +} + +// reportDone prints the last log when the whole generation is finished. +func (stat *generateStats) reportDone() { + stat.lock.RLock() + defer stat.lock.RUnlock() + + var ctx []interface{} + ctx = append(ctx, []interface{}{"accounts", stat.accounts}...) + if stat.slots != 0 { + ctx = append(ctx, []interface{}{"slots", stat.slots}...) + } + ctx = append(ctx, []interface{}{"elapsed", common.PrettyDuration(time.Since(stat.start))}...) + log.Info("Iterated snapshot", ctx...) +} + +// runReport periodically prints the progress information. +func runReport(stats *generateStats, stop chan bool) { + timer := time.NewTimer(0) + defer timer.Stop() + + for { + select { + case <-timer.C: + stats.report() + timer.Reset(time.Second * 8) + case success := <-stop: + if success { + stats.reportDone() + } + return + } + } +} + +// generateTrieRoot generates the trie hash based on the snapshot iterator. +// It can be used for generating account trie, storage trie or even the +// whole state which connects the accounts and the corresponding storages. +func generateTrieRoot(it Iterator, account common.Hash, generatorFn trieHasherFn, leafCallback leafCallbackFn, stats *generateStats, report bool) (common.Hash, error) { + var ( + in = make(chan trieKV) // chan to pass leaves + out = make(chan common.Hash, 1) // chan to collect result + stoplog = make(chan bool, 1) // 1-size buffer, works when logging is not enabled + wg sync.WaitGroup + ) + // Spin up a go-routine for trie hash re-generation + wg.Add(1) + go func() { + defer wg.Done() + generatorFn(in, out) + }() + // Spin up a go-routine for progress logging + if report && stats != nil { + wg.Add(1) + go func() { + defer wg.Done() + runReport(stats, stoplog) + }() + } + // Create a semaphore to assign tasks and collect results through. We'll pre- + // fill it with nils, thus using the same channel for both limiting concurrent + // processing and gathering results. + threads := runtime.NumCPU() + results := make(chan error, threads) + for i := 0; i < threads; i++ { + results <- nil // fill the semaphore + } + // stop is a helper function to shutdown the background threads + // and return the re-generated trie hash. + stop := func(fail error) (common.Hash, error) { + close(in) + result := <-out + for i := 0; i < threads; i++ { + if err := <-results; err != nil && fail == nil { + fail = err + } + } + stoplog <- fail == nil + + wg.Wait() + return result, fail + } + var ( + logged = time.Now() + processed = uint64(0) + leaf trieKV + ) + // Start to feed leaves + for it.Next() { + if account == (common.Hash{}) { + var ( + err error + fullData []byte + ) + if leafCallback == nil { + fullData, err = types.FullAccountRLP(it.(AccountIterator).Account()) + if err != nil { + return stop(err) + } + } else { + // Wait until the semaphore allows us to continue, aborting if + // a sub-task failed + if err := <-results; err != nil { + results <- nil // stop will drain the results, add a noop back for this error we just consumed + return stop(err) + } + // Fetch the next account and process it concurrently + account, err := types.FullAccount(it.(AccountIterator).Account()) + if err != nil { + return stop(err) + } + go func(hash common.Hash) { + subroot, err := leafCallback(hash, common.BytesToHash(account.CodeHash), stats) + if err != nil { + results <- err + return + } + if account.Root != subroot { + results <- fmt.Errorf("invalid subroot(path %x), want %x, have %x", hash, account.Root, subroot) + return + } + results <- nil + }(it.Hash()) + fullData, err = rlp.EncodeToBytes(account) + if err != nil { + return stop(err) + } + } + leaf = trieKV{it.Hash(), fullData} + } else { + leaf = trieKV{it.Hash(), common.CopyBytes(it.(StorageIterator).Slot())} + } + in <- leaf + + // Accumulate the generation statistic if it's required. + processed++ + if time.Since(logged) > 3*time.Second && stats != nil { + if account == (common.Hash{}) { + stats.progressAccounts(it.Hash(), processed) + } else { + stats.progressContract(account, it.Hash(), processed) + } + logged, processed = time.Now(), 0 + } + } + // Commit the last part statistic. + if processed > 0 && stats != nil { + if account == (common.Hash{}) { + stats.finishAccounts(processed) + } else { + stats.finishContract(account, processed) + } + } + return stop(nil) +} + +func stackTrieHasher(in chan trieKV, out chan common.Hash) { + t := trie.NewStackTrie(nil) + for leaf := range in { + t.Update(leaf.key[:], leaf.value) + } + out <- t.Hash() +} diff --git a/version/version.go b/version/version.go index 51cf410cda73..ab1559d8aa87 100644 --- a/version/version.go +++ b/version/version.go @@ -18,7 +18,7 @@ package version const ( Major = 1 // Major version component of the current release - Minor = 15 // Minor version component of the current release - Patch = 12 // Patch version component of the current release + Minor = 16 // Minor version component of the current release + Patch = 2 // Patch version component of the current release Meta = "unstable" // Version metadata to append to the version string )