Merge commit '12b4131ff' into po/par_exe

This commit is contained in:
Po 2025-08-04 05:04:32 +02:00
commit 86a72911a7
353 changed files with 18682 additions and 6727 deletions

View file

@ -0,0 +1,27 @@
on:
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
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Run cleanup script
run: |
go run build/ci.go purge -store gethstore/builds -days 14
env:
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}

View file

@ -0,0 +1,46 @@
on:
push:
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
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Show environment
run: |
env
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Install deb toolchain
run: |
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot
- name: Add launchpad to known_hosts
run: |
echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts
- name: Run ci.go
run: |
go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>"
env:
PPA_SIGNING_KEY: ${{ secrets.PPA_SIGNING_KEY }}
PPA_SSH_KEY: ${{ secrets.PPA_SSH_KEY }}

View file

@ -0,0 +1,147 @@
on:
push:
branches:
- "master"
tags:
- "v*"
jobs:
linux-intel:
name: Linux Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Install cross toolchain
run: |
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
- name: Build (amd64)
run: |
go run build/ci.go install -static -arch amd64 -dlgo
- name: Create/upload archive (amd64)
run: |
go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -f build/bin/*
env:
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: Build (386)
run: |
go run build/ci.go install -static -arch 386 -dlgo
- name: Create/upload archive (386)
run: |
go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -f build/bin/*
env:
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
linux-arm:
name: Linux Build (arm)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Install cross toolchain
run: |
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends 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
ln -s /usr/include/asm-generic /usr/include/asm
- name: Build (arm64)
run: |
go run build/ci.go install -static -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
- name: Create/upload archive (arm64)
run: |
go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -fr build/bin/*
env:
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: Run build (arm5)
run: |
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
env:
GOARM: "5"
- name: Create/upload archive (arm5)
run: |
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
env:
GOARM: "5"
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: Run build (arm6)
run: |
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
env:
GOARM: "6"
- name: Create/upload archive (arm6)
run: |
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -fr build/bin/*
env:
GOARM: "6"
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: Run build (arm7)
run: |
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
env:
GOARM: "7"
- name: Create/upload archive (arm7)
run: |
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
rm -fr build/bin/*
env:
GOARM: "7"
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
docker:
name: Docker Image
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24
cache: false
- name: Run docker build
env:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
run: |
go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 -upload

View file

@ -1,115 +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
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 Linux Azure uploads
- stage: build
if: type = push
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
# These builders run the tests
- stage: build
if: type = push
os: linux
arch: amd64
dist: focal
go: 1.24.x
script:
- travis_wait 45 go run build/ci.go test $TEST_PACKAGES
- stage: build
if: type = push
os: linux
dist: focal
go: 1.23.x
script:
- travis_wait 45 go run build/ci.go test $TEST_PACKAGES
# This builder does the Ubuntu PPA nightly uploads
- stage: build
if: type = cron || (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 <geth-ci@ethereum.org>"
# 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
# This builder executes race tests
- stage: build
if: type = cron
os: linux
dist: focal
go: 1.24.x
env:
- racetests
script:
- travis_wait 60 go run build/ci.go test -race $TEST_PACKAGES

View file

@ -2,7 +2,7 @@
# with Go source code. If you know what GOPATH is then you probably # with Go source code. If you know what GOPATH is then you probably
# don't need to bother with make. # 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 GOBIN = ./build/bin
GO ?= latest GO ?= latest
@ -14,6 +14,12 @@ geth:
@echo "Done building." @echo "Done building."
@echo "Run \"$(GOBIN)/geth\" to launch geth." @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: Build all packages and executables.
all: all:
$(GORUN) build/ci.go install $(GORUN) build/ci.go install

View file

@ -162,7 +162,7 @@ accessible from the outside.
As a developer, sooner rather than later you'll want to start interacting with `geth` and the As a developer, sooner rather than later you'll want to start interacting with `geth` and the
Ethereum network via your own programs and not manually through the console. To aid Ethereum network via your own programs and not manually through the console. To aid
this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/) this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.org/en/developers/docs/apis/json-rpc/)
and [`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)). and [`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)).
These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based
platforms, and named pipes on Windows). platforms, and named pipes on Windows).

View file

@ -281,7 +281,7 @@ func TestBindingV2ConvertedV1Tests(t *testing.T) {
} }
// Set this environment variable to regenerate the test outputs. // Set this environment variable to regenerate the test outputs.
if os.Getenv("WRITE_TEST_FILES") != "" { 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) t.Fatalf("err writing expected output to file: %v\n", err)
} }
} }

View file

@ -90,7 +90,8 @@ var (
{{range .Calls}} {{range .Calls}}
// Pack{{.Normalized.Name}} is the Go binding used to pack the parameters required for calling // 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}} // Solidity: {{.Original.String}}
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Pack{{.Normalized.Name}}({{range .Normalized.Inputs}} {{.Name}} {{bindtype .Type $structs}}, {{end}}) []byte { 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 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 */}} {{/* Unpack method is needed only when there are return args */}}
{{if .Normalized.Outputs }} {{if .Normalized.Outputs }}
{{ if .Structured }} {{ if .Structured }}
@ -133,8 +143,7 @@ var (
outstruct.{{capitalise .Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}) outstruct.{{capitalise .Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}})
{{- end }} {{- end }}
{{- end }} {{- end }}
return *outstruct, err return *outstruct, nil{{else}}
{{else}}
if err != nil { if err != nil {
return {{range $i, $_ := .Normalized.Outputs}}{{if ispointertype .Type}}new({{underlyingbindtype .Type }}), {{else}}*new({{bindtype .Type $structs}}), {{end}}{{end}} err return {{range $i, $_ := .Normalized.Outputs}}{{if ispointertype .Type}}new({{underlyingbindtype .Type }}), {{else}}*new({{bindtype .Type $structs}}), {{end}}{{end}} err
} }
@ -145,7 +154,7 @@ var (
out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}) out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}})
{{- end }} {{- end }}
{{- end}} {{- end}}
return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} nil
{{- end}} {{- end}}
} }
{{end}} {{end}}

View file

@ -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 // 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() // Solidity: function test(function callback) returns()
func (callbackParam *CallbackParam) PackTest(callback [24]byte) []byte { func (callbackParam *CallbackParam) PackTest(callback [24]byte) []byte {
@ -62,3 +63,12 @@ func (callbackParam *CallbackParam) PackTest(callback [24]byte) []byte {
} }
return enc 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)
}

View file

@ -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 // 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) // Solidity: function amountRaised() returns(uint256)
func (crowdsale *Crowdsale) PackAmountRaised() []byte { func (crowdsale *Crowdsale) PackAmountRaised() []byte {
@ -75,6 +76,15 @@ func (crowdsale *Crowdsale) PackAmountRaised() []byte {
return enc 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 // UnpackAmountRaised is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x7b3e5e7b. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function beneficiary() returns(address)
func (crowdsale *Crowdsale) PackBeneficiary() []byte { func (crowdsale *Crowdsale) PackBeneficiary() []byte {
@ -100,6 +111,15 @@ func (crowdsale *Crowdsale) PackBeneficiary() []byte {
return enc 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 // UnpackBeneficiary is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x38af3eed. // 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 return *new(common.Address), err
} }
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) 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 // 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() // Solidity: function checkGoalReached() returns()
func (crowdsale *Crowdsale) PackCheckGoalReached() []byte { func (crowdsale *Crowdsale) PackCheckGoalReached() []byte {
@ -125,8 +146,18 @@ func (crowdsale *Crowdsale) PackCheckGoalReached() []byte {
return enc 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 // 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) // Solidity: function deadline() returns(uint256)
func (crowdsale *Crowdsale) PackDeadline() []byte { func (crowdsale *Crowdsale) PackDeadline() []byte {
@ -137,6 +168,15 @@ func (crowdsale *Crowdsale) PackDeadline() []byte {
return enc 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 // UnpackDeadline is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x29dcb0cf. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function funders(uint256 ) returns(address addr, uint256 amount)
func (crowdsale *Crowdsale) PackFunders(arg0 *big.Int) []byte { func (crowdsale *Crowdsale) PackFunders(arg0 *big.Int) []byte {
@ -162,6 +203,15 @@ func (crowdsale *Crowdsale) PackFunders(arg0 *big.Int) []byte {
return enc 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 // FundersOutput serves as a container for the return parameters of contract
// method Funders. // method Funders.
type FundersOutput struct { 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.Addr = *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
outstruct.Amount = abi.ConvertType(out[1], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function fundingGoal() returns(uint256)
func (crowdsale *Crowdsale) PackFundingGoal() []byte { func (crowdsale *Crowdsale) PackFundingGoal() []byte {
@ -197,6 +247,15 @@ func (crowdsale *Crowdsale) PackFundingGoal() []byte {
return enc 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 // UnpackFundingGoal is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x7a3a0e84. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function price() returns(uint256)
func (crowdsale *Crowdsale) PackPrice() []byte { func (crowdsale *Crowdsale) PackPrice() []byte {
@ -222,6 +282,15 @@ func (crowdsale *Crowdsale) PackPrice() []byte {
return enc 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 // UnpackPrice is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xa035b1fe. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function tokenReward() returns(address)
func (crowdsale *Crowdsale) PackTokenReward() []byte { func (crowdsale *Crowdsale) PackTokenReward() []byte {
@ -247,6 +317,15 @@ func (crowdsale *Crowdsale) PackTokenReward() []byte {
return enc 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 // UnpackTokenReward is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x6e66f6e9. // 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 return *new(common.Address), err
} }
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) 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. // CrowdsaleFundTransfer represents a FundTransfer event raised by the Crowdsale contract.

View file

@ -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 // 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() // Solidity: function changeMembership(address targetMember, bool canVote, string memberName) returns()
func (dAO *DAO) PackChangeMembership(targetMember common.Address, canVote bool, memberName string) []byte { 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 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 // 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() // Solidity: function changeVotingRules(uint256 minimumQuorumForProposals, uint256 minutesForDebate, int256 marginOfVotesForMajority) returns()
func (dAO *DAO) PackChangeVotingRules(minimumQuorumForProposals *big.Int, minutesForDebate *big.Int, marginOfVotesForMajority *big.Int) []byte { 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 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 // 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) // 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 { 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 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 // UnpackCheckProposalCode is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xeceb2945. // from invoking the contract method with ID 0xeceb2945.
// //
@ -109,11 +139,12 @@ func (dAO *DAO) UnpackCheckProposalCode(data []byte) (bool, error) {
return *new(bool), err return *new(bool), err
} }
out0 := *abi.ConvertType(out[0], new(bool)).(*bool) 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 // 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) // Solidity: function debatingPeriodInMinutes() returns(uint256)
func (dAO *DAO) PackDebatingPeriodInMinutes() []byte { func (dAO *DAO) PackDebatingPeriodInMinutes() []byte {
@ -124,6 +155,15 @@ func (dAO *DAO) PackDebatingPeriodInMinutes() []byte {
return enc 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 // UnpackDebatingPeriodInMinutes is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x69bd3436. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function executeProposal(uint256 proposalNumber, bytes transactionBytecode) returns(int256 result)
func (dAO *DAO) PackExecuteProposal(proposalNumber *big.Int, transactionBytecode []byte) []byte { func (dAO *DAO) PackExecuteProposal(proposalNumber *big.Int, transactionBytecode []byte) []byte {
@ -149,6 +190,15 @@ func (dAO *DAO) PackExecuteProposal(proposalNumber *big.Int, transactionBytecode
return enc 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 // UnpackExecuteProposal is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x237e9492. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function majorityMargin() returns(int256)
func (dAO *DAO) PackMajorityMargin() []byte { func (dAO *DAO) PackMajorityMargin() []byte {
@ -174,6 +225,15 @@ func (dAO *DAO) PackMajorityMargin() []byte {
return enc 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 // UnpackMajorityMargin is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xaa02a90f. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function memberId(address ) returns(uint256)
func (dAO *DAO) PackMemberId(arg0 common.Address) []byte { func (dAO *DAO) PackMemberId(arg0 common.Address) []byte {
@ -199,6 +260,15 @@ func (dAO *DAO) PackMemberId(arg0 common.Address) []byte {
return enc 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 // UnpackMemberId is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x39106821. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function members(uint256 ) returns(address member, bool canVote, string name, uint256 memberSince)
func (dAO *DAO) PackMembers(arg0 *big.Int) []byte { func (dAO *DAO) PackMembers(arg0 *big.Int) []byte {
@ -224,6 +295,15 @@ func (dAO *DAO) PackMembers(arg0 *big.Int) []byte {
return enc 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 // MembersOutput serves as a container for the return parameters of contract
// method Members. // method Members.
type MembersOutput struct { 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.CanVote = *abi.ConvertType(out[1], new(bool)).(*bool)
outstruct.Name = *abi.ConvertType(out[2], new(string)).(*string) outstruct.Name = *abi.ConvertType(out[2], new(string)).(*string)
outstruct.MemberSince = abi.ConvertType(out[3], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function minimumQuorum() returns(uint256)
func (dAO *DAO) PackMinimumQuorum() []byte { func (dAO *DAO) PackMinimumQuorum() []byte {
@ -263,6 +343,15 @@ func (dAO *DAO) PackMinimumQuorum() []byte {
return enc 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 // UnpackMinimumQuorum is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x8160f0b5. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // 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 { 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 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 // UnpackNewProposal is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xb1050da5. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function numProposals() returns(uint256)
func (dAO *DAO) PackNumProposals() []byte { func (dAO *DAO) PackNumProposals() []byte {
@ -313,6 +413,15 @@ func (dAO *DAO) PackNumProposals() []byte {
return enc 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 // UnpackNumProposals is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x400e3949. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function owner() returns(address)
func (dAO *DAO) PackOwner() []byte { func (dAO *DAO) PackOwner() []byte {
@ -338,6 +448,15 @@ func (dAO *DAO) PackOwner() []byte {
return enc 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 // UnpackOwner is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x8da5cb5b. // 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 return *new(common.Address), err
} }
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) 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 // 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) // 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 { func (dAO *DAO) PackProposals(arg0 *big.Int) []byte {
@ -363,6 +483,15 @@ func (dAO *DAO) PackProposals(arg0 *big.Int) []byte {
return enc 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 // ProposalsOutput serves as a container for the return parameters of contract
// method Proposals. // method Proposals.
type ProposalsOutput struct { 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.NumberOfVotes = abi.ConvertType(out[6], new(big.Int)).(*big.Int)
outstruct.CurrentResult = abi.ConvertType(out[7], 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) 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 // 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() // Solidity: function transferOwnership(address newOwner) returns()
func (dAO *DAO) PackTransferOwnership(newOwner common.Address) []byte { func (dAO *DAO) PackTransferOwnership(newOwner common.Address) []byte {
@ -412,8 +541,18 @@ func (dAO *DAO) PackTransferOwnership(newOwner common.Address) []byte {
return enc 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 // 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) // Solidity: function vote(uint256 proposalNumber, bool supportsProposal, string justificationText) returns(uint256 voteID)
func (dAO *DAO) PackVote(proposalNumber *big.Int, supportsProposal bool, justificationText string) []byte { 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 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 // UnpackVote is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xd3c0715b. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // DAOChangeOfRules represents a ChangeOfRules event raised by the DAO contract.

View file

@ -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 // 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) // Solidity: function deepUint64Array(uint256 , uint256 , uint256 ) view returns(uint64)
func (deeplyNestedArray *DeeplyNestedArray) PackDeepUint64Array(arg0 *big.Int, arg1 *big.Int, arg2 *big.Int) []byte { 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 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 // UnpackDeepUint64Array is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x98ed1856. // from invoking the contract method with ID 0x98ed1856.
// //
@ -73,11 +83,12 @@ func (deeplyNestedArray *DeeplyNestedArray) UnpackDeepUint64Array(data []byte) (
return *new(uint64), err return *new(uint64), err
} }
out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) 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 // 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]) // Solidity: function retrieveDeepArray() view returns(uint64[3][4][5])
func (deeplyNestedArray *DeeplyNestedArray) PackRetrieveDeepArray() []byte { func (deeplyNestedArray *DeeplyNestedArray) PackRetrieveDeepArray() []byte {
@ -88,6 +99,15 @@ func (deeplyNestedArray *DeeplyNestedArray) PackRetrieveDeepArray() []byte {
return enc 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 // UnpackRetrieveDeepArray is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x8ed4573a. // 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 return *new([5][4][3]uint64), err
} }
out0 := *abi.ConvertType(out[0], new([5][4][3]uint64)).(*[5][4][3]uint64) 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 // 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() // Solidity: function storeDeepUintArray(uint64[3][4][5] arr) returns()
func (deeplyNestedArray *DeeplyNestedArray) PackStoreDeepUintArray(arr [5][4][3]uint64) []byte { func (deeplyNestedArray *DeeplyNestedArray) PackStoreDeepUintArray(arr [5][4][3]uint64) []byte {
@ -112,3 +133,12 @@ func (deeplyNestedArray *DeeplyNestedArray) PackStoreDeepUintArray(arr [5][4][3]
} }
return enc 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)
}

View file

@ -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 // 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) // Solidity: function getter() returns(string, int256, bytes32)
func (getter *Getter) PackGetter() []byte { func (getter *Getter) PackGetter() []byte {
@ -63,6 +64,15 @@ func (getter *Getter) PackGetter() []byte {
return enc 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 // GetterOutput serves as a container for the return parameters of contract
// method Getter. // method Getter.
type GetterOutput struct { 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.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int) outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
outstruct.Arg2 = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) outstruct.Arg2 = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte)
return *outstruct, err return *outstruct, nil
} }

View file

@ -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 // 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) // Solidity: function MyVar() view returns(uint256)
func (identifierCollision *IdentifierCollision) PackMyVar() []byte { func (identifierCollision *IdentifierCollision) PackMyVar() []byte {
@ -63,6 +64,15 @@ func (identifierCollision *IdentifierCollision) PackMyVar() []byte {
return enc 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 // UnpackMyVar is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x4ef1f0ad. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function _myVar() view returns(uint256)
func (identifierCollision *IdentifierCollision) PackPubVar() []byte { func (identifierCollision *IdentifierCollision) PackPubVar() []byte {
@ -88,6 +99,15 @@ func (identifierCollision *IdentifierCollision) PackPubVar() []byte {
return enc 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 // UnpackPubVar is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x01ad4d87. // from invoking the contract method with ID 0x01ad4d87.
// //
@ -98,5 +118,5 @@ func (identifierCollision *IdentifierCollision) UnpackPubVar(data []byte) (*big.
return new(big.Int), err return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, err return out0, nil
} }

View file

@ -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 // 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() // Solidity: function anonInput(string ) returns()
func (inputChecker *InputChecker) PackAnonInput(arg0 string) []byte { func (inputChecker *InputChecker) PackAnonInput(arg0 string) []byte {
@ -62,8 +63,18 @@ func (inputChecker *InputChecker) PackAnonInput(arg0 string) []byte {
return enc 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 // 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() // Solidity: function anonInputs(string , string ) returns()
func (inputChecker *InputChecker) PackAnonInputs(arg0 string, arg1 string) []byte { func (inputChecker *InputChecker) PackAnonInputs(arg0 string, arg1 string) []byte {
@ -74,8 +85,18 @@ func (inputChecker *InputChecker) PackAnonInputs(arg0 string, arg1 string) []byt
return enc 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 // 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() // Solidity: function mixedInputs(string , string str) returns()
func (inputChecker *InputChecker) PackMixedInputs(arg0 string, str string) []byte { func (inputChecker *InputChecker) PackMixedInputs(arg0 string, str string) []byte {
@ -86,8 +107,18 @@ func (inputChecker *InputChecker) PackMixedInputs(arg0 string, str string) []byt
return enc 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 // 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() // Solidity: function namedInput(string str) returns()
func (inputChecker *InputChecker) PackNamedInput(str string) []byte { func (inputChecker *InputChecker) PackNamedInput(str string) []byte {
@ -98,8 +129,18 @@ func (inputChecker *InputChecker) PackNamedInput(str string) []byte {
return enc 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 // 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() // Solidity: function namedInputs(string str1, string str2) returns()
func (inputChecker *InputChecker) PackNamedInputs(str1 string, str2 string) []byte { func (inputChecker *InputChecker) PackNamedInputs(str1 string, str2 string) []byte {
@ -110,8 +151,18 @@ func (inputChecker *InputChecker) PackNamedInputs(str1 string, str2 string) []by
return enc 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 // 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() // Solidity: function noInput() returns()
func (inputChecker *InputChecker) PackNoInput() []byte { func (inputChecker *InputChecker) PackNoInput() []byte {
@ -121,3 +172,12 @@ func (inputChecker *InputChecker) PackNoInput() []byte {
} }
return enc 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")
}

View file

@ -64,7 +64,8 @@ func (interactor *Interactor) PackConstructor(str string) []byte {
} }
// PackDeployString is the Go binding used to pack the parameters required for calling // 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) // Solidity: function deployString() returns(string)
func (interactor *Interactor) PackDeployString() []byte { func (interactor *Interactor) PackDeployString() []byte {
@ -75,6 +76,15 @@ func (interactor *Interactor) PackDeployString() []byte {
return enc 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 // UnpackDeployString is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x6874e809. // from invoking the contract method with ID 0x6874e809.
// //
@ -85,11 +95,12 @@ func (interactor *Interactor) UnpackDeployString(data []byte) (string, error) {
return *new(string), err return *new(string), err
} }
out0 := *abi.ConvertType(out[0], new(string)).(*string) 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 // 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() // Solidity: function transact(string str) returns()
func (interactor *Interactor) PackTransact(str string) []byte { func (interactor *Interactor) PackTransact(str string) []byte {
@ -100,8 +111,18 @@ func (interactor *Interactor) PackTransact(str string) []byte {
return enc 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 // 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) // Solidity: function transactString() returns(string)
func (interactor *Interactor) PackTransactString() []byte { func (interactor *Interactor) PackTransactString() []byte {
@ -112,6 +133,15 @@ func (interactor *Interactor) PackTransactString() []byte {
return enc 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 // UnpackTransactString is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x0d86a0e1. // from invoking the contract method with ID 0x0d86a0e1.
// //
@ -122,5 +152,5 @@ func (interactor *Interactor) UnpackTransactString(data []byte) (string, error)
return *new(string), err return *new(string), err
} }
out0 := *abi.ConvertType(out[0], new(string)).(*string) out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, err return out0, nil
} }

View file

@ -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 // 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() // Solidity: function addRequest((bytes,bytes) req) pure returns()
func (nameConflict *NameConflict) PackAddRequest(req Oraclerequest) []byte { func (nameConflict *NameConflict) PackAddRequest(req Oraclerequest) []byte {
@ -69,8 +70,18 @@ func (nameConflict *NameConflict) PackAddRequest(req Oraclerequest) []byte {
return enc 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 // 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)) // Solidity: function getRequest() pure returns((bytes,bytes))
func (nameConflict *NameConflict) PackGetRequest() []byte { func (nameConflict *NameConflict) PackGetRequest() []byte {
@ -81,6 +92,15 @@ func (nameConflict *NameConflict) PackGetRequest() []byte {
return enc 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 // UnpackGetRequest is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xc2bb515f. // from invoking the contract method with ID 0xc2bb515f.
// //
@ -91,7 +111,7 @@ func (nameConflict *NameConflict) UnpackGetRequest(data []byte) (Oraclerequest,
return *new(Oraclerequest), err return *new(Oraclerequest), err
} }
out0 := *abi.ConvertType(out[0], new(Oraclerequest)).(*Oraclerequest) out0 := *abi.ConvertType(out[0], new(Oraclerequest)).(*Oraclerequest)
return out0, err return out0, nil
} }
// NameConflictLog represents a log event raised by the NameConflict contract. // NameConflictLog represents a log event raised by the NameConflict contract.

View file

@ -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 // 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() // Solidity: function _1test() pure returns()
func (numericMethodName *NumericMethodName) PackE1test() []byte { func (numericMethodName *NumericMethodName) PackE1test() []byte {
@ -63,8 +64,18 @@ func (numericMethodName *NumericMethodName) PackE1test() []byte {
return enc 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 // 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() // Solidity: function __1test() pure returns()
func (numericMethodName *NumericMethodName) PackE1test0() []byte { func (numericMethodName *NumericMethodName) PackE1test0() []byte {
@ -75,8 +86,18 @@ func (numericMethodName *NumericMethodName) PackE1test0() []byte {
return enc 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 // 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() // Solidity: function __2test() pure returns()
func (numericMethodName *NumericMethodName) PackE2test() []byte { func (numericMethodName *NumericMethodName) PackE2test() []byte {
@ -87,6 +108,15 @@ func (numericMethodName *NumericMethodName) PackE2test() []byte {
return enc 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. // NumericMethodNameE1TestEvent represents a _1TestEvent event raised by the NumericMethodName contract.
type NumericMethodNameE1TestEvent struct { type NumericMethodNameE1TestEvent struct {
Param common.Address Param common.Address

View file

@ -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 // 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) // Solidity: function anonOutput() returns(string)
func (outputChecker *OutputChecker) PackAnonOutput() []byte { func (outputChecker *OutputChecker) PackAnonOutput() []byte {
@ -62,6 +63,15 @@ func (outputChecker *OutputChecker) PackAnonOutput() []byte {
return enc 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 // UnpackAnonOutput is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x008bda05. // from invoking the contract method with ID 0x008bda05.
// //
@ -72,11 +82,12 @@ func (outputChecker *OutputChecker) UnpackAnonOutput(data []byte) (string, error
return *new(string), err return *new(string), err
} }
out0 := *abi.ConvertType(out[0], new(string)).(*string) 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 // 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) // Solidity: function anonOutputs() returns(string, string)
func (outputChecker *OutputChecker) PackAnonOutputs() []byte { func (outputChecker *OutputChecker) PackAnonOutputs() []byte {
@ -87,6 +98,15 @@ func (outputChecker *OutputChecker) PackAnonOutputs() []byte {
return enc 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 // AnonOutputsOutput serves as a container for the return parameters of contract
// method AnonOutputs. // method AnonOutputs.
type AnonOutputsOutput struct { type AnonOutputsOutput struct {
@ -106,12 +126,12 @@ func (outputChecker *OutputChecker) UnpackAnonOutputs(data []byte) (AnonOutputsO
} }
outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Arg1 = *abi.ConvertType(out[1], 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 // 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) // Solidity: function collidingOutputs() returns(string str, string Str)
func (outputChecker *OutputChecker) PackCollidingOutputs() []byte { func (outputChecker *OutputChecker) PackCollidingOutputs() []byte {
@ -122,6 +142,15 @@ func (outputChecker *OutputChecker) PackCollidingOutputs() []byte {
return enc 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 // CollidingOutputsOutput serves as a container for the return parameters of contract
// method CollidingOutputs. // method CollidingOutputs.
type CollidingOutputsOutput struct { type CollidingOutputsOutput struct {
@ -141,12 +170,12 @@ func (outputChecker *OutputChecker) UnpackCollidingOutputs(data []byte) (Collidi
} }
outstruct.Str = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Str = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Str0 = *abi.ConvertType(out[1], 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 // 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) // Solidity: function mixedOutputs() returns(string, string str)
func (outputChecker *OutputChecker) PackMixedOutputs() []byte { func (outputChecker *OutputChecker) PackMixedOutputs() []byte {
@ -157,6 +186,15 @@ func (outputChecker *OutputChecker) PackMixedOutputs() []byte {
return enc 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 // MixedOutputsOutput serves as a container for the return parameters of contract
// method MixedOutputs. // method MixedOutputs.
type MixedOutputsOutput struct { type MixedOutputsOutput struct {
@ -176,12 +214,12 @@ func (outputChecker *OutputChecker) UnpackMixedOutputs(data []byte) (MixedOutput
} }
outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Str = *abi.ConvertType(out[1], 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 // 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) // Solidity: function namedOutput() returns(string str)
func (outputChecker *OutputChecker) PackNamedOutput() []byte { func (outputChecker *OutputChecker) PackNamedOutput() []byte {
@ -192,6 +230,15 @@ func (outputChecker *OutputChecker) PackNamedOutput() []byte {
return enc 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 // UnpackNamedOutput is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x5e632bd5. // from invoking the contract method with ID 0x5e632bd5.
// //
@ -202,11 +249,12 @@ func (outputChecker *OutputChecker) UnpackNamedOutput(data []byte) (string, erro
return *new(string), err return *new(string), err
} }
out0 := *abi.ConvertType(out[0], new(string)).(*string) 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 // 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) // Solidity: function namedOutputs() returns(string str1, string str2)
func (outputChecker *OutputChecker) PackNamedOutputs() []byte { func (outputChecker *OutputChecker) PackNamedOutputs() []byte {
@ -217,6 +265,15 @@ func (outputChecker *OutputChecker) PackNamedOutputs() []byte {
return enc 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 // NamedOutputsOutput serves as a container for the return parameters of contract
// method NamedOutputs. // method NamedOutputs.
type NamedOutputsOutput struct { type NamedOutputsOutput struct {
@ -236,12 +293,12 @@ func (outputChecker *OutputChecker) UnpackNamedOutputs(data []byte) (NamedOutput
} }
outstruct.Str1 = *abi.ConvertType(out[0], new(string)).(*string) outstruct.Str1 = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.Str2 = *abi.ConvertType(out[1], 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 // 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() // Solidity: function noOutput() returns()
func (outputChecker *OutputChecker) PackNoOutput() []byte { func (outputChecker *OutputChecker) PackNoOutput() []byte {
@ -251,3 +308,12 @@ func (outputChecker *OutputChecker) PackNoOutput() []byte {
} }
return enc 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")
}

View file

@ -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 // 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() // Solidity: function foo(uint256 i, uint256 j) returns()
func (overload *Overload) PackFoo(i *big.Int, j *big.Int) []byte { 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 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 // 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() // Solidity: function foo(uint256 i) returns()
func (overload *Overload) PackFoo0(i *big.Int) []byte { func (overload *Overload) PackFoo0(i *big.Int) []byte {
@ -75,6 +86,15 @@ func (overload *Overload) PackFoo0(i *big.Int) []byte {
return enc 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. // OverloadBar represents a bar event raised by the Overload contract.
type OverloadBar struct { type OverloadBar struct {
I *big.Int I *big.Int

View file

@ -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 // 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() // Solidity: function functionWithKeywordParameter(uint256 range) pure returns()
func (rangeKeyword *RangeKeyword) PackFunctionWithKeywordParameter(arg0 *big.Int) []byte { func (rangeKeyword *RangeKeyword) PackFunctionWithKeywordParameter(arg0 *big.Int) []byte {
@ -62,3 +63,12 @@ func (rangeKeyword *RangeKeyword) PackFunctionWithKeywordParameter(arg0 *big.Int
} }
return enc 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)
}

View file

@ -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 // 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) // Solidity: function echoAddresses(address[] input) returns(address[] output)
func (slicer *Slicer) PackEchoAddresses(input []common.Address) []byte { func (slicer *Slicer) PackEchoAddresses(input []common.Address) []byte {
@ -63,6 +64,15 @@ func (slicer *Slicer) PackEchoAddresses(input []common.Address) []byte {
return enc 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 // UnpackEchoAddresses is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xbe1127a3. // 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 return *new([]common.Address), err
} }
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) 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 // 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) // Solidity: function echoBools(bool[] input) returns(bool[] output)
func (slicer *Slicer) PackEchoBools(input []bool) []byte { func (slicer *Slicer) PackEchoBools(input []bool) []byte {
@ -88,6 +99,15 @@ func (slicer *Slicer) PackEchoBools(input []bool) []byte {
return enc 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 // UnpackEchoBools is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xf637e589. // from invoking the contract method with ID 0xf637e589.
// //
@ -98,11 +118,12 @@ func (slicer *Slicer) UnpackEchoBools(data []byte) ([]bool, error) {
return *new([]bool), err return *new([]bool), err
} }
out0 := *abi.ConvertType(out[0], new([]bool)).(*[]bool) 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 // 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) // Solidity: function echoFancyInts(uint24[23] input) returns(uint24[23] output)
func (slicer *Slicer) PackEchoFancyInts(input [23]*big.Int) []byte { func (slicer *Slicer) PackEchoFancyInts(input [23]*big.Int) []byte {
@ -113,6 +134,15 @@ func (slicer *Slicer) PackEchoFancyInts(input [23]*big.Int) []byte {
return enc 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 // UnpackEchoFancyInts is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xd88becc0. // 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 return *new([23]*big.Int), err
} }
out0 := *abi.ConvertType(out[0], new([23]*big.Int)).(*[23]*big.Int) 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 // 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) // Solidity: function echoInts(int256[] input) returns(int256[] output)
func (slicer *Slicer) PackEchoInts(input []*big.Int) []byte { func (slicer *Slicer) PackEchoInts(input []*big.Int) []byte {
@ -138,6 +169,15 @@ func (slicer *Slicer) PackEchoInts(input []*big.Int) []byte {
return enc 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 // UnpackEchoInts is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xe15a3db7. // 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 return *new([]*big.Int), err
} }
out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int)
return out0, err return out0, nil
} }

View file

@ -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 // 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) // Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
func (structs *Structs) PackF() []byte { func (structs *Structs) PackF() []byte {
@ -68,6 +69,15 @@ func (structs *Structs) PackF() []byte {
return enc 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 // FOutput serves as a container for the return parameters of contract
// method F. // method F.
type FOutput struct { 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.A = *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
outstruct.C = *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int) outstruct.C = *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int)
outstruct.D = *abi.ConvertType(out[2], new([]bool)).(*[]bool) 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 // 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) // Solidity: function G() view returns((bytes32)[] a)
func (structs *Structs) PackG() []byte { func (structs *Structs) PackG() []byte {
@ -105,6 +115,15 @@ func (structs *Structs) PackG() []byte {
return enc 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 // UnpackG is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x6fecb623. // from invoking the contract method with ID 0x6fecb623.
// //
@ -115,5 +134,5 @@ func (structs *Structs) UnpackG(data []byte) ([]Struct0, error) {
return *new([]Struct0), err return *new([]Struct0), err
} }
out0 := *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0) out0 := *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
return out0, err return out0, nil
} }

View file

@ -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 // 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) // Solidity: function allowance(address , address ) returns(uint256)
func (token *Token) PackAllowance(arg0 common.Address, arg1 common.Address) []byte { 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 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 // UnpackAllowance is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xdd62ed3e. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // 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 { 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 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 // UnpackApproveAndCall is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xcae9ca51. // from invoking the contract method with ID 0xcae9ca51.
// //
@ -110,11 +130,12 @@ func (token *Token) UnpackApproveAndCall(data []byte) (bool, error) {
return *new(bool), err return *new(bool), err
} }
out0 := *abi.ConvertType(out[0], new(bool)).(*bool) 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 // 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) // Solidity: function balanceOf(address ) returns(uint256)
func (token *Token) PackBalanceOf(arg0 common.Address) []byte { func (token *Token) PackBalanceOf(arg0 common.Address) []byte {
@ -125,6 +146,15 @@ func (token *Token) PackBalanceOf(arg0 common.Address) []byte {
return enc 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 // UnpackBalanceOf is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x70a08231. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function decimals() returns(uint8)
func (token *Token) PackDecimals() []byte { func (token *Token) PackDecimals() []byte {
@ -150,6 +181,15 @@ func (token *Token) PackDecimals() []byte {
return enc 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 // UnpackDecimals is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x313ce567. // from invoking the contract method with ID 0x313ce567.
// //
@ -160,11 +200,12 @@ func (token *Token) UnpackDecimals(data []byte) (uint8, error) {
return *new(uint8), err return *new(uint8), err
} }
out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) 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 // 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) // Solidity: function name() returns(string)
func (token *Token) PackName() []byte { func (token *Token) PackName() []byte {
@ -175,6 +216,15 @@ func (token *Token) PackName() []byte {
return enc 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 // UnpackName is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x06fdde03. // from invoking the contract method with ID 0x06fdde03.
// //
@ -185,11 +235,12 @@ func (token *Token) UnpackName(data []byte) (string, error) {
return *new(string), err return *new(string), err
} }
out0 := *abi.ConvertType(out[0], new(string)).(*string) 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 // 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) // Solidity: function spentAllowance(address , address ) returns(uint256)
func (token *Token) PackSpentAllowance(arg0 common.Address, arg1 common.Address) []byte { 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 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 // UnpackSpentAllowance is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xdc3080f2. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function symbol() returns(string)
func (token *Token) PackSymbol() []byte { func (token *Token) PackSymbol() []byte {
@ -225,6 +286,15 @@ func (token *Token) PackSymbol() []byte {
return enc 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 // UnpackSymbol is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x95d89b41. // from invoking the contract method with ID 0x95d89b41.
// //
@ -235,11 +305,12 @@ func (token *Token) UnpackSymbol(data []byte) (string, error) {
return *new(string), err return *new(string), err
} }
out0 := *abi.ConvertType(out[0], new(string)).(*string) 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 // 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() // Solidity: function transfer(address _to, uint256 _value) returns()
func (token *Token) PackTransfer(to common.Address, value *big.Int) []byte { 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 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 // 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) // 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 { 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 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 // UnpackTransferFrom is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x23b872dd. // from invoking the contract method with ID 0x23b872dd.
// //
@ -272,7 +362,7 @@ func (token *Token) UnpackTransferFrom(data []byte) (bool, error) {
return *new(bool), err return *new(bool), err
} }
out0 := *abi.ConvertType(out[0], new(bool)).(*bool) out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err return out0, nil
} }
// TokenTransfer represents a Transfer event raised by the Token contract. // TokenTransfer represents a Transfer event raised by the Token contract.

View file

@ -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 // 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[]) // 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 { 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 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 // Func1Output serves as a container for the return parameters of contract
// method Func1. // method Func1.
type Func1Output struct { 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.Arg2 = *abi.ConvertType(out[2], new([2][]TupleT)).(*[2][]TupleT)
outstruct.Arg3 = *abi.ConvertType(out[3], new([]TupleS)).(*[]TupleS) outstruct.Arg3 = *abi.ConvertType(out[3], new([]TupleS)).(*[]TupleS)
outstruct.Arg4 = *abi.ConvertType(out[4], new([]*big.Int)).(*[]*big.Int) 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 // 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() // 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 { 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 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 // 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() // Solidity: function func3((uint16,uint16)[] ) pure returns()
func (tuple *Tuple) PackFunc3(arg0 []TupleQ) []byte { func (tuple *Tuple) PackFunc3(arg0 []TupleQ) []byte {
@ -141,6 +161,15 @@ func (tuple *Tuple) PackFunc3(arg0 []TupleQ) []byte {
return enc 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. // TupleTupleEvent represents a TupleEvent event raised by the Tuple contract.
type TupleTupleEvent struct { type TupleTupleEvent struct {
A TupleS A TupleS

View file

@ -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 // 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) // Solidity: function tuple() returns(string a, int256 b, bytes32 c)
func (tupler *Tupler) PackTuple() []byte { func (tupler *Tupler) PackTuple() []byte {
@ -63,6 +64,15 @@ func (tupler *Tupler) PackTuple() []byte {
return enc 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 // TupleOutput serves as a container for the return parameters of contract
// method Tuple. // method Tuple.
type TupleOutput struct { 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.A = *abi.ConvertType(out[0], new(string)).(*string)
outstruct.B = abi.ConvertType(out[1], new(big.Int)).(*big.Int) outstruct.B = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
outstruct.C = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) outstruct.C = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte)
return *outstruct, err return *outstruct, nil
} }

View file

@ -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 // 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 __) // Solidity: function AllPurelyUnderscoredOutput() view returns(int256 _, int256 __)
func (underscorer *Underscorer) PackAllPurelyUnderscoredOutput() []byte { func (underscorer *Underscorer) PackAllPurelyUnderscoredOutput() []byte {
@ -63,6 +64,15 @@ func (underscorer *Underscorer) PackAllPurelyUnderscoredOutput() []byte {
return enc 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 // AllPurelyUnderscoredOutputOutput serves as a container for the return parameters of contract
// method AllPurelyUnderscoredOutput. // method AllPurelyUnderscoredOutput.
type AllPurelyUnderscoredOutputOutput struct { 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.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Arg1 = abi.ConvertType(out[1], 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 // 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) // Solidity: function LowerLowerCollision() view returns(int256 _res, int256 res)
func (underscorer *Underscorer) PackLowerLowerCollision() []byte { func (underscorer *Underscorer) PackLowerLowerCollision() []byte {
@ -98,6 +108,15 @@ func (underscorer *Underscorer) PackLowerLowerCollision() []byte {
return enc 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 // LowerLowerCollisionOutput serves as a container for the return parameters of contract
// method LowerLowerCollision. // method LowerLowerCollision.
type LowerLowerCollisionOutput struct { 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.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res0 = abi.ConvertType(out[1], 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 // 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) // Solidity: function LowerUpperCollision() view returns(int256 _res, int256 Res)
func (underscorer *Underscorer) PackLowerUpperCollision() []byte { func (underscorer *Underscorer) PackLowerUpperCollision() []byte {
@ -133,6 +152,15 @@ func (underscorer *Underscorer) PackLowerUpperCollision() []byte {
return enc 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 // LowerUpperCollisionOutput serves as a container for the return parameters of contract
// method LowerUpperCollision. // method LowerUpperCollision.
type LowerUpperCollisionOutput struct { 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.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res0 = abi.ConvertType(out[1], 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 // 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) // Solidity: function PurelyUnderscoredOutput() view returns(int256 _, int256 res)
func (underscorer *Underscorer) PackPurelyUnderscoredOutput() []byte { func (underscorer *Underscorer) PackPurelyUnderscoredOutput() []byte {
@ -168,6 +196,15 @@ func (underscorer *Underscorer) PackPurelyUnderscoredOutput() []byte {
return enc 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 // PurelyUnderscoredOutputOutput serves as a container for the return parameters of contract
// method PurelyUnderscoredOutput. // method PurelyUnderscoredOutput.
type PurelyUnderscoredOutputOutput struct { 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.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res = abi.ConvertType(out[1], 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 // 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) // Solidity: function UnderscoredOutput() view returns(int256 _int, string _string)
func (underscorer *Underscorer) PackUnderscoredOutput() []byte { func (underscorer *Underscorer) PackUnderscoredOutput() []byte {
@ -203,6 +240,15 @@ func (underscorer *Underscorer) PackUnderscoredOutput() []byte {
return enc 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 // UnderscoredOutputOutput serves as a container for the return parameters of contract
// method UnderscoredOutput. // method UnderscoredOutput.
type UnderscoredOutputOutput struct { 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.Int = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.String = *abi.ConvertType(out[1], new(string)).(*string) 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 // 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) // Solidity: function UpperLowerCollision() view returns(int256 _Res, int256 res)
func (underscorer *Underscorer) PackUpperLowerCollision() []byte { func (underscorer *Underscorer) PackUpperLowerCollision() []byte {
@ -238,6 +284,15 @@ func (underscorer *Underscorer) PackUpperLowerCollision() []byte {
return enc 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 // UpperLowerCollisionOutput serves as a container for the return parameters of contract
// method UpperLowerCollision. // method UpperLowerCollision.
type UpperLowerCollisionOutput struct { 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.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res0 = abi.ConvertType(out[1], 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 // 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) // Solidity: function UpperUpperCollision() view returns(int256 _Res, int256 Res)
func (underscorer *Underscorer) PackUpperUpperCollision() []byte { func (underscorer *Underscorer) PackUpperUpperCollision() []byte {
@ -273,6 +328,15 @@ func (underscorer *Underscorer) PackUpperUpperCollision() []byte {
return enc 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 // UpperUpperCollisionOutput serves as a container for the return parameters of contract
// method UpperUpperCollision. // method UpperUpperCollision.
type UpperUpperCollisionOutput struct { 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.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Res0 = abi.ConvertType(out[1], 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 // 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) // Solidity: function _under_scored_func() view returns(int256 _int)
func (underscorer *Underscorer) PackUnderScoredFunc() []byte { func (underscorer *Underscorer) PackUnderScoredFunc() []byte {
@ -308,6 +372,15 @@ func (underscorer *Underscorer) PackUnderScoredFunc() []byte {
return enc 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 // UnpackUnderScoredFunc is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x46546dbe. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, err return out0, nil
} }

View file

@ -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 // 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) // Solidity: function get(uint256 k) returns(uint256)
func (dB *DB) PackGet(k *big.Int) []byte { func (dB *DB) PackGet(k *big.Int) []byte {
@ -70,6 +71,15 @@ func (dB *DB) PackGet(k *big.Int) []byte {
return enc 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 // UnpackGet is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x9507d39a. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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 // 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) // Solidity: function getNamedStatParams() view returns(uint256 gets, uint256 inserts, uint256 mods)
func (dB *DB) PackGetNamedStatParams() []byte { func (dB *DB) PackGetNamedStatParams() []byte {
@ -95,6 +106,15 @@ func (dB *DB) PackGetNamedStatParams() []byte {
return enc 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 // GetNamedStatParamsOutput serves as a container for the return parameters of contract
// method GetNamedStatParams. // method GetNamedStatParams.
type GetNamedStatParamsOutput struct { 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.Gets = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Inserts = abi.ConvertType(out[1], 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) 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 // 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) // Solidity: function getStatParams() view returns(uint256, uint256, uint256)
func (dB *DB) PackGetStatParams() []byte { func (dB *DB) PackGetStatParams() []byte {
@ -132,6 +152,15 @@ func (dB *DB) PackGetStatParams() []byte {
return enc 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 // GetStatParamsOutput serves as a container for the return parameters of contract
// method GetStatParams. // method GetStatParams.
type GetStatParamsOutput struct { 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.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
outstruct.Arg1 = abi.ConvertType(out[1], 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) 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 // 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)) // Solidity: function getStatsStruct() view returns((uint256,uint256,uint256))
func (dB *DB) PackGetStatsStruct() []byte { func (dB *DB) PackGetStatsStruct() []byte {
@ -169,6 +198,15 @@ func (dB *DB) PackGetStatsStruct() []byte {
return enc 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 // UnpackGetStatsStruct is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xee8161e0. // from invoking the contract method with ID 0xee8161e0.
// //
@ -179,11 +217,12 @@ func (dB *DB) UnpackGetStatsStruct(data []byte) (DBStats, error) {
return *new(DBStats), err return *new(DBStats), err
} }
out0 := *abi.ConvertType(out[0], new(DBStats)).(*DBStats) 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 // 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) // Solidity: function insert(uint256 k, uint256 v) returns(uint256)
func (dB *DB) PackInsert(k *big.Int, v *big.Int) []byte { 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 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 // UnpackInsert is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x1d834a1b. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // DBInsert represents a Insert event raised by the DB contract.

View file

@ -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 // 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() // Solidity: function EmitMulti() returns()
func (c *C) PackEmitMulti() []byte { func (c *C) PackEmitMulti() []byte {
@ -63,8 +64,18 @@ func (c *C) PackEmitMulti() []byte {
return enc 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 // 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() // Solidity: function EmitOne() returns()
func (c *C) PackEmitOne() []byte { func (c *C) PackEmitOne() []byte {
@ -75,6 +86,15 @@ func (c *C) PackEmitOne() []byte {
return enc 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. // CBasic1 represents a basic1 event raised by the C contract.
type CBasic1 struct { type CBasic1 struct {
Id *big.Int Id *big.Int

View file

@ -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 // 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) // Solidity: function Do(uint256 val) pure returns(uint256 res)
func (c1 *C1) PackDo(val *big.Int) []byte { func (c1 *C1) PackDo(val *big.Int) []byte {
@ -79,6 +80,15 @@ func (c1 *C1) PackDo(val *big.Int) []byte {
return enc 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 // UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // 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 // 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) // Solidity: function Do(uint256 val) pure returns(uint256 res)
func (c2 *C2) PackDo(val *big.Int) []byte { func (c2 *C2) PackDo(val *big.Int) []byte {
@ -147,6 +158,15 @@ func (c2 *C2) PackDo(val *big.Int) []byte {
return enc 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 // UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // 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 // 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) // Solidity: function Do(uint256 val) pure returns(uint256)
func (l1 *L1) PackDo(val *big.Int) []byte { func (l1 *L1) PackDo(val *big.Int) []byte {
@ -199,6 +220,15 @@ func (l1 *L1) PackDo(val *big.Int) []byte {
return enc 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 // UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // 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 // 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) // Solidity: function Do(uint256 val) pure returns(uint256)
func (l2 *L2) PackDo(val *big.Int) []byte { func (l2 *L2) PackDo(val *big.Int) []byte {
@ -254,6 +285,15 @@ func (l2 *L2) PackDo(val *big.Int) []byte {
return enc 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 // UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // 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 // 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) // Solidity: function Do(uint256 val) pure returns(uint256)
func (l2b *L2b) PackDo(val *big.Int) []byte { func (l2b *L2b) PackDo(val *big.Int) []byte {
@ -309,6 +350,15 @@ func (l2b *L2b) PackDo(val *big.Int) []byte {
return enc 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 // UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // 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 // 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) // Solidity: function Do(uint256 val) pure returns(uint256)
func (l3 *L3) PackDo(val *big.Int) []byte { func (l3 *L3) PackDo(val *big.Int) []byte {
@ -361,6 +412,15 @@ func (l3 *L3) PackDo(val *big.Int) []byte {
return enc 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 // UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // 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 // 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) // Solidity: function Do(uint256 val) pure returns(uint256)
func (l4 *L4) PackDo(val *big.Int) []byte { func (l4 *L4) PackDo(val *big.Int) []byte {
@ -417,6 +478,15 @@ func (l4 *L4) PackDo(val *big.Int) []byte {
return enc 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 // UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) 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. // 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 // 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) // Solidity: function Do(uint256 val) pure returns(uint256)
func (l4b *L4b) PackDo(val *big.Int) []byte { func (l4b *L4b) PackDo(val *big.Int) []byte {
@ -472,6 +543,15 @@ func (l4b *L4b) PackDo(val *big.Int) []byte {
return enc 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 // UnpackDo is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0x2ad11272. // 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 return new(big.Int), err
} }
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int) out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
return out0, err return out0, nil
} }

View file

@ -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 // 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() // Solidity: function Bar() pure returns()
func (c *C) PackBar() []byte { func (c *C) PackBar() []byte {
@ -63,8 +64,18 @@ func (c *C) PackBar() []byte {
return enc 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 // 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() // Solidity: function Foo() pure returns()
func (c *C) PackFoo() []byte { func (c *C) PackFoo() []byte {
@ -75,6 +86,15 @@ func (c *C) PackFoo() []byte {
return enc 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 // UnpackError attempts to decode the provided error data using user-defined
// error definitions. // error definitions.
func (c *C) UnpackError(raw []byte) (any, error) { 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 // 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() // Solidity: function Foo() pure returns()
func (c2 *C2) PackFoo() []byte { func (c2 *C2) PackFoo() []byte {
@ -180,6 +201,15 @@ func (c2 *C2) PackFoo() []byte {
return enc 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 // UnpackError attempts to decode the provided error data using user-defined
// error definitions. // error definitions.
func (c2 *C2) UnpackError(raw []byte) (any, error) { func (c2 *C2) UnpackError(raw []byte) (any, error) {

View file

@ -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 // 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]) // Solidity: function GetNums() pure returns(uint256[5])
func (myContract *MyContract) PackGetNums() []byte { func (myContract *MyContract) PackGetNums() []byte {
@ -63,6 +64,15 @@ func (myContract *MyContract) PackGetNums() []byte {
return enc 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 // UnpackGetNums is the Go binding that unpacks the parameters returned
// from invoking the contract method with ID 0xbd6d1007. // 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 return *new([5]*big.Int), err
} }
out0 := *abi.ConvertType(out[0], new([5]*big.Int)).(*[5]*big.Int) out0 := *abi.ConvertType(out[0], new([5]*big.Int)).(*[5]*big.Int)
return out0, err return out0, nil
} }

View file

@ -32,6 +32,7 @@ var (
errBadInt16 = errors.New("abi: improperly encoded int16 value") errBadInt16 = errors.New("abi: improperly encoded int16 value")
errBadInt32 = errors.New("abi: improperly encoded int32 value") errBadInt32 = errors.New("abi: improperly encoded int32 value")
errBadInt64 = errors.New("abi: improperly encoded int64 value") errBadInt64 = errors.New("abi: improperly encoded int64 value")
errInvalidSign = errors.New("abi: negatively-signed value cannot be packed into uint parameter")
) )
// formatSliceString formats the reflection kind with the given slice size // formatSliceString formats the reflection kind with the given slice size

View file

@ -37,7 +37,16 @@ func packBytesSlice(bytes []byte, l int) []byte {
// t. // t.
func packElement(t Type, reflectValue reflect.Value) ([]byte, error) { func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
switch t.T { switch t.T {
case IntTy, UintTy: case UintTy:
// make sure to not pack a negative value into a uint type.
if reflectValue.Kind() == reflect.Ptr {
val := new(big.Int).Set(reflectValue.Interface().(*big.Int))
if val.Sign() == -1 {
return nil, errInvalidSign
}
}
return packNum(reflectValue), nil
case IntTy:
return packNum(reflectValue), nil return packNum(reflectValue), nil
case StringTy: case StringTy:
return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len()), nil return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len()), nil

View file

@ -177,6 +177,11 @@ func TestMethodPack(t *testing.T) {
if !bytes.Equal(packed, sig) { if !bytes.Equal(packed, sig) {
t.Errorf("expected %x got %x", sig, packed) t.Errorf("expected %x got %x", sig, packed)
} }
// test that we can't pack a negative value for a parameter that is specified as a uint
if _, err := abi.Pack("send", big.NewInt(-1)); err == nil {
t.Fatal("expected error when trying to pack negative big.Int into uint256 value")
}
} }
func TestPackNumber(t *testing.T) { func TestPackNumber(t *testing.T) {

View file

@ -1014,128 +1014,134 @@ func TestPackAndUnpackIncompatibleNumber(t *testing.T) {
cases := []struct { cases := []struct {
decodeType string decodeType string
inputValue *big.Int inputValue *big.Int
err error unpackErr error
packErr error
expectValue interface{} expectValue interface{}
}{ }{
{ {
decodeType: "uint8", decodeType: "uint8",
inputValue: big.NewInt(math.MaxUint8 + 1), inputValue: big.NewInt(math.MaxUint8 + 1),
err: errBadUint8, unpackErr: errBadUint8,
}, },
{ {
decodeType: "uint8", decodeType: "uint8",
inputValue: big.NewInt(math.MaxUint8), inputValue: big.NewInt(math.MaxUint8),
err: nil, unpackErr: nil,
expectValue: uint8(math.MaxUint8), expectValue: uint8(math.MaxUint8),
}, },
{ {
decodeType: "uint16", decodeType: "uint16",
inputValue: big.NewInt(math.MaxUint16 + 1), inputValue: big.NewInt(math.MaxUint16 + 1),
err: errBadUint16, unpackErr: errBadUint16,
}, },
{ {
decodeType: "uint16", decodeType: "uint16",
inputValue: big.NewInt(math.MaxUint16), inputValue: big.NewInt(math.MaxUint16),
err: nil, unpackErr: nil,
expectValue: uint16(math.MaxUint16), expectValue: uint16(math.MaxUint16),
}, },
{ {
decodeType: "uint32", decodeType: "uint32",
inputValue: big.NewInt(math.MaxUint32 + 1), inputValue: big.NewInt(math.MaxUint32 + 1),
err: errBadUint32, unpackErr: errBadUint32,
}, },
{ {
decodeType: "uint32", decodeType: "uint32",
inputValue: big.NewInt(math.MaxUint32), inputValue: big.NewInt(math.MaxUint32),
err: nil, unpackErr: nil,
expectValue: uint32(math.MaxUint32), expectValue: uint32(math.MaxUint32),
}, },
{ {
decodeType: "uint64", decodeType: "uint64",
inputValue: maxU64Plus1, inputValue: maxU64Plus1,
err: errBadUint64, unpackErr: errBadUint64,
}, },
{ {
decodeType: "uint64", decodeType: "uint64",
inputValue: maxU64, inputValue: maxU64,
err: nil, unpackErr: nil,
expectValue: uint64(math.MaxUint64), expectValue: uint64(math.MaxUint64),
}, },
{ {
decodeType: "uint256", decodeType: "uint256",
inputValue: maxU64Plus1, inputValue: maxU64Plus1,
err: nil, unpackErr: nil,
expectValue: maxU64Plus1, expectValue: maxU64Plus1,
}, },
{ {
decodeType: "int8", decodeType: "int8",
inputValue: big.NewInt(math.MaxInt8 + 1), inputValue: big.NewInt(math.MaxInt8 + 1),
err: errBadInt8, unpackErr: errBadInt8,
}, },
{ {
decodeType: "int8",
inputValue: big.NewInt(math.MinInt8 - 1), inputValue: big.NewInt(math.MinInt8 - 1),
err: errBadInt8, packErr: errInvalidSign,
}, },
{ {
decodeType: "int8", decodeType: "int8",
inputValue: big.NewInt(math.MaxInt8), inputValue: big.NewInt(math.MaxInt8),
err: nil, unpackErr: nil,
expectValue: int8(math.MaxInt8), expectValue: int8(math.MaxInt8),
}, },
{ {
decodeType: "int16", decodeType: "int16",
inputValue: big.NewInt(math.MaxInt16 + 1), inputValue: big.NewInt(math.MaxInt16 + 1),
err: errBadInt16, unpackErr: errBadInt16,
}, },
{ {
decodeType: "int16",
inputValue: big.NewInt(math.MinInt16 - 1), inputValue: big.NewInt(math.MinInt16 - 1),
err: errBadInt16, packErr: errInvalidSign,
}, },
{ {
decodeType: "int16", decodeType: "int16",
inputValue: big.NewInt(math.MaxInt16), inputValue: big.NewInt(math.MaxInt16),
err: nil, unpackErr: nil,
expectValue: int16(math.MaxInt16), expectValue: int16(math.MaxInt16),
}, },
{ {
decodeType: "int32", decodeType: "int32",
inputValue: big.NewInt(math.MaxInt32 + 1), inputValue: big.NewInt(math.MaxInt32 + 1),
err: errBadInt32, unpackErr: errBadInt32,
}, },
{ {
decodeType: "int32",
inputValue: big.NewInt(math.MinInt32 - 1), inputValue: big.NewInt(math.MinInt32 - 1),
err: errBadInt32, packErr: errInvalidSign,
}, },
{ {
decodeType: "int32", decodeType: "int32",
inputValue: big.NewInt(math.MaxInt32), inputValue: big.NewInt(math.MaxInt32),
err: nil, unpackErr: nil,
expectValue: int32(math.MaxInt32), expectValue: int32(math.MaxInt32),
}, },
{ {
decodeType: "int64", decodeType: "int64",
inputValue: new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(1)), inputValue: new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(1)),
err: errBadInt64, unpackErr: errBadInt64,
}, },
{ {
decodeType: "int64",
inputValue: new(big.Int).Sub(big.NewInt(math.MinInt64), big.NewInt(1)), inputValue: new(big.Int).Sub(big.NewInt(math.MinInt64), big.NewInt(1)),
err: errBadInt64, packErr: errInvalidSign,
}, },
{ {
decodeType: "int64", decodeType: "int64",
inputValue: big.NewInt(math.MaxInt64), inputValue: big.NewInt(math.MaxInt64),
err: nil, unpackErr: nil,
expectValue: int64(math.MaxInt64), expectValue: int64(math.MaxInt64),
}, },
} }
for i, testCase := range cases { for i, testCase := range cases {
packed, err := encodeABI.Pack(testCase.inputValue) packed, err := encodeABI.Pack(testCase.inputValue)
if err != nil { if testCase.packErr != nil {
panic(err) if err == nil {
t.Fatalf("expected packing of testcase input value to fail")
}
if err != testCase.packErr {
t.Fatalf("expected error '%v', got '%v'", testCase.packErr, err)
}
continue
}
if err != nil && err != testCase.packErr {
panic(fmt.Errorf("unexpected error packing test-case input: %v", err))
} }
ty, err := NewType(testCase.decodeType, "", nil) ty, err := NewType(testCase.decodeType, "", nil)
if err != nil { if err != nil {
@ -1145,8 +1151,8 @@ func TestPackAndUnpackIncompatibleNumber(t *testing.T) {
{Type: ty}, {Type: ty},
} }
decoded, err := decodeABI.Unpack(packed) decoded, err := decodeABI.Unpack(packed)
if err != testCase.err { if err != testCase.unpackErr {
t.Fatalf("Expected error %v, actual error %v. case %d", testCase.err, err, i) t.Fatalf("Expected error %v, actual error %v. case %d", testCase.unpackErr, err, i)
} }
if err != nil { if err != nil {
continue continue

View file

@ -93,9 +93,6 @@ func NewManager(config *Config, backends ...Backend) *Manager {
// Close terminates the account manager's internal notification processes. // Close terminates the account manager's internal notification processes.
func (am *Manager) Close() error { func (am *Manager) Close() error {
for _, w := range am.wallets {
w.Close()
}
errc := make(chan error) errc := make(chan error)
am.quit <- errc am.quit <- errc
return <-errc return <-errc
@ -149,6 +146,10 @@ func (am *Manager) update() {
am.lock.Unlock() am.lock.Unlock()
close(event.processed) close(event.processed)
case errc := <-am.quit: case errc := <-am.quit:
// Close all owned wallets
for _, w := range am.wallets {
w.Close()
}
// Manager terminating, return // Manager terminating, return
errc <- nil errc <- nil
// Signals event emitters the loop is not receiving values // Signals event emitters the loop is not receiving values

View file

@ -123,6 +123,11 @@ type BlobAndProofV1 struct {
Proof hexutil.Bytes `json:"proof"` Proof hexutil.Bytes `json:"proof"`
} }
type BlobAndProofV2 struct {
Blob hexutil.Bytes `json:"blob"`
CellProofs []hexutil.Bytes `json:"proofs"`
}
// JSON type overrides for ExecutionPayloadEnvelope. // JSON type overrides for ExecutionPayloadEnvelope.
type executionPayloadEnvelopeMarshaling struct { type executionPayloadEnvelopeMarshaling struct {
BlockValue *hexutil.Big BlockValue *hexutil.Big
@ -331,7 +336,9 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
for j := range sidecar.Blobs { for j := range sidecar.Blobs {
bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:])) bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:]))
bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[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[:]))
} }
} }

View file

@ -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 <http://www.gnu.org/licenses/>.
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))
}
}

View file

@ -1,58 +1,58 @@
# This file contains sha256 checksums of optional build dependencies. # This file contains sha256 checksums of optional build dependencies.
# version:spec-tests pectra-devnet-6@v1.0.0 # version:spec-tests v4.5.0
# https://github.com/ethereum/execution-spec-tests/releases # https://github.com/ethereum/execution-spec-tests/releases
# https://github.com/ethereum/execution-spec-tests/releases/download/pectra-devnet-6%40v1.0.0/ # https://github.com/ethereum/execution-spec-tests/releases/download/v4.5.0/
b69211752a3029083c020dc635fe12156ca1a6725a08559da540a0337586a77e fixtures_pectra-devnet-6.tar.gz 58afb92a0075a2cb7c4dec1281f7cb88b21b02afbedad096b580f3f8cc14c54c fixtures_develop.tar.gz
# version:golang 1.24.3 # version:golang 1.24.4
# https://go.dev/dl/ # https://go.dev/dl/
229c08b600b1446798109fae1f569228102c8473caba8104b6418cb5bc032878 go1.24.3.src.tar.gz 5a86a83a31f9fa81490b8c5420ac384fd3d95a3e71fba665c7b3f95d1dfef2b4 go1.24.4.src.tar.gz
6f6901497547db3b77c14f7f953fbcef9fa5fb84199ee2ee14a5686e66bed5a6 go1.24.3.aix-ppc64.tar.gz 0d2af78e3b6e08f8013dbbdb26ae33052697b6b72e03ec17d496739c2a1aed68 go1.24.4.aix-ppc64.tar.gz
a05fa7e4043a4fec66897135219e3b8ab2202b5ef351c60c2fbb531dfb8f2900 go1.24.3.darwin-amd64.pkg 69bef555e114b4a2252452b6e7049afc31fbdf2d39790b669165e89525cd3f5c go1.24.4.darwin-amd64.tar.gz
13e6fe3fcf65689d77d40e633de1e31c6febbdbcb846eb05fc2434ed2213e92b go1.24.3.darwin-amd64.tar.gz c4d74453a26f488bdb4b0294da4840d9020806de4661785334eb6d1803ee5c27 go1.24.4.darwin-amd64.pkg
97055ff4214043b39dc32e043fdd5c565df7c0a4e2fc0174e779a134c347ae0e go1.24.3.darwin-arm64.pkg 27973684b515eaf461065054e6b572d9390c05e69ba4a423076c160165336470 go1.24.4.darwin-arm64.tar.gz
64a3fa22142f627e78fac3018ce3d4aeace68b743eff0afda8aae0411df5e4fb go1.24.3.darwin-arm64.tar.gz 2fe1f8746745c4bfebd494583aaef24cad42594f6d25ed67856879d567ee66e7 go1.24.4.darwin-arm64.pkg
32de3fd44d5055973978436a7f1f0ffbaae85c1b603ec6105e5c38d8a674c721 go1.24.3.dragonfly-amd64.tar.gz 70b2de9c1cafe5af7be3eb8f80753cce0501ef300db3f3bd59be7ccc464234e1 go1.24.4.dragonfly-amd64.tar.gz
9fe6101b3797919bd7337ee5ce591954f85d59db7ae88983904db29fd64c3dd1 go1.24.3.freebsd-386.tar.gz 8d529839db29ee171505b89dc9c3de76003a4ab56202d84bddbbecacbfb6d7c9 go1.24.4.freebsd-386.tar.gz
6ccf4cca287e90cc28cd7954b6172f5d177a17e20b072b65f7f39636c325e2fb go1.24.3.freebsd-amd64.tar.gz 6cbc3ad6cc21bdcc7283824d3ac0e85512c02022f6a35eb2e844882ea6e8448c go1.24.4.freebsd-amd64.tar.gz
ce45ebf389066f82a7b056b66dd650efb51fde6f8bf92a2a3ab6990f02788ebf go1.24.3.freebsd-arm.tar.gz d49ae050c20aff646a7641dd903f03eb674570790b90ffb298076c4d41e36655 go1.24.4.freebsd-arm.tar.gz
8f6494a12a874d0ea57c67987829359e016960ce3ba0673273609d6ac2af589a go1.24.3.freebsd-arm64.tar.gz e31924abef2a28456b7103c0a5d333dcc11ecf19e76d5de1a383ad5fe0b42457 go1.24.4.freebsd-arm64.tar.gz
f9db392560cf0851f0bc8f2190e1978e01b4603038c27fecfc8658a695b71616 go1.24.3.freebsd-riscv64.tar.gz b5bca135eae8ebddf22972611ac1c58ae9fbb5979fd953cc5245c5b1b2517546 go1.24.4.freebsd-riscv64.tar.gz
01717fff64c5d98457272002fa825d0a15e307bf6e189f2b0c23817fa033b61c go1.24.3.illumos-amd64.tar.gz 7d5efda511ff7e3114b130acee5d0bffbb078fedbfa9b2c1b6a807107e1ca23a go1.24.4.illumos-amd64.tar.gz
41b1051063e68cbd2b919bf12326764fe33937cf1d32b5c529dd1a4f43dce578 go1.24.3.linux-386.tar.gz 130c9b061082eca15513e595e9952a2ded32e737e609dd0e49f7dfa74eba026d go1.24.4.linux-386.tar.gz
3333f6ea53afa971e9078895eaa4ac7204a8c6b5c68c10e6bc9a33e8e391bdd8 go1.24.3.linux-amd64.tar.gz 77e5da33bb72aeaef1ba4418b6fe511bc4d041873cbf82e5aa6318740df98717 go1.24.4.linux-amd64.tar.gz
a463cb59382bd7ae7d8f4c68846e73c4d589f223c589ac76871b66811ded7836 go1.24.3.linux-arm64.tar.gz d5501ee5aca0f258d5fe9bfaed401958445014495dc115f202d43d5210b45241 go1.24.4.linux-arm64.tar.gz
17a392d7e826625dd12a32099df0b00b85c32d8132ed86fe917183ee5c3f88ed go1.24.3.linux-armv6l.tar.gz 6a554e32301cecae3162677e66d4264b81b3b1a89592dd1b7b5c552c7a49fe37 go1.24.4.linux-armv6l.tar.gz
e4b003c04c902edc140153d279b42167f1ad7c229f48f1f729bbef5e65e88d1f go1.24.3.linux-loong64.tar.gz b208eb25fe244408cbe269ed426454bc46e59d0e0a749b6240d39e884e969875 go1.24.4.linux-loong64.tar.gz
1c79d89edf835edf9d4336ccea7cb89bc5c0ca82b12b36b218d599a5400d60fe go1.24.3.linux-mips.tar.gz fddfcb28fd36fe63d2ae181026798f86f3bbd3a7bb0f1e1f617dd3d604bf3fe4 go1.24.4.linux-mips.tar.gz
0b64fe147d69f4d681d8e8a035c760477531432f83d831f18d37cb9bf3652488 go1.24.3.linux-mips64.tar.gz 7934b924d5ab8c8ae3134a09a6ae74d3c39f63f6c4322ec289364dbbf0bac3ca go1.24.4.linux-mips64.tar.gz
396b784c255b64512dc00c302c053e43a3cbfc77518664c6ac5569aafad4d1e6 go1.24.3.linux-mips64le.tar.gz fa763d8673f94d6e534bb72c3cf675d4c2b8da4a6da42a89f08c5586106db39c go1.24.4.linux-mips64le.tar.gz
93898313887f14e8efbe9d7386d5da4792b2d6c492bee562993fd4c9daa75c6d go1.24.3.linux-mipsle.tar.gz 84363dbfe49b41d43df84420a09bd53a4770053d63bfa509868c46a5f8eb3ff7 go1.24.4.linux-mipsle.tar.gz
873ae3a6a6655a7b6f820e095d9965507e8dfd3cf76bc92d75c564ecbca385f6 go1.24.3.linux-ppc64.tar.gz 28fcbd5d3b56493606873c33f2b4bdd84ba93c633f37313613b5a1e6495c6fe5 go1.24.4.linux-ppc64.tar.gz
341a749d168f47b1d4dad25e32cae70849b7ceed7c290823b853c9e6b0df0856 go1.24.3.linux-ppc64le.tar.gz 9ca4afef813a2578c23843b640ae0290aa54b2e3c950a6cc4c99e16a57dec2ec go1.24.4.linux-ppc64le.tar.gz
fa482f53ccb4ba280316b8c5751ea67291507280d9166f2a38fe4d9b5d5fb64b go1.24.3.linux-riscv64.tar.gz 1d7034f98662d8f2c8abd7c700ada4093acb4f9c00e0e51a30344821d0785c77 go1.24.4.linux-riscv64.tar.gz
a87b0c2a079a0bece1620fb29a00e02b4dba17507850f837e754af7d57cda282 go1.24.3.linux-s390x.tar.gz 0449f3203c39703ab27684be763e9bb78ca9a051e0e4176727aead9461b6deb5 go1.24.4.linux-s390x.tar.gz
63155382308db1306200aff7821aa26bf2a2dda23537dd637a9704b485b6ddf0 go1.24.3.netbsd-386.tar.gz 954b49ccc2cfcf4b5f7cd33ff662295e0d3b74e7590c8e25fc2abb30bce120ba go1.24.4.netbsd-386.tar.gz
fe2c5c79482958b867c08a4fc2a10a998de9c0206b08d5b3ebcb2232e8d2777c go1.24.3.netbsd-amd64.tar.gz 370fabcdfee7c18857c96fdd5b706e025d4fb86a208da88ba56b1493b35498e9 go1.24.4.netbsd-amd64.tar.gz
e8ff77aef21521b5dd94e44282a3243309b80717414cf12f72835a45886a049f go1.24.3.netbsd-arm.tar.gz 7935ef95d4d1acc48587b1eb4acab98b0a7d9569736a32398b9c1d2e89026865 go1.24.4.netbsd-arm.tar.gz
b337fbaf82822685940ffaa76fbcf4be5d2f0258bc819cd80bc408b491f45c04 go1.24.3.netbsd-arm64.tar.gz ead78fd0fa29fbb176cc83f1caa54032e1a44f842affa56a682c647e0759f237 go1.24.4.netbsd-arm64.tar.gz
c1bb9dd8418480aa7f65452b08de3759da3bf89702be71b5a9fc084836b24ad5 go1.24.3.openbsd-386.tar.gz 913e217394b851a636b99de175f0c2f9ab9938b41c557f047168f77ee485d776 go1.24.4.openbsd-386.tar.gz
531218de748b0caaf6d1ad18921206fc12baaa89bf483a0a5e60a571c206fe6f go1.24.3.openbsd-amd64.tar.gz 24568da3dcbcdb24ec18b631f072faf0f3763e3d04f79032dc56ad9ec35379c4 go1.24.4.openbsd-amd64.tar.gz
bcd0dc959986fc346969b5d4111c3c8031882d8bf8d87a2c2ecf1328962a91f2 go1.24.3.openbsd-arm.tar.gz 45abf523f870632417ab007de3841f64dd906bde546ffc8c6380ccbe91c7fb73 go1.24.4.openbsd-arm.tar.gz
00ee6f8f1c41fd2e28ad386bd7e39acce7cab84af6de835855b29d1c597335c4 go1.24.3.openbsd-arm64.tar.gz 7c57c69b5dd1e946b28a3034c285240a48e2861bdcb50b7d9c0ed61bcf89c879 go1.24.4.openbsd-arm64.tar.gz
9f4ec0a9203ed3c54ce1a2a390ad3d45838cdb7efd85baeff857e37dfde04edd go1.24.3.openbsd-ppc64.tar.gz 91ed711f704829372d6931e1897631ef40288b8f9e3cd6ef4a24df7126d1066a go1.24.4.openbsd-ppc64.tar.gz
da4d6f80e2373250d8c31c32dcd1e08775c327c0d610923604660cc0e07e8cba go1.24.3.openbsd-riscv64.tar.gz de5e270d971c8790e8880168d56a2ea103979927c10ded136d792bbdf9bce3d3 go1.24.4.openbsd-riscv64.tar.gz
f5d02149132eedda6c2d46b360d7da462b8a5f9e3f8567db100c2d7bff0ddcd7 go1.24.3.plan9-386.tar.gz ff429d03f00bcd32a50f445320b8329d0fadb2a2fff899c11e95e0922a82c543 go1.24.4.plan9-386.tar.gz
175f3d79f4762a3c545d2c6393bf6b8bac24e838026869dafab06b930735c94f go1.24.3.plan9-amd64.tar.gz 39d6363a43fd16b60ae9ad7346a264e982e4fa653dee3b45f83e03cd2f7a6647 go1.24.4.plan9-amd64.tar.gz
d1e4ac15095da1611659261c2228c2058756cf87d61d9fad262f76755ef26849 go1.24.3.plan9-arm.tar.gz 1964ae2571259de77b930e97f2891aa92706ff81aac9909d45bb107b0fab16c8 go1.24.4.plan9-arm.tar.gz
e644220a6ced3c07a7acc1364193cb709a97737dd8b6792a07a8ec6d9996713e go1.24.3.solaris-amd64.tar.gz a7f9af424e8fb87886664754badca459513f64f6a321d17f1d219b8edf519821 go1.24.4.solaris-amd64.tar.gz
0d7e7dc0a31ba0cdd487415709d03b02fc9490ef111e8dfd22788a6d63316f37 go1.24.3.windows-386.msi d454d3cb144432f1726bf00e28c6017e78ccb256a8d01b8e3fb1b2e6b5650f28 go1.24.4.windows-386.zip
c27c463a61ab849266baa0c17a6c5c4256a574ab642f609ba25c96ec965dc184 go1.24.3.windows-386.zip 966ecace1cdbb3497a2b930bdb0f90c3ad32922fa1a7c655b2d4bbeb7e4ac308 go1.24.4.windows-386.msi
d5b7637e7e138be877d96a4501709d480e050d86a8f402bc950e72112b5aedc5 go1.24.3.windows-amd64.msi b751a1136cb9d8a2e7ebb22c538c4f02c09b98138c7c8bfb78a54a4566c013b1 go1.24.4.windows-amd64.zip
be9787cb08998b1860fe3513e48a5fe5b96302d358a321b58e651184fa9638b3 go1.24.3.windows-amd64.zip 0cbb6e83865747dbe69b3d4155f92e88fcf336ff5d70182dba145e9d7bd3d8f6 go1.24.4.windows-amd64.msi
7efde2e5e8468e9caf2c7fc94f4da78a726a5031a1ed63acff7899527cdddff6 go1.24.3.windows-arm64.msi d17da51bc85bd010754a4063215d15d2c033cc289d67ca9201a03c9041b2969d go1.24.4.windows-arm64.zip
eec9fa736056b54dd88ecb669db2bfad39b0c48f6f9080f036dfa1ca42dc4bb5 go1.24.3.windows-arm64.zip 47dbe734b6a829de45654648a7abcf05bdceef5c80e03ea0b208eeebef75a852 go1.24.4.windows-arm64.msi
# version:golangci 2.0.2 # version:golangci 2.0.2
# https://github.com/golangci/golangci-lint/releases/ # https://github.com/golangci/golangci-lint/releases/

View file

@ -332,7 +332,7 @@ func doTest(cmdline []string) {
// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures. // downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures.
func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string { func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string {
ext := ".tar.gz" ext := ".tar.gz"
base := "fixtures_pectra-devnet-6" // TODO(s1na) rename once the version becomes part of the filename base := "fixtures_develop"
archivePath := filepath.Join(cachedir, base+ext) archivePath := filepath.Join(cachedir, base+ext)
if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil { if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil {
log.Fatal(err) log.Fatal(err)

View file

@ -150,7 +150,7 @@ All hex encoded values must be prefixed with `0x`.
#### Create new password protected account #### 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. 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 #### Arguments

View file

@ -66,10 +66,9 @@ func (s *Suite) dialAs(key *ecdsa.PrivateKey) (*Conn, error) {
return nil, err return nil, err
} }
conn.caps = []p2p.Cap{ conn.caps = []p2p.Cap{
{Name: "eth", Version: 67}, {Name: "eth", Version: 69},
{Name: "eth", Version: 68},
} }
conn.ourHighestProtoVersion = 68 conn.ourHighestProtoVersion = 69
return &conn, nil return &conn, nil
} }
@ -156,7 +155,7 @@ func (c *Conn) ReadEth() (any, error) {
var msg any var msg any
switch int(code) { switch int(code) {
case eth.StatusMsg: case eth.StatusMsg:
msg = new(eth.StatusPacket) msg = new(eth.StatusPacket69)
case eth.GetBlockHeadersMsg: case eth.GetBlockHeadersMsg:
msg = new(eth.GetBlockHeadersPacket) msg = new(eth.GetBlockHeadersPacket)
case eth.BlockHeadersMsg: case eth.BlockHeadersMsg:
@ -229,9 +228,21 @@ func (c *Conn) ReadSnap() (any, error) {
} }
} }
// dialAndPeer creates a peer connection and runs the handshake.
func (s *Suite) dialAndPeer(status *eth.StatusPacket69) (*Conn, error) {
c, err := s.dial()
if err != nil {
return nil, err
}
if err = c.peer(s.chain, status); err != nil {
c.Close()
}
return c, err
}
// peer performs both the protocol handshake and the status message // peer performs both the protocol handshake and the status message
// exchange with the node in order to peer with it. // exchange with the node in order to peer with it.
func (c *Conn) peer(chain *Chain, status *eth.StatusPacket) error { func (c *Conn) peer(chain *Chain, status *eth.StatusPacket69) error {
if err := c.handshake(); err != nil { if err := c.handshake(); err != nil {
return fmt.Errorf("handshake failed: %v", err) return fmt.Errorf("handshake failed: %v", err)
} }
@ -304,7 +315,7 @@ func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) {
} }
// statusExchange performs a `Status` message exchange with the given node. // statusExchange performs a `Status` message exchange with the given node.
func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket) error { func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket69) error {
loop: loop:
for { for {
code, data, err := c.Read() code, data, err := c.Read()
@ -313,11 +324,15 @@ loop:
} }
switch code { switch code {
case eth.StatusMsg + protoOffset(ethProto): case eth.StatusMsg + protoOffset(ethProto):
msg := new(eth.StatusPacket) msg := new(eth.StatusPacket69)
if err := rlp.DecodeBytes(data, &msg); err != nil { if err := rlp.DecodeBytes(data, &msg); err != nil {
return fmt.Errorf("error decoding status packet: %w", err) return fmt.Errorf("error decoding status packet: %w", err)
} }
if have, want := msg.Head, chain.blocks[chain.Len()-1].Hash(); have != want { if have, want := msg.LatestBlock, chain.blocks[chain.Len()-1].NumberU64(); have != want {
return fmt.Errorf("wrong head block in status, want: %d, have %d",
want, have)
}
if have, want := msg.LatestBlockHash, chain.blocks[chain.Len()-1].Hash(); have != want {
return fmt.Errorf("wrong head block in status, want: %#x (block %d) have %#x", return fmt.Errorf("wrong head block in status, want: %#x (block %d) have %#x",
want, chain.blocks[chain.Len()-1].NumberU64(), have) want, chain.blocks[chain.Len()-1].NumberU64(), have)
} }
@ -348,13 +363,14 @@ loop:
} }
if status == nil { if status == nil {
// default status message // default status message
status = &eth.StatusPacket{ status = &eth.StatusPacket69{
ProtocolVersion: uint32(c.negotiatedProtoVersion), ProtocolVersion: uint32(c.negotiatedProtoVersion),
NetworkID: chain.config.ChainID.Uint64(), NetworkID: chain.config.ChainID.Uint64(),
TD: chain.TD(),
Head: chain.blocks[chain.Len()-1].Hash(),
Genesis: chain.blocks[0].Hash(), Genesis: chain.blocks[0].Hash(),
ForkID: chain.ForkID(), ForkID: chain.ForkID(),
EarliestBlock: 0,
LatestBlock: chain.blocks[chain.Len()-1].NumberU64(),
LatestBlockHash: chain.blocks[chain.Len()-1].Hash(),
} }
} }
if err := c.Write(ethProto, eth.StatusMsg, status); err != nil { if err := c.Write(ethProto, eth.StatusMsg, status); err != nil {

View file

@ -32,7 +32,7 @@ const (
// Unexported devp2p protocol lengths from p2p package. // Unexported devp2p protocol lengths from p2p package.
const ( const (
baseProtoLen = 16 baseProtoLen = 16
ethProtoLen = 17 ethProtoLen = 18
snapProtoLen = 8 snapProtoLen = 8
) )

View file

@ -68,16 +68,19 @@ func (s *Suite) EthTests() []utesting.Test {
return []utesting.Test{ return []utesting.Test{
// status // status
{Name: "Status", Fn: s.TestStatus}, {Name: "Status", Fn: s.TestStatus},
{Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake},
{Name: "BlockRangeUpdateExpired", Fn: s.TestBlockRangeUpdateHistoryExp},
{Name: "BlockRangeUpdateFuture", Fn: s.TestBlockRangeUpdateFuture},
{Name: "BlockRangeUpdateInvalid", Fn: s.TestBlockRangeUpdateInvalid},
// get block headers // get block headers
{Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders}, {Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders},
{Name: "GetNonexistentBlockHeaders", Fn: s.TestGetNonexistentBlockHeaders}, {Name: "GetNonexistentBlockHeaders", Fn: s.TestGetNonexistentBlockHeaders},
{Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests}, {Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests},
{Name: "SameRequestID", Fn: s.TestSameRequestID}, {Name: "SameRequestID", Fn: s.TestSameRequestID},
{Name: "ZeroRequestID", Fn: s.TestZeroRequestID}, {Name: "ZeroRequestID", Fn: s.TestZeroRequestID},
// get block bodies // get history
{Name: "GetBlockBodies", Fn: s.TestGetBlockBodies}, {Name: "GetBlockBodies", Fn: s.TestGetBlockBodies},
// // malicious handshakes + status {Name: "GetReceipts", Fn: s.TestGetReceipts},
{Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake},
// test transactions // test transactions
{Name: "LargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true}, {Name: "LargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true},
{Name: "Transaction", Fn: s.TestTransaction}, {Name: "Transaction", Fn: s.TestTransaction},
@ -101,15 +104,11 @@ func (s *Suite) SnapTests() []utesting.Test {
func (s *Suite) TestStatus(t *utesting.T) { func (s *Suite) TestStatus(t *utesting.T) {
t.Log(`This test is just a sanity check. It performs an eth protocol handshake.`) t.Log(`This test is just a sanity check. It performs an eth protocol handshake.`)
conn, err := s.dialAndPeer(nil)
conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatal("peering failed:", err)
}
defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
} }
conn.Close()
} }
// headersMatch returns whether the received headers match the given request // headersMatch returns whether the received headers match the given request
@ -119,15 +118,12 @@ func headersMatch(expected []*types.Header, headers []*types.Header) bool {
func (s *Suite) TestGetBlockHeaders(t *utesting.T) { func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
t.Log(`This test requests block headers from the node.`) t.Log(`This test requests block headers from the node.`)
conn, err := s.dialAndPeer(nil)
conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
defer conn.Close()
// Send headers request. // Send headers request.
req := &eth.GetBlockHeadersPacket{ req := &eth.GetBlockHeadersPacket{
RequestId: 33, RequestId: 33,
@ -162,16 +158,11 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
func (s *Suite) TestGetNonexistentBlockHeaders(t *utesting.T) { func (s *Suite) TestGetNonexistentBlockHeaders(t *utesting.T) {
t.Log(`This test sends GetBlockHeaders requests for nonexistent blocks (using max uint64 value) t.Log(`This test sends GetBlockHeaders requests for nonexistent blocks (using max uint64 value)
to check if the node disconnects after receiving multiple invalid requests.`) to check if the node disconnects after receiving multiple invalid requests.`)
conn, err := s.dialAndPeer(nil)
conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
defer conn.Close()
// Create request with max uint64 value for a nonexistent block // Create request with max uint64 value for a nonexistent block
badReq := &eth.GetBlockHeadersPacket{ badReq := &eth.GetBlockHeadersPacket{
@ -204,15 +195,11 @@ to check if the node disconnects after receiving multiple invalid requests.`)
func (s *Suite) TestSimultaneousRequests(t *utesting.T) { func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
t.Log(`This test requests blocks headers from the node, performing two requests t.Log(`This test requests blocks headers from the node, performing two requests
concurrently, with different request IDs.`) concurrently, with different request IDs.`)
conn, err := s.dialAndPeer(nil)
conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
defer conn.Close()
// Create two different requests. // Create two different requests.
req1 := &eth.GetBlockHeadersPacket{ req1 := &eth.GetBlockHeadersPacket{
@ -278,15 +265,11 @@ concurrently, with different request IDs.`)
func (s *Suite) TestSameRequestID(t *utesting.T) { func (s *Suite) TestSameRequestID(t *utesting.T) {
t.Log(`This test requests block headers, performing two concurrent requests with the t.Log(`This test requests block headers, performing two concurrent requests with the
same request ID. The node should handle the request by responding to both requests.`) same request ID. The node should handle the request by responding to both requests.`)
conn, err := s.dialAndPeer(nil)
conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
defer conn.Close()
// Create two different requests with the same ID. // Create two different requests with the same ID.
reqID := uint64(1234) reqID := uint64(1234)
@ -349,15 +332,12 @@ same request ID. The node should handle the request by responding to both reques
func (s *Suite) TestZeroRequestID(t *utesting.T) { func (s *Suite) TestZeroRequestID(t *utesting.T) {
t.Log(`This test sends a GetBlockHeaders message with a request-id of zero, t.Log(`This test sends a GetBlockHeaders message with a request-id of zero,
and expects a response.`) and expects a response.`)
conn, err := s.dialAndPeer(nil)
conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
defer conn.Close()
req := &eth.GetBlockHeadersPacket{ req := &eth.GetBlockHeadersPacket{
GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{ GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{
Origin: eth.HashOrNumber{Number: 0}, Origin: eth.HashOrNumber{Number: 0},
@ -384,15 +364,12 @@ and expects a response.`)
func (s *Suite) TestGetBlockBodies(t *utesting.T) { func (s *Suite) TestGetBlockBodies(t *utesting.T) {
t.Log(`This test sends GetBlockBodies requests to the node for known blocks in the test chain.`) t.Log(`This test sends GetBlockBodies requests to the node for known blocks in the test chain.`)
conn, err := s.dialAndPeer(nil)
conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
defer conn.Close()
// Create block bodies request. // Create block bodies request.
req := &eth.GetBlockBodiesPacket{ req := &eth.GetBlockBodiesPacket{
RequestId: 55, RequestId: 55,
@ -418,6 +395,47 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) {
} }
} }
func (s *Suite) TestGetReceipts(t *utesting.T) {
t.Log(`This test sends GetReceipts requests to the node for known blocks in the test chain.`)
conn, err := s.dialAndPeer(nil)
if err != nil {
t.Fatalf("peering failed: %v", err)
}
defer conn.Close()
// Find some blocks containing receipts.
var hashes = make([]common.Hash, 0, 3)
for i := range s.chain.Len() {
block := s.chain.GetBlock(i)
if len(block.Transactions()) > 0 {
hashes = append(hashes, block.Hash())
}
if len(hashes) == cap(hashes) {
break
}
}
// Create block bodies request.
req := &eth.GetReceiptsPacket{
RequestId: 66,
GetReceiptsRequest: (eth.GetReceiptsRequest)(hashes),
}
if err := conn.Write(ethProto, eth.GetReceiptsMsg, req); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
// Wait for response.
resp := new(eth.ReceiptsPacket[*eth.ReceiptList69])
if err := conn.ReadMsg(ethProto, eth.ReceiptsMsg, &resp); err != nil {
t.Fatalf("error reading block bodies msg: %v", err)
}
if got, want := resp.RequestId, req.RequestId; got != want {
t.Fatalf("unexpected request id in respond", got, want)
}
if len(resp.List) != len(req.GetReceiptsRequest) {
t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetReceiptsRequest), len(resp.List))
}
}
// randBuf makes a random buffer size kilobytes large. // randBuf makes a random buffer size kilobytes large.
func randBuf(size int) []byte { func randBuf(size int) []byte {
buf := make([]byte, size*1024) buf := make([]byte, size*1024)
@ -500,6 +518,97 @@ func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
} }
} }
func (s *Suite) TestBlockRangeUpdateInvalid(t *utesting.T) {
t.Log(`This test sends an invalid BlockRangeUpdate message to the node and expects to be disconnected.`)
conn, err := s.dialAndPeer(nil)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
conn.Write(ethProto, eth.BlockRangeUpdateMsg, &eth.BlockRangeUpdatePacket{
EarliestBlock: 10,
LatestBlock: 8,
LatestBlockHash: s.chain.GetBlock(8).Hash(),
})
if code, _, err := conn.Read(); err != nil {
t.Fatalf("expected disconnect, got err: %v", err)
} else if code != discMsg {
t.Fatalf("expected disconnect message, got msg code %d", code)
}
}
func (s *Suite) TestBlockRangeUpdateFuture(t *utesting.T) {
t.Log(`This test sends a BlockRangeUpdate that is beyond the chain head.
The node should accept the update and should not disonnect.`)
conn, err := s.dialAndPeer(nil)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
head := s.chain.Head().NumberU64()
var hash common.Hash
rand.Read(hash[:])
conn.Write(ethProto, eth.BlockRangeUpdateMsg, &eth.BlockRangeUpdatePacket{
EarliestBlock: head + 10,
LatestBlock: head + 50,
LatestBlockHash: hash,
})
// Ensure the node does not disconnect us.
// Just send a few ping messages.
for range 10 {
time.Sleep(100 * time.Millisecond)
if err := conn.Write(baseProto, pingMsg, []any{}); err != nil {
t.Fatal("write error:", err)
}
code, _, err := conn.Read()
switch {
case err != nil:
t.Fatal("read error:", err)
case code == discMsg:
t.Fatal("got disconnect")
case code == pongMsg:
}
}
}
func (s *Suite) TestBlockRangeUpdateHistoryExp(t *utesting.T) {
t.Log(`This test sends a BlockRangeUpdate announcing incomplete (expired) history.
The node should accept the update and should not disonnect.`)
conn, err := s.dialAndPeer(nil)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
head := s.chain.Head()
conn.Write(ethProto, eth.BlockRangeUpdateMsg, &eth.BlockRangeUpdatePacket{
EarliestBlock: head.NumberU64() - 10,
LatestBlock: head.NumberU64(),
LatestBlockHash: head.Hash(),
})
// Ensure the node does not disconnect us.
// Just send a few ping messages.
for range 10 {
time.Sleep(100 * time.Millisecond)
if err := conn.Write(baseProto, pingMsg, []any{}); err != nil {
t.Fatal("write error:", err)
}
code, _, err := conn.Read()
switch {
case err != nil:
t.Fatal("read error:", err)
case code == discMsg:
t.Fatal("got disconnect")
case code == pongMsg:
}
}
}
func (s *Suite) TestTransaction(t *utesting.T) { func (s *Suite) TestTransaction(t *utesting.T) {
t.Log(`This test sends a valid transaction to the node and checks if the t.Log(`This test sends a valid transaction to the node and checks if the
transaction gets propagated.`) transaction gets propagated.`)

View file

@ -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 <http://www.gnu.org/licenses/>.
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
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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++
}
}

View file

@ -303,7 +303,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
} }
// Set the receipt logs and create the bloom filter. // 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) receipt.Bloom = types.CreateBloom(receipt)
// These three are non-consensus fields: // These three are non-consensus fields:

View file

@ -210,8 +210,6 @@ func init() {
stateTransitionCommand, stateTransitionCommand,
transactionCommand, transactionCommand,
blockBuilderCommand, blockBuilderCommand,
eofParseCommand,
eofDumpCommand,
} }
app.Before = func(ctx *cli.Context) error { app.Before = func(ctx *cli.Context) error {
flags.MigrateGlobalFlags(ctx) flags.MigrateGlobalFlags(ctx)

View file

@ -46,6 +46,7 @@ import (
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
@ -59,7 +60,7 @@ var (
ArgsUsage: "<genesisPath>", ArgsUsage: "<genesisPath>",
Flags: slices.Concat([]cli.Flag{ Flags: slices.Concat([]cli.Flag{
utils.CachePreimagesFlag, utils.CachePreimagesFlag,
utils.OverridePrague, utils.OverrideOsaka,
utils.OverrideVerkle, utils.OverrideVerkle,
}, utils.DatabaseFlags), }, utils.DatabaseFlags),
Description: ` Description: `
@ -270,19 +271,16 @@ func initGenesis(ctx *cli.Context) error {
defer stack.Close() defer stack.Close()
var overrides core.ChainOverrides var overrides core.ChainOverrides
if ctx.IsSet(utils.OverridePrague.Name) { if ctx.IsSet(utils.OverrideOsaka.Name) {
v := ctx.Uint64(utils.OverridePrague.Name) v := ctx.Uint64(utils.OverrideOsaka.Name)
overrides.OverridePrague = &v overrides.OverrideOsaka = &v
} }
if ctx.IsSet(utils.OverrideVerkle.Name) { if ctx.IsSet(utils.OverrideVerkle.Name) {
v := ctx.Uint64(utils.OverrideVerkle.Name) v := ctx.Uint64(utils.OverrideVerkle.Name)
overrides.OverrideVerkle = &v overrides.OverrideVerkle = &v
} }
chaindb, err := stack.OpenDatabaseWithFreezer("chaindata", 0, 0, ctx.String(utils.AncientFlag.Name), "", false) chaindb := utils.MakeChainDatabase(ctx, stack, false)
if err != nil {
utils.Fatalf("Failed to open database: %v", err)
}
defer chaindb.Close() defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
@ -319,7 +317,7 @@ func dumpGenesis(ctx *cli.Context) error {
// dump whatever already exists in the datadir // dump whatever already exists in the datadir
stack, _ := makeConfigNode(ctx) stack, _ := makeConfigNode(ctx)
db, err := stack.OpenDatabase("chaindata", 0, 0, "", true) db, err := stack.OpenDatabaseWithOptions("chaindata", node.DatabaseOptions{ReadOnly: true})
if err != nil { if err != nil {
return err return err
} }
@ -798,8 +796,12 @@ func downloadEra(ctx *cli.Context) error {
// Resolve the destination directory. // Resolve the destination directory.
stack, _ := makeConfigNode(ctx) stack, _ := makeConfigNode(ctx)
defer stack.Close() defer stack.Close()
ancients := stack.ResolveAncient("chaindata", "") ancients := stack.ResolveAncient("chaindata", "")
dir := filepath.Join(ancients, "era") dir := filepath.Join(ancients, rawdb.ChainFreezerName, "era")
if ctx.IsSet(utils.EraFlag.Name) {
dir = filepath.Join(ancients, ctx.String(utils.EraFlag.Name))
}
baseURL := ctx.String(eraServerFlag.Name) baseURL := ctx.String(eraServerFlag.Name)
if baseURL == "" { if baseURL == "" {
@ -836,15 +838,8 @@ func downloadEra(ctx *cli.Context) error {
} }
func parseRange(s string) (start uint64, end uint64, ok bool) { func parseRange(s string) (start uint64, end uint64, ok bool) {
if m, _ := regexp.MatchString("[0-9]+", s); m { log.Info("Parsing block range", "input", s)
start, err := strconv.ParseUint(s, 10, 64) if m, _ := regexp.MatchString("^[0-9]+-[0-9]+$", s); m {
if err != nil {
return 0, 0, false
}
end = start
return start, end, true
}
if m, _ := regexp.MatchString("[0-9]+-[0-9]+", s); m {
s1, s2, _ := strings.Cut(s, "-") s1, s2, _ := strings.Cut(s, "-")
start, err := strconv.ParseUint(s1, 10, 64) start, err := strconv.ParseUint(s1, 10, 64)
if err != nil { if err != nil {
@ -854,6 +849,19 @@ func parseRange(s string) (start uint64, end uint64, ok bool) {
if err != nil { if err != nil {
return 0, 0, false 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 start, end, true
} }
return 0, 0, false return 0, 0, false

98
cmd/geth/chaincmd_test.go Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
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)
}
}
}
}

View file

@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
@ -180,12 +181,51 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
return stack, cfg return stack, cfg
} }
// constructs the disclaimer text block which will be printed in the logs upon
// startup when Geth is running in dev mode.
func constructDevModeBanner(ctx *cli.Context, cfg gethConfig) string {
devModeBanner := `You are running Geth in --dev mode. Please note the following:
1. This mode is only intended for fast, iterative development without assumptions on
security or persistence.
2. The database is created in memory unless specified otherwise. Therefore, shutting down
your computer or losing power will wipe your entire block data and chain state for
your dev environment.
3. A random, pre-allocated developer account will be available and unlocked as
eth.coinbase, which can be used for testing. The random dev account is temporary,
stored on a ramdisk, and will be lost if your machine is restarted.
4. Mining is enabled by default. However, the client will only seal blocks if transactions
are pending in the mempool. The miner's minimum accepted gas price is 1.
5. Networking is disabled; there is no listen-address, the maximum number of peers is set
to 0, and discovery is disabled.
`
if !ctx.IsSet(utils.DataDirFlag.Name) {
devModeBanner += fmt.Sprintf(`
Running in ephemeral mode. The following account has been prefunded in the genesis:
Account
------------------
0x%x (10^49 ETH)
`, cfg.Eth.Miner.PendingFeeRecipient)
if cfg.Eth.Miner.PendingFeeRecipient == utils.DeveloperAddr {
devModeBanner += fmt.Sprintf(`
Private Key
------------------
0x%x
`, crypto.FromECDSA(utils.DeveloperKey))
}
}
return devModeBanner
}
// makeFullNode loads geth configuration and creates the Ethereum backend. // makeFullNode loads geth configuration and creates the Ethereum backend.
func makeFullNode(ctx *cli.Context) *node.Node { func makeFullNode(ctx *cli.Context) *node.Node {
stack, cfg := makeConfigNode(ctx) stack, cfg := makeConfigNode(ctx)
if ctx.IsSet(utils.OverridePrague.Name) { if ctx.IsSet(utils.OverrideOsaka.Name) {
v := ctx.Uint64(utils.OverridePrague.Name) v := ctx.Uint64(utils.OverrideOsaka.Name)
cfg.Eth.OverridePrague = &v cfg.Eth.OverrideOsaka = &v
} }
if ctx.IsSet(utils.OverrideVerkle.Name) { if ctx.IsSet(utils.OverrideVerkle.Name) {
v := ctx.Uint64(utils.OverrideVerkle.Name) v := ctx.Uint64(utils.OverrideVerkle.Name)
@ -239,6 +279,11 @@ func makeFullNode(ctx *cli.Context) *node.Node {
} }
catalyst.RegisterSimulatedBeaconAPIs(stack, simBeacon) catalyst.RegisterSimulatedBeaconAPIs(stack, simBeacon)
stack.RegisterLifecycle(simBeacon) stack.RegisterLifecycle(simBeacon)
banner := constructDevModeBanner(ctx, cfg)
for _, line := range strings.Split(banner, "\n") {
log.Warn(line)
}
} else if ctx.IsSet(utils.BeaconApiFlag.Name) { } else if ctx.IsSet(utils.BeaconApiFlag.Name) {
// Start blsync mode. // Start blsync mode.
srv := rpc.NewServer() srv := rpc.NewServer()

View file

@ -62,7 +62,7 @@ var (
utils.NoUSBFlag, // deprecated utils.NoUSBFlag, // deprecated
utils.USBFlag, utils.USBFlag,
utils.SmartCardDaemonPathFlag, utils.SmartCardDaemonPathFlag,
utils.OverridePrague, utils.OverrideOsaka,
utils.OverrideVerkle, utils.OverrideVerkle,
utils.EnablePersonal, // deprecated utils.EnablePersonal, // deprecated
utils.TxPoolLocalsFlag, utils.TxPoolLocalsFlag,
@ -91,13 +91,7 @@ var (
utils.LogNoHistoryFlag, utils.LogNoHistoryFlag,
utils.LogExportCheckpointsFlag, utils.LogExportCheckpointsFlag,
utils.StateHistoryFlag, utils.StateHistoryFlag,
utils.LightServeFlag, // deprecated
utils.LightIngressFlag, // deprecated
utils.LightEgressFlag, // deprecated
utils.LightMaxPeersFlag, // deprecated
utils.LightNoPruneFlag, // deprecated
utils.LightKDFFlag, utils.LightKDFFlag,
utils.LightNoSyncServeFlag, // deprecated
utils.EthRequiredBlocksFlag, utils.EthRequiredBlocksFlag,
utils.LegacyWhitelistFlag, // deprecated utils.LegacyWhitelistFlag, // deprecated
utils.CacheFlag, utils.CacheFlag,
@ -300,24 +294,6 @@ func prepare(ctx *cli.Context) {
case ctx.IsSet(utils.HoodiFlag.Name): case ctx.IsSet(utils.HoodiFlag.Name):
log.Info("Starting Geth on Hoodi testnet...") log.Info("Starting Geth on Hoodi testnet...")
case ctx.IsSet(utils.DeveloperFlag.Name):
log.Info("Starting Geth in ephemeral dev mode...")
log.Warn(`You are running Geth in --dev mode. Please note the following:
1. This mode is only intended for fast, iterative development without assumptions on
security or persistence.
2. The database is created in memory unless specified otherwise. Therefore, shutting down
your computer or losing power will wipe your entire block data and chain state for
your dev environment.
3. A random, pre-allocated developer account will be available and unlocked as
eth.coinbase, which can be used for testing. The random dev account is temporary,
stored on a ramdisk, and will be lost if your machine is restarted.
4. Mining is enabled by default. However, the client will only seal blocks if transactions
are pending in the mempool. The miner's minimum accepted gas price is 1.
5. Networking is disabled; there is no listen-address, the maximum number of peers is set
to 0, and discovery is disabled.
`)
case !ctx.IsSet(utils.NetworkIdFlag.Name): case !ctx.IsSet(utils.NetworkIdFlag.Name):
log.Info("Starting Geth on Ethereum mainnet...") log.Info("Starting Geth on Ethereum mainnet...")
} }

View file

@ -220,6 +220,27 @@ func verifyState(ctx *cli.Context) error {
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close() defer triedb.Close()
var (
err error
root = headBlock.Root()
)
if ctx.NArg() == 1 {
root, err = parseRoot(ctx.Args().First())
if err != nil {
log.Error("Failed to resolve state 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{ snapConfig := snapshot.Config{
CacheSize: 256, CacheSize: 256,
Recovery: false, Recovery: false,
@ -231,18 +252,6 @@ func verifyState(ctx *cli.Context) error {
log.Error("Failed to open snapshot tree", "err", err) log.Error("Failed to open snapshot tree", "err", err)
return err return err
} }
if ctx.NArg() > 1 {
log.Error("Too many arguments given")
return errors.New("too many arguments")
}
var root = headBlock.Root()
if ctx.NArg() == 1 {
root, err = parseRoot(ctx.Args().First())
if err != nil {
log.Error("Failed to resolve state root", "err", err)
return err
}
}
if err := snaptree.Verify(root); err != nil { if err := snaptree.Verify(root); err != nil {
log.Error("Failed to verify state", "root", root, "err", err) log.Error("Failed to verify state", "root", root, "err", err)
return err return err
@ -250,6 +259,7 @@ func verifyState(ctx *cli.Context) error {
log.Info("Verified the state", "root", root) log.Info("Verified the state", "root", root)
return snapshot.CheckDanglingStorage(chaindb) return snapshot.CheckDanglingStorage(chaindb)
} }
}
// checkDanglingStorage iterates the snap storage data, and verifies that all // checkDanglingStorage iterates the snap storage data, and verifies that all
// storage also has corresponding account data. // storage also has corresponding account data.

View file

@ -309,7 +309,8 @@ func ImportHistory(chain *core.BlockChain, dir string, network string) error {
if err != nil { if err != nil {
return fmt.Errorf("error reading receipts %d: %w", it.Number(), err) return fmt.Errorf("error reading receipts %d: %w", it.Number(), err)
} }
if _, err := chain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{receipts}, 2^64-1); err != nil { encReceipts := types.EncodeBlockReceiptLists([]types.Receipts{receipts})
if _, err := chain.InsertReceiptChain([]*types.Block{block}, encReceipts, 2^64-1); err != nil {
return fmt.Errorf("error inserting body %d: %w", it.Number(), err) return fmt.Errorf("error inserting body %d: %w", it.Number(), err)
} }
imported += 1 imported += 1

View file

@ -111,6 +111,11 @@ var (
Usage: "Root directory for ancient data (default = inside chaindata)", Usage: "Root directory for ancient data (default = inside chaindata)",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
EraFlag = &flags.DirectoryFlag{
Name: "datadir.era",
Usage: "Root directory for era1 history (default = inside ancient/chain)",
Category: flags.EthCategory,
}
MinFreeDiskSpaceFlag = &flags.DirectoryFlag{ MinFreeDiskSpaceFlag = &flags.DirectoryFlag{
Name: "datadir.minfreedisk", Name: "datadir.minfreedisk",
Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)", Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)",
@ -145,7 +150,7 @@ var (
} }
SepoliaFlag = &cli.BoolFlag{ SepoliaFlag = &cli.BoolFlag{
Name: "sepolia", Name: "sepolia",
Usage: "Sepolia network: pre-configured proof-of-work test network", Usage: "Sepolia network: pre-configured proof-of-stake test network",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
HoleskyFlag = &cli.BoolFlag{ HoleskyFlag = &cli.BoolFlag{
@ -238,9 +243,9 @@ var (
Value: 2048, Value: 2048,
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverridePrague = &cli.Uint64Flag{ OverrideOsaka = &cli.Uint64Flag{
Name: "override.prague", Name: "override.osaka",
Usage: "Manually specify the Prague fork timestamp, overriding the bundled setting", Usage: "Manually specify the Osaka fork timestamp, overriding the bundled setting",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverrideVerkle = &cli.Uint64Flag{ OverrideVerkle = &cli.Uint64Flag{
@ -977,6 +982,7 @@ var (
DatabaseFlags = []cli.Flag{ DatabaseFlags = []cli.Flag{
DataDirFlag, DataDirFlag,
AncientFlag, AncientFlag,
EraFlag,
RemoteDBFlag, RemoteDBFlag,
DBEngineFlag, DBEngineFlag,
StateSchemeFlag, StateSchemeFlag,
@ -984,6 +990,12 @@ var (
} }
) )
// default account to prefund when running Geth in dev mode
var (
DeveloperKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
DeveloperAddr = crypto.PubkeyToAddress(DeveloperKey.PublicKey)
)
// MakeDataDir retrieves the currently requested data directory, terminating // MakeDataDir retrieves the currently requested data directory, terminating
// if none (or the empty string) is specified. If the node is starting a testnet, // if none (or the empty string) is specified. If the node is starting a testnet,
// then a subdirectory of the specified datadir will be used. // then a subdirectory of the specified datadir will be used.
@ -1245,28 +1257,6 @@ func setIPC(ctx *cli.Context, cfg *node.Config) {
} }
} }
// setLes shows the deprecation warnings for LES flags.
func setLes(ctx *cli.Context, cfg *ethconfig.Config) {
if ctx.IsSet(LightServeFlag.Name) {
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightServeFlag.Name)
}
if ctx.IsSet(LightIngressFlag.Name) {
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightIngressFlag.Name)
}
if ctx.IsSet(LightEgressFlag.Name) {
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightEgressFlag.Name)
}
if ctx.IsSet(LightMaxPeersFlag.Name) {
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightMaxPeersFlag.Name)
}
if ctx.IsSet(LightNoPruneFlag.Name) {
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoPruneFlag.Name)
}
if ctx.IsSet(LightNoSyncServeFlag.Name) {
log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoSyncServeFlag.Name)
}
}
// MakeDatabaseHandles raises out the number of allowed file handles per process // MakeDatabaseHandles raises out the number of allowed file handles per process
// for Geth and returns half of the allowance to assign to the database. // for Geth and returns half of the allowance to assign to the database.
func MakeDatabaseHandles(max int) int { func MakeDatabaseHandles(max int) int {
@ -1582,7 +1572,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
setBlobPool(ctx, &cfg.BlobPool) setBlobPool(ctx, &cfg.BlobPool)
setMiner(ctx, &cfg.Miner) setMiner(ctx, &cfg.Miner)
setRequiredBlocks(ctx, cfg) setRequiredBlocks(ctx, cfg)
setLes(ctx, cfg)
// Cap the cache allowance and tune the garbage collector // Cap the cache allowance and tune the garbage collector
mem, err := gopsutil.VirtualMemory() mem, err := gopsutil.VirtualMemory()
@ -1630,6 +1619,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(AncientFlag.Name) { if ctx.IsSet(AncientFlag.Name) {
cfg.DatabaseFreezer = ctx.String(AncientFlag.Name) cfg.DatabaseFreezer = ctx.String(AncientFlag.Name)
} }
if ctx.IsSet(EraFlag.Name) {
cfg.DatabaseEra = ctx.String(EraFlag.Name)
}
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
@ -1669,11 +1661,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.TransactionHistory = 0 cfg.TransactionHistory = 0
log.Warn("Disabled transaction unindexing for archive node") 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) { if ctx.IsSet(LogHistoryFlag.Name) {
cfg.LogHistory = ctx.Uint64(LogHistoryFlag.Name) cfg.LogHistory = ctx.Uint64(LogHistoryFlag.Name)
@ -1792,9 +1779,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
} else if accs := ks.Accounts(); len(accs) > 0 { } else if accs := ks.Accounts(); len(accs) > 0 {
developer = ks.Accounts()[0] developer = ks.Accounts()[0]
} else { } else {
developer, err = ks.NewAccount(passphrase) developer, err = ks.ImportECDSA(DeveloperKey, passphrase)
if err != nil { if err != nil {
Fatalf("Failed to create developer account: %v", err) Fatalf("Failed to import developer account: %v", err)
} }
} }
// Make sure the address is configured as fee recipient, otherwise // Make sure the address is configured as fee recipient, otherwise
@ -1809,14 +1796,18 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
} }
log.Info("Using developer account", "address", developer.Address) log.Info("Using developer account", "address", developer.Address)
// Create a new developer genesis block or reuse existing one // configure default developer genesis which will be used unless a
// datadir is specified and a chain is preexisting at that location.
cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), &developer.Address) cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), &developer.Address)
// If a datadir is specified, ensure that any preexisting chain in that location
// has a configuration that is compatible with dev mode: it must be merged at genesis.
if ctx.IsSet(DataDirFlag.Name) { if ctx.IsSet(DataDirFlag.Name) {
chaindb := tryMakeReadOnlyDatabase(ctx, stack) chaindb := tryMakeReadOnlyDatabase(ctx, stack)
if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) { if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
cfg.Genesis = nil // fallback to db content // signal fallback to preexisting chain on disk
cfg.Genesis = nil
//validate genesis has PoS enabled in block 0
genesis, err := core.ReadGenesis(chaindb) genesis, err := core.ReadGenesis(chaindb)
if err != nil { if err != nil {
Fatalf("Could not read genesis from database: %v", err) Fatalf("Could not read genesis from database: %v", err)
@ -1900,11 +1891,11 @@ func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig {
if c, err := hexutil.Decode(ctx.String(BeaconGenesisRootFlag.Name)); err == nil && len(c) <= 32 { if c, err := hexutil.Decode(ctx.String(BeaconGenesisRootFlag.Name)); err == nil && len(c) <= 32 {
copy(config.GenesisValidatorsRoot[:len(c)], c) copy(config.GenesisValidatorsRoot[:len(c)], c)
} else { } 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) configFile := ctx.String(BeaconConfigFlag.Name)
if err := config.ChainConfig.LoadForks(configFile); err != nil { 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) log.Info("Using custom beacon chain config", "file", configFile)
} else { } else {
@ -1921,17 +1912,17 @@ func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig {
// are saved to the specified file. // are saved to the specified file.
if ctx.IsSet(BeaconCheckpointFileFlag.Name) { if ctx.IsSet(BeaconCheckpointFileFlag.Name) {
if _, err := config.SetCheckpointFile(ctx.String(BeaconCheckpointFileFlag.Name)); err != nil { 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) { if ctx.IsSet(BeaconCheckpointFlag.Name) {
hex := ctx.String(BeaconCheckpointFlag.Name) hex := ctx.String(BeaconCheckpointFlag.Name)
c, err := hexutil.Decode(hex) c, err := hexutil.Decode(hex)
if err != nil { 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 { 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) copy(config.Checkpoint[:len(c)], c)
} }
@ -2043,7 +2034,6 @@ func SetupMetrics(cfg *metrics.Config) {
log.Info("Enabling metrics export to InfluxDB") log.Info("Enabling metrics export to InfluxDB")
go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
} else if enableExportV2 { } else if enableExportV2 {
tagsMap := SplitTagsFlag(cfg.InfluxDBTags)
log.Info("Enabling metrics export to InfluxDB (v2)") log.Info("Enabling metrics export to InfluxDB (v2)")
go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap) go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap)
} }
@ -2096,7 +2086,15 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
} }
chainDb = remotedb.New(client) chainDb = remotedb.New(client)
default: default:
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "eth/db/chaindata/", readonly) options := node.DatabaseOptions{
ReadOnly: readonly,
Cache: cache,
Handles: handles,
AncientsDirectory: ctx.String(AncientFlag.Name),
MetricsNamespace: "eth/db/chaindata/",
EraDirectory: ctx.String(EraFlag.Name),
}
chainDb, err = stack.OpenDatabaseWithOptions("chaindata", options)
} }
if err != nil { if err != nil {
Fatalf("Could not open database: %v", err) Fatalf("Could not open database: %v", err)
@ -2188,36 +2186,38 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
if err != nil { if err != nil {
Fatalf("%v", err) Fatalf("%v", err)
} }
cache := &core.CacheConfig{ options := &core.BlockChainConfig{
TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, TrieCleanLimit: ethconfig.Defaults.TrieCleanCache,
TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), NoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name),
TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache,
TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive", ArchiveMode: ctx.String(GCModeFlag.Name) == "archive",
TrieTimeLimit: ethconfig.Defaults.TrieTimeout, TrieTimeLimit: ethconfig.Defaults.TrieTimeout,
SnapshotLimit: ethconfig.Defaults.SnapshotCache, SnapshotLimit: ethconfig.Defaults.SnapshotCache,
Preimages: ctx.Bool(CachePreimagesFlag.Name), Preimages: ctx.Bool(CachePreimagesFlag.Name),
StateScheme: scheme, StateScheme: scheme,
StateHistory: ctx.Uint64(StateHistoryFlag.Name), StateHistory: ctx.Uint64(StateHistoryFlag.Name),
// Disable transaction indexing/unindexing.
TxLookupLimit: -1,
} }
if cache.TrieDirtyDisabled && !cache.Preimages { if options.ArchiveMode && !options.Preimages {
cache.Preimages = true options.Preimages = true
log.Info("Enabling recording of key preimages since archive mode is used") log.Info("Enabling recording of key preimages since archive mode is used")
} }
if !ctx.Bool(SnapshotFlag.Name) { if !ctx.Bool(SnapshotFlag.Name) {
cache.SnapshotLimit = 0 // Disabled options.SnapshotLimit = 0 // Disabled
} else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) { } 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 we're in readonly, do not bother generating snapshot data.
if readonly { if readonly {
cache.SnapshotNoBuild = true options.SnapshotNoBuild = true
} }
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { 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) { 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{ vmcfg := vm.Config{
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name), EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
@ -2232,8 +2232,9 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
vmcfg.Tracer = t vmcfg.Tracer = t
} }
} }
// Disable transaction indexing/unindexing by default. options.VmConfig = vmcfg
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil)
chain, err := core.NewBlockChain(chainDb, gspec, engine, options)
if err != nil { if err != nil {
Fatalf("Can't create BlockChain: %v", err) Fatalf("Can't create BlockChain: %v", err)
} }

View file

@ -39,12 +39,6 @@ var DeprecatedFlags = []cli.Flag{
CacheTrieRejournalFlag, CacheTrieRejournalFlag,
LegacyDiscoveryV5Flag, LegacyDiscoveryV5Flag,
TxLookupLimitFlag, TxLookupLimitFlag,
LightServeFlag,
LightIngressFlag,
LightEgressFlag,
LightMaxPeersFlag,
LightNoPruneFlag,
LightNoSyncServeFlag,
LogBacktraceAtFlag, LogBacktraceAtFlag,
LogDebugFlag, LogDebugFlag,
MinerNewPayloadTimeoutFlag, MinerNewPayloadTimeoutFlag,
@ -88,37 +82,6 @@ var (
Value: ethconfig.Defaults.TransactionHistory, Value: ethconfig.Defaults.TransactionHistory,
Category: flags.DeprecatedCategory, Category: flags.DeprecatedCategory,
} }
// Light server and client settings, Deprecated November 2023
LightServeFlag = &cli.IntFlag{
Name: "light.serve",
Usage: "Maximum percentage of time allowed for serving LES requests (deprecated)",
Category: flags.DeprecatedCategory,
}
LightIngressFlag = &cli.IntFlag{
Name: "light.ingress",
Usage: "Incoming bandwidth limit for serving light clients (deprecated)",
Category: flags.DeprecatedCategory,
}
LightEgressFlag = &cli.IntFlag{
Name: "light.egress",
Usage: "Outgoing bandwidth limit for serving light clients (deprecated)",
Category: flags.DeprecatedCategory,
}
LightMaxPeersFlag = &cli.IntFlag{
Name: "light.maxpeers",
Usage: "Maximum number of light clients to serve, or light servers to attach to (deprecated)",
Category: flags.DeprecatedCategory,
}
LightNoPruneFlag = &cli.BoolFlag{
Name: "light.nopruning",
Usage: "Disable ancient light chain data pruning (deprecated)",
Category: flags.DeprecatedCategory,
}
LightNoSyncServeFlag = &cli.BoolFlag{
Name: "light.nosyncserve",
Usage: "Enables serving light clients before syncing (deprecated)",
Category: flags.DeprecatedCategory,
}
// Deprecated November 2023 // Deprecated November 2023
LogBacktraceAtFlag = &cli.StringFlag{ LogBacktraceAtFlag = &cli.StringFlag{
Name: "log.backtrace", Name: "log.backtrace",

View file

@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/internal/era" "github.com/ethereum/go-ethereum/internal/era"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -78,7 +77,7 @@ func TestHistoryImportAndExport(t *testing.T) {
}) })
// Initialize BlockChain. // 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 { if err != nil {
t.Fatalf("unable to initialize chain: %v", err) t.Fatalf("unable to initialize chain: %v", err)
} }
@ -158,7 +157,7 @@ func TestHistoryImportAndExport(t *testing.T) {
} }
// Now import Era. // Now import Era.
db2, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) db2, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -167,7 +166,7 @@ func TestHistoryImportAndExport(t *testing.T) {
}) })
genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults)) 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 { if err != nil {
t.Fatalf("unable to initialize chain: %v", err) t.Fatalf("unable to initialize chain: %v", err)
} }

View file

@ -26,4 +26,5 @@ the following commands (in this directory) against a synced mainnet node:
```shell ```shell
> go run . filtergen --queries queries/filter_queries_mainnet.json http://host:8545 > 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 . historygen --history-tests queries/history_mainnet.json http://host:8545
> go run . tracegen --trace-tests queries/trace_mainnet.json http://host:8545
``` ```

104
cmd/workload/client.go Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
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
}

View file

@ -45,11 +45,11 @@ func newFilterTestSuite(cfg testConfig) *filterTestSuite {
return s return s
} }
func (s *filterTestSuite) allTests() []utesting.Test { func (s *filterTestSuite) allTests() []workloadTest {
return []utesting.Test{ return []workloadTest{
{Name: "Filter/ShortRange", Fn: s.filterShortRange}, newWorkLoadTest("Filter/ShortRange", s.filterShortRange),
{Name: "Filter/LongRange", Fn: s.filterLongRange, Slow: true}, newSlowWorkloadTest("Filter/LongRange", s.filterLongRange),
{Name: "Filter/FullRange", Fn: s.filterFullRange, Slow: true}, newSlowWorkloadTest("Filter/FullRange", s.filterFullRange),
} }
} }

View file

@ -23,7 +23,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/utesting" "github.com/ethereum/go-ethereum/internal/utesting"
) )
@ -65,40 +64,16 @@ func (s *historyTestSuite) loadTests() error {
return nil return nil
} }
func (s *historyTestSuite) allTests() []utesting.Test { func (s *historyTestSuite) allTests() []workloadTest {
return []utesting.Test{ return []workloadTest{
{ newWorkLoadTest("History/getBlockByHash", s.testGetBlockByHash),
Name: "History/getBlockByHash", newWorkLoadTest("History/getBlockByNumber", s.testGetBlockByNumber),
Fn: s.testGetBlockByHash, newWorkLoadTest("History/getBlockReceiptsByHash", s.testGetBlockReceiptsByHash),
}, newWorkLoadTest("History/getBlockReceiptsByNumber", s.testGetBlockReceiptsByNumber),
{ newWorkLoadTest("History/getBlockTransactionCountByHash", s.testGetBlockTransactionCountByHash),
Name: "History/getBlockByNumber", newWorkLoadTest("History/getBlockTransactionCountByNumber", s.testGetBlockTransactionCountByNumber),
Fn: s.testGetBlockByNumber, newWorkLoadTest("History/getTransactionByBlockHashAndIndex", s.testGetTransactionByBlockHashAndIndex),
}, newWorkLoadTest("History/getTransactionByBlockNumberAndIndex", s.testGetTransactionByBlockNumberAndIndex),
{
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,
},
} }
} }
@ -279,55 +254,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
}

View file

@ -51,7 +51,7 @@ var (
} }
historyTestEarliestFlag = &cli.IntFlag{ historyTestEarliestFlag = &cli.IntFlag{
Name: "earliest", Name: "earliest",
Usage: "JSON file containing filter test queries", Usage: "The earliest block to test queries",
Value: 0, Value: 0,
Category: flags.TestingCategory, Category: flags.TestingCategory,
} }
@ -139,7 +139,7 @@ func calcReceiptsHash(rcpt []*types.Receipt) common.Hash {
func writeJSON(fileName string, value any) { func writeJSON(fileName string, value any) {
file, err := os.Create(fileName) file, err := os.Create(fileName)
if err != nil { if err != nil {
exit(fmt.Errorf("Error creating %s: %v", fileName, err)) exit(fmt.Errorf("error creating %s: %v", fileName, err))
return return
} }
defer file.Close() defer file.Close()

View file

@ -20,10 +20,8 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/rpc"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@ -49,6 +47,7 @@ func init() {
runTestCommand, runTestCommand,
historyGenerateCommand, historyGenerateCommand,
filterGenerateCommand, filterGenerateCommand,
traceGenerateCommand,
filterPerfCommand, filterPerfCommand,
} }
} }
@ -57,26 +56,6 @@ func main() {
exit(app.Run(os.Args)) 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) { func exit(err any) {
if err == nil { if err == nil {
os.Exit(0) os.Exit(0)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -21,7 +21,6 @@ import (
"fmt" "fmt"
"io/fs" "io/fs"
"os" "os"
"slices"
"github.com/ethereum/go-ethereum/core/history" "github.com/ethereum/go-ethereum/core/history"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
@ -45,10 +44,13 @@ var (
testPatternFlag, testPatternFlag,
testTAPFlag, testTAPFlag,
testSlowFlag, testSlowFlag,
testArchiveFlag,
testSepoliaFlag, testSepoliaFlag,
testMainnetFlag, testMainnetFlag,
filterQueryFileFlag, filterQueryFileFlag,
historyTestFileFlag, historyTestFileFlag,
traceTestFileFlag,
traceTestInvalidOutputFlag,
}, },
} }
testPatternFlag = &cli.StringFlag{ testPatternFlag = &cli.StringFlag{
@ -67,6 +69,12 @@ var (
Value: false, Value: false,
Category: flags.TestingCategory, Category: flags.TestingCategory,
} }
testArchiveFlag = &cli.BoolFlag{
Name: "archive",
Usage: "Enable archive tests",
Value: false,
Category: flags.TestingCategory,
}
testSepoliaFlag = &cli.BoolFlag{ testSepoliaFlag = &cli.BoolFlag{
Name: "sepolia", Name: "sepolia",
Usage: "Use test cases for sepolia network", Usage: "Use test cases for sepolia network",
@ -86,6 +94,7 @@ type testConfig struct {
filterQueryFile string filterQueryFile string
historyTestFile string historyTestFile string
historyPruneBlock *uint64 historyPruneBlock *uint64
traceTestFile string
} }
var errPrunedHistory = fmt.Errorf("attempt to access pruned history") var errPrunedHistory = fmt.Errorf("attempt to access pruned history")
@ -125,36 +134,85 @@ func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) {
cfg.historyTestFile = "queries/history_mainnet.json" cfg.historyTestFile = "queries/history_mainnet.json"
cfg.historyPruneBlock = new(uint64) cfg.historyPruneBlock = new(uint64)
*cfg.historyPruneBlock = history.PrunePoints[params.MainnetGenesisHash].BlockNumber *cfg.historyPruneBlock = history.PrunePoints[params.MainnetGenesisHash].BlockNumber
cfg.traceTestFile = "queries/trace_mainnet.json"
case ctx.Bool(testSepoliaFlag.Name): case ctx.Bool(testSepoliaFlag.Name):
cfg.fsys = builtinTestFiles cfg.fsys = builtinTestFiles
cfg.filterQueryFile = "queries/filter_queries_sepolia.json" cfg.filterQueryFile = "queries/filter_queries_sepolia.json"
cfg.historyTestFile = "queries/history_sepolia.json" cfg.historyTestFile = "queries/history_sepolia.json"
cfg.historyPruneBlock = new(uint64) cfg.historyPruneBlock = new(uint64)
*cfg.historyPruneBlock = history.PrunePoints[params.SepoliaGenesisHash].BlockNumber *cfg.historyPruneBlock = history.PrunePoints[params.SepoliaGenesisHash].BlockNumber
cfg.traceTestFile = "queries/trace_sepolia.json"
default: default:
cfg.fsys = os.DirFS(".") cfg.fsys = os.DirFS(".")
cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name) cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name)
cfg.historyTestFile = ctx.String(historyTestFileFlag.Name) cfg.historyTestFile = ctx.String(historyTestFileFlag.Name)
cfg.traceTestFile = ctx.String(traceTestFileFlag.Name)
} }
return cfg 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 { func runTestCmd(ctx *cli.Context) error {
cfg := testConfigFromCLI(ctx) cfg := testConfigFromCLI(ctx)
filterSuite := newFilterTestSuite(cfg) filterSuite := newFilterTestSuite(cfg)
historySuite := newHistoryTestSuite(cfg) historySuite := newHistoryTestSuite(cfg)
traceSuite := newTraceTestSuite(cfg, ctx)
// Filter test cases. // Filter test cases.
tests := filterSuite.allTests() tests := filterSuite.allTests()
tests = append(tests, historySuite.allTests()...) tests = append(tests, historySuite.allTests()...)
if ctx.IsSet(testPatternFlag.Name) { tests = append(tests, traceSuite.allTests()...)
tests = utesting.MatchTests(tests, ctx.String(testPatternFlag.Name))
utests := filterTests(tests, ctx.String(testPatternFlag.Name), func(t workloadTest) bool {
if t.Slow && !ctx.Bool(testSlowFlag.Name) {
return false
} }
if !ctx.Bool(testSlowFlag.Name) { if t.archive && !ctx.Bool(testArchiveFlag.Name) {
tests = slices.DeleteFunc(tests, func(test utesting.Test) bool { return false
return test.Slow }
return true
}) })
}
// Disable logging unless explicitly enabled. // Disable logging unless explicitly enabled.
if !ctx.IsSet("verbosity") && !ctx.IsSet("vmodule") { if !ctx.IsSet("verbosity") && !ctx.IsSet("vmodule") {
@ -166,7 +224,7 @@ func runTestCmd(ctx *cli.Context) error {
if ctx.Bool(testTAPFlag.Name) { if ctx.Bool(testTAPFlag.Name) {
run = utesting.RunTAP run = utesting.RunTAP
} }
results := run(tests, os.Stdout) results := run(utests, os.Stdout)
if utesting.CountFailures(results) > 0 { if utesting.CountFailures(results) > 0 {
os.Exit(1) os.Exit(1)
} }

126
cmd/workload/tracetest.go Normal file
View file

@ -0,0 +1,126 @@
// Copyright 2025 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package 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 {
TxHashes []common.Hash `json:"txHashes"`
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 {
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.TxHashes) == 0 {
return fmt.Errorf("traceTestFile %s has no test data", s.cfg.traceTestFile)
}
return nil
}
func (s *traceTestSuite) allTests() []workloadTest {
return []workloadTest{
newArchiveWorkloadTest("Trace/Transaction", s.traceTransaction),
}
}
// traceTransaction runs all transaction tracing tests
func (s *traceTestSuite) traceTransaction(t *utesting.T) {
ctx := context.Background()
for i, hash := range s.tests.TxHashes {
config := s.tests.TraceConfigs[i]
result, err := s.cfg.client.Geth.TraceTransaction(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
}
}

View file

@ -0,0 +1,195 @@
// Copyright 2025 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>
package 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 (
defaultBlocksToTrace = 64 // the number of states assumed to be available
traceGenerateCommand = &cli.Command{
Name: "tracegen",
Usage: "Generates tests for state tracing",
ArgsUsage: "<RPC endpoint URL>",
Action: generateTraceTests,
Flags: []cli.Flag{
traceTestFileFlag,
traceTestResultOutputFlag,
traceTestBlockFlag,
},
}
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 the trace output files",
Value: "",
Category: flags.TestingCategory,
}
traceTestBlockFlag = &cli.IntFlag{
Name: "trace-blocks",
Usage: "The number of blocks for tracing",
Value: defaultBlocksToTrace,
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)
blocks = clictx.Int(traceTestBlockFlag.Name)
ctx = context.Background()
test = new(traceTest)
)
if outputDir != "" {
err := os.MkdirAll(outputDir, os.ModePerm)
if err != nil {
return err
}
}
latest, err := client.Eth.BlockNumber(ctx)
if err != nil {
exit(err)
}
if latest < uint64(blocks) {
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, "blocks", blocks)
for i := 0; i < blocks; i++ {
number := latest - uint64(i)
block, err := client.Eth.BlockByNumber(ctx, big.NewInt(int64(number)))
if err != nil {
exit(err)
}
for _, tx := range block.Transactions() {
config, configName := randomTraceOption()
result, err := client.Geth.TraceTransaction(ctx, tx.Hash(), config)
if err != nil {
failed += 1
break
}
blob, err := json.Marshal(result)
if err != nil {
failed += 1
break
}
test.TxHashes = append(test.TxHashes, tx.Hash())
test.TraceConfigs = append(test.TraceConfigs, *config)
test.ResultHashes = append(test.ResultHashes, crypto.Keccak256Hash(blob))
writeTraceResult(outputDir, tx.Hash(), result, configName)
}
if time.Since(logged) > time.Second*8 {
logged = time.Now()
log.Info("Tracing transactions", "executed", len(test.TxHashes), "failed", failed, "elapsed", common.PrettyDuration(time.Since(start)))
}
}
log.Info("Traced transactions", "executed", len(test.TxHashes), "failed", failed, "elapsed", common.PrettyDuration(time.Since(start)))
// Write output file.
writeJSON(outputFile, test)
return nil
}
func randomTraceOption() (*tracers.TraceConfig, string) {
x := rand.Intn(11)
if x == 0 {
// struct-logger, with all fields enabled, very heavy
return &tracers.TraceConfig{
Config: &logger.Config{
EnableMemory: true,
EnableReturnData: true,
},
}, "structAll"
}
if x == 1 {
// default options for struct-logger, with stack and storage capture
// enabled
return &tracers.TraceConfig{
Config: &logger.Config{},
}, "structDefault"
}
if x == 2 || x == 3 || x == 4 {
// 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-5],
}, loggers[x-5]
}
func writeTraceResult(dir string, hash common.Hash, result any, configName string) {
if dir == "" {
return
}
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
}
}

View file

@ -47,30 +47,37 @@ func NewBasicLRU[K comparable, V any](capacity int) BasicLRU[K, V] {
// Add adds a value to the cache. Returns true if an item was evicted to store the new item. // Add adds a value to the cache. Returns true if an item was evicted to store the new item.
func (c *BasicLRU[K, V]) Add(key K, value V) (evicted bool) { func (c *BasicLRU[K, V]) Add(key K, value V) (evicted bool) {
_, _, evicted = c.Add3(key, value)
return evicted
}
// Add3 adds a value to the cache. If an item was evicted to store the new one, it returns the evicted item.
func (c *BasicLRU[K, V]) Add3(key K, value V) (ek K, ev V, evicted bool) {
item, ok := c.items[key] item, ok := c.items[key]
if ok { if ok {
// Already exists in cache.
item.value = value item.value = value
c.items[key] = item c.items[key] = item
c.list.moveToFront(item.elem) c.list.moveToFront(item.elem)
return false return ek, ev, false
} }
var elem *listElem[K] var elem *listElem[K]
if c.Len() >= c.cap { if c.Len() >= c.cap {
elem = c.list.removeLast() elem = c.list.removeLast()
delete(c.items, elem.v)
evicted = true evicted = true
ek = elem.v
ev = c.items[ek].value
delete(c.items, ek)
} else { } else {
elem = new(listElem[K]) elem = new(listElem[K])
} }
// Store the new item. // Store the new item.
// Note that, if another item was evicted, we re-use its list element here. // Note that if another item was evicted, we re-use its list element here.
elem.v = key elem.v = key
c.items[key] = cacheItem[K, V]{elem, value} c.items[key] = cacheItem[K, V]{elem, value}
c.list.pushElem(elem) c.list.pushElem(elem)
return evicted return ek, ev, evicted
} }
// Contains reports whether the given key exists in the cache. // Contains reports whether the given key exists in the cache.

View file

@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
@ -392,8 +391,12 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
if err != nil { if err != nil {
return nil, fmt.Errorf("error opening pre-state tree root: %w", err) 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) 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 // The witness is only attached iff both parent and current block are
// using verkle tree. // using verkle tree.
@ -445,11 +448,6 @@ func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uin
return beaconDifficulty return beaconDifficulty
} }
// APIs implements consensus.Engine, returning the user facing RPC APIs.
func (beacon *Beacon) APIs(chain consensus.ChainHeaderReader) []rpc.API {
return beacon.ethone.APIs(chain)
}
// Close shutdowns the consensus engine // Close shutdowns the consensus engine
func (beacon *Beacon) Close() error { func (beacon *Beacon) Close() error {
return beacon.ethone.Close() return beacon.ethone.Close()

View file

@ -1,235 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package clique
import (
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
)
// API is a user facing RPC API to allow controlling the signer and voting
// mechanisms of the proof-of-authority scheme.
type API struct {
chain consensus.ChainHeaderReader
clique *Clique
}
// GetSnapshot retrieves the state snapshot at a given block.
func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
// Retrieve the requested block number (or current if none requested)
var header *types.Header
if number == nil || *number == rpc.LatestBlockNumber {
header = api.chain.CurrentHeader()
} else {
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
}
// Ensure we have an actually valid block and return its snapshot
if header == nil {
return nil, errUnknownBlock
}
return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
}
// GetSnapshotAtHash retrieves the state snapshot at a given block.
func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) {
header := api.chain.GetHeaderByHash(hash)
if header == nil {
return nil, errUnknownBlock
}
return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
}
// GetSigners retrieves the list of authorized signers at the specified block.
func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) {
// Retrieve the requested block number (or current if none requested)
var header *types.Header
if number == nil || *number == rpc.LatestBlockNumber {
header = api.chain.CurrentHeader()
} else {
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
}
// Ensure we have an actually valid block and return the signers from its snapshot
if header == nil {
return nil, errUnknownBlock
}
snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
if err != nil {
return nil, err
}
return snap.signers(), nil
}
// GetSignersAtHash retrieves the list of authorized signers at the specified block.
func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) {
header := api.chain.GetHeaderByHash(hash)
if header == nil {
return nil, errUnknownBlock
}
snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
if err != nil {
return nil, err
}
return snap.signers(), nil
}
// Proposals returns the current proposals the node tries to uphold and vote on.
func (api *API) Proposals() map[common.Address]bool {
api.clique.lock.RLock()
defer api.clique.lock.RUnlock()
proposals := make(map[common.Address]bool)
for address, auth := range api.clique.proposals {
proposals[address] = auth
}
return proposals
}
// Propose injects a new authorization proposal that the signer will attempt to
// push through.
func (api *API) Propose(address common.Address, auth bool) {
api.clique.lock.Lock()
defer api.clique.lock.Unlock()
api.clique.proposals[address] = auth
}
// Discard drops a currently running proposal, stopping the signer from casting
// further votes (either for or against).
func (api *API) Discard(address common.Address) {
api.clique.lock.Lock()
defer api.clique.lock.Unlock()
delete(api.clique.proposals, address)
}
type status struct {
InturnPercent float64 `json:"inturnPercent"`
SigningStatus map[common.Address]int `json:"sealerActivity"`
NumBlocks uint64 `json:"numBlocks"`
}
// Status returns the status of the last N blocks,
// - the number of active signers,
// - the number of signers,
// - the percentage of in-turn blocks
func (api *API) Status() (*status, error) {
var (
numBlocks = uint64(64)
header = api.chain.CurrentHeader()
diff = uint64(0)
optimals = 0
)
snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
if err != nil {
return nil, err
}
var (
signers = snap.signers()
end = header.Number.Uint64()
start = end - numBlocks
)
if numBlocks > end {
start = 1
numBlocks = end - start
}
signStatus := make(map[common.Address]int)
for _, s := range signers {
signStatus[s] = 0
}
for n := start; n < end; n++ {
h := api.chain.GetHeaderByNumber(n)
if h == nil {
return nil, fmt.Errorf("missing block %d", n)
}
if h.Difficulty.Cmp(diffInTurn) == 0 {
optimals++
}
diff += h.Difficulty.Uint64()
sealer, err := api.clique.Author(h)
if err != nil {
return nil, err
}
signStatus[sealer]++
}
return &status{
InturnPercent: float64(100*optimals) / float64(numBlocks),
SigningStatus: signStatus,
NumBlocks: numBlocks,
}, nil
}
type blockNumberOrHashOrRLP struct {
*rpc.BlockNumberOrHash
RLP hexutil.Bytes `json:"rlp,omitempty"`
}
func (sb *blockNumberOrHashOrRLP) UnmarshalJSON(data []byte) error {
bnOrHash := new(rpc.BlockNumberOrHash)
// Try to unmarshal bNrOrHash
if err := bnOrHash.UnmarshalJSON(data); err == nil {
sb.BlockNumberOrHash = bnOrHash
return nil
}
// Try to unmarshal RLP
var input string
if err := json.Unmarshal(data, &input); err != nil {
return err
}
blob, err := hexutil.Decode(input)
if err != nil {
return err
}
sb.RLP = blob
return nil
}
// GetSigner returns the signer for a specific clique block.
// Can be called with a block number, a block hash or a rlp encoded blob.
// The RLP encoded blob can either be a block or a header.
func (api *API) GetSigner(rlpOrBlockNr *blockNumberOrHashOrRLP) (common.Address, error) {
if len(rlpOrBlockNr.RLP) == 0 {
blockNrOrHash := rlpOrBlockNr.BlockNumberOrHash
var header *types.Header
if blockNrOrHash == nil {
header = api.chain.CurrentHeader()
} else if hash, ok := blockNrOrHash.Hash(); ok {
header = api.chain.GetHeaderByHash(hash)
} else if number, ok := blockNrOrHash.Number(); ok {
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
}
if header == nil {
return common.Address{}, fmt.Errorf("missing block %v", blockNrOrHash.String())
}
return api.clique.Author(header)
}
block := new(types.Block)
if err := rlp.DecodeBytes(rlpOrBlockNr.RLP, block); err == nil {
return api.clique.Author(block.Header())
}
header := new(types.Header)
if err := rlp.DecodeBytes(rlpOrBlockNr.RLP, header); err != nil {
return common.Address{}, err
}
return api.clique.Author(header)
}

View file

@ -41,7 +41,6 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
@ -641,15 +640,6 @@ func (c *Clique) Close() error {
return nil return nil
} }
// APIs implements consensus.Engine, returning the user facing RPC API to allow
// controlling the signer voting.
func (c *Clique) APIs(chain consensus.ChainHeaderReader) []rpc.API {
return []rpc.API{{
Namespace: "clique",
Service: &API{chain: chain, clique: c},
}}
}
// SealHash returns the hash of a block prior to it being sealed. // SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header) (hash common.Hash) { func SealHash(header *types.Header) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256() hasher := sha3.NewLegacyKeccak256()

View file

@ -24,7 +24,6 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -55,7 +54,7 @@ func TestReimportMirroredState(t *testing.T) {
copy(genspec.ExtraData[extraVanity:], addr[:]) copy(genspec.ExtraData[extraVanity:], addr[:])
// Generate a batch of blocks, each properly signed // 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() defer chain.Stop()
_, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) { _, 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 // Insert the first two blocks and make sure the chain is valid
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil) chain, _ = core.NewBlockChain(db, genspec, engine, nil)
defer chain.Stop() defer chain.Stop()
if _, err := chain.InsertChain(blocks[:2]); err != nil { 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 // 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 // flushing the dirty states out. Insert the last block, triggering a sidechain
// reimport. // reimport.
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil) chain, _ = core.NewBlockChain(db, genspec, engine, nil)
defer chain.Stop() defer chain.Stop()
if _, err := chain.InsertChain(blocks[2:]); err != nil { if _, err := chain.InsertChain(blocks[2:]); err != nil {

View file

@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/params" "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) batches[len(batches)-1] = append(batches[len(batches)-1], block)
} }
// Pass all the headers through clique and ensure tallying succeeds // 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 { if err != nil {
t.Fatalf("failed to create test chain: %v", err) t.Fatalf("failed to create test chain: %v", err)
} }

View file

@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
) )
// ChainHeaderReader defines a small collection of methods needed to access the local // ChainHeaderReader defines a small collection of methods needed to access the local
@ -109,9 +108,6 @@ type Engine interface {
// that a new block should have. // that a new block should have.
CalcDifficulty(chain ChainHeaderReader, time uint64, parent *types.Header) *big.Int CalcDifficulty(chain ChainHeaderReader, time uint64, parent *types.Header) *big.Int
// APIs returns the RPC APIs this consensus engine provides.
APIs(chain ChainHeaderReader) []rpc.API
// Close terminates any background threads maintained by the consensus engine. // Close terminates any background threads maintained by the consensus engine.
Close() error Close() error
} }

View file

@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
) )
// Ethash is a consensus engine based on proof-of-work implementing the ethash // Ethash is a consensus engine based on proof-of-work implementing the ethash
@ -71,12 +70,6 @@ func (ethash *Ethash) Close() error {
return nil return nil
} }
// APIs implements consensus.Engine, returning no APIs as ethash is an empty
// shell in the post-merge world.
func (ethash *Ethash) APIs(chain consensus.ChainHeaderReader) []rpc.API {
return []rpc.API{}
}
// Seal generates a new sealing request for the given input block and pushes // Seal generates a new sealing request for the given input block and pushes
// the result into the given channel. For the ethash engine, this method will // the result into the given channel. For the ethash engine, this method will
// just panic as sealing is not supported anymore. // just panic as sealing is not supported anymore.

View file

@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/pebble" "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. // Time the insertion of the new chain.
// State and blocks are stored in the same DB. // 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() defer chainman.Stop()
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
@ -325,9 +324,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
genesis := &Genesis{Config: params.AllEthashProtocolChanges} genesis := &Genesis{Config: params.AllEthashProtocolChanges}
makeChainForBench(db, genesis, full, count) makeChainForBench(db, genesis, full, count)
db.Close() db.Close()
cacheConfig := *defaultCacheConfig options := DefaultConfig().WithArchive(true)
cacheConfig.TrieDirtyDisabled = true
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
@ -338,7 +335,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
} }
db = rawdb.NewDatabase(pdb) 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 { if err != nil {
b.Fatalf("error creating chain: %v", err) b.Fatalf("error creating chain: %v", err)
} }

View file

@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -50,7 +49,8 @@ func testHeaderVerification(t *testing.T, scheme string) {
headers[i] = block.Header() headers[i] = block.Header()
} }
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces // 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() defer chain.Stop()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -166,7 +166,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
postHeaders[i] = block.Header() postHeaders[i] = block.Header()
} }
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces // 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() defer chain.Stop()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -66,7 +66,7 @@ var (
headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil) headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil)
chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", 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) accountReadTimer = metrics.NewRegisteredResettingTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredResettingTimer("chain/account/hashes", nil) accountHashTimer = metrics.NewRegisteredResettingTimer("chain/account/hashes", nil)
@ -77,6 +77,16 @@ var (
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil) storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", 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) accountReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/account/single/reads", nil)
storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil) storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil)
@ -151,65 +161,102 @@ const (
BlockChainVersion uint64 = 9 BlockChainVersion uint64 = 9
) )
// CacheConfig contains the configuration values for the trie database // BlockChainConfig contains the configuration of the BlockChain object.
// and state snapshot these are resident in a blockchain. type BlockChainConfig struct {
type CacheConfig struct { // Trie database related options
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory 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 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 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 TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed
Preimages bool // Whether to store preimage of trie key to the disk Preimages bool // Whether to store preimage of trie key to the disk
StateHistory uint64 // Number of blocks from head whose state histories are reserved. 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 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 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 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. // This defines the cutoff block for history expiry.
// Blocks before this number may be unavailable in the chain database. // Blocks before this number may be unavailable in the chain database.
ChainHistoryMode history.HistoryMode 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
} }
// triedbConfig derives the configures for trie database. // DefaultConfig returns the default config.
func (c *CacheConfig) triedbConfig(isVerkle bool) *triedb.Config { // Note the returned object is safe to modify!
config := &triedb.Config{ func DefaultConfig() *BlockChainConfig {
Preimages: c.Preimages, return &BlockChainConfig{
IsVerkle: isVerkle,
}
if c.StateScheme == rawdb.HashScheme {
config.HashDB = &hashdb.Config{
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
}
}
if c.StateScheme == rawdb.PathScheme {
config.PathDB = &pathdb.Config{
StateHistory: c.StateHistory,
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
WriteBufferSize: c.TrieDirtyLimit * 1024 * 1024,
}
}
return config
}
// defaultCacheConfig are the default caching values if none are specified by the
// user (also used during testing).
var defaultCacheConfig = &CacheConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
TrieDirtyLimit: 256, TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
StateScheme: rawdb.HashScheme,
SnapshotLimit: 256, SnapshotLimit: 256,
SnapshotWait: true, SnapshotWait: true,
StateScheme: rawdb.HashScheme, ChainHistoryMode: history.KeepAll,
// Transaction indexing is disabled by default.
// This is appropriate for most unit tests.
TxLookupLimit: -1,
}
} }
// DefaultCacheConfigWithScheme returns a deep copied default cache config with // WithArchive enables/disables archive mode on the config.
// a provided trie node scheme. func (cfg BlockChainConfig) WithArchive(on bool) *BlockChainConfig {
func DefaultCacheConfigWithScheme(scheme string) *CacheConfig { cfg.ArchiveMode = on
config := *defaultCacheConfig return &cfg
config.StateScheme = scheme }
return &config
// 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 (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config {
config := &triedb.Config{
Preimages: cfg.Preimages,
IsVerkle: isVerkle,
}
if cfg.StateScheme == rawdb.HashScheme {
config.HashDB = &hashdb.Config{
CleanCacheSize: cfg.TrieCleanLimit * 1024 * 1024,
}
}
if cfg.StateScheme == rawdb.PathScheme {
config.PathDB = &pathdb.Config{
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: cfg.TrieDirtyLimit * 1024 * 1024,
NoAsyncFlush: cfg.TrieNoAsyncFlush,
}
}
return config
} }
// txLookup is wrapper over transaction lookup along with the corresponding // txLookup is wrapper over transaction lookup along with the corresponding
@ -235,7 +282,7 @@ type txLookup struct {
// canonical chain. // canonical chain.
type BlockChain struct { type BlockChain struct {
chainConfig *params.ChainConfig // Chain & network configuration 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 db ethdb.Database // Low level persistent database to store final content in
snaps *snapshot.Tree // Snapshot tree for fast trie leaf access snaps *snapshot.Tree // Snapshot tree for fast trie leaf access
@ -269,13 +316,12 @@ type BlockChain struct {
bodyCache *lru.Cache[common.Hash, *types.Body] bodyCache *lru.Cache[common.Hash, *types.Body]
bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] 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] blockCache *lru.Cache[common.Hash, *types.Block]
txLookupLock sync.RWMutex txLookupLock sync.RWMutex
txLookupCache *lru.Cache[common.Hash, txLookup] 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 stopping atomic.Bool // false if chain is running, true when stopped
procInterrupt atomic.Bool // interrupt signaler for block processing procInterrupt atomic.Bool // interrupt signaler for block processing
@ -283,7 +329,6 @@ type BlockChain struct {
validator Validator // Block and state validator interface validator Validator // Block and state validator interface
prefetcher Prefetcher prefetcher Prefetcher
processor Processor // Block transaction processor interface processor Processor // Block transaction processor interface
vmConfig vm.Config
logger *tracing.Hooks logger *tracing.Hooks
lastForkReadyAlert time.Time // Last time there was a fork readiness print out lastForkReadyAlert time.Time // Last time there was a fork readiness print out
@ -292,22 +337,23 @@ type BlockChain struct {
// NewBlockChain returns a fully initialised block chain using information // NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialises the default Ethereum Validator // available in the database. It initialises the default Ethereum Validator
// and Processor. // and Processor.
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, txLookupLimit *uint64) (*BlockChain, error) { func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine, cfg *BlockChainConfig) (*BlockChain, error) {
if cacheConfig == nil { if cfg == nil {
cacheConfig = defaultCacheConfig cfg = DefaultConfig()
} }
// Open trie database with provided config // Open trie database with provided config
enableVerkle, err := EnableVerkleAtGenesis(db, genesis) enableVerkle, err := EnableVerkleAtGenesis(db, genesis)
if err != nil { if err != nil {
return nil, err 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 // Write the supplied genesis to the database if it has not been initialized
// yet. The corresponding chain config will be returned, either from the // yet. The corresponding chain config will be returned, either from the
// provided genesis or from the locally stored configuration if the genesis // provided genesis or from the locally stored configuration if the genesis
// has already been initialized. // 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 { if err != nil {
return nil, err return nil, err
} }
@ -321,11 +367,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bc := &BlockChain{ bc := &BlockChain{
chainConfig: chainConfig, chainConfig: chainConfig,
cacheConfig: cacheConfig, cfg: cfg,
db: db, db: db,
triedb: triedb, triedb: triedb,
triegc: prque.New[int64, common.Hash](nil), triegc: prque.New[int64, common.Hash](nil),
quit: make(chan struct{}),
chainmu: syncx.NewClosableMutex(), chainmu: syncx.NewClosableMutex(),
bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit), bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit),
bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit), bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit),
@ -333,14 +378,13 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit), blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit),
txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit), txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit),
engine: engine, engine: engine,
vmConfig: vmConfig, logger: cfg.VmConfig.Tracer,
logger: vmConfig.Tracer,
} }
bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped) bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit)) bc.flushInterval.Store(int64(cfg.TrieTimeLimit))
bc.statedb = state.NewDatabase(bc.triedb, nil) bc.statedb = state.NewDatabase(bc.triedb, nil)
bc.validator = NewBlockValidator(chainConfig, bc) bc.validator = NewBlockValidator(chainConfig, bc)
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc) bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
@ -383,11 +427,14 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
// Do nothing here until the state syncer picks it up. // Do nothing here until the state syncer picks it up.
log.Info("Genesis state is missing, wait state sync") log.Info("Genesis state is missing, wait state sync")
} else { } else {
// Head state is missing, before the state recovery, find out the // Head state is missing, before the state recovery, find out the disk
// disk layer point of snapshot(if it's enabled). Make sure the // layer point of snapshot(if it's enabled). Make sure the rewound point
// rewound point is lower than disk layer. // is lower than disk layer.
//
// Note it's unnecessary in path mode which always keep trie data and
// state data consistent.
var diskRoot common.Hash var diskRoot common.Hash
if bc.cacheConfig.SnapshotLimit > 0 { if bc.cfg.SnapshotLimit > 0 && bc.cfg.StateScheme == rawdb.HashScheme {
diskRoot = rawdb.ReadSnapshotRoot(bc.db) diskRoot = rawdb.ReadSnapshotRoot(bc.db)
} }
if diskRoot != (common.Hash{}) { if diskRoot != (common.Hash{}) {
@ -460,31 +507,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bc.logger.OnGenesisBlock(bc.genesisBlock, alloc) bc.logger.OnGenesisBlock(bc.genesisBlock, alloc)
} }
} }
bc.setupSnapshot()
// Load any existing snapshot, regenerating it if loading failed
if bc.cacheConfig.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
// head mismatch.
var recover bool
head := bc.CurrentBlock()
if layer := rawdb.ReadSnapshotRecoveryNumber(bc.db); layer != nil && *layer >= head.Number.Uint64() {
log.Warn("Enabling snapshot recovery", "chainhead", head.Number, "diskbase", *layer)
recover = true
}
snapconfig := snapshot.Config{
CacheSize: bc.cacheConfig.SnapshotLimit,
Recovery: recover,
NoBuild: bc.cacheConfig.SnapshotNoBuild,
AsyncBuild: !bc.cacheConfig.SnapshotWait,
}
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
// Re-initialize the state database with snapshot
bc.statedb = state.NewDatabase(bc.triedb, bc.snaps)
}
// Rewind the chain in case of an incompatible config upgrade. // Rewind the chain in case of an incompatible config upgrade.
if compatErr != nil { if compatErr != nil {
@ -496,13 +519,45 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
} }
rawdb.WriteChainConfig(db, genesisHash, chainConfig) rawdb.WriteChainConfig(db, genesisHash, chainConfig)
} }
// Start tx indexer if it's enabled. // Start tx indexer if it's enabled.
if txLookupLimit != nil { if bc.cfg.TxLookupLimit >= 0 {
bc.txIndexer = newTxIndexer(*txLookupLimit, bc) bc.txIndexer = newTxIndexer(uint64(bc.cfg.TxLookupLimit), bc)
} }
return bc, nil return bc, nil
} }
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.cfg.StateScheme == rawdb.PathScheme {
return
}
// Load any existing snapshot, regenerating it if loading failed
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
// head mismatch.
var recover bool
head := bc.CurrentBlock()
if layer := rawdb.ReadSnapshotRecoveryNumber(bc.db); layer != nil && *layer >= head.Number.Uint64() {
log.Warn("Enabling snapshot recovery", "chainhead", head.Number, "diskbase", *layer)
recover = true
}
snapconfig := snapshot.Config{
CacheSize: bc.cfg.SnapshotLimit,
Recovery: recover,
NoBuild: bc.cfg.SnapshotNoBuild,
AsyncBuild: !bc.cfg.SnapshotWait,
}
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
// Re-initialize the state database with snapshot
bc.statedb = state.NewDatabase(bc.triedb, bc.snaps)
}
}
// empty returns an indicator whether the blockchain is empty. // empty returns an indicator whether the blockchain is empty.
// Note, it's a special case that we connect a non-empty ancient // Note, it's a special case that we connect a non-empty ancient
// database with an empty node, so that we can plugin the ancient // database with an empty node, so that we can plugin the ancient
@ -618,7 +673,7 @@ func (bc *BlockChain) loadLastState() error {
func (bc *BlockChain) initializeHistoryPruning(latest uint64) error { func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
freezerTail, _ := bc.db.Tail() freezerTail, _ := bc.db.Tail()
switch bc.cacheConfig.ChainHistoryMode { switch bc.cfg.ChainHistoryMode {
case history.KeepAll: case history.KeepAll:
if freezerTail == 0 { if freezerTail == 0 {
return nil return nil
@ -639,7 +694,7 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
// postmerge directly on an existing DB. We could just trigger the pruning // 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 // 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. // 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.")) log.Error(fmt.Sprintf("Run 'geth prune-history' to prune pre-merge history."))
return fmt.Errorf("history pruning requested via configuration") return fmt.Errorf("history pruning requested via configuration")
} }
@ -655,7 +710,7 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
return nil return nil
default: default:
return fmt.Errorf("invalid history mode: %d", bc.cacheConfig.ChainHistoryMode) return fmt.Errorf("invalid history mode: %d", bc.cfg.ChainHistoryMode)
} }
} }
@ -1193,8 +1248,7 @@ func (bc *BlockChain) stopWithoutSaving() {
bc.scope.Close() bc.scope.Close()
// Signal shutdown to all goroutines. // Signal shutdown to all goroutines.
close(bc.quit) bc.InterruptInsert(true)
bc.StopInsert()
// Now wait for all chain modifications to end and persistent goroutines to exit. // Now wait for all chain modifications to end and persistent goroutines to exit.
// //
@ -1230,7 +1284,7 @@ func (bc *BlockChain) Stop() {
// - HEAD: So we don't need to reprocess any blocks in the general case // - 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-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 // - 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 triedb := bc.triedb
for _, offset := range []uint64{0, 1, state.TriesInMemory - 1} { for _, offset := range []uint64{0, 1, state.TriesInMemory - 1} {
@ -1268,11 +1322,15 @@ func (bc *BlockChain) Stop() {
log.Info("Blockchain stopped") log.Info("Blockchain stopped")
} }
// StopInsert interrupts all insertion methods, causing them to return // InterruptInsert interrupts all insertion methods, causing them to return
// errInsertionInterrupted as soon as possible. Insertion is permanently disabled after // errInsertionInterrupted as soon as possible, or resume the chain insertion
// calling this method. // if required.
func (bc *BlockChain) StopInsert() { func (bc *BlockChain) InterruptInsert(on bool) {
if on {
bc.procInterrupt.Store(true) bc.procInterrupt.Store(true)
} else {
bc.procInterrupt.Store(false)
}
} }
// insertStopped returns true after StopInsert has been called. // insertStopped returns true after StopInsert has been called.
@ -1296,12 +1354,11 @@ const (
// //
// The optional ancientLimit can also be specified and chain segment before that // The optional ancientLimit can also be specified and chain segment before that
// will be directly stored in the ancient, getting rid of the chain migration. // will be directly stored in the ancient, getting rid of the chain migration.
func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts, ancientLimit uint64) (int, error) { func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []rlp.RawValue, ancientLimit uint64) (int, error) {
// Verify the supplied headers before insertion without lock // Verify the supplied headers before insertion without lock
var headers []*types.Header var headers []*types.Header
for _, block := range blockChain { for _, block := range blockChain {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
// Here we also validate that blob transactions in the block do not // Here we also validate that blob transactions in the block do not
// contain a sidecar. While the sidecar does not affect the block hash // contain a sidecar. While the sidecar does not affect the block hash
// or tx hash, sending blobs within a block is not allowed. // or tx hash, sending blobs within a block is not allowed.
@ -1344,11 +1401,11 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// //
// this function only accepts canonical chain data. All side chain will be reverted // this function only accepts canonical chain data. All side chain will be reverted
// eventually. // eventually.
writeAncient := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { writeAncient := func(blockChain types.Blocks, receiptChain []rlp.RawValue) (int, error) {
// Ensure genesis is in the ancient store // Ensure genesis is in the ancient store
if blockChain[0].NumberU64() == 1 { if blockChain[0].NumberU64() == 1 {
if frozen, _ := bc.db.Ancients(); frozen == 0 { if frozen, _ := bc.db.Ancients(); frozen == 0 {
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}) writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList})
if err != nil { if err != nil {
log.Error("Error writing genesis to ancients", "err", err) log.Error("Error writing genesis to ancients", "err", err)
return 0, err return 0, err
@ -1391,7 +1448,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// existing local chain segments (reorg around the chain tip). The reorganized part // existing local chain segments (reorg around the chain tip). The reorganized part
// will be included in the provided chain segment, and stale canonical markers will be // will be included in the provided chain segment, and stale canonical markers will be
// silently rewritten. Therefore, no explicit reorg logic is needed. // silently rewritten. Therefore, no explicit reorg logic is needed.
writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { writeLive := func(blockChain types.Blocks, receiptChain []rlp.RawValue) (int, error) {
var ( var (
skipPresenceCheck = false skipPresenceCheck = false
batch = bc.db.NewBatch() batch = bc.db.NewBatch()
@ -1416,7 +1473,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// Write all the data out into the database // Write all the data out into the database
rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64()) rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
rawdb.WriteBlock(batch, block) rawdb.WriteBlock(batch, block)
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i]) rawdb.WriteRawReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
// Write everything belongs to the blocks into the database. So that // Write everything belongs to the blocks into the database. So that
// we can ensure all components of body is completed(body, receipts) // we can ensure all components of body is completed(body, receipts)
@ -1537,7 +1594,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
return nil return nil
} }
// If we're running an archive node, always flush // If we're running an archive node, always flush
if bc.cacheConfig.TrieDirtyDisabled { if bc.cfg.ArchiveMode {
return bc.triedb.Commit(root, false) return bc.triedb.Commit(root, false)
} }
// Full but not archive node, do proper garbage collection // Full but not archive node, do proper garbage collection
@ -1552,7 +1609,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
// If we exceeded our memory allowance, flush matured singleton nodes to disk // If we exceeded our memory allowance, flush matured singleton nodes to disk
var ( var (
_, nodes, imgs = bc.triedb.Size() // all memory is contained within the nodes return for hashdb _, 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 { if nodes > limit || imgs > 4*1024*1024 {
bc.triedb.Cap(limit - ethdb.IdealBatchSize) bc.triedb.Cap(limit - ethdb.IdealBatchSize)
@ -1902,8 +1959,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
) )
defer interrupt.Store(true) // terminate the prefetch at the end defer interrupt.Store(true) // terminate the prefetch at the end
bc.cacheConfig.TrieCleanNoPrefetch = true if bc.cfg.NoPrefetch {
if bc.cacheConfig.TrieCleanNoPrefetch {
statedb, err = state.New(parentRoot, bc.statedb) statedb, err = state.New(parentRoot, bc.statedb)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1923,21 +1979,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 // Note: the main processor and prefetcher share the same reader with a local
// cache for mitigating the overhead of state access. // cache for mitigating the overhead of state access.
reader, err := bc.statedb.ReaderWithCache(parentRoot) prefetch, process, err := bc.statedb.ReadersWithCacheStats(parentRoot)
if err != nil { if err != nil {
return nil, err return nil, err
} }
throwaway, err := state.NewWithReader(parentRoot, bc.statedb, reader) throwaway, err := state.NewWithReader(parentRoot, bc.statedb, prefetch)
if err != nil { if err != nil {
return nil, err return nil, err
} }
statedb, err = state.NewWithReader(parentRoot, bc.statedb, reader) statedb, err = state.NewWithReader(parentRoot, bc.statedb, process)
if err != nil { if err != nil {
return nil, err 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) { go func(start time.Time, throwaway *state.StateDB, block *types.Block) {
// Disable tracing for prefetcher executions. // Disable tracing for prefetcher executions.
vmCfg := bc.vmConfig vmCfg := bc.cfg.VmConfig
vmCfg.Tracer = nil vmCfg.Tracer = nil
bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt) bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt)
@ -1956,7 +2026,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 // Generate witnesses either if we're self-testing, or if it's the
// only block being inserted. A bit crude, but witnesses are huge, // only block being inserted. A bit crude, but witnesses are huge,
// so we refuse to make an entire chain of them. // 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) witness, err = stateless.NewWitness(block.Header(), bc)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1981,7 +2051,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
// Process block using the parent state as reference point // Process block using the parent state as reference point
pstart := time.Now() 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 { if err != nil {
bc.reportBlock(block, res, err) bc.reportBlock(block, res, err)
return nil, err return nil, err
@ -2001,7 +2071,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
// witness builder/runner, which would otherwise be impossible due to the // witness builder/runner, which would otherwise be impossible due to the
// various invalid chain states/behaviors being contained in those tests. // various invalid chain states/behaviors being contained in those tests.
xvstart := time.Now() 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()) log.Warn("Running stateless self-validation", "block", block.Number(), "hash", block.Hash())
// Remove critical computed fields from the block to force true recalculation // Remove critical computed fields from the block to force true recalculation
@ -2012,7 +2082,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
task := types.NewBlockWithHeader(context).WithBody(*block.Body()) task := types.NewBlockWithHeader(context).WithBody(*block.Body())
// Run the stateless self-cross-validation // 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 { if err != nil {
return nil, fmt.Errorf("stateless self-validation failed: %v", err) return nil, fmt.Errorf("stateless self-validation failed: %v", err)
} }
@ -2065,7 +2135,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 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) 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{ return &blockProcessingResult{
usedGas: res.GasUsed, usedGas: res.GasUsed,
@ -2647,7 +2722,7 @@ func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, e
first = headers[0].Number.Uint64() first = headers[0].Number.Uint64()
) )
if first == 1 && frozen == 0 { if first == 1 && frozen == 0 {
_, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}) _, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList})
if err != nil { if err != nil {
log.Error("Error writing genesis to ancients", "err", err) log.Error("Error writing genesis to ancients", "err", err)
return 0, err return 0, err

View file

@ -27,7 +27,7 @@ import (
// insertStats tracks and reports on block insertion. // insertStats tracks and reports on block insertion.
type insertStats struct { type insertStats struct {
queued, processed, ignored int processed, ignored int
usedGas uint64 usedGas uint64
lastIndex int lastIndex int
startTime mclock.AbsTime startTime mclock.AbsTime
@ -79,9 +79,6 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn
} }
context = append(context, []interface{}{"triedirty", triebufNodes}...) context = append(context, []interface{}{"triedirty", triebufNodes}...)
if st.queued > 0 {
context = append(context, []interface{}{"queued", st.queued}...)
}
if st.ignored > 0 { if st.ignored > 0 {
context = append(context, []interface{}{"ignored", st.ignored}...) context = append(context, []interface{}{"ignored", st.ignored}...)
} }

View file

@ -18,9 +18,12 @@ package core
import ( import (
"errors" "errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus" "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/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/state/snapshot"
@ -213,6 +216,44 @@ func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*type
return 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. // GetReceiptsByHash retrieves the receipts for all transactions in a given block.
func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
if receipts, ok := bc.receiptsCache.Get(hash); ok { if receipts, ok := bc.receiptsCache.Get(hash); ok {
@ -234,12 +275,22 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
return receipts return receipts
} }
func (bc *BlockChain) GetRawReceiptsByHash(hash common.Hash) types.Receipts { // GetRawReceipts retrieves the receipts for all transactions in a given block
// without deriving the internal fields and the Bloom.
func (bc *BlockChain) GetRawReceipts(hash common.Hash, number uint64) types.Receipts {
if receipts, ok := bc.receiptsCache.Get(hash); ok {
return receipts
}
return rawdb.ReadRawReceipts(bc.db, hash, number)
}
// GetReceiptsRLP retrieves the receipts of a block.
func (bc *BlockChain) GetReceiptsRLP(hash common.Hash) rlp.RawValue {
number := rawdb.ReadHeaderNumber(bc.db, hash) number := rawdb.ReadHeaderNumber(bc.db, hash)
if number == nil { if number == nil {
return nil return nil
} }
return rawdb.ReadRawReceipts(bc.db, hash, *number) return rawdb.ReadReceiptsRLP(bc.db, hash, *number)
} }
// GetUnclesInChain retrieves all the uncles from a given block backwards until // GetUnclesInChain retrieves all the uncles from a given block backwards until
@ -267,13 +318,15 @@ func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, max
return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) 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. // itself associate with the given transaction hash.
// //
// A null will be returned if the transaction is not found. This can be due to // 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 transaction indexer not being finished. The caller must explicitly check
// the indexer progress. // 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() bc.txLookupLock.RLock()
defer bc.txLookupLock.RUnlock() defer bc.txLookupLock.RUnlock()
@ -281,7 +334,7 @@ func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLoo
if item, exist := bc.txLookupCache.Get(hash); exist { if item, exist := bc.txLookupCache.Get(hash); exist {
return item.lookup, item.transaction 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 { if tx == nil {
return nil, nil return nil, nil
} }
@ -360,6 +413,13 @@ func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
return state.New(root, bc.statedb) 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. // Config retrieves the chain's fork configuration.
func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig }
@ -398,7 +458,7 @@ func (bc *BlockChain) Genesis() *types.Block {
// GetVMConfig returns the block chain VM config. // GetVMConfig returns the block chain VM config.
func (bc *BlockChain) GetVMConfig() *vm.Config { func (bc *BlockChain) GetVMConfig() *vm.Config {
return &bc.vmConfig return &bc.cfg.VmConfig
} }
// TxIndexProgress returns the transaction indexing progress. // TxIndexProgress returns the transaction indexing progress.
@ -409,6 +469,11 @@ func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) {
return bc.txIndexer.txIndexProgress(), nil 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. // HistoryPruningCutoff returns the configured history pruning point.
// Blocks before this might not be available in the database. // Blocks before this might not be available in the database.
func (bc *BlockChain) HistoryPruningCutoff() (uint64, common.Hash) { func (bc *BlockChain) HistoryPruningCutoff() (uint64, common.Hash) {

View file

@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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/ethdb/pebble"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -1769,7 +1768,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent key-value database: %v", err) t.Fatalf("Failed to create persistent key-value database: %v", err)
} }
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient})
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent freezer database: %v", err) t.Fatalf("Failed to create persistent freezer database: %v", err)
} }
@ -1782,20 +1781,21 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
Config: params.AllEthashProtocolChanges, Config: params.AllEthashProtocolChanges,
} }
engine = ethash.NewFullFaker() engine = ethash.NewFullFaker()
config = &CacheConfig{ option = &BlockChainConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
TrieDirtyLimit: 256, TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, // Disable snapshot by default SnapshotLimit: 0, // disable snapshot by default
TxLookupLimit: -1, // disable tx indexing
StateScheme: scheme, StateScheme: scheme,
} }
) )
defer engine.Close() defer engine.Close()
if snapshots { if snapshots && scheme == rawdb.HashScheme {
config.SnapshotLimit = 256 option.SnapshotLimit = 256
config.SnapshotWait = true option.SnapshotWait = true
} }
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil) chain, err := NewBlockChain(db, gspec, engine, option)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
@ -1820,7 +1820,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
if err := chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false); err != nil { if err := chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false); err != nil {
t.Fatalf("Failed to flush trie state: %v", err) t.Fatalf("Failed to flush trie state: %v", err)
} }
if snapshots { if snapshots && scheme == rawdb.HashScheme {
if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err) t.Fatalf("Failed to flatten snapshots: %v", err)
} }
@ -1854,13 +1854,13 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
if err != nil { if err != nil {
t.Fatalf("Failed to reopen persistent key-value database: %v", err) t.Fatalf("Failed to reopen persistent key-value database: %v", err)
} }
db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) db, err = rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient})
if err != nil { if err != nil {
t.Fatalf("Failed to reopen persistent freezer database: %v", err) t.Fatalf("Failed to reopen persistent freezer database: %v", err)
} }
defer db.Close() defer db.Close()
newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil) newChain, err := NewBlockChain(db, gspec, engine, option)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -1919,7 +1919,7 @@ func testIssue23496(t *testing.T, scheme string) {
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent key-value database: %v", err) t.Fatalf("Failed to create persistent key-value database: %v", err)
} }
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient})
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent freezer database: %v", err) t.Fatalf("Failed to create persistent freezer database: %v", err)
} }
@ -1932,8 +1932,9 @@ func testIssue23496(t *testing.T, scheme string) {
BaseFee: big.NewInt(params.InitialBaseFee), 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 { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
@ -1952,9 +1953,11 @@ func testIssue23496(t *testing.T, scheme string) {
if _, err := chain.InsertChain(blocks[1:2]); err != nil { if _, err := chain.InsertChain(blocks[1:2]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err) t.Fatalf("Failed to import canonical chain start: %v", err)
} }
if scheme == rawdb.HashScheme {
if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil { if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err) t.Fatalf("Failed to flatten snapshots: %v", err)
} }
}
// Insert block B3 and commit the state into disk // Insert block B3 and commit the state into disk
if _, err := chain.InsertChain(blocks[2:3]); err != nil { if _, err := chain.InsertChain(blocks[2:3]); err != nil {
@ -1977,13 +1980,13 @@ func testIssue23496(t *testing.T, scheme string) {
if err != nil { if err != nil {
t.Fatalf("Failed to reopen persistent key-value database: %v", err) t.Fatalf("Failed to reopen persistent key-value database: %v", err)
} }
db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) db, err = rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient})
if err != nil { if err != nil {
t.Fatalf("Failed to reopen persistent freezer database: %v", err) t.Fatalf("Failed to reopen persistent freezer database: %v", err)
} }
defer db.Close() 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -1997,16 +2000,24 @@ func testIssue23496(t *testing.T, scheme string) {
} }
expHead := uint64(1) expHead := uint64(1)
if scheme == rawdb.PathScheme { if scheme == rawdb.PathScheme {
expHead = uint64(2) // The pathdb database makes sure that snapshot and trie are consistent,
// so only the last block is reverted in case of a crash.
expHead = uint64(3)
} }
if head := chain.CurrentBlock(); head.Number.Uint64() != expHead { if head := chain.CurrentBlock(); head.Number.Uint64() != expHead {
t.Errorf("Head block mismatch: have %d, want %d", head.Number, expHead) t.Errorf("Head block mismatch: have %d, want %d", head.Number, expHead)
} }
if scheme == rawdb.PathScheme {
// Reinsert B4
if _, err := chain.InsertChain(blocks[3:]); err != nil {
t.Fatalf("Failed to import canonical chain tail: %v", err)
}
} else {
// Reinsert B2-B4 // Reinsert B2-B4
if _, err := chain.InsertChain(blocks[1:]); err != nil { if _, err := chain.InsertChain(blocks[1:]); err != nil {
t.Fatalf("Failed to import canonical chain tail: %v", err) t.Fatalf("Failed to import canonical chain tail: %v", err)
} }
}
if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
} }
@ -2016,7 +2027,9 @@ func testIssue23496(t *testing.T, scheme string) {
if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) { if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4)) t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4))
} }
if scheme == rawdb.HashScheme {
if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil { if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil {
t.Error("Failed to regenerate the snapshot of known state") t.Error("Failed to regenerate the snapshot of known state")
} }
} }
}

View file

@ -32,7 +32,6 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "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/ethdb/pebble"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
@ -1973,7 +1972,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent key-value database: %v", err) t.Fatalf("Failed to create persistent key-value database: %v", err)
} }
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient})
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent freezer database: %v", err) t.Fatalf("Failed to create persistent freezer database: %v", err)
} }
@ -1986,19 +1985,20 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
Config: params.AllEthashProtocolChanges, Config: params.AllEthashProtocolChanges,
} }
engine = ethash.NewFullFaker() engine = ethash.NewFullFaker()
config = &CacheConfig{ options = &BlockChainConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
TrieDirtyLimit: 256, TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, // Disable snapshot SnapshotLimit: 0, // disable snapshot
TxLookupLimit: -1, // disable tx indexing
StateScheme: scheme, StateScheme: scheme,
} }
) )
if snapshots { if snapshots {
config.SnapshotLimit = 256 options.SnapshotLimit = 256
config.SnapshotWait = true options.SnapshotWait = true
} }
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil) chain, err := NewBlockChain(db, gspec, engine, options)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
@ -2023,7 +2023,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
} }
if tt.commitBlock > 0 { if tt.commitBlock > 0 {
chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false) chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false)
if snapshots { if snapshots && scheme == rawdb.HashScheme {
if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err) t.Fatalf("Failed to flatten snapshots: %v", err)
} }

View file

@ -33,7 +33,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/ethdb/pebble" "github.com/ethereum/go-ethereum/ethdb/pebble"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -70,7 +69,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent key-value database: %v", err) t.Fatalf("Failed to create persistent key-value database: %v", err)
} }
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient})
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent freezer database: %v", err) t.Fatalf("Failed to create persistent freezer database: %v", err)
} }
@ -82,7 +81,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
} }
engine = ethash.NewFullFaker() 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 { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
@ -105,7 +104,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
if basic.commitBlock > 0 && basic.commitBlock == point { if basic.commitBlock > 0 && basic.commitBlock == point {
chain.TrieDB().Commit(blocks[point-1].Root(), false) chain.TrieDB().Commit(blocks[point-1].Root(), false)
} }
if basic.snapshotBlock > 0 && basic.snapshotBlock == point { if basic.snapshotBlock > 0 && basic.snapshotBlock == point && basic.scheme == rawdb.HashScheme {
// Flushing the entire snap tree into the disk, the // Flushing the entire snap tree into the disk, the
// relevant (a) snapshot root and (b) snapshot generator // relevant (a) snapshot root and (b) snapshot generator
// will be persisted atomically. // will be persisted atomically.
@ -149,15 +148,19 @@ func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks [
block := chain.GetBlockByNumber(basic.expSnapshotBottom) block := chain.GetBlockByNumber(basic.expSnapshotBottom)
if block == nil { if block == nil {
t.Errorf("The corresponding block[%d] of snapshot disk layer is missing", basic.expSnapshotBottom) t.Errorf("The corresponding block[%d] of snapshot disk layer is missing", basic.expSnapshotBottom)
} else if !bytes.Equal(chain.snaps.DiskRoot().Bytes(), block.Root().Bytes()) { } else if basic.scheme == rawdb.HashScheme {
if !bytes.Equal(chain.snaps.DiskRoot().Bytes(), block.Root().Bytes()) {
t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.snaps.DiskRoot()) t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.snaps.DiskRoot())
} }
}
// Check the snapshot, ensure it's integrated // Check the snapshot, ensure it's integrated
if basic.scheme == rawdb.HashScheme {
if err := chain.snaps.Verify(block.Root()); err != nil { if err := chain.snaps.Verify(block.Root()); err != nil {
t.Errorf("The disk layer is not integrated %v", err) t.Errorf("The disk layer is not integrated %v", err)
} }
} }
}
//nolint:unused //nolint:unused
func (basic *snapshotTestBasic) dump() string { func (basic *snapshotTestBasic) dump() string {
@ -229,7 +232,7 @@ func (snaptest *snapshotTest) test(t *testing.T) {
// Restart the chain normally // Restart the chain normally
chain.Stop() 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -261,7 +264,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent key-value database: %v", err) t.Fatalf("Failed to create persistent key-value database: %v", err)
} }
newdb, err := rawdb.NewDatabaseWithFreezer(pdb, snaptest.ancient, "", false) newdb, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: snaptest.ancient})
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent freezer database: %v", err) t.Fatalf("Failed to create persistent freezer database: %v", err)
} }
@ -271,13 +274,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
// the crash, we do restart twice here: one after the crash and one // 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 // after the normal stop. It's used to ensure the broken snapshot
// can be detected all the time. // 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
newchain.Stop() 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -307,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) {}) 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 // Insert a few more blocks without enabling snapshot
var cacheConfig = &CacheConfig{ var options = &BlockChainConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
TrieDirtyLimit: 256, TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, SnapshotLimit: 0,
StateScheme: snaptest.scheme, 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -322,7 +326,8 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
newchain.Stop() newchain.Stop()
// Restart the chain with enabling the snapshot // 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -350,7 +355,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
chain.SetHead(snaptest.setHead) chain.SetHead(snaptest.setHead)
chain.Stop() 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -379,14 +384,15 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
// and state committed. // and state committed.
chain.Stop() chain.Stop()
config := &CacheConfig{ config := &BlockChainConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
TrieDirtyLimit: 256, TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, SnapshotLimit: 0,
StateScheme: snaptest.scheme, 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -395,15 +401,16 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
newchain.Stop() newchain.Stop()
// Restart the chain, the wiper should start working // Restart the chain, the wiper should start working
config = &CacheConfig{ config = &BlockChainConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
TrieDirtyLimit: 256, TrieDirtyLimit: 256,
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 256, SnapshotLimit: 256,
SnapshotWait: false, // Don't wait rebuild SnapshotWait: false, // Don't wait rebuild
StateScheme: snaptest.scheme, 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -412,7 +419,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
tmp.triedb.Close() tmp.triedb.Close()
tmp.stopWithoutSaving() 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 { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -565,12 +572,14 @@ func TestHighCommitCrashWithNewSnapshot(t *testing.T) {
// //
// Expected head header : C8 // Expected head header : C8
// Expected head fast block: C8 // Expected head fast block: C8
// Expected head block : G // Expected head block : G (Hash mode), C6 (Path mode)
// Expected snapshot disk : C4 // Expected snapshot disk : C4 (Hash mode)
for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} {
expHead := uint64(0) expHead := uint64(0)
if scheme == rawdb.PathScheme { if scheme == rawdb.PathScheme {
expHead = uint64(4) // The pathdb database makes sure that snapshot and trie are consistent,
// so only the last two blocks are reverted in case of a crash.
expHead = uint64(6)
} }
test := &crashSnapshotTest{ test := &crashSnapshotTest{
snapshotTestBasic{ snapshotTestBasic{

View file

@ -25,10 +25,12 @@ import (
"math/rand" "math/rand"
"os" "os"
"path" "path"
"reflect"
"sync" "sync"
"testing" "testing"
"time" "time"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/beacon"
@ -46,6 +48,7 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256" "github.com/holiman/uint256"
"github.com/stretchr/testify/assert"
) )
// So we can deterministically seed different blockchains // 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 // 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 // Create and inject the requested chain
if n == 0 { 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 // Import the chain as an archive node for the comparison baseline
archiveDb := rawdb.NewMemoryDatabase() 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() defer archive.Stop()
if n, err := archive.InsertChain(blocks); err != nil { if n, err := archive.InsertChain(blocks); err != nil {
@ -731,23 +735,23 @@ func testFastVsFullChains(t *testing.T, scheme string) {
} }
// Fast import the chain as a non-archive node to test // Fast import the chain as a non-archive node to test
fastDb := rawdb.NewMemoryDatabase() 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() defer fast.Stop()
if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil {
t.Fatalf("failed to insert receipt %d: %v", n, err) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
// Freezer style fast import the chain. // Freezer style fast import the chain.
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) ancientDb, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
if err != nil { if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
defer ancientDb.Close() 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() defer ancient.Stop()
if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil { if n, err := ancient.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), uint64(len(blocks)/2)); err != nil {
t.Fatalf("failed to insert receipt %d: %v", n, err) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
@ -824,7 +828,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
// makeDb creates a db instance for testing. // makeDb creates a db instance for testing.
makeDb := func() ethdb.Database { makeDb := func() ethdb.Database {
db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) db, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
if err != nil { if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
@ -851,11 +855,8 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
archiveDb := makeDb() archiveDb := makeDb()
defer archiveDb.Close() defer archiveDb.Close()
archiveCaching := *defaultCacheConfig options := DefaultConfig().WithArchive(true).WithStateScheme(scheme)
archiveCaching.TrieDirtyDisabled = true archive, _ := NewBlockChain(archiveDb, gspec, ethash.NewFaker(), options)
archiveCaching.StateScheme = scheme
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
if n, err := archive.InsertChain(blocks); err != nil { if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err) t.Fatalf("failed to process block %d: %v", n, err)
} }
@ -868,10 +869,10 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
// Import the chain as a non-archive node and ensure all pointers are updated // Import the chain as a non-archive node and ensure all pointers are updated
fastDb := makeDb() fastDb := makeDb()
defer fastDb.Close() 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() defer fast.Stop()
if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { if n, err := fast.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0); err != nil {
t.Fatalf("failed to insert receipt %d: %v", n, err) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
assert(t, "fast", fast, height, height, 0) assert(t, "fast", fast, height, height, 0)
@ -881,10 +882,10 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
// Import the chain as a ancient-first node and ensure all pointers are updated // Import the chain as a ancient-first node and ensure all pointers are updated
ancientDb := makeDb() ancientDb := makeDb()
defer ancientDb.Close() 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() defer ancient.Stop()
if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 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) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
assert(t, "ancient", ancient, height, height, 0) assert(t, "ancient", ancient, height, height, 0)
@ -902,7 +903,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
for i, block := range blocks { for i, block := range blocks {
headers[i] = block.Header() 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 { if n, err := light.InsertHeaderChain(headers); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) 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. // Import the chain. This runs all block validation rules.
db := rawdb.NewMemoryDatabase() 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 { if i, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert original chain[%d]: %v", i, err) t.Fatalf("failed to insert original chain[%d]: %v", i, err)
} }
@ -1006,29 +1007,47 @@ func testChainTxReorgs(t *testing.T, scheme string) {
// removed tx // removed tx
for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 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) 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) t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt)
} }
} }
// added tx // added tx
for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 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) 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) 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 // shared tx
for i, tx := range (types.Transactions{postponed, swapped}) { 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) 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) 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) 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() defer blockchain.Stop()
rmLogsCh := make(chan RemovedLogsEvent) 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)}}} gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
engine = ethash.NewFaker() 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() defer blockchain.Stop()
@ -1186,7 +1205,7 @@ func testSideLogRebirth(t *testing.T, scheme string) {
addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr1 = crypto.PubkeyToAddress(key1.PublicKey)
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
signer = types.LatestSigner(gspec.Config) 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() 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() defer blockchain.Stop()
if _, err := blockchain.InsertChain(blocks); err != nil { if _, err := blockchain.InsertChain(blocks); err != nil {
@ -1478,7 +1497,7 @@ func testEIP161AccountRemoval(t *testing.T, scheme string) {
block.AddTx(tx) block.AddTx(tx)
}) })
// account must exist pre eip 161 // 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() defer blockchain.Stop()
if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 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 // Import the canonical and fork chain side by side, verifying the current block
// and current header consistency // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1580,7 +1599,7 @@ func TestTrieForkGC(t *testing.T) {
forks[i] = fork[0] forks[i] = fork[0]
} }
// Import the canonical and fork chain side by side, forcing the trie cache to cache both // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1623,10 +1642,10 @@ func testLargeReorgTrieGC(t *testing.T, scheme string) {
competitor, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*state.TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) competitor, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*state.TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
// Import the shared chain and the original canonical one // Import the shared chain and the original canonical one
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
defer db.Close() 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1689,14 +1708,14 @@ func testBlockchainRecovery(t *testing.T, scheme string) {
_, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), int(height), nil) _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), int(height), nil)
// Import the chain as a ancient-first node and ensure all pointers are updated // Import the chain as a ancient-first node and ensure all pointers are updated
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) ancientDb, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{Ancient: t.TempDir()})
if err != nil { if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
defer ancientDb.Close() 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, receipts, uint64(3*len(blocks)/4)); err != nil { 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) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
rawdb.WriteLastPivotNumber(ancientDb, blocks[len(blocks)-1].NumberU64()) // Force fast sync behavior rawdb.WriteLastPivotNumber(ancientDb, blocks[len(blocks)-1].NumberU64()) // Force fast sync behavior
@ -1707,7 +1726,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) {
rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash()) rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())
// Reopen broken blockchain again // 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() defer ancient.Stop()
if num := ancient.CurrentBlock().Number.Uint64(); num != 0 { if num := ancient.CurrentBlock().Number.Uint64(); num != 0 {
t.Errorf("head block mismatch: have #%v, want #%v", num, 0) t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
@ -1747,10 +1766,10 @@ func testLowDiffLongChain(t *testing.T, scheme string) {
}) })
// Import the canonical chain // Import the canonical chain
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
defer diskdb.Close() 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1811,7 +1830,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
mergeBlock = gomath.MaxInt32 mergeBlock = gomath.MaxInt32
) )
// Generate and import the canonical chain // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1959,13 +1978,13 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) {
b.OffsetTime(-9) // A higher difficulty b.OffsetTime(-9) // A higher difficulty
}) })
// Import the shared chain and the original canonical one // Import the shared chain and the original canonical one
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) chaindb, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
if err != nil { if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
defer chaindb.Close() 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1991,7 +2010,7 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) {
} }
} else if typ == "receipts" { } else if typ == "receipts" {
inserter = func(blocks []*types.Block, receipts []types.Receipts) error { inserter = func(blocks []*types.Block, receipts []types.Receipts) error {
_, err = chain.InsertReceiptChain(blocks, receipts, 0) _, err = chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0)
return err return err
} }
asserter = func(t *testing.T, block *types.Block) { asserter = func(t *testing.T, block *types.Block) {
@ -2122,13 +2141,13 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
} }
}) })
// Import the shared chain and the original canonical one // Import the shared chain and the original canonical one
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) chaindb, err := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
if err != nil { if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
defer chaindb.Close() defer chaindb.Close()
chain, err := NewBlockChain(chaindb, nil, genesis, nil, engine, vm.Config{}, nil) chain, err := NewBlockChain(chaindb, genesis, engine, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2157,7 +2176,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
} }
} else if typ == "receipts" { } else if typ == "receipts" {
inserter = func(blocks []*types.Block, receipts []types.Receipts) error { inserter = func(blocks []*types.Block, receipts []types.Receipts) error {
_, err = chain.InsertReceiptChain(blocks, receipts, 0) _, err = chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), 0)
return err return err
} }
asserter = func(t *testing.T, block *types.Block) { asserter = func(t *testing.T, block *types.Block) {
@ -2234,7 +2253,7 @@ func getLongAndShortChains(scheme string) (*BlockChain, []*types.Block, []*types
genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) { genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{1}) 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 { if err != nil {
return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) 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() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
// Import the shared chain and the original canonical one // 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 { if err != nil {
b.Fatalf("failed to create tester chain: %v", err) b.Fatalf("failed to create tester chain: %v", err)
} }
@ -2496,13 +2515,13 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) {
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent key-value database: %v", err) t.Fatalf("Failed to create persistent key-value database: %v", err)
} }
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false) db, err := rawdb.Open(pdb, rawdb.OpenOptions{Ancient: ancient})
if err != nil { if err != nil {
t.Fatalf("Failed to create persistent freezer database: %v", err) t.Fatalf("Failed to create persistent freezer database: %v", err)
} }
defer db.Close() 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2601,7 +2620,8 @@ func testDeleteCreateRevert(t *testing.T, scheme string) {
b.AddTx(tx) b.AddTx(tx)
}) })
// Import the canonical chain // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2714,9 +2734,11 @@ func testDeleteRecreateSlots(t *testing.T, scheme string) {
b.AddTx(tx) b.AddTx(tx)
}) })
// Import the canonical chain // 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), Tracer: logger.NewJSONLogger(nil, os.Stdout),
}, nil) }
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2796,9 +2818,11 @@ func testDeleteRecreateAccount(t *testing.T, scheme string) {
b.AddTx(tx) b.AddTx(tx)
}) })
// Import the canonical chain // 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), Tracer: logger.NewJSONLogger(nil, os.Stdout),
}, nil) }
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2971,10 +2995,12 @@ func testDeleteRecreateSlotsAcrossManyBlocks(t *testing.T, scheme string) {
current = exp current = exp
}) })
// Import the canonical chain // 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, //Debug: true,
//Tracer: vm.NewJSONLogger(nil, os.Stdout), //Tracer: vm.NewJSONLogger(nil, os.Stdout),
}, nil) }
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3109,10 +3135,12 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) {
}) })
// Import the canonical chain // 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, //Debug: true,
//Tracer: vm.NewJSONLogger(nil, os.Stdout), //Tracer: vm.NewJSONLogger(nil, os.Stdout),
}, nil) }
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, options)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3199,7 +3227,8 @@ func testEIP2718Transition(t *testing.T, scheme string) {
}) })
// Import the canonical chain // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3293,7 +3322,8 @@ func testEIP1559Transition(t *testing.T, scheme string) {
b.AddTx(tx) 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3403,10 +3433,11 @@ func testSetCanonical(t *testing.T, scheme string) {
} }
gen.AddTx(tx) gen.AddTx(tx)
}) })
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) diskdb, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
defer diskdb.Close() 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) 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) {}) _, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {})
// Initialize test chain // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3649,10 +3681,7 @@ func testCreateThenDelete(t *testing.T, config *params.ChainConfig) {
nonce++ nonce++
}) })
// Import the canonical chain // Import the canonical chain
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{ chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), gspec, engine, nil)
//Debug: true,
//Tracer: logger.NewJSONLogger(nil, os.Stdout),
}, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3764,7 +3793,7 @@ func TestDeleteThenCreate(t *testing.T) {
} }
}) })
// Import the canonical chain // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3849,7 +3878,9 @@ func TestTransientStorageReset(t *testing.T) {
}) })
// Initialize the blockchain with 1153 enabled. // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3943,7 +3974,11 @@ func TestEIP3651(t *testing.T) {
b.AddTx(tx) 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -4052,7 +4087,7 @@ func TestPragueRequests(t *testing.T) {
} }
// Insert block to check validation. // 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -4124,7 +4159,7 @@ func TestEIP7702(t *testing.T) {
tx := types.MustSignNewTx(key1, signer, txdata) tx := types.MustSignNewTx(key1, signer, txdata)
b.AddTx(tx) 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 { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -4199,16 +4234,17 @@ func testChainReorgSnapSync(t *testing.T, ancientLimit uint64) {
gen.SetCoinbase(common.Address{0: byte(0xb), 19: byte(i)}) gen.SetCoinbase(common.Address{0: byte(0xb), 19: byte(i)})
}) })
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
defer db.Close() 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() defer chain.Stop()
if n, err := chain.InsertReceiptChain(blocks, receipts, ancientLimit); err != nil { if n, err := chain.InsertReceiptChain(blocks, types.EncodeBlockReceiptLists(receipts), ancientLimit); err != nil {
t.Fatalf("failed to insert receipt %d: %v", n, err) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
if n, err := chain.InsertReceiptChain(chainA, receiptsA, ancientLimit); err != nil { if n, err := chain.InsertReceiptChain(chainA, types.EncodeBlockReceiptLists(receiptsA), ancientLimit); err != nil {
t.Fatalf("failed to insert receipt %d: %v", n, err) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
// If the common ancestor is below the ancient limit, rewind the chain head. // If the common ancestor is below the ancient limit, rewind the chain head.
@ -4218,7 +4254,7 @@ func testChainReorgSnapSync(t *testing.T, ancientLimit uint64) {
rawdb.WriteLastPivotNumber(db, ancestor) rawdb.WriteLastPivotNumber(db, ancestor)
chain.SetHead(ancestor) chain.SetHead(ancestor)
} }
if n, err := chain.InsertReceiptChain(chainB, receiptsB, ancientLimit); err != nil { if n, err := chain.InsertReceiptChain(chainB, types.EncodeBlockReceiptLists(receiptsB), ancientLimit); err != nil {
t.Fatalf("failed to insert receipt %d: %v", n, err) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
head := chain.CurrentSnapBlock() head := chain.CurrentSnapBlock()
@ -4312,12 +4348,14 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64,
}() }()
// Enable pruning in cache config. // Enable pruning in cache config.
config := DefaultCacheConfigWithScheme(rawdb.PathScheme) config := DefaultConfig().WithStateScheme(rawdb.PathScheme)
config.ChainHistoryMode = history.KeepPostMerge config.ChainHistoryMode = history.KeepPostMerge
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false) db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
defer db.Close() 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() defer chain.Stop()
var ( var (
@ -4336,7 +4374,7 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64,
if n, err := chain.InsertHeadersBeforeCutoff(headersBefore); err != nil { if n, err := chain.InsertHeadersBeforeCutoff(headersBefore); err != nil {
t.Fatalf("failed to insert headers before cutoff %d: %v", n, err) t.Fatalf("failed to insert headers before cutoff %d: %v", n, err)
} }
if n, err := chain.InsertReceiptChain(blocksAfter, receiptsAfter, ancientLimit); err != nil { if n, err := chain.InsertReceiptChain(blocksAfter, types.EncodeBlockReceiptLists(receiptsAfter), ancientLimit); err != nil {
t.Fatalf("failed to insert receipt %d: %v", n, err) t.Fatalf("failed to insert receipt %d: %v", n, err)
} }
headSnap := chain.CurrentSnapBlock() headSnap := chain.CurrentSnapBlock()
@ -4387,6 +4425,93 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64,
if receipts == nil || len(receipts) != 1 { if receipts == nil || len(receipts) != 1 {
t.Fatalf("Missed block receipts: %d, cutoff: %d", num, cutoffBlock.NumberU64()) 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)
}
} }
} }
} }

View file

@ -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 // Merge the tx-local access event into the "block-local" one, in order to collect
// all values, so that the witness can be built. // 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.statedb.AccessEvents().Merge(evm.AccessEvents)
} }
b.txs = append(b.txs, tx) 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) { 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() db := rawdb.NewMemoryDatabase()
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) cacheConfig := DefaultConfig().WithStateScheme(rawdb.PathScheme)
cacheConfig.SnapshotLimit = 0 cacheConfig.SnapshotLimit = 0
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true)) triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
defer triedb.Close() defer triedb.Close()

View file

@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
@ -119,7 +118,7 @@ func TestGeneratePOSChain(t *testing.T) {
}) })
// Import the chain. This runs all block validation rules. // 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() defer blockchain.Stop()
if i, err := blockchain.InsertChain(genchain); err != nil { if i, err := blockchain.InsertChain(genchain); err != nil {
@ -234,7 +233,7 @@ func ExampleGenerateChain() {
}) })
// Import the chain. This runs all block validation rules. // 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() defer blockchain.Stop()
if i, err := blockchain.InsertChain(chain); err != nil { if i, err := blockchain.InsertChain(chain); err != nil {

View file

@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -50,7 +49,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
BaseFee: big.NewInt(params.InitialBaseFee), BaseFee: big.NewInt(params.InitialBaseFee),
Config: &proConf, Config: &proConf,
} }
proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil) proBc, _ := NewBlockChain(proDb, progspec, ethash.NewFaker(), nil)
defer proBc.Stop() defer proBc.Stop()
conDb := rawdb.NewMemoryDatabase() conDb := rawdb.NewMemoryDatabase()
@ -62,7 +61,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
BaseFee: big.NewInt(params.InitialBaseFee), BaseFee: big.NewInt(params.InitialBaseFee),
Config: &conConf, Config: &conConf,
} }
conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil) conBc, _ := NewBlockChain(conDb, congspec, ethash.NewFaker(), nil)
defer conBc.Stop() defer conBc.Stop()
if _, err := proBc.InsertChain(prefix); err != nil { 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 // 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++ { for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
// Create a pro-fork block, and try to feed into the no-fork chain // 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())) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
for j := 0; j < len(blocks)/2; j++ { 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) 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 // 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())) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
for j := 0; j < len(blocks)/2; j++ { 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 // 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() defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64())) 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) 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 // 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() defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64())) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))

View file

@ -29,7 +29,7 @@ type blockchain interface {
GetHeader(hash common.Hash, number uint64) *types.Header GetHeader(hash common.Hash, number uint64) *types.Header
GetCanonicalHash(number uint64) common.Hash GetCanonicalHash(number uint64) common.Hash
GetReceiptsByHash(hash common.Hash) types.Receipts GetReceiptsByHash(hash common.Hash) types.Receipts
GetRawReceiptsByHash(hash common.Hash) types.Receipts GetRawReceipts(hash common.Hash, number uint64) types.Receipts
} }
// ChainView represents an immutable view of a chain with a block id and a set // ChainView represents an immutable view of a chain with a block id and a set
@ -55,7 +55,9 @@ func NewChainView(chain blockchain, number uint64, hash common.Hash) *ChainView
headNumber: number, headNumber: number,
hashes: []common.Hash{hash}, hashes: []common.Hash{hash},
} }
cv.extendNonCanonical() if !cv.extendNonCanonical() {
return nil
}
return cv return cv
} }
@ -117,7 +119,7 @@ func (cv *ChainView) RawReceipts(number uint64) types.Receipts {
log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber) log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber)
return nil return nil
} }
return cv.chain.GetRawReceiptsByHash(blockHash) return cv.chain.GetRawReceipts(blockHash, number)
} }
// SharedRange returns the block range shared by two chain views. // SharedRange returns the block range shared by two chain views.
@ -129,7 +131,11 @@ func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
return common.Range[uint64]{} return common.Range[uint64]{}
} }
var sharedLen 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 sharedLen = n + 1
} }
return common.NewRange(0, sharedLen) return common.NewRange(0, sharedLen)
@ -153,10 +159,13 @@ func matchViews(cv1, cv2 *ChainView, number uint64) bool {
if cv1.headNumber < number || cv2.headNumber < number { if cv1.headNumber < number || cv2.headNumber < number {
return false return false
} }
var h1, h2 common.Hash
if number == cv1.headNumber || number == cv2.headNumber { 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 // 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) header := cv.chain.GetHeader(hash, number)
if header == nil { 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 return false
} }
cv.hashes = append(cv.hashes, header.ParentHash) cv.hashes = append(cv.hashes, header.ParentHash)

View file

@ -53,7 +53,6 @@ const (
databaseVersion = 2 // reindexed if database version does not match databaseVersion = 2 // reindexed if database version does not match
cachedLastBlocks = 1000 // last block of map pointers cachedLastBlocks = 1000 // last block of map pointers
cachedLvPointers = 1000 // first log value pointer of block pointers cachedLvPointers = 1000 // first log value pointer of block pointers
cachedBaseRows = 100 // groups of base layer filter row data
cachedFilterMaps = 3 // complete filter maps (cached by map renderer) cachedFilterMaps = 3 // complete filter maps (cached by map renderer)
cachedRenderSnapshots = 8 // saved map renderer data at block boundaries cachedRenderSnapshots = 8 // saved map renderer data at block boundaries
) )
@ -101,7 +100,6 @@ type FilterMaps struct {
filterMapCache *lru.Cache[uint32, filterMap] filterMapCache *lru.Cache[uint32, filterMap]
lastBlockCache *lru.Cache[uint32, lastBlockOfMap] lastBlockCache *lru.Cache[uint32, lastBlockOfMap]
lvPointerCache *lru.Cache[uint64, uint64] lvPointerCache *lru.Cache[uint64, uint64]
baseRowsCache *lru.Cache[uint64, [][]uint32]
// the matchers set and the fields of FilterMapsMatcherBackend instances are // the matchers set and the fields of FilterMapsMatcherBackend instances are
// read and written both by exported functions and the indexer. // read and written both by exported functions and the indexer.
@ -187,11 +185,14 @@ type filterMapsRange struct {
initialized bool initialized bool
headIndexed bool headIndexed bool
headDelimiter uint64 // zero if headIndexed is false headDelimiter uint64 // zero if headIndexed is false
// if initialized then all maps are rendered in the maps range // if initialized then all maps are rendered in the maps range
maps common.Range[uint32] maps common.Range[uint32]
// if tailPartialEpoch > 0 then maps between firstRenderedMap-mapsPerEpoch and // if tailPartialEpoch > 0 then maps between firstRenderedMap-mapsPerEpoch and
// firstRenderedMap-mapsPerEpoch+tailPartialEpoch-1 are rendered // firstRenderedMap-mapsPerEpoch+tailPartialEpoch-1 are rendered
tailPartialEpoch uint32 tailPartialEpoch uint32
// if initialized then all log values in the blocks range are fully // if initialized then all log values in the blocks range are fully
// rendered // rendered
// blockLvPointers are available in the blocks range // blockLvPointers are available in the blocks range
@ -225,13 +226,15 @@ type Config struct {
} }
// NewFilterMaps creates a new FilterMaps and starts the indexer. // 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) rs, initialized, err := rawdb.ReadFilterMapsRange(db)
if err != nil || rs.Version != databaseVersion { if err != nil || (initialized && rs.Version != databaseVersion) {
rs, initialized = rawdb.FilterMapsRange{}, false rs, initialized = rawdb.FilterMapsRange{}, false
log.Warn("Invalid log index database version; resetting log index") log.Warn("Invalid log index database version; resetting log index")
} }
params.deriveFields() if err := params.sanitize(); err != nil {
return nil, err
}
f := &FilterMaps{ f := &FilterMaps{
db: db, db: db,
closeCh: make(chan struct{}), closeCh: make(chan struct{}),
@ -256,7 +259,6 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
}, },
// deleting last unindexed epoch might have been interrupted by shutdown // deleting last unindexed epoch might have been interrupted by shutdown
cleanedEpochsBefore: max(rs.MapsFirst>>params.logMapsPerEpoch, 1) - 1, cleanedEpochsBefore: max(rs.MapsFirst>>params.logMapsPerEpoch, 1) - 1,
historyCutoff: historyCutoff, historyCutoff: historyCutoff,
finalBlock: finalBlock, finalBlock: finalBlock,
matcherSyncCh: make(chan *FilterMapsMatcherBackend), matcherSyncCh: make(chan *FilterMapsMatcherBackend),
@ -264,7 +266,6 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
filterMapCache: lru.NewCache[uint32, filterMap](cachedFilterMaps), filterMapCache: lru.NewCache[uint32, filterMap](cachedFilterMaps),
lastBlockCache: lru.NewCache[uint32, lastBlockOfMap](cachedLastBlocks), lastBlockCache: lru.NewCache[uint32, lastBlockOfMap](cachedLastBlocks),
lvPointerCache: lru.NewCache[uint64, uint64](cachedLvPointers), lvPointerCache: lru.NewCache[uint64, uint64](cachedLvPointers),
baseRowsCache: lru.NewCache[uint64, [][]uint32](cachedBaseRows),
renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots), renderSnapshots: lru.NewCache[uint64, *renderedMap](cachedRenderSnapshots),
} }
f.checkRevertRange() // revert maps that are inconsistent with the current chain view f.checkRevertRange() // revert maps that are inconsistent with the current chain view
@ -275,7 +276,7 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, f
"firstmap", f.indexedRange.maps.First(), "lastmap", f.indexedRange.maps.Last(), "firstmap", f.indexedRange.maps.First(), "lastmap", f.indexedRange.maps.Last(),
"headindexed", f.indexedRange.headIndexed) "headindexed", f.indexedRange.headIndexed)
} }
return f return f, nil
} }
// Start starts the indexer. // Start starts the indexer.
@ -348,7 +349,6 @@ func (f *FilterMaps) reset() {
f.renderSnapshots.Purge() f.renderSnapshots.Purge()
f.lastBlockCache.Purge() f.lastBlockCache.Purge()
f.lvPointerCache.Purge() f.lvPointerCache.Purge()
f.baseRowsCache.Purge()
f.indexLock.Unlock() f.indexLock.Unlock()
// deleting the range first ensures that resetDb will be called again at next // deleting the range first ensures that resetDb will be called again at next
// startup and any leftover data will be removed even if it cannot finish now. // startup and any leftover data will be removed even if it cannot finish now.
@ -403,7 +403,7 @@ func (f *FilterMaps) init() error {
batch := f.db.NewBatch() batch := f.db.NewBatch()
for epoch := range bestLen { for epoch := range bestLen {
cp := checkpoints[bestIdx][epoch] cp := checkpoints[bestIdx][epoch]
f.storeLastBlockOfMap(batch, (uint32(epoch+1)<<f.logMapsPerEpoch)-1, cp.BlockNumber, cp.BlockId) f.storeLastBlockOfMap(batch, f.lastEpochMap(uint32(epoch)), cp.BlockNumber, cp.BlockId)
f.storeBlockLvPointer(batch, cp.BlockNumber, cp.FirstIndex) f.storeBlockLvPointer(batch, cp.BlockNumber, cp.FirstIndex)
} }
fmr := filterMapsRange{ fmr := filterMapsRange{
@ -412,7 +412,7 @@ func (f *FilterMaps) init() error {
if bestLen > 0 { if bestLen > 0 {
cp := checkpoints[bestIdx][bestLen-1] cp := checkpoints[bestIdx][bestLen-1]
fmr.blocks = common.NewRange(cp.BlockNumber+1, 0) fmr.blocks = common.NewRange(cp.BlockNumber+1, 0)
fmr.maps = common.NewRange(uint32(bestLen)<<f.logMapsPerEpoch, 0) fmr.maps = common.NewRange(f.firstEpochMap(uint32(bestLen)), 0)
} }
f.setRange(batch, f.targetView, fmr, false) f.setRange(batch, f.targetView, fmr, false)
return batch.Write() return batch.Write()
@ -565,53 +565,81 @@ func (f *FilterMaps) getFilterMap(mapIndex uint32) (filterMap, error) {
} }
fm := make(filterMap, f.mapHeight) fm := make(filterMap, f.mapHeight)
for rowIndex := range fm { for rowIndex := range fm {
var err error rows, err := f.getFilterMapRows([]uint32{mapIndex}, uint32(rowIndex), false)
fm[rowIndex], err = f.getFilterMapRow(mapIndex, uint32(rowIndex), false)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load filter map %d from database: %v", mapIndex, err) return nil, fmt.Errorf("failed to load filter map %d from database: %v", mapIndex, err)
} }
fm[rowIndex] = rows[0]
} }
f.filterMapCache.Add(mapIndex, fm) f.filterMapCache.Add(mapIndex, fm)
return fm, nil return fm, nil
} }
// getFilterMapRow fetches the given filter map row. If baseLayerOnly is true // getFilterMapRows fetches a set of filter map rows at the corresponding map
// then only the first baseRowLength entries are returned. // indices and a shared row index. If baseLayerOnly is true then only the first
func (f *FilterMaps) getFilterMapRow(mapIndex, rowIndex uint32, baseLayerOnly bool) (FilterRow, error) { // baseRowLength entries are returned.
baseMapRowIndex := f.mapRowIndex(mapIndex&-f.baseRowGroupLength, rowIndex) func (f *FilterMaps) getFilterMapRows(mapIndices []uint32, rowIndex uint32, baseLayerOnly bool) ([]FilterRow, error) {
baseRows, ok := f.baseRowsCache.Get(baseMapRowIndex) rows := make([]FilterRow, len(mapIndices))
if !ok { var ptr int
var err error for len(mapIndices) > ptr {
baseRows, err = rawdb.ReadFilterMapBaseRows(f.db, baseMapRowIndex, f.baseRowGroupLength, f.logMapWidth) 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 {
return nil, err
}
ptr += groupLength
}
return rows, nil
}
// 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 {
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 { if err != nil {
return nil, fmt.Errorf("failed to retrieve filter map %d base rows %d: %v", mapIndex, rowIndex, err) return fmt.Errorf("failed to retrieve base row group %d of row %d: %v", groupIndex, rowIndex, err)
} }
f.baseRowsCache.Add(baseMapRowIndex, baseRows) for i, mapIndex := range mapIndices {
} if f.mapGroupIndex(mapIndex) != groupIndex {
baseRow := slices.Clone(baseRows[mapIndex&(f.baseRowGroupLength-1)]) return fmt.Errorf("maps are not in the same base row group, index: %d, group: %d", mapIndex, groupIndex)
if baseLayerOnly {
return baseRow, nil
} }
row := baseRows[f.mapGroupOffset(mapIndex)]
if !baseLayerOnly {
extRow, err := rawdb.ReadFilterMapExtRow(f.db, f.mapRowIndex(mapIndex, rowIndex), f.logMapWidth) extRow, err := rawdb.ReadFilterMapExtRow(f.db, f.mapRowIndex(mapIndex, rowIndex), f.logMapWidth)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to retrieve filter map %d extended row %d: %v", mapIndex, rowIndex, err) return fmt.Errorf("failed to retrieve filter map %d extended row %d: %v", mapIndex, rowIndex, err)
} }
return FilterRow(append(baseRow, extRow...)), nil row = append(row, extRow...)
}
target[i] = row
}
return nil
} }
// storeFilterMapRows stores a set of filter map rows at the corresponding map // storeFilterMapRows stores a set of filter map rows at the corresponding map
// indices and a shared row index. // indices and a shared row index.
func (f *FilterMaps) storeFilterMapRows(batch ethdb.Batch, mapIndices []uint32, rowIndex uint32, rows []FilterRow) error { func (f *FilterMaps) storeFilterMapRows(batch ethdb.Batch, mapIndices []uint32, rowIndex uint32, rows []FilterRow) error {
for len(mapIndices) > 0 { for len(mapIndices) > 0 {
baseMapIndex := mapIndices[0] & -f.baseRowGroupLength var (
groupLength := 1 pos = 1
for groupLength < len(mapIndices) && mapIndices[groupLength]&-f.baseRowGroupLength == baseMapIndex { groupIndex = f.mapGroupIndex(mapIndices[0])
groupLength++ )
for pos < len(mapIndices) && f.mapGroupIndex(mapIndices[pos]) == groupIndex {
pos++
} }
if err := f.storeFilterMapRowsOfGroup(batch, mapIndices[:groupLength], rowIndex, rows[:groupLength]); err != nil { if err := f.storeFilterMapRowsOfGroup(batch, mapIndices[:pos], rowIndex, rows[:pos]); err != nil {
return err return err
} }
mapIndices, rows = mapIndices[groupLength:], rows[groupLength:] mapIndices, rows = mapIndices[pos:], rows[pos:]
} }
return nil return nil
} }
@ -619,27 +647,23 @@ func (f *FilterMaps) storeFilterMapRows(batch ethdb.Batch, mapIndices []uint32,
// storeFilterMapRowsOfGroup stores a set of filter map rows at map indices // storeFilterMapRowsOfGroup stores a set of filter map rows at map indices
// belonging to the same base row group. // belonging to the same base row group.
func (f *FilterMaps) storeFilterMapRowsOfGroup(batch ethdb.Batch, mapIndices []uint32, rowIndex uint32, rows []FilterRow) error { func (f *FilterMaps) storeFilterMapRowsOfGroup(batch ethdb.Batch, mapIndices []uint32, rowIndex uint32, rows []FilterRow) error {
baseMapIndex := mapIndices[0] & -f.baseRowGroupLength var (
baseMapRowIndex := f.mapRowIndex(baseMapIndex, rowIndex) baseRows [][]uint32
var baseRows [][]uint32 groupIndex = f.mapGroupIndex(mapIndices[0])
if uint32(len(mapIndices)) != f.baseRowGroupLength { // skip base rows read if all rows are replaced mapRowIndex = f.mapRowIndex(groupIndex, rowIndex)
var ok bool )
baseRows, ok = f.baseRowsCache.Get(baseMapRowIndex) if uint32(len(mapIndices)) != f.baseRowGroupSize { // skip base rows read if all rows are replaced
if ok {
baseRows = slices.Clone(baseRows)
} else {
var err error 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 { if err != nil {
return fmt.Errorf("failed to retrieve filter map %d base rows %d for modification: %v", mapIndices[0]&-f.baseRowGroupLength, rowIndex, err) return fmt.Errorf("failed to retrieve filter map %d base rows %d for modification: %v", groupIndex, rowIndex, err)
}
} }
} else { } else {
baseRows = make([][]uint32, f.baseRowGroupLength) baseRows = make([][]uint32, f.baseRowGroupSize)
} }
for i, mapIndex := range mapIndices { for i, mapIndex := range mapIndices {
if mapIndex&-f.baseRowGroupLength != baseMapIndex { if f.mapGroupIndex(mapIndex) != groupIndex {
panic("mapIndices are not in the same base row group") return fmt.Errorf("maps are not in the same base row group, index: %d, group: %d", mapIndex, groupIndex)
} }
baseRow := []uint32(rows[i]) baseRow := []uint32(rows[i])
var extRow FilterRow var extRow FilterRow
@ -647,11 +671,10 @@ func (f *FilterMaps) storeFilterMapRowsOfGroup(batch ethdb.Batch, mapIndices []u
extRow = baseRow[f.baseRowLength:] extRow = baseRow[f.baseRowLength:]
baseRow = 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.WriteFilterMapExtRow(batch, f.mapRowIndex(mapIndex, rowIndex), extRow, f.logMapWidth)
} }
f.baseRowsCache.Add(baseMapRowIndex, baseRows) rawdb.WriteFilterMapBaseRows(batch, mapRowIndex, baseRows, f.logMapWidth)
rawdb.WriteFilterMapBaseRows(batch, baseMapRowIndex, baseRows, f.logMapWidth)
return nil return nil
} }
@ -736,12 +759,12 @@ func (f *FilterMaps) deleteTailEpoch(epoch uint32) (bool, error) {
defer f.indexLock.Unlock() defer f.indexLock.Unlock()
// determine epoch boundaries // determine epoch boundaries
firstMap := epoch << f.logMapsPerEpoch lastBlock, _, err := f.getLastBlockOfMap(f.lastEpochMap(epoch))
lastBlock, _, err := f.getLastBlockOfMap(firstMap + f.mapsPerEpoch - 1)
if err != nil { if err != nil {
return false, fmt.Errorf("failed to retrieve last block of deleted epoch %d: %v", epoch, err) return false, fmt.Errorf("failed to retrieve last block of deleted epoch %d: %v", epoch, err)
} }
var firstBlock uint64 var firstBlock uint64
firstMap := f.firstEpochMap(epoch)
if epoch > 0 { if epoch > 0 {
firstBlock, _, err = f.getLastBlockOfMap(firstMap - 1) firstBlock, _, err = f.getLastBlockOfMap(firstMap - 1)
if err != nil { if err != nil {
@ -752,8 +775,8 @@ func (f *FilterMaps) deleteTailEpoch(epoch uint32) (bool, error) {
// update rendered range if necessary // update rendered range if necessary
var ( var (
fmr = f.indexedRange fmr = f.indexedRange
firstEpoch = f.indexedRange.maps.First() >> f.logMapsPerEpoch firstEpoch = f.mapEpoch(f.indexedRange.maps.First())
afterLastEpoch = (f.indexedRange.maps.AfterLast() + f.mapsPerEpoch - 1) >> f.logMapsPerEpoch afterLastEpoch = f.mapEpoch(f.indexedRange.maps.AfterLast() + f.mapsPerEpoch - 1)
) )
if f.indexedRange.tailPartialEpoch != 0 && firstEpoch > 0 { if f.indexedRange.tailPartialEpoch != 0 && firstEpoch > 0 {
firstEpoch-- firstEpoch--
@ -765,7 +788,7 @@ func (f *FilterMaps) deleteTailEpoch(epoch uint32) (bool, error) {
// first fully or partially rendered epoch and there is at least one // first fully or partially rendered epoch and there is at least one
// rendered map in the next epoch; remove from indexed range // rendered map in the next epoch; remove from indexed range
fmr.tailPartialEpoch = 0 fmr.tailPartialEpoch = 0
fmr.maps.SetFirst((epoch + 1) << f.logMapsPerEpoch) fmr.maps.SetFirst(f.firstEpochMap(epoch + 1))
fmr.blocks.SetFirst(lastBlock + 1) fmr.blocks.SetFirst(lastBlock + 1)
f.setRange(f.db, f.indexedView, fmr, false) f.setRange(f.db, f.indexedView, fmr, false)
default: default:
@ -846,7 +869,7 @@ func (f *FilterMaps) exportCheckpoints() {
w.WriteString("[\n") w.WriteString("[\n")
comma := "," comma := ","
for epoch := uint32(0); epoch < epochCount; epoch++ { for epoch := uint32(0); epoch < epochCount; epoch++ {
lastBlock, lastBlockId, err := f.getLastBlockOfMap((epoch+1)<<f.logMapsPerEpoch - 1) lastBlock, lastBlockId, err := f.getLastBlockOfMap(f.lastEpochMap(epoch))
if err != nil { if err != nil {
log.Error("Error fetching last block of epoch", "epoch", epoch, "error", err) log.Error("Error fetching last block of epoch", "epoch", epoch, "error", err)
return return

View file

@ -281,7 +281,7 @@ func (f *FilterMaps) tryIndexHead() error {
// is changed. // is changed.
func (f *FilterMaps) tryIndexTail() (bool, error) { func (f *FilterMaps) tryIndexTail() (bool, error) {
for { for {
firstEpoch := f.indexedRange.maps.First() >> f.logMapsPerEpoch firstEpoch := f.mapEpoch(f.indexedRange.maps.First())
if firstEpoch == 0 || !f.needTailEpoch(firstEpoch-1) { if firstEpoch == 0 || !f.needTailEpoch(firstEpoch-1) {
break break
} }
@ -359,7 +359,7 @@ func (f *FilterMaps) tryIndexTail() (bool, error) {
// Note that unindexing is very quick as it only removes continuous ranges of // 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. // data from the database and is also called while running head indexing.
func (f *FilterMaps) tryUnindexTail() (bool, error) { 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 { if f.indexedRange.tailPartialEpoch > 0 && firstEpoch > 0 {
firstEpoch-- firstEpoch--
} }
@ -392,11 +392,11 @@ func (f *FilterMaps) tryUnindexTail() (bool, error) {
// needTailEpoch returns true if the given tail epoch needs to be kept // needTailEpoch returns true if the given tail epoch needs to be kept
// according to the current tail target, false if it can be removed. // according to the current tail target, false if it can be removed.
func (f *FilterMaps) needTailEpoch(epoch uint32) bool { func (f *FilterMaps) needTailEpoch(epoch uint32) bool {
firstEpoch := f.indexedRange.maps.First() >> f.logMapsPerEpoch firstEpoch := f.mapEpoch(f.indexedRange.maps.First())
if epoch > firstEpoch { if epoch > firstEpoch {
return true return true
} }
if (epoch+1)<<f.logMapsPerEpoch >= f.indexedRange.maps.AfterLast() { if f.firstEpochMap(epoch+1) >= f.indexedRange.maps.AfterLast() {
return true return true
} }
if epoch+1 < firstEpoch { if epoch+1 < firstEpoch {
@ -405,7 +405,7 @@ func (f *FilterMaps) needTailEpoch(epoch uint32) bool {
var lastBlockOfPrevEpoch uint64 var lastBlockOfPrevEpoch uint64
if epoch > 0 { if epoch > 0 {
var err error var err error
lastBlockOfPrevEpoch, _, err = f.getLastBlockOfMap(epoch<<f.logMapsPerEpoch - 1) lastBlockOfPrevEpoch, _, err = f.getLastBlockOfMap(f.lastEpochMap(epoch - 1))
if err != nil { if err != nil {
log.Error("Could not get last block of previous epoch", "epoch", epoch-1, "error", err) log.Error("Could not get last block of previous epoch", "epoch", epoch-1, "error", err)
return epoch >= firstEpoch return epoch >= firstEpoch
@ -414,7 +414,7 @@ func (f *FilterMaps) needTailEpoch(epoch uint32) bool {
if f.historyCutoff > lastBlockOfPrevEpoch { if f.historyCutoff > lastBlockOfPrevEpoch {
return false return false
} }
lastBlockOfEpoch, _, err := f.getLastBlockOfMap((epoch+1)<<f.logMapsPerEpoch - 1) lastBlockOfEpoch, _, err := f.getLastBlockOfMap(f.lastEpochMap(epoch))
if err != nil { if err != nil {
log.Error("Could not get last block of epoch", "epoch", epoch, "error", err) log.Error("Could not get last block of epoch", "epoch", epoch, "error", err)
return epoch >= firstEpoch return epoch >= firstEpoch

View file

@ -41,7 +41,7 @@ var testParams = Params{
logMapWidth: 24, logMapWidth: 24,
logMapsPerEpoch: 4, logMapsPerEpoch: 4,
logValuesPerMap: 4, logValuesPerMap: 4,
baseRowGroupLength: 4, baseRowGroupSize: 4,
baseRowLengthRatio: 2, baseRowLengthRatio: 2,
logLayerDiff: 2, logLayerDiff: 2,
} }
@ -370,7 +370,7 @@ func (ts *testSetup) setHistory(history uint64, noHistory bool) {
History: history, History: history,
Disabled: noHistory, 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.testDisableSnapshots = ts.testDisableSnapshots
ts.fm.Start() ts.fm.Start()
} }
@ -428,13 +428,15 @@ func (ts *testSetup) matcherViewHash() common.Hash {
binary.LittleEndian.PutUint32(enc[:4], r) binary.LittleEndian.PutUint32(enc[:4], r)
for m := uint32(0); m <= headMap; m++ { for m := uint32(0); m <= headMap; m++ {
binary.LittleEndian.PutUint32(enc[4:8], m) binary.LittleEndian.PutUint32(enc[4:8], m)
row, _ := mb.GetFilterMapRow(ctx, m, r, false) rows, _ := mb.GetFilterMapRows(ctx, []uint32{m}, r, false)
for _, row := range rows {
for _, v := range row { for _, v := range row {
binary.LittleEndian.PutUint32(enc[8:], v) binary.LittleEndian.PutUint32(enc[8:], v)
hasher.Write(enc[:]) hasher.Write(enc[:])
} }
} }
} }
}
var hash common.Hash var hash common.Hash
hasher.Sum(hash[:0]) hasher.Sum(hash[:0])
for i := 0; i < 50; i++ { for i := 0; i < 50; i++ {
@ -515,7 +517,7 @@ func (tc *testChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
return tc.receipts[hash] return tc.receipts[hash]
} }
func (tc *testChain) GetRawReceiptsByHash(hash common.Hash) types.Receipts { func (tc *testChain) GetRawReceipts(hash common.Hash, number uint64) types.Receipts {
tc.lock.RLock() tc.lock.RLock()
defer tc.lock.RUnlock() defer tc.lock.RUnlock()

View file

@ -284,7 +284,7 @@ func (r *mapRenderer) run(stopCb func() bool, writeCb func()) (bool, error) {
// map finished // map finished
r.finishedMaps[r.currentMap.mapIndex] = r.currentMap r.finishedMaps[r.currentMap.mapIndex] = r.currentMap
r.finished.SetLast(r.finished.AfterLast()) 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 { if err := r.writeFinishedMaps(stopCb); err != nil {
return false, err return false, err
} }

View file

@ -20,7 +20,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -45,7 +44,7 @@ var ErrMatchAll = errors.New("match all patterns not supported")
type MatcherBackend interface { type MatcherBackend interface {
GetParams() *Params GetParams() *Params
GetBlockLvPointer(ctx context.Context, blockNumber uint64) (uint64, error) GetBlockLvPointer(ctx context.Context, blockNumber uint64) (uint64, error)
GetFilterMapRow(ctx context.Context, mapIndex, rowIndex uint32, baseLayerOnly bool) (FilterRow, error) GetFilterMapRows(ctx context.Context, mapIndices []uint32, rowIndex uint32, baseLayerOnly bool) ([]FilterRow, error)
GetLogByLvIndex(ctx context.Context, lvIndex uint64) (*types.Log, error) GetLogByLvIndex(ctx context.Context, lvIndex uint64) (*types.Log, error)
SyncLogIndex(ctx context.Context) (SyncRange, error) SyncLogIndex(ctx context.Context) (SyncRange, error)
Close() Close()
@ -365,26 +364,32 @@ func (m *singleMatcherInstance) getMatchesForLayer(ctx context.Context, layerInd
var st int var st int
m.stats.setState(&st, stOther) m.stats.setState(&st, stOther)
params := m.backend.GetParams() params := m.backend.GetParams()
maskedMapIndex, rowIndex := uint32(math.MaxUint32), uint32(0) var ptr int
for _, mapIndex := range m.mapIndices { for len(m.mapIndices) > ptr {
filterRows, ok := m.filterRows[mapIndex] // find next group of map indices mapped onto the same row
if !ok { maskedMapIndex := params.maskedMapIndex(m.mapIndices[ptr], layerIndex)
continue rowIndex := params.rowIndex(m.mapIndices[ptr], layerIndex, m.value)
} groupLength := 1
if mm := params.maskedMapIndex(mapIndex, layerIndex); mm != maskedMapIndex { for ptr+groupLength < len(m.mapIndices) && params.maskedMapIndex(m.mapIndices[ptr+groupLength], layerIndex) == maskedMapIndex {
// only recalculate rowIndex when necessary groupLength++
maskedMapIndex = mm
rowIndex = params.rowIndex(mapIndex, layerIndex, m.value)
} }
if layerIndex == 0 { if layerIndex == 0 {
m.stats.setState(&st, stFetchFirst) m.stats.setState(&st, stFetchFirst)
} else { } else {
m.stats.setState(&st, stFetchMore) m.stats.setState(&st, stFetchMore)
} }
filterRow, err := m.backend.GetFilterMapRow(ctx, mapIndex, rowIndex, layerIndex == 0) groupRows, err := m.backend.GetFilterMapRows(ctx, m.mapIndices[ptr:ptr+groupLength], rowIndex, layerIndex == 0)
if err != nil { if err != nil {
m.stats.setState(&st, stNone) m.stats.setState(&st, stNone)
return nil, fmt.Errorf("failed to retrieve filter map %d row %d: %v", mapIndex, rowIndex, err) return nil, fmt.Errorf("failed to retrieve filter map %d row %d: %v", m.mapIndices[ptr], rowIndex, err)
}
m.stats.setState(&st, stOther)
for i := range groupLength {
mapIndex := m.mapIndices[ptr+i]
filterRow := groupRows[i]
filterRows, ok := m.filterRows[mapIndex]
if !ok {
panic("dropped map in mapIndices")
} }
if layerIndex == 0 { if layerIndex == 0 {
matchBaseRowAccessMeter.Mark(1) matchBaseRowAccessMeter.Mark(1)
@ -394,7 +399,6 @@ func (m *singleMatcherInstance) getMatchesForLayer(ctx context.Context, layerInd
matchExtRowSizeMeter.Mark(int64(len(filterRow))) matchExtRowSizeMeter.Mark(int64(len(filterRow)))
} }
m.stats.addAmount(st, int64(len(filterRow))) m.stats.addAmount(st, int64(len(filterRow)))
m.stats.setState(&st, stOther)
filterRows = append(filterRows, filterRow) filterRows = append(filterRows, filterRow)
if uint32(len(filterRow)) < params.maxRowLength(layerIndex) { if uint32(len(filterRow)) < params.maxRowLength(layerIndex) {
m.stats.setState(&st, stProcess) m.stats.setState(&st, stProcess)
@ -410,6 +414,8 @@ func (m *singleMatcherInstance) getMatchesForLayer(ctx context.Context, layerInd
m.filterRows[mapIndex] = filterRows m.filterRows[mapIndex] = filterRows
} }
} }
ptr += groupLength
}
m.cleanMapIndices() m.cleanMapIndices()
m.stats.setState(&st, stNone) m.stats.setState(&st, stNone)
return results, nil return results, nil
@ -838,7 +844,7 @@ func (m *matchSequenceInstance) dropNext(mapIndex uint32) bool {
// results at mapIndex and mapIndex+1. Note that acquiring nextNextRes may be // 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 // 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. // 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 == nil || (baseRes != nil && len(baseRes) == 0) {
// if nextRes is a wild card or baseRes is empty then the sequence matcher // if nextRes is a wild card or baseRes is empty then the sequence matcher
// result equals baseRes. // result equals baseRes.
@ -848,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 // 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 is the items of nextRes with a negative offset applied.
result := make(potentialMatches, 0, len(nextRes)) result := make(potentialMatches, 0, len(nextRes))
min := (uint64(mapIndex) << params.logValuesPerMap) + offset min := (uint64(mapIndex) << p.logValuesPerMap) + offset
for _, v := range nextRes { for _, v := range nextRes {
if v >= min { if v >= min {
result = append(result, v-offset) result = append(result, v-offset)

View file

@ -67,18 +67,15 @@ func (fm *FilterMapsMatcherBackend) Close() {
delete(fm.f.matchers, fm) delete(fm.f.matchers, fm)
} }
// GetFilterMapRow returns the given row of the given map. If the row is empty // GetFilterMapRows returns the given row of the given map. If the row is empty
// then a non-nil zero length row is returned. If baseLayerOnly is true then // then a non-nil zero length row is returned. If baseLayerOnly is true then
// only the first baseRowLength entries of the row are guaranteed to be // only the first baseRowLength entries of the row are guaranteed to be
// returned. // returned.
// Note that the returned slices should not be modified, they should be copied // Note that the returned slices should not be modified, they should be copied
// on write. // on write.
// GetFilterMapRow implements MatcherBackend. // GetFilterMapRows implements MatcherBackend.
func (fm *FilterMapsMatcherBackend) GetFilterMapRow(ctx context.Context, mapIndex, rowIndex uint32, baseLayerOnly bool) (FilterRow, error) { func (fm *FilterMapsMatcherBackend) GetFilterMapRows(ctx context.Context, mapIndices []uint32, rowIndex uint32, baseLayerOnly bool) ([]FilterRow, error) {
fm.f.indexLock.RLock() return fm.f.getFilterMapRows(mapIndices, rowIndex, baseLayerOnly)
defer fm.f.indexLock.RUnlock()
return fm.f.getFilterMapRow(mapIndex, rowIndex, baseLayerOnly)
} }
// GetBlockLvPointer returns the starting log value index where the log values // GetBlockLvPointer returns the starting log value index where the log values

View file

@ -19,6 +19,7 @@ package filtermaps
import ( import (
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"fmt"
"hash/fnv" "hash/fnv"
"math" "math"
"sort" "sort"
@ -28,19 +29,36 @@ import (
// Params defines the basic parameters of the log index structure. // Params defines the basic parameters of the log index structure.
type Params struct { type Params struct {
logMapHeight uint // log2(mapHeight) logMapHeight uint // The number of bits required to represent the map height
logMapWidth uint // log2(mapWidth) logMapWidth uint // The number of bits required to represent the map width
logMapsPerEpoch uint // log2(mapsPerEpoch) logMapsPerEpoch uint // The number of bits required to represent the number of maps per epoch
logValuesPerMap uint // log2(logValuesPerMap) logValuesPerMap uint // The number of bits required to represent the number of log values per map
baseRowLengthRatio uint // baseRowLength / average row length
logLayerDiff uint // maxRowLength log2 growth per layer // baseRowLengthRatio represents the ratio of base row length
// derived fields // to the average row length.
mapHeight uint32 // filter map height (number of rows) baseRowLengthRatio uint
mapsPerEpoch uint32 // number of maps in an epoch
// 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 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 // baseRowGroupSize defines the number of base row entries grouped together
baseRowGroupLength uint32 // length of base row groups in local database // 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. // DefaultParams is the set of parameters used on mainnet.
@ -49,7 +67,7 @@ var DefaultParams = Params{
logMapWidth: 24, logMapWidth: 24,
logMapsPerEpoch: 10, logMapsPerEpoch: 10,
logValuesPerMap: 16, logValuesPerMap: 16,
baseRowGroupLength: 32, baseRowGroupSize: 32,
baseRowLengthRatio: 8, baseRowLengthRatio: 8,
logLayerDiff: 4, logLayerDiff: 4,
} }
@ -60,7 +78,7 @@ var RangeTestParams = Params{
logMapWidth: 24, logMapWidth: 24,
logMapsPerEpoch: 0, logMapsPerEpoch: 0,
logValuesPerMap: 0, logValuesPerMap: 0,
baseRowGroupLength: 32, baseRowGroupSize: 32,
baseRowLengthRatio: 16, // baseRowLength >= 1 baseRowLengthRatio: 16, // baseRowLength >= 1
logLayerDiff: 4, logLayerDiff: 4,
} }
@ -91,6 +109,44 @@ func topicValue(topic common.Hash) common.Hash {
return result 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)<<p.logMapsPerEpoch - 1
}
// rowIndex returns the row index in which the given log value should be marked // rowIndex returns the row index in which the given log value should be marked
// on the given map and mapping layer. Note that row assignments are re-shuffled // on the given map and mapping layer. Note that row assignments are re-shuffled
// with a different frequency on each mapping layer, allowing efficient disk // with a different frequency on each mapping layer, allowing efficient disk
@ -125,17 +181,20 @@ func (p *Params) columnIndex(lvIndex uint64, logValue *common.Hash) uint32 {
return uint32(lvIndex%p.valuesPerMap)<<hashBits + (uint32(hash>>(64-hashBits)) ^ uint32(hash)>>(32-hashBits)) return uint32(lvIndex%p.valuesPerMap)<<hashBits + (uint32(hash>>(64-hashBits)) ^ uint32(hash)>>(32-hashBits))
} }
// maxRowLength returns the maximum length filter rows are populated up to // maxRowLength returns the maximum length filter rows are populated up to when
// when using the given mapping layer. A log value can be marked on the map // using the given mapping layer.
// 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. // 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 // This means that a row that is considered full on a given layer may still be
// extended further on a higher order layer. // extended further on a higher order layer.
//
// Each value is marked on the lowest order layer possible, assuming that marks // Each value is marked on the lowest order layer possible, assuming that marks
// are added in ascending log value index order. // are added in ascending log value index order. When searching for a log value
// When searching for a log value one should consider all layers and process // one should consider all layers and process corresponding rows up until the
// corresponding rows up until the first one where the row mapped to the given // first one where the row mapped to the given layer is not full.
// layer is not full.
func (p *Params) maxRowLength(layerIndex uint32) uint32 { func (p *Params) maxRowLength(layerIndex uint32) uint32 {
logLayerDiff := uint(layerIndex) * p.logLayerDiff logLayerDiff := uint(layerIndex) * p.logLayerDiff
if logLayerDiff > p.logMapsPerEpoch { if logLayerDiff > p.logMapsPerEpoch {

View file

@ -258,7 +258,7 @@ func (e *GenesisMismatchError) Error() string {
// ChainOverrides contains the changes to chain config. // ChainOverrides contains the changes to chain config.
type ChainOverrides struct { type ChainOverrides struct {
OverridePrague *uint64 OverrideOsaka *uint64
OverrideVerkle *uint64 OverrideVerkle *uint64
} }
@ -267,8 +267,8 @@ func (o *ChainOverrides) apply(cfg *params.ChainConfig) error {
if o == nil || cfg == nil { if o == nil || cfg == nil {
return nil return nil
} }
if o.OverridePrague != nil { if o.OverrideOsaka != nil {
cfg.PragueTime = o.OverridePrague cfg.OsakaTime = o.OverrideOsaka
} }
if o.OverrideVerkle != nil { if o.OverrideVerkle != nil {
cfg.VerkleTime = o.OverrideVerkle cfg.VerkleTime = o.OverrideVerkle

View file

@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "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"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
@ -131,7 +130,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
oldcustomg.Commit(db, tdb) 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() defer bc.Stop()
_, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil) _, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil)
@ -257,7 +256,9 @@ func newDbConfig(scheme string) *triedb.Config {
if scheme == rawdb.HashScheme { if scheme == rawdb.HashScheme {
return triedb.HashDefaults 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) { func TestVerkleGenesisCommit(t *testing.T) {
@ -314,7 +315,14 @@ func TestVerkleGenesisCommit(t *testing.T) {
} }
db := rawdb.NewMemoryDatabase() 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) block := genesis.MustCommit(db, triedb)
if !bytes.Equal(block.Root().Bytes(), expected) { if !bytes.Equal(block.Root().Bytes(), expected) {
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, block.Root()) t.Fatalf("invalid genesis state root, expected %x, got %x", expected, block.Root())

View file

@ -449,9 +449,10 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
return data return data
} }
// ReadCanonicalBodyRLP retrieves the block body (transactions and uncles) for the canonical // ReadCanonicalBodyRLP retrieves the block body (transactions and uncles) for the
// block at number, in RLP encoding. // canonical block at number, in RLP encoding. Optionally it takes the block hash
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { // to avoid looking it up
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.RawValue {
var data []byte var data []byte
db.ReadAncients(func(reader ethdb.AncientReaderOp) error { db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
data, _ = reader.Ancient(ChainFreezerBodiesTable, number) data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
@ -459,10 +460,14 @@ func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
return nil return nil
} }
// Block is not in ancients, read from leveldb by hash and number. // Block is not in ancients, read from leveldb by hash and number.
if hash != nil {
data, _ = db.Get(blockBodyKey(number, *hash))
} else {
// Note: ReadCanonicalHash cannot be used here because it also // Note: ReadCanonicalHash cannot be used here because it also
// calls ReadAncients internally. // calls ReadAncients internally.
hash, _ := db.Get(headerHashKey(number)) hashBytes, _ := db.Get(headerHashKey(number))
data, _ = db.Get(blockBodyKey(number, common.BytesToHash(hash))) data, _ = db.Get(blockBodyKey(number, common.BytesToHash(hashBytes)))
}
return nil return nil
}) })
return data return data
@ -544,9 +549,32 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa
return data 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. // ReadRawReceipts retrieves all the transaction receipts belonging to a block.
// The receipt metadata fields are not guaranteed to be populated, so they // The receipt metadata fields and the Bloom are not guaranteed to be populated,
// should not be used. Use ReadReceipts instead if the metadata is needed. // so they should not be used. Use ReadReceipts instead if the metadata is needed.
func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts {
// Retrieve the flattened receipt slice // Retrieve the flattened receipt slice
data := ReadReceiptsRLP(db, hash, number) data := ReadReceiptsRLP(db, hash, number)
@ -621,6 +649,14 @@ func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rec
} }
} }
// WriteRawReceipts stores all the transaction receipts belonging to a block.
func WriteRawReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts rlp.RawValue) {
// Store the flattened receipt slice
if err := db.Put(blockReceiptsKey(number, hash), receipts); err != nil {
log.Crit("Failed to store block receipts", "err", err)
}
}
// DeleteReceipts removes all receipt data associated with a block hash. // DeleteReceipts removes all receipt data associated with a block hash.
func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { if err := db.Delete(blockReceiptsKey(number, hash)); err != nil {
@ -701,18 +737,11 @@ func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
} }
// WriteAncientBlocks writes entire block data into ancient store and returns the total written size. // WriteAncientBlocks writes entire block data into ancient store and returns the total written size.
func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []types.Receipts) (int64, error) { func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []rlp.RawValue) (int64, error) {
var stReceipts []*types.ReceiptForStorage
return db.ModifyAncients(func(op ethdb.AncientWriteOp) error { return db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i, block := range blocks { for i, block := range blocks {
// Convert receipts to storage format and sum up total difficulty.
stReceipts = stReceipts[:0]
for _, receipt := range receipts[i] {
stReceipts = append(stReceipts, (*types.ReceiptForStorage)(receipt))
}
header := block.Header() header := block.Header()
if err := writeAncientBlock(op, block, header, stReceipts); err != nil { if err := writeAncientBlock(op, block, header, receipts[i]); err != nil {
return err return err
} }
} }
@ -720,7 +749,7 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts
}) })
} }
func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts []*types.ReceiptForStorage) error { func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts rlp.RawValue) error {
num := block.NumberU64() num := block.NumberU64()
if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil { if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil {
return fmt.Errorf("can't add block %d hash: %v", num, err) return fmt.Errorf("can't add block %d hash: %v", num, err)

Some files were not shown because too many files have changed in this diff Show more