Compare commits
56 Commits
v1.14.5
...
unbork-mas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5c36a8e2c | ||
|
|
afddce396d | ||
|
|
2b5d289b66 | ||
|
|
09056601d8 | ||
|
|
41abab9e39 | ||
|
|
a4e338f05e | ||
|
|
7cfff30ba3 | ||
|
|
06f1d077d3 | ||
|
|
4939c25341 | ||
|
|
36d67be41b | ||
|
|
19c3c1e205 | ||
|
|
045b9718d5 | ||
|
|
269e80b07e | ||
|
|
9298d2db88 | ||
|
|
98b5930d2d | ||
|
|
ed8fd0ac09 | ||
|
|
73f7e7c087 | ||
|
|
fe0c0b04fe | ||
|
|
0a651f8972 | ||
|
|
d8ea7ac2b0 | ||
|
|
a71f6f91fd | ||
|
|
c10ac4f48f | ||
|
|
e0e45dbc32 | ||
|
|
27654d3022 | ||
|
|
00675c5876 | ||
|
|
27008408a5 | ||
|
|
c11aac249d | ||
|
|
0e3a0a693c | ||
|
|
67a862db9d | ||
|
|
7cf6a63687 | ||
|
|
d8664490da | ||
|
|
c736b04d9b | ||
|
|
115d154392 | ||
|
|
b78d2352ef | ||
|
|
a58e4f0674 | ||
|
|
34b46a2f75 | ||
|
|
fd5078c779 | ||
|
|
86150af2e5 | ||
|
|
69351e8b0f | ||
|
|
3687c34cfc | ||
|
|
1e97148249 | ||
|
|
b6f2bbd417 | ||
|
|
c732039a34 | ||
|
|
caa066dcb0 | ||
|
|
ffb29be7d4 | ||
|
|
3aa874bed2 | ||
|
|
85587d5ef2 | ||
|
|
2eb185c92b | ||
|
|
db273c8733 | ||
|
|
8bda642963 | ||
|
|
349fcdd22d | ||
|
|
1098d148a5 | ||
|
|
deaf10982c | ||
|
|
6a49d13c13 | ||
|
|
4405f18519 | ||
|
|
4461c1fc17 |
6
.github/CODEOWNERS
vendored
6
.github/CODEOWNERS
vendored
@@ -4,14 +4,18 @@
|
|||||||
accounts/usbwallet @karalabe
|
accounts/usbwallet @karalabe
|
||||||
accounts/scwallet @gballet
|
accounts/scwallet @gballet
|
||||||
accounts/abi @gballet @MariusVanDerWijden
|
accounts/abi @gballet @MariusVanDerWijden
|
||||||
|
beacon/engine @lightclient
|
||||||
cmd/clef @holiman
|
cmd/clef @holiman
|
||||||
|
cmd/evm @holiman @MariusVanDerWijden @lightclient
|
||||||
consensus @karalabe
|
consensus @karalabe
|
||||||
core/ @karalabe @holiman @rjl493456442
|
core/ @karalabe @holiman @rjl493456442
|
||||||
eth/ @karalabe @holiman @rjl493456442
|
eth/ @karalabe @holiman @rjl493456442
|
||||||
eth/catalyst/ @gballet
|
eth/catalyst/ @gballet @lightclient
|
||||||
eth/tracers/ @s1na
|
eth/tracers/ @s1na
|
||||||
core/tracing/ @s1na
|
core/tracing/ @s1na
|
||||||
graphql/ @s1na
|
graphql/ @s1na
|
||||||
|
internal/ethapi @lightclient
|
||||||
|
internal/era @lightclient
|
||||||
les/ @zsfelfoldi @rjl493456442
|
les/ @zsfelfoldi @rjl493456442
|
||||||
light/ @zsfelfoldi @rjl493456442
|
light/ @zsfelfoldi @rjl493456442
|
||||||
node/ @fjl
|
node/ @fjl
|
||||||
|
|||||||
1
.github/workflows/go.yml
vendored
1
.github/workflows/go.yml
vendored
@@ -16,6 +16,7 @@ jobs:
|
|||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.21.4
|
go-version: 1.21.4
|
||||||
|
cache: false
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: go test -short ./...
|
run: go test -short ./...
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ linters:
|
|||||||
- durationcheck
|
- durationcheck
|
||||||
- exportloopref
|
- exportloopref
|
||||||
- whitespace
|
- whitespace
|
||||||
|
- revive # only certain checks enabled
|
||||||
|
|
||||||
### linters we tried and will not be using:
|
### linters we tried and will not be using:
|
||||||
###
|
###
|
||||||
@@ -38,6 +39,15 @@ linters:
|
|||||||
linters-settings:
|
linters-settings:
|
||||||
gofmt:
|
gofmt:
|
||||||
simplify: true
|
simplify: true
|
||||||
|
revive:
|
||||||
|
enable-all-rules: false
|
||||||
|
# here we enable specific useful rules
|
||||||
|
# see https://golangci-lint.run/usage/linters/#revive for supported rules
|
||||||
|
rules:
|
||||||
|
- name: receiver-naming
|
||||||
|
severity: warning
|
||||||
|
disabled: false
|
||||||
|
exclude: [""]
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
exclude-files:
|
exclude-files:
|
||||||
@@ -47,6 +57,9 @@ issues:
|
|||||||
linters:
|
linters:
|
||||||
- deadcode
|
- deadcode
|
||||||
- staticcheck
|
- staticcheck
|
||||||
|
- path: crypto/bn256/
|
||||||
|
linters:
|
||||||
|
- revive
|
||||||
- path: internal/build/pgp.go
|
- path: internal/build/pgp.go
|
||||||
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
|
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
|
||||||
- path: core/vm/contracts.go
|
- path: core/vm/contracts.go
|
||||||
|
|||||||
487
accounts/abi/bind/source.go.tpl
Normal file
487
accounts/abi/bind/source.go.tpl
Normal file
@@ -0,0 +1,487 @@
|
|||||||
|
// Code generated - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package {{.Package}}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = strings.NewReader
|
||||||
|
_ = ethereum.NotFound
|
||||||
|
_ = bind.Bind
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = event.NewSubscription
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
{{$structs := .Structs}}
|
||||||
|
{{range $structs}}
|
||||||
|
// {{.Name}} is an auto generated low-level Go binding around an user-defined struct.
|
||||||
|
type {{.Name}} struct {
|
||||||
|
{{range $field := .Fields}}
|
||||||
|
{{$field.Name}} {{$field.Type}}{{end}}
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{range $contract := .Contracts}}
|
||||||
|
// {{.Type}}MetaData contains all meta data concerning the {{.Type}} contract.
|
||||||
|
var {{.Type}}MetaData = &bind.MetaData{
|
||||||
|
ABI: "{{.InputABI}}",
|
||||||
|
{{if $contract.FuncSigs -}}
|
||||||
|
Sigs: map[string]string{
|
||||||
|
{{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}",
|
||||||
|
{{end}}
|
||||||
|
},
|
||||||
|
{{end -}}
|
||||||
|
{{if .InputBin -}}
|
||||||
|
Bin: "0x{{.InputBin}}",
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
// {{.Type}}ABI is the input ABI used to generate the binding from.
|
||||||
|
// Deprecated: Use {{.Type}}MetaData.ABI instead.
|
||||||
|
var {{.Type}}ABI = {{.Type}}MetaData.ABI
|
||||||
|
|
||||||
|
{{if $contract.FuncSigs}}
|
||||||
|
// Deprecated: Use {{.Type}}MetaData.Sigs instead.
|
||||||
|
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
|
||||||
|
var {{.Type}}FuncSigs = {{.Type}}MetaData.Sigs
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if .InputBin}}
|
||||||
|
// {{.Type}}Bin is the compiled bytecode used for deploying new contracts.
|
||||||
|
// Deprecated: Use {{.Type}}MetaData.Bin instead.
|
||||||
|
var {{.Type}}Bin = {{.Type}}MetaData.Bin
|
||||||
|
|
||||||
|
// Deploy{{.Type}} deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
|
||||||
|
func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type $structs}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) {
|
||||||
|
parsed, err := {{.Type}}MetaData.GetAbi()
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, nil, err
|
||||||
|
}
|
||||||
|
if parsed == nil {
|
||||||
|
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
|
||||||
|
}
|
||||||
|
{{range $pattern, $name := .Libraries}}
|
||||||
|
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend)
|
||||||
|
{{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:])
|
||||||
|
{{end}}
|
||||||
|
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, nil, err
|
||||||
|
}
|
||||||
|
return address, tx, &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract}, {{.Type}}Filterer: {{.Type}}Filterer{contract: contract} }, nil
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
// {{.Type}} is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type {{.Type}} struct {
|
||||||
|
{{.Type}}Caller // Read-only binding to the contract
|
||||||
|
{{.Type}}Transactor // Write-only binding to the contract
|
||||||
|
{{.Type}}Filterer // Log filterer for contract events
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}Caller is an auto generated read-only Go binding around an Ethereum contract.
|
||||||
|
type {{.Type}}Caller struct {
|
||||||
|
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}Transactor is an auto generated write-only Go binding around an Ethereum contract.
|
||||||
|
type {{.Type}}Transactor struct {
|
||||||
|
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}Filterer is an auto generated log filtering Go binding around an Ethereum contract events.
|
||||||
|
type {{.Type}}Filterer struct {
|
||||||
|
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}Session is an auto generated Go binding around an Ethereum contract,
|
||||||
|
// with pre-set call and transact options.
|
||||||
|
type {{.Type}}Session struct {
|
||||||
|
Contract *{{.Type}} // Generic contract binding to set the session for
|
||||||
|
CallOpts bind.CallOpts // Call options to use throughout this session
|
||||||
|
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}CallerSession is an auto generated read-only Go binding around an Ethereum contract,
|
||||||
|
// with pre-set call options.
|
||||||
|
type {{.Type}}CallerSession struct {
|
||||||
|
Contract *{{.Type}}Caller // Generic contract caller binding to set the session for
|
||||||
|
CallOpts bind.CallOpts // Call options to use throughout this session
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}TransactorSession is an auto generated write-only Go binding around an Ethereum contract,
|
||||||
|
// with pre-set transact options.
|
||||||
|
type {{.Type}}TransactorSession struct {
|
||||||
|
Contract *{{.Type}}Transactor // Generic contract transactor binding to set the session for
|
||||||
|
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}Raw is an auto generated low-level Go binding around an Ethereum contract.
|
||||||
|
type {{.Type}}Raw struct {
|
||||||
|
Contract *{{.Type}} // Generic contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
|
||||||
|
type {{.Type}}CallerRaw struct {
|
||||||
|
Contract *{{.Type}}Caller // Generic read-only contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}}TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
|
||||||
|
type {{.Type}}TransactorRaw struct {
|
||||||
|
Contract *{{.Type}}Transactor // Generic write-only contract binding to access the raw methods on
|
||||||
|
}
|
||||||
|
|
||||||
|
// New{{.Type}} creates a new instance of {{.Type}}, bound to a specific deployed contract.
|
||||||
|
func New{{.Type}}(address common.Address, backend bind.ContractBackend) (*{{.Type}}, error) {
|
||||||
|
contract, err := bind{{.Type}}(address, backend, backend, backend)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract}, {{.Type}}Filterer: {{.Type}}Filterer{contract: contract} }, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// New{{.Type}}Caller creates a new read-only instance of {{.Type}}, bound to a specific deployed contract.
|
||||||
|
func New{{.Type}}Caller(address common.Address, caller bind.ContractCaller) (*{{.Type}}Caller, error) {
|
||||||
|
contract, err := bind{{.Type}}(address, caller, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &{{.Type}}Caller{contract: contract}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// New{{.Type}}Transactor creates a new write-only instance of {{.Type}}, bound to a specific deployed contract.
|
||||||
|
func New{{.Type}}Transactor(address common.Address, transactor bind.ContractTransactor) (*{{.Type}}Transactor, error) {
|
||||||
|
contract, err := bind{{.Type}}(address, nil, transactor, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &{{.Type}}Transactor{contract: contract}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// New{{.Type}}Filterer creates a new log filterer instance of {{.Type}}, bound to a specific deployed contract.
|
||||||
|
func New{{.Type}}Filterer(address common.Address, filterer bind.ContractFilterer) (*{{.Type}}Filterer, error) {
|
||||||
|
contract, err := bind{{.Type}}(address, nil, nil, filterer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &{{.Type}}Filterer{contract: contract}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind{{.Type}} binds a generic wrapper to an already deployed contract.
|
||||||
|
func bind{{.Type}}(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
|
||||||
|
parsed, err := {{.Type}}MetaData.GetAbi()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call invokes the (constant) contract method with params as input values and
|
||||||
|
// sets the output to result. The result type might be a single field for simple
|
||||||
|
// returns, a slice of interfaces for anonymous returns and a struct for named
|
||||||
|
// returns.
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
|
||||||
|
return _{{$contract.Type}}.Contract.{{$contract.Type}}Caller.contract.Call(opts, result, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||||
|
// its default method if one is available.
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.{{$contract.Type}}Transactor.contract.Transfer(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transact invokes the (paid) contract method with params as input values.
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.{{$contract.Type}}Transactor.contract.Transact(opts, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call invokes the (constant) contract method with params as input values and
|
||||||
|
// sets the output to result. The result type might be a single field for simple
|
||||||
|
// returns, a slice of interfaces for anonymous returns and a struct for named
|
||||||
|
// returns.
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
|
||||||
|
return _{{$contract.Type}}.Contract.contract.Call(opts, result, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||||
|
// its default method if one is available.
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.contract.Transfer(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transact invokes the (paid) contract method with params as input values.
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.contract.Transact(opts, method, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
{{range .Calls}}
|
||||||
|
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) {
|
||||||
|
var out []interface{}
|
||||||
|
err := _{{$contract.Type}}.contract.Call(opts, &out, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
|
{{if .Structured}}
|
||||||
|
outstruct := new(struct{ {{range .Normalized.Outputs}} {{.Name}} {{bindtype .Type $structs}}; {{end}} })
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
{{range $i, $t := .Normalized.Outputs}}
|
||||||
|
outstruct.{{.Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
|
||||||
|
|
||||||
|
return *outstruct, err
|
||||||
|
{{else}}
|
||||||
|
if err != nil {
|
||||||
|
return {{range $i, $_ := .Normalized.Outputs}}*new({{bindtype .Type $structs}}), {{end}} err
|
||||||
|
}
|
||||||
|
{{range $i, $t := .Normalized.Outputs}}
|
||||||
|
out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
|
||||||
|
|
||||||
|
return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) {
|
||||||
|
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}CallerSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) {
|
||||||
|
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{range .Transacts}}
|
||||||
|
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Normalized.Name}}(opts *bind.TransactOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.contract.Transact(opts, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if .Fallback}}
|
||||||
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Fallback.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.contract.RawTransact(opts, calldata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Fallback.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Session) Fallback(calldata []byte) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Fallback.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if .Receive}}
|
||||||
|
// Receive is a paid mutator transaction binding the contract receive function.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Receive.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.contract.RawTransact(opts, nil) // calldata is disallowed for receive function
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive is a paid mutator transaction binding the contract receive function.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Receive.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Session) Receive() (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive is a paid mutator transaction binding the contract receive function.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Receive.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Receive() (*types.Transaction, error) {
|
||||||
|
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{range .Events}}
|
||||||
|
// {{$contract.Type}}{{.Normalized.Name}}Iterator is returned from Filter{{.Normalized.Name}} and is used to iterate over the raw logs and unpacked data for {{.Normalized.Name}} events raised by the {{$contract.Type}} contract.
|
||||||
|
type {{$contract.Type}}{{.Normalized.Name}}Iterator struct {
|
||||||
|
Event *{{$contract.Type}}{{.Normalized.Name}} // Event containing the contract specifics and raw log
|
||||||
|
|
||||||
|
contract *bind.BoundContract // Generic contract to use for unpacking event data
|
||||||
|
event string // Event name to use for unpacking event data
|
||||||
|
|
||||||
|
logs chan types.Log // Log channel receiving the found contract events
|
||||||
|
sub ethereum.Subscription // Subscription for errors, completion and termination
|
||||||
|
done bool // Whether the subscription completed delivering logs
|
||||||
|
fail error // Occurred error to stop iteration
|
||||||
|
}
|
||||||
|
// Next advances the iterator to the subsequent event, returning whether there
|
||||||
|
// are any more events found. In case of a retrieval or parsing error, false is
|
||||||
|
// returned and Error() can be queried for the exact failure.
|
||||||
|
func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Next() bool {
|
||||||
|
// If the iterator failed, stop iterating
|
||||||
|
if (it.fail != nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// If the iterator completed, deliver directly whatever's available
|
||||||
|
if (it.done) {
|
||||||
|
select {
|
||||||
|
case log := <-it.logs:
|
||||||
|
it.Event = new({{$contract.Type}}{{.Normalized.Name}})
|
||||||
|
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||||
|
it.fail = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
it.Event.Raw = log
|
||||||
|
return true
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Iterator still in progress, wait for either a data or an error event
|
||||||
|
select {
|
||||||
|
case log := <-it.logs:
|
||||||
|
it.Event = new({{$contract.Type}}{{.Normalized.Name}})
|
||||||
|
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||||
|
it.fail = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
it.Event.Raw = log
|
||||||
|
return true
|
||||||
|
|
||||||
|
case err := <-it.sub.Err():
|
||||||
|
it.done = true
|
||||||
|
it.fail = err
|
||||||
|
return it.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Error returns any retrieval or parsing error occurred during filtering.
|
||||||
|
func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Error() error {
|
||||||
|
return it.fail
|
||||||
|
}
|
||||||
|
// Close terminates the iteration process, releasing any pending underlying
|
||||||
|
// resources.
|
||||||
|
func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Close() error {
|
||||||
|
it.sub.Unsubscribe()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{$contract.Type}}{{.Normalized.Name}} represents a {{.Normalized.Name}} event raised by the {{$contract.Type}} contract.
|
||||||
|
type {{$contract.Type}}{{.Normalized.Name}} struct { {{range .Normalized.Inputs}}
|
||||||
|
{{capitalise .Name}} {{if .Indexed}}{{bindtopictype .Type $structs}}{{else}}{{bindtype .Type $structs}}{{end}}; {{end}}
|
||||||
|
Raw types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter{{.Normalized.Name}} is a free log retrieval operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Filter{{.Normalized.Name}}(opts *bind.FilterOpts{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (*{{$contract.Type}}{{.Normalized.Name}}Iterator, error) {
|
||||||
|
{{range .Normalized.Inputs}}
|
||||||
|
{{if .Indexed}}var {{.Name}}Rule []interface{}
|
||||||
|
for _, {{.Name}}Item := range {{.Name}} {
|
||||||
|
{{.Name}}Rule = append({{.Name}}Rule, {{.Name}}Item)
|
||||||
|
}{{end}}{{end}}
|
||||||
|
|
||||||
|
logs, sub, err := _{{$contract.Type}}.contract.FilterLogs(opts, "{{.Original.Name}}"{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}}Rule{{end}}{{end}})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &{{$contract.Type}}{{.Normalized.Name}}Iterator{contract: _{{$contract.Type}}.contract, event: "{{.Original.Name}}", logs: logs, sub: sub}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch{{.Normalized.Name}} is a free log subscription operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Watch{{.Normalized.Name}}(opts *bind.WatchOpts, sink chan<- *{{$contract.Type}}{{.Normalized.Name}}{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (event.Subscription, error) {
|
||||||
|
{{range .Normalized.Inputs}}
|
||||||
|
{{if .Indexed}}var {{.Name}}Rule []interface{}
|
||||||
|
for _, {{.Name}}Item := range {{.Name}} {
|
||||||
|
{{.Name}}Rule = append({{.Name}}Rule, {{.Name}}Item)
|
||||||
|
}{{end}}{{end}}
|
||||||
|
|
||||||
|
logs, sub, err := _{{$contract.Type}}.contract.WatchLogs(opts, "{{.Original.Name}}"{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}}Rule{{end}}{{end}})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return event.NewSubscription(func(quit <-chan struct{}) error {
|
||||||
|
defer sub.Unsubscribe()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case log := <-logs:
|
||||||
|
// New log arrived, parse the event and forward to the user
|
||||||
|
event := new({{$contract.Type}}{{.Normalized.Name}})
|
||||||
|
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
event.Raw = log
|
||||||
|
|
||||||
|
select {
|
||||||
|
case sink <- event:
|
||||||
|
case err := <-sub.Err():
|
||||||
|
return err
|
||||||
|
case <-quit:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case err := <-sub.Err():
|
||||||
|
return err
|
||||||
|
case <-quit:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
||||||
|
event := new({{$contract.Type}}{{.Normalized.Name}})
|
||||||
|
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
event.Raw = log
|
||||||
|
return event, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
@@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
package bind
|
package bind
|
||||||
|
|
||||||
import "github.com/ethereum/go-ethereum/accounts/abi"
|
import (
|
||||||
|
_ "embed"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
)
|
||||||
|
|
||||||
// tmplData is the data structure required to fill the binding template.
|
// tmplData is the data structure required to fill the binding template.
|
||||||
type tmplData struct {
|
type tmplData struct {
|
||||||
@@ -80,492 +84,6 @@ var tmplSource = map[Lang]string{
|
|||||||
|
|
||||||
// tmplSourceGo is the Go source template that the generated Go contract binding
|
// tmplSourceGo is the Go source template that the generated Go contract binding
|
||||||
// is based on.
|
// is based on.
|
||||||
const tmplSourceGo = `
|
//
|
||||||
// Code generated - DO NOT EDIT.
|
//go:embed source.go.tpl
|
||||||
// This file is a generated binding and any manual changes will be lost.
|
var tmplSourceGo string
|
||||||
|
|
||||||
package {{.Package}}
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
"strings"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
ethereum "github.com/ethereum/go-ethereum"
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var (
|
|
||||||
_ = errors.New
|
|
||||||
_ = big.NewInt
|
|
||||||
_ = strings.NewReader
|
|
||||||
_ = ethereum.NotFound
|
|
||||||
_ = bind.Bind
|
|
||||||
_ = common.Big1
|
|
||||||
_ = types.BloomLookup
|
|
||||||
_ = event.NewSubscription
|
|
||||||
_ = abi.ConvertType
|
|
||||||
)
|
|
||||||
|
|
||||||
{{$structs := .Structs}}
|
|
||||||
{{range $structs}}
|
|
||||||
// {{.Name}} is an auto generated low-level Go binding around an user-defined struct.
|
|
||||||
type {{.Name}} struct {
|
|
||||||
{{range $field := .Fields}}
|
|
||||||
{{$field.Name}} {{$field.Type}}{{end}}
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{range $contract := .Contracts}}
|
|
||||||
// {{.Type}}MetaData contains all meta data concerning the {{.Type}} contract.
|
|
||||||
var {{.Type}}MetaData = &bind.MetaData{
|
|
||||||
ABI: "{{.InputABI}}",
|
|
||||||
{{if $contract.FuncSigs -}}
|
|
||||||
Sigs: map[string]string{
|
|
||||||
{{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}",
|
|
||||||
{{end}}
|
|
||||||
},
|
|
||||||
{{end -}}
|
|
||||||
{{if .InputBin -}}
|
|
||||||
Bin: "0x{{.InputBin}}",
|
|
||||||
{{end}}
|
|
||||||
}
|
|
||||||
// {{.Type}}ABI is the input ABI used to generate the binding from.
|
|
||||||
// Deprecated: Use {{.Type}}MetaData.ABI instead.
|
|
||||||
var {{.Type}}ABI = {{.Type}}MetaData.ABI
|
|
||||||
|
|
||||||
{{if $contract.FuncSigs}}
|
|
||||||
// Deprecated: Use {{.Type}}MetaData.Sigs instead.
|
|
||||||
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
|
|
||||||
var {{.Type}}FuncSigs = {{.Type}}MetaData.Sigs
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{if .InputBin}}
|
|
||||||
// {{.Type}}Bin is the compiled bytecode used for deploying new contracts.
|
|
||||||
// Deprecated: Use {{.Type}}MetaData.Bin instead.
|
|
||||||
var {{.Type}}Bin = {{.Type}}MetaData.Bin
|
|
||||||
|
|
||||||
// Deploy{{.Type}} deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
|
|
||||||
func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type $structs}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) {
|
|
||||||
parsed, err := {{.Type}}MetaData.GetAbi()
|
|
||||||
if err != nil {
|
|
||||||
return common.Address{}, nil, nil, err
|
|
||||||
}
|
|
||||||
if parsed == nil {
|
|
||||||
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
|
|
||||||
}
|
|
||||||
{{range $pattern, $name := .Libraries}}
|
|
||||||
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend)
|
|
||||||
{{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:])
|
|
||||||
{{end}}
|
|
||||||
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
|
|
||||||
if err != nil {
|
|
||||||
return common.Address{}, nil, nil, err
|
|
||||||
}
|
|
||||||
return address, tx, &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract}, {{.Type}}Filterer: {{.Type}}Filterer{contract: contract} }, nil
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
// {{.Type}} is an auto generated Go binding around an Ethereum contract.
|
|
||||||
type {{.Type}} struct {
|
|
||||||
{{.Type}}Caller // Read-only binding to the contract
|
|
||||||
{{.Type}}Transactor // Write-only binding to the contract
|
|
||||||
{{.Type}}Filterer // Log filterer for contract events
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}Caller is an auto generated read-only Go binding around an Ethereum contract.
|
|
||||||
type {{.Type}}Caller struct {
|
|
||||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}Transactor is an auto generated write-only Go binding around an Ethereum contract.
|
|
||||||
type {{.Type}}Transactor struct {
|
|
||||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}Filterer is an auto generated log filtering Go binding around an Ethereum contract events.
|
|
||||||
type {{.Type}}Filterer struct {
|
|
||||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}Session is an auto generated Go binding around an Ethereum contract,
|
|
||||||
// with pre-set call and transact options.
|
|
||||||
type {{.Type}}Session struct {
|
|
||||||
Contract *{{.Type}} // Generic contract binding to set the session for
|
|
||||||
CallOpts bind.CallOpts // Call options to use throughout this session
|
|
||||||
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}CallerSession is an auto generated read-only Go binding around an Ethereum contract,
|
|
||||||
// with pre-set call options.
|
|
||||||
type {{.Type}}CallerSession struct {
|
|
||||||
Contract *{{.Type}}Caller // Generic contract caller binding to set the session for
|
|
||||||
CallOpts bind.CallOpts // Call options to use throughout this session
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}TransactorSession is an auto generated write-only Go binding around an Ethereum contract,
|
|
||||||
// with pre-set transact options.
|
|
||||||
type {{.Type}}TransactorSession struct {
|
|
||||||
Contract *{{.Type}}Transactor // Generic contract transactor binding to set the session for
|
|
||||||
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}Raw is an auto generated low-level Go binding around an Ethereum contract.
|
|
||||||
type {{.Type}}Raw struct {
|
|
||||||
Contract *{{.Type}} // Generic contract binding to access the raw methods on
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
|
|
||||||
type {{.Type}}CallerRaw struct {
|
|
||||||
Contract *{{.Type}}Caller // Generic read-only contract binding to access the raw methods on
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Type}}TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
|
|
||||||
type {{.Type}}TransactorRaw struct {
|
|
||||||
Contract *{{.Type}}Transactor // Generic write-only contract binding to access the raw methods on
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{.Type}} creates a new instance of {{.Type}}, bound to a specific deployed contract.
|
|
||||||
func New{{.Type}}(address common.Address, backend bind.ContractBackend) (*{{.Type}}, error) {
|
|
||||||
contract, err := bind{{.Type}}(address, backend, backend, backend)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract}, {{.Type}}Filterer: {{.Type}}Filterer{contract: contract} }, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{.Type}}Caller creates a new read-only instance of {{.Type}}, bound to a specific deployed contract.
|
|
||||||
func New{{.Type}}Caller(address common.Address, caller bind.ContractCaller) (*{{.Type}}Caller, error) {
|
|
||||||
contract, err := bind{{.Type}}(address, caller, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &{{.Type}}Caller{contract: contract}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{.Type}}Transactor creates a new write-only instance of {{.Type}}, bound to a specific deployed contract.
|
|
||||||
func New{{.Type}}Transactor(address common.Address, transactor bind.ContractTransactor) (*{{.Type}}Transactor, error) {
|
|
||||||
contract, err := bind{{.Type}}(address, nil, transactor, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &{{.Type}}Transactor{contract: contract}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// New{{.Type}}Filterer creates a new log filterer instance of {{.Type}}, bound to a specific deployed contract.
|
|
||||||
func New{{.Type}}Filterer(address common.Address, filterer bind.ContractFilterer) (*{{.Type}}Filterer, error) {
|
|
||||||
contract, err := bind{{.Type}}(address, nil, nil, filterer)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &{{.Type}}Filterer{contract: contract}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind{{.Type}} binds a generic wrapper to an already deployed contract.
|
|
||||||
func bind{{.Type}}(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
|
|
||||||
parsed, err := {{.Type}}MetaData.GetAbi()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call invokes the (constant) contract method with params as input values and
|
|
||||||
// sets the output to result. The result type might be a single field for simple
|
|
||||||
// returns, a slice of interfaces for anonymous returns and a struct for named
|
|
||||||
// returns.
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
|
|
||||||
return _{{$contract.Type}}.Contract.{{$contract.Type}}Caller.contract.Call(opts, result, method, params...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer initiates a plain transaction to move funds to the contract, calling
|
|
||||||
// its default method if one is available.
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.{{$contract.Type}}Transactor.contract.Transfer(opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transact invokes the (paid) contract method with params as input values.
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.{{$contract.Type}}Transactor.contract.Transact(opts, method, params...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call invokes the (constant) contract method with params as input values and
|
|
||||||
// sets the output to result. The result type might be a single field for simple
|
|
||||||
// returns, a slice of interfaces for anonymous returns and a struct for named
|
|
||||||
// returns.
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
|
|
||||||
return _{{$contract.Type}}.Contract.contract.Call(opts, result, method, params...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer initiates a plain transaction to move funds to the contract, calling
|
|
||||||
// its default method if one is available.
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.contract.Transfer(opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transact invokes the (paid) contract method with params as input values.
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.contract.Transact(opts, method, params...)
|
|
||||||
}
|
|
||||||
|
|
||||||
{{range .Calls}}
|
|
||||||
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) {
|
|
||||||
var out []interface{}
|
|
||||||
err := _{{$contract.Type}}.contract.Call(opts, &out, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
|
||||||
{{if .Structured}}
|
|
||||||
outstruct := new(struct{ {{range .Normalized.Outputs}} {{.Name}} {{bindtype .Type $structs}}; {{end}} })
|
|
||||||
if err != nil {
|
|
||||||
return *outstruct, err
|
|
||||||
}
|
|
||||||
{{range $i, $t := .Normalized.Outputs}}
|
|
||||||
outstruct.{{.Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
|
|
||||||
|
|
||||||
return *outstruct, err
|
|
||||||
{{else}}
|
|
||||||
if err != nil {
|
|
||||||
return {{range $i, $_ := .Normalized.Outputs}}*new({{bindtype .Type $structs}}), {{end}} err
|
|
||||||
}
|
|
||||||
{{range $i, $t := .Normalized.Outputs}}
|
|
||||||
out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
|
|
||||||
|
|
||||||
return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err
|
|
||||||
{{end}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) {
|
|
||||||
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}CallerSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) {
|
|
||||||
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{range .Transacts}}
|
|
||||||
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Normalized.Name}}(opts *bind.TransactOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.contract.Transact(opts, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{if .Fallback}}
|
|
||||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Fallback.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.contract.RawTransact(opts, calldata)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Fallback.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) Fallback(calldata []byte) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Fallback.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata)
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{if .Receive}}
|
|
||||||
// Receive is a paid mutator transaction binding the contract receive function.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Receive.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.contract.RawTransact(opts, nil) // calldata is disallowed for receive function
|
|
||||||
}
|
|
||||||
|
|
||||||
// Receive is a paid mutator transaction binding the contract receive function.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Receive.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Session) Receive() (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Receive is a paid mutator transaction binding the contract receive function.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Receive.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Receive() (*types.Transaction, error) {
|
|
||||||
return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts)
|
|
||||||
}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{range .Events}}
|
|
||||||
// {{$contract.Type}}{{.Normalized.Name}}Iterator is returned from Filter{{.Normalized.Name}} and is used to iterate over the raw logs and unpacked data for {{.Normalized.Name}} events raised by the {{$contract.Type}} contract.
|
|
||||||
type {{$contract.Type}}{{.Normalized.Name}}Iterator struct {
|
|
||||||
Event *{{$contract.Type}}{{.Normalized.Name}} // Event containing the contract specifics and raw log
|
|
||||||
|
|
||||||
contract *bind.BoundContract // Generic contract to use for unpacking event data
|
|
||||||
event string // Event name to use for unpacking event data
|
|
||||||
|
|
||||||
logs chan types.Log // Log channel receiving the found contract events
|
|
||||||
sub ethereum.Subscription // Subscription for errors, completion and termination
|
|
||||||
done bool // Whether the subscription completed delivering logs
|
|
||||||
fail error // Occurred error to stop iteration
|
|
||||||
}
|
|
||||||
// Next advances the iterator to the subsequent event, returning whether there
|
|
||||||
// are any more events found. In case of a retrieval or parsing error, false is
|
|
||||||
// returned and Error() can be queried for the exact failure.
|
|
||||||
func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Next() bool {
|
|
||||||
// If the iterator failed, stop iterating
|
|
||||||
if (it.fail != nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// If the iterator completed, deliver directly whatever's available
|
|
||||||
if (it.done) {
|
|
||||||
select {
|
|
||||||
case log := <-it.logs:
|
|
||||||
it.Event = new({{$contract.Type}}{{.Normalized.Name}})
|
|
||||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
|
||||||
it.fail = err
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
it.Event.Raw = log
|
|
||||||
return true
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Iterator still in progress, wait for either a data or an error event
|
|
||||||
select {
|
|
||||||
case log := <-it.logs:
|
|
||||||
it.Event = new({{$contract.Type}}{{.Normalized.Name}})
|
|
||||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
|
||||||
it.fail = err
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
it.Event.Raw = log
|
|
||||||
return true
|
|
||||||
|
|
||||||
case err := <-it.sub.Err():
|
|
||||||
it.done = true
|
|
||||||
it.fail = err
|
|
||||||
return it.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Error returns any retrieval or parsing error occurred during filtering.
|
|
||||||
func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Error() error {
|
|
||||||
return it.fail
|
|
||||||
}
|
|
||||||
// Close terminates the iteration process, releasing any pending underlying
|
|
||||||
// resources.
|
|
||||||
func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Close() error {
|
|
||||||
it.sub.Unsubscribe()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// {{$contract.Type}}{{.Normalized.Name}} represents a {{.Normalized.Name}} event raised by the {{$contract.Type}} contract.
|
|
||||||
type {{$contract.Type}}{{.Normalized.Name}} struct { {{range .Normalized.Inputs}}
|
|
||||||
{{capitalise .Name}} {{if .Indexed}}{{bindtopictype .Type $structs}}{{else}}{{bindtype .Type $structs}}{{end}}; {{end}}
|
|
||||||
Raw types.Log // Blockchain specific contextual infos
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter{{.Normalized.Name}} is a free log retrieval operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Filter{{.Normalized.Name}}(opts *bind.FilterOpts{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (*{{$contract.Type}}{{.Normalized.Name}}Iterator, error) {
|
|
||||||
{{range .Normalized.Inputs}}
|
|
||||||
{{if .Indexed}}var {{.Name}}Rule []interface{}
|
|
||||||
for _, {{.Name}}Item := range {{.Name}} {
|
|
||||||
{{.Name}}Rule = append({{.Name}}Rule, {{.Name}}Item)
|
|
||||||
}{{end}}{{end}}
|
|
||||||
|
|
||||||
logs, sub, err := _{{$contract.Type}}.contract.FilterLogs(opts, "{{.Original.Name}}"{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}}Rule{{end}}{{end}})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &{{$contract.Type}}{{.Normalized.Name}}Iterator{contract: _{{$contract.Type}}.contract, event: "{{.Original.Name}}", logs: logs, sub: sub}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch{{.Normalized.Name}} is a free log subscription operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Watch{{.Normalized.Name}}(opts *bind.WatchOpts, sink chan<- *{{$contract.Type}}{{.Normalized.Name}}{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (event.Subscription, error) {
|
|
||||||
{{range .Normalized.Inputs}}
|
|
||||||
{{if .Indexed}}var {{.Name}}Rule []interface{}
|
|
||||||
for _, {{.Name}}Item := range {{.Name}} {
|
|
||||||
{{.Name}}Rule = append({{.Name}}Rule, {{.Name}}Item)
|
|
||||||
}{{end}}{{end}}
|
|
||||||
|
|
||||||
logs, sub, err := _{{$contract.Type}}.contract.WatchLogs(opts, "{{.Original.Name}}"{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}}Rule{{end}}{{end}})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return event.NewSubscription(func(quit <-chan struct{}) error {
|
|
||||||
defer sub.Unsubscribe()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case log := <-logs:
|
|
||||||
// New log arrived, parse the event and forward to the user
|
|
||||||
event := new({{$contract.Type}}{{.Normalized.Name}})
|
|
||||||
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
event.Raw = log
|
|
||||||
|
|
||||||
select {
|
|
||||||
case sink <- event:
|
|
||||||
case err := <-sub.Err():
|
|
||||||
return err
|
|
||||||
case <-quit:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case err := <-sub.Err():
|
|
||||||
return err
|
|
||||||
case <-quit:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
|
||||||
//
|
|
||||||
// Solidity: {{.Original.String}}
|
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
|
||||||
event := new({{$contract.Type}}{{.Normalized.Name}})
|
|
||||||
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
event.Raw = log
|
|
||||||
return event, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
`
|
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ type Type struct {
|
|||||||
var (
|
var (
|
||||||
// typeRegex parses the abi sub types
|
// typeRegex parses the abi sub types
|
||||||
typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
|
typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
|
||||||
|
|
||||||
|
// sliceSizeRegex grab the slice size
|
||||||
|
sliceSizeRegex = regexp.MustCompile("[0-9]+")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewType creates a new reflection type of abi type given in t.
|
// NewType creates a new reflection type of abi type given in t.
|
||||||
@@ -91,8 +94,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
|
|||||||
// grab the last cell and create a type from there
|
// grab the last cell and create a type from there
|
||||||
sliced := t[i:]
|
sliced := t[i:]
|
||||||
// grab the slice size with regexp
|
// grab the slice size with regexp
|
||||||
re := regexp.MustCompile("[0-9]+")
|
intz := sliceSizeRegex.FindAllString(sliced, -1)
|
||||||
intz := re.FindAllString(sliced, -1)
|
|
||||||
|
|
||||||
if len(intz) == 0 {
|
if len(intz) == 0 {
|
||||||
// is a slice
|
// is a slice
|
||||||
|
|||||||
@@ -325,11 +325,7 @@ func TestUpdatedKeyfileContents(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create a temporary keystore to test with
|
// Create a temporary keystore to test with
|
||||||
dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-updatedkeyfilecontents-test-%d-%d", os.Getpid(), rand.Int()))
|
dir := t.TempDir()
|
||||||
|
|
||||||
// Create the directory
|
|
||||||
os.MkdirAll(dir, 0700)
|
|
||||||
defer os.RemoveAll(dir)
|
|
||||||
|
|
||||||
ks := NewKeyStore(dir, LightScryptN, LightScryptP)
|
ks := NewKeyStore(dir, LightScryptN, LightScryptP)
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,14 @@ var (
|
|||||||
DerivationSignatureHash = sha256.Sum256(common.Hash{}.Bytes())
|
DerivationSignatureHash = sha256.Sum256(common.Hash{}.Bytes())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// PinRegexp is the regular expression used to validate PIN codes.
|
||||||
|
pinRegexp = regexp.MustCompile(`^[0-9]{6,}$`)
|
||||||
|
|
||||||
|
// PukRegexp is the regular expression used to validate PUK codes.
|
||||||
|
pukRegexp = regexp.MustCompile(`^[0-9]{12,}$`)
|
||||||
|
)
|
||||||
|
|
||||||
// List of APDU command-related constants
|
// List of APDU command-related constants
|
||||||
const (
|
const (
|
||||||
claISO7816 = 0
|
claISO7816 = 0
|
||||||
@@ -380,7 +388,7 @@ func (w *Wallet) Open(passphrase string) error {
|
|||||||
case passphrase == "":
|
case passphrase == "":
|
||||||
return ErrPINUnblockNeeded
|
return ErrPINUnblockNeeded
|
||||||
case status.PinRetryCount > 0:
|
case status.PinRetryCount > 0:
|
||||||
if !regexp.MustCompile(`^[0-9]{6,}$`).MatchString(passphrase) {
|
if !pinRegexp.MatchString(passphrase) {
|
||||||
w.log.Error("PIN needs to be at least 6 digits")
|
w.log.Error("PIN needs to be at least 6 digits")
|
||||||
return ErrPINNeeded
|
return ErrPINNeeded
|
||||||
}
|
}
|
||||||
@@ -388,7 +396,7 @@ func (w *Wallet) Open(passphrase string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if !regexp.MustCompile(`^[0-9]{12,}$`).MatchString(passphrase) {
|
if !pukRegexp.MatchString(passphrase) {
|
||||||
w.log.Error("PUK needs to be at least 12 digits")
|
w.log.Error("PUK needs to be at least 12 digits")
|
||||||
return ErrPINUnblockNeeded
|
return ErrPINUnblockNeeded
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,8 @@
|
|||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
package hw.trezor.messages.common;
|
package hw.trezor.messages.common;
|
||||||
|
|
||||||
|
option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response: Success of the previous request
|
* Response: Success of the previous request
|
||||||
* @end
|
* @end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,8 @@
|
|||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
package hw.trezor.messages.ethereum;
|
package hw.trezor.messages.ethereum;
|
||||||
|
|
||||||
|
option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
|
||||||
|
|
||||||
// Sugar for easier handling in Java
|
// Sugar for easier handling in Java
|
||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageEthereum";
|
option java_outer_classname = "TrezorMessageEthereum";
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,8 @@
|
|||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
package hw.trezor.messages.management;
|
package hw.trezor.messages.management;
|
||||||
|
|
||||||
|
option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
|
||||||
|
|
||||||
// Sugar for easier handling in Java
|
// Sugar for easier handling in Java
|
||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageManagement";
|
option java_outer_classname = "TrezorMessageManagement";
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,10 +9,13 @@ package hw.trezor.messages;
|
|||||||
* Messages for TREZOR communication
|
* Messages for TREZOR communication
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
|
||||||
|
|
||||||
// Sugar for easier handling in Java
|
// Sugar for easier handling in Java
|
||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessage";
|
option java_outer_classname = "TrezorMessage";
|
||||||
|
|
||||||
|
|
||||||
import "google/protobuf/descriptor.proto";
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
// - Grab the latest Go plugin `go get -u github.com/golang/protobuf/protoc-gen-go`
|
// - Grab the latest Go plugin `go get -u github.com/golang/protobuf/protoc-gen-go`
|
||||||
// - Vendor in the latest Go plugin `govendor fetch github.com/golang/protobuf/...`
|
// - Vendor in the latest Go plugin `govendor fetch github.com/golang/protobuf/...`
|
||||||
|
|
||||||
//go:generate protoc -I/usr/local/include:. --go_out=import_path=trezor:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
|
//go:generate protoc -I/usr/local/include:. --go_out=paths=source_relative:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
|
||||||
|
|
||||||
// Package trezor contains the wire protocol.
|
// Package trezor contains the wire protocol.
|
||||||
package trezor
|
package trezor
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ for:
|
|||||||
- image: Ubuntu
|
- image: Ubuntu
|
||||||
build_script:
|
build_script:
|
||||||
- go run build/ci.go lint
|
- go run build/ci.go lint
|
||||||
|
- go run build/ci.go generate -verify
|
||||||
- go run build/ci.go install -dlgo
|
- go run build/ci.go install -dlgo
|
||||||
test_script:
|
test_script:
|
||||||
- go run build/ci.go test -dlgo -short
|
- go run build/ci.go test -dlgo -short
|
||||||
|
|||||||
@@ -494,9 +494,6 @@ func (api *BeaconLightApi) StartHeadListener(listener HeadEventListener) func()
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
stream.Close()
|
|
||||||
|
|
||||||
case event, ok := <-stream.Events:
|
case event, ok := <-stream.Events:
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Trace("Event stream closed")
|
log.Trace("Event stream closed")
|
||||||
|
|||||||
@@ -186,10 +186,14 @@ func (s *serverWithTimeout) eventCallback(event Event) {
|
|||||||
// call will just do nothing
|
// call will just do nothing
|
||||||
timer.Stop()
|
timer.Stop()
|
||||||
delete(s.timeouts, id)
|
delete(s.timeouts, id)
|
||||||
s.childEventCb(event)
|
if s.childEventCb != nil {
|
||||||
|
s.childEventCb(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
s.childEventCb(event)
|
if s.childEventCb != nil {
|
||||||
|
s.childEventCb(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,25 +215,27 @@ func (s *serverWithTimeout) startTimeout(reqData RequestResponse) {
|
|||||||
delete(s.timeouts, id)
|
delete(s.timeouts, id)
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
childEventCb(Event{Type: EvFail, Data: reqData})
|
if childEventCb != nil {
|
||||||
|
childEventCb(Event{Type: EvFail, Data: reqData})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
childEventCb(Event{Type: EvTimeout, Data: reqData})
|
if childEventCb != nil {
|
||||||
|
childEventCb(Event{Type: EvTimeout, Data: reqData})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsubscribe stops all goroutines associated with the server.
|
// unsubscribe stops all goroutines associated with the server.
|
||||||
func (s *serverWithTimeout) unsubscribe() {
|
func (s *serverWithTimeout) unsubscribe() {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
for _, timer := range s.timeouts {
|
for _, timer := range s.timeouts {
|
||||||
if timer != nil {
|
if timer != nil {
|
||||||
timer.Stop()
|
timer.Stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.childEventCb = nil
|
s.lock.Unlock()
|
||||||
s.parent.Unsubscribe()
|
s.parent.Unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,10 +334,10 @@ func (s *serverWithLimits) eventCallback(event Event) {
|
|||||||
}
|
}
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
if passEvent {
|
if passEvent && childEventCb != nil {
|
||||||
childEventCb(event)
|
childEventCb(event)
|
||||||
}
|
}
|
||||||
if sendCanRequestAgain {
|
if sendCanRequestAgain && childEventCb != nil {
|
||||||
childEventCb(Event{Type: EvCanRequestAgain})
|
childEventCb(Event{Type: EvCanRequestAgain})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,13 +353,12 @@ func (s *serverWithLimits) sendRequest(request Request) (reqId ID) {
|
|||||||
// unsubscribe stops all goroutines associated with the server.
|
// unsubscribe stops all goroutines associated with the server.
|
||||||
func (s *serverWithLimits) unsubscribe() {
|
func (s *serverWithLimits) unsubscribe() {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
if s.delayTimer != nil {
|
if s.delayTimer != nil {
|
||||||
s.delayTimer.Stop()
|
s.delayTimer.Stop()
|
||||||
s.delayTimer = nil
|
s.delayTimer = nil
|
||||||
}
|
}
|
||||||
s.childEventCb = nil
|
s.childEventCb = nil
|
||||||
|
s.lock.Unlock()
|
||||||
s.serverWithTimeout.unsubscribe()
|
s.serverWithTimeout.unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +388,7 @@ func (s *serverWithLimits) canRequestNow() bool {
|
|||||||
}
|
}
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
if sendCanRequestAgain {
|
if sendCanRequestAgain && childEventCb != nil {
|
||||||
childEventCb(Event{Type: EvCanRequestAgain})
|
childEventCb(Event{Type: EvCanRequestAgain})
|
||||||
}
|
}
|
||||||
return canRequest
|
return canRequest
|
||||||
@@ -415,7 +420,7 @@ func (s *serverWithLimits) delay(delay time.Duration) {
|
|||||||
}
|
}
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
if sendCanRequestAgain {
|
if sendCanRequestAgain && childEventCb != nil {
|
||||||
childEventCb(Event{Type: EvCanRequestAgain})
|
childEventCb(Event{Type: EvCanRequestAgain})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ func TestServerEvents(t *testing.T) {
|
|||||||
expEvent(EvFail)
|
expEvent(EvFail)
|
||||||
rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 1, Request: testRequest, Response: testResponse}})
|
rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 1, Request: testRequest, Response: testResponse}})
|
||||||
expEvent(nil)
|
expEvent(nil)
|
||||||
|
srv.unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServerParallel(t *testing.T) {
|
func TestServerParallel(t *testing.T) {
|
||||||
@@ -129,9 +130,7 @@ func TestServerEventRateLimit(t *testing.T) {
|
|||||||
srv := NewServer(rs, clock)
|
srv := NewServer(rs, clock)
|
||||||
var eventCount int
|
var eventCount int
|
||||||
srv.subscribe(func(event Event) {
|
srv.subscribe(func(event Event) {
|
||||||
if !event.IsRequestEvent() {
|
eventCount++
|
||||||
eventCount++
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
expEvents := func(send, expAllowed int) {
|
expEvents := func(send, expAllowed int) {
|
||||||
eventCount = 0
|
eventCount = 0
|
||||||
@@ -147,6 +146,30 @@ func TestServerEventRateLimit(t *testing.T) {
|
|||||||
expEvents(5, 1)
|
expEvents(5, 1)
|
||||||
clock.Run(maxServerEventRate * maxServerEventBuffer * 2)
|
clock.Run(maxServerEventRate * maxServerEventBuffer * 2)
|
||||||
expEvents(maxServerEventBuffer+5, maxServerEventBuffer)
|
expEvents(maxServerEventBuffer+5, maxServerEventBuffer)
|
||||||
|
srv.unsubscribe()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServerUnsubscribe(t *testing.T) {
|
||||||
|
rs := &testRequestServer{}
|
||||||
|
clock := &mclock.Simulated{}
|
||||||
|
srv := NewServer(rs, clock)
|
||||||
|
var eventCount int
|
||||||
|
srv.subscribe(func(event Event) {
|
||||||
|
eventCount++
|
||||||
|
})
|
||||||
|
eventCb := rs.eventCb
|
||||||
|
eventCb(Event{Type: testEventType})
|
||||||
|
if eventCount != 1 {
|
||||||
|
t.Errorf("Server event callback not called before unsubscribe")
|
||||||
|
}
|
||||||
|
srv.unsubscribe()
|
||||||
|
if rs.eventCb != nil {
|
||||||
|
t.Errorf("Server event callback not removed after unsubscribe")
|
||||||
|
}
|
||||||
|
eventCb(Event{Type: testEventType})
|
||||||
|
if eventCount != 1 {
|
||||||
|
t.Errorf("Server event callback called after unsubscribe")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type testRequestServer struct {
|
type testRequestServer struct {
|
||||||
@@ -156,4 +179,4 @@ type testRequestServer struct {
|
|||||||
func (rs *testRequestServer) Name() string { return "" }
|
func (rs *testRequestServer) Name() string { return "" }
|
||||||
func (rs *testRequestServer) Subscribe(eventCb func(Event)) { rs.eventCb = eventCb }
|
func (rs *testRequestServer) Subscribe(eventCb func(Event)) { rs.eventCb = eventCb }
|
||||||
func (rs *testRequestServer) SendRequest(ID, Request) {}
|
func (rs *testRequestServer) SendRequest(ID, Request) {}
|
||||||
func (rs *testRequestServer) Unsubscribe() {}
|
func (rs *testRequestServer) Unsubscribe() { rs.eventCb = nil }
|
||||||
|
|||||||
@@ -173,24 +173,24 @@ type TestCommitteeChain struct {
|
|||||||
init bool
|
init bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestCommitteeChain) CheckpointInit(bootstrap types.BootstrapData) error {
|
func (tc *TestCommitteeChain) CheckpointInit(bootstrap types.BootstrapData) error {
|
||||||
t.fsp, t.nsp, t.init = bootstrap.Header.SyncPeriod(), bootstrap.Header.SyncPeriod()+2, true
|
tc.fsp, tc.nsp, tc.init = bootstrap.Header.SyncPeriod(), bootstrap.Header.SyncPeriod()+2, true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestCommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommittee *types.SerializedSyncCommittee) error {
|
func (tc *TestCommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommittee *types.SerializedSyncCommittee) error {
|
||||||
period := update.AttestedHeader.Header.SyncPeriod()
|
period := update.AttestedHeader.Header.SyncPeriod()
|
||||||
if period < t.fsp || period > t.nsp || !t.init {
|
if period < tc.fsp || period > tc.nsp || !tc.init {
|
||||||
return light.ErrInvalidPeriod
|
return light.ErrInvalidPeriod
|
||||||
}
|
}
|
||||||
if period == t.nsp {
|
if period == tc.nsp {
|
||||||
t.nsp++
|
tc.nsp++
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestCommitteeChain) NextSyncPeriod() (uint64, bool) {
|
func (tc *TestCommitteeChain) NextSyncPeriod() (uint64, bool) {
|
||||||
return t.nsp, t.init
|
return tc.nsp, tc.init
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TestCommitteeChain) ExpInit(t *testing.T, ExpInit bool) {
|
func (tc *TestCommitteeChain) ExpInit(t *testing.T, ExpInit bool) {
|
||||||
@@ -199,8 +199,8 @@ func (tc *TestCommitteeChain) ExpInit(t *testing.T, ExpInit bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestCommitteeChain) SetNextSyncPeriod(nsp uint64) {
|
func (tc *TestCommitteeChain) SetNextSyncPeriod(nsp uint64) {
|
||||||
t.init, t.nsp = true, nsp
|
tc.init, tc.nsp = true, nsp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TestCommitteeChain) ExpNextSyncPeriod(t *testing.T, expNsp uint64) {
|
func (tc *TestCommitteeChain) ExpNextSyncPeriod(t *testing.T, expNsp uint64) {
|
||||||
|
|||||||
@@ -99,3 +99,28 @@ d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.t
|
|||||||
# version:ppa-builder-2 1.21.9
|
# version:ppa-builder-2 1.21.9
|
||||||
# https://go.dev/dl/
|
# https://go.dev/dl/
|
||||||
58f0c5ced45a0012bce2ff7a9df03e128abcc8818ebabe5027bb92bafe20e421 go1.21.9.src.tar.gz
|
58f0c5ced45a0012bce2ff7a9df03e128abcc8818ebabe5027bb92bafe20e421 go1.21.9.src.tar.gz
|
||||||
|
|
||||||
|
# version:protoc 27.1
|
||||||
|
# https://github.com/protocolbuffers/protobuf/releases/
|
||||||
|
# https://github.com/protocolbuffers/protobuf/releases/download/v27.1/
|
||||||
|
8809c2ec85368c6b6e9af161b6771a153aa92670a24adbe46dd34fa02a04df2f protoc-27.1-linux-aarch_64.zip
|
||||||
|
5d21979a6d27475e810b76b88863d1e784fa01ffb15e511a3ec5bd1924d89426 protoc-27.1-linux-ppcle_64.zip
|
||||||
|
84d8852750ed186dc4a057a1a86bcac409be5362d6af04770f42367fee6b7bc1 protoc-27.1-linux-s390_64.zip
|
||||||
|
2f028796ff5741691650e0eea290e61ff2f1c0d87f8d31fe45ef47fd967cef0c protoc-27.1-linux-x86_32.zip
|
||||||
|
8970e3d8bbd67d53768fe8c2e3971bdd71e51cfe2001ca06dacad17258a7dae3 protoc-27.1-linux-x86_64.zip
|
||||||
|
03b7af1bf469e7285dc51976ee5fa99412704dbd1c017105114852a37b165c12 protoc-27.1-osx-aarch_64.zip
|
||||||
|
f14d3973cf13283d07c520ed6f4c12405ad41b9efd18089a1c74897037d742b5 protoc-27.1-osx-universal_binary.zip
|
||||||
|
8520d944f3a3890fa296a3b3b0d4bb18337337e2526bbbf1b507eeea3c2a1ec4 protoc-27.1-osx-x86_64.zip
|
||||||
|
6263718ff96547b8392a079f6fdf02a4156f2e8d13cd51649a0d03fb7afa2de8 protoc-27.1-win32.zip
|
||||||
|
da531c51ccd1290d8d34821f0ce4e219c7fbaa6f9825f5a3fb092a9d03fe6206 protoc-27.1-win64.zip
|
||||||
|
|
||||||
|
# version:protoc-gen-go 1.34.2
|
||||||
|
# https://github.com/protocolbuffers/protobuf-go/releases/
|
||||||
|
# https://github.com/protocolbuffers/protobuf-go/releases/download/v1.34.2/
|
||||||
|
9b48d8f90add02e8e94e14962fed74e7ce2b2d6bda4dd42f1f4fbccf0f766f1a protoc-gen-go.v1.34.2.darwin.amd64.tar.gz
|
||||||
|
17aca7f948dbb624049030cf841e35895cf34183ba006e721247fdeb95ff2780 protoc-gen-go.v1.34.2.darwin.arm64.tar.gz
|
||||||
|
a191849433fd489f1d44f37788d762658f3f5fb225f3a85d4ce6ba32666703ed protoc-gen-go.v1.34.2.linux.386.tar.gz
|
||||||
|
b87bc134dee55576a842141bf0ed27761c635d746780fce5dee038c6dd16554f protoc-gen-go.v1.34.2.linux.amd64.tar.gz
|
||||||
|
63d400167e75ab9f6690688f6fdc6a9455aa20bc1faa71e32149dbd322f7f198 protoc-gen-go.v1.34.2.linux.arm64.tar.gz
|
||||||
|
56e7675816db6e62be4f833a51544d5716b8420c462515579e05ca8444ab06ed protoc-gen-go.v1.34.2.windows.386.zip
|
||||||
|
abafd39612177dd4e9a65207cadd5374a9352d8611e8e040f8462fcfa3010daf protoc-gen-go.v1.34.2.windows.amd64.zip
|
||||||
|
|||||||
174
build/ci.go
174
build/ci.go
@@ -39,9 +39,11 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -169,6 +171,8 @@ func main() {
|
|||||||
doPurge(os.Args[2:])
|
doPurge(os.Args[2:])
|
||||||
case "sanitycheck":
|
case "sanitycheck":
|
||||||
doSanityCheck()
|
doSanityCheck()
|
||||||
|
case "generate":
|
||||||
|
doGenerate()
|
||||||
default:
|
default:
|
||||||
log.Fatal("unknown command ", os.Args[1])
|
log.Fatal("unknown command ", os.Args[1])
|
||||||
}
|
}
|
||||||
@@ -345,6 +349,86 @@ func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string {
|
|||||||
return filepath.Join(cachedir, base)
|
return filepath.Join(cachedir, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hashSourceFiles iterates all files under the top-level project directory
|
||||||
|
// computing the hash of each file (excluding files within the tests
|
||||||
|
// subrepo)
|
||||||
|
func hashSourceFiles() (map[string]common.Hash, error) {
|
||||||
|
res := make(map[string]common.Hash)
|
||||||
|
err := filepath.WalkDir(".", func(path string, d os.DirEntry, err error) error {
|
||||||
|
if strings.HasPrefix(path, filepath.FromSlash("tests/testdata")) {
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
if !d.Type().IsRegular() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// open the file and hash it
|
||||||
|
f, err := os.OpenFile(path, os.O_RDONLY, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hasher := sha256.New()
|
||||||
|
if _, err := io.Copy(hasher, f); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
res[path] = common.Hash(hasher.Sum(nil))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// doGenerate ensures that re-generating generated files does not cause
|
||||||
|
// any mutations in the source file tree: i.e. all generated files were
|
||||||
|
// updated and committed. Any stale generated files are updated.
|
||||||
|
func doGenerate() {
|
||||||
|
var (
|
||||||
|
tc = new(build.GoToolchain)
|
||||||
|
cachedir = flag.String("cachedir", "./build/cache", "directory for caching binaries.")
|
||||||
|
verify = flag.Bool("verify", false, "check whether any files are changed by go generate")
|
||||||
|
)
|
||||||
|
|
||||||
|
protocPath := downloadProtoc(*cachedir)
|
||||||
|
protocGenGoPath := downloadProtocGenGo(*cachedir)
|
||||||
|
|
||||||
|
var preHashes map[string]common.Hash
|
||||||
|
if *verify {
|
||||||
|
var err error
|
||||||
|
preHashes, err = hashSourceFiles()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("failed to compute map of source hashes", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c := tc.Go("generate", "./...")
|
||||||
|
pathList := []string{filepath.Join(protocPath, "bin"), protocGenGoPath, os.Getenv("PATH")}
|
||||||
|
c.Env = append(c.Env, "PATH="+strings.Join(pathList, string(os.PathListSeparator)))
|
||||||
|
build.MustRun(c)
|
||||||
|
|
||||||
|
if !*verify {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Check if files were changed.
|
||||||
|
postHashes, err := hashSourceFiles()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("error computing source tree file hashes", "err", err)
|
||||||
|
}
|
||||||
|
updates := []string{}
|
||||||
|
for path, postHash := range postHashes {
|
||||||
|
preHash, ok := preHashes[path]
|
||||||
|
if !ok || preHash != postHash {
|
||||||
|
updates = append(updates, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, updatedFile := range updates {
|
||||||
|
fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile)
|
||||||
|
}
|
||||||
|
if len(updates) != 0 {
|
||||||
|
log.Fatal("One or more generated files were updated by running 'go generate ./...'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// doLint runs golangci-lint on requested packages.
|
// doLint runs golangci-lint on requested packages.
|
||||||
func doLint(cmdline []string) {
|
func doLint(cmdline []string) {
|
||||||
var (
|
var (
|
||||||
@@ -390,6 +474,96 @@ func downloadLinter(cachedir string) string {
|
|||||||
return filepath.Join(cachedir, base, "golangci-lint")
|
return filepath.Join(cachedir, base, "golangci-lint")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// protocArchiveBaseName returns the name of the protoc archive file for
|
||||||
|
// the current system, stripped of version and file suffix.
|
||||||
|
func protocArchiveBaseName() (string, error) {
|
||||||
|
switch runtime.GOOS + "-" + runtime.GOARCH {
|
||||||
|
case "windows-amd64":
|
||||||
|
return "win64", nil
|
||||||
|
case "windows-386":
|
||||||
|
return "win32", nil
|
||||||
|
case "linux-arm64":
|
||||||
|
return "linux-aarch_64", nil
|
||||||
|
case "linux-386":
|
||||||
|
return "linux-x86_32", nil
|
||||||
|
case "linux-amd64":
|
||||||
|
return "linux-x86_64", nil
|
||||||
|
case "darwin-arm64":
|
||||||
|
return "osx-aarch_64", nil
|
||||||
|
case "darwin-amd64":
|
||||||
|
return "osx-x86_64", nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("no prebuilt release of protoc available for this system (os: %s, arch: %s)", runtime.GOOS, runtime.GOARCH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// downloadProtocGenGo downloads protoc-gen-go, which is used by protoc
|
||||||
|
// in the generate command. It returns the full path of the directory
|
||||||
|
// containing the 'protoc-gen-go' executable.
|
||||||
|
func downloadProtocGenGo(cachedir string) string {
|
||||||
|
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||||
|
version, err := build.Version(csdb, "protoc-gen-go")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
baseName := fmt.Sprintf("protoc-gen-go.v%s.%s.%s", version, runtime.GOOS, runtime.GOARCH)
|
||||||
|
archiveName := baseName
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
archiveName += ".zip"
|
||||||
|
} else {
|
||||||
|
archiveName += ".tar.gz"
|
||||||
|
}
|
||||||
|
|
||||||
|
url := fmt.Sprintf("https://github.com/protocolbuffers/protobuf-go/releases/download/v%s/%s", version, archiveName)
|
||||||
|
|
||||||
|
archivePath := path.Join(cachedir, archiveName)
|
||||||
|
if err := csdb.DownloadFile(url, archivePath); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
extractDest := filepath.Join(cachedir, baseName)
|
||||||
|
if err := build.ExtractArchive(archivePath, extractDest); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
extractDest, err = filepath.Abs(extractDest)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("error resolving absolute path for protoc", "err", err)
|
||||||
|
}
|
||||||
|
return extractDest
|
||||||
|
}
|
||||||
|
|
||||||
|
// downloadProtoc downloads the prebuilt protoc binary used to lint generated
|
||||||
|
// files as a CI step. It returns the full path to the directory containing
|
||||||
|
// the protoc executable.
|
||||||
|
func downloadProtoc(cachedir string) string {
|
||||||
|
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||||
|
version, err := build.Version(csdb, "protoc")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
baseName, err := protocArchiveBaseName()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := fmt.Sprintf("protoc-%s-%s", version, baseName)
|
||||||
|
archiveFileName := fileName + ".zip"
|
||||||
|
url := fmt.Sprintf("https://github.com/protocolbuffers/protobuf/releases/download/v%s/%s", version, archiveFileName)
|
||||||
|
archivePath := filepath.Join(cachedir, archiveFileName)
|
||||||
|
|
||||||
|
if err := csdb.DownloadFile(url, archivePath); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
extractDest := filepath.Join(cachedir, fileName)
|
||||||
|
if err := build.ExtractArchive(archivePath, extractDest); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
extractDest, err = filepath.Abs(extractDest)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("error resolving absolute path for protoc", "err", err)
|
||||||
|
}
|
||||||
|
return extractDest
|
||||||
|
}
|
||||||
|
|
||||||
// Release Packaging
|
// Release Packaging
|
||||||
func doArchive(cmdline []string) {
|
func doArchive(cmdline []string) {
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -19,39 +19,21 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/beacon/blsync"
|
"github.com/ethereum/go-ethereum/beacon/blsync"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
|
"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/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/mattn/go-colorable"
|
|
||||||
"github.com/mattn/go-isatty"
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
verbosityFlag = &cli.IntFlag{
|
|
||||||
Name: "verbosity",
|
|
||||||
Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail",
|
|
||||||
Value: 3,
|
|
||||||
Category: flags.LoggingCategory,
|
|
||||||
}
|
|
||||||
vmoduleFlag = &cli.StringFlag{
|
|
||||||
Name: "vmodule",
|
|
||||||
Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)",
|
|
||||||
Value: "",
|
|
||||||
Hidden: true,
|
|
||||||
Category: flags.LoggingCategory,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := flags.NewApp("beacon light syncer tool")
|
app := flags.NewApp("beacon light syncer tool")
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = flags.Merge([]cli.Flag{
|
||||||
utils.BeaconApiFlag,
|
utils.BeaconApiFlag,
|
||||||
utils.BeaconApiHeaderFlag,
|
utils.BeaconApiHeaderFlag,
|
||||||
utils.BeaconThresholdFlag,
|
utils.BeaconThresholdFlag,
|
||||||
@@ -66,8 +48,16 @@ func main() {
|
|||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.BlsyncApiFlag,
|
utils.BlsyncApiFlag,
|
||||||
utils.BlsyncJWTSecretFlag,
|
utils.BlsyncJWTSecretFlag,
|
||||||
verbosityFlag,
|
},
|
||||||
vmoduleFlag,
|
debug.Flags,
|
||||||
|
)
|
||||||
|
app.Before = func(ctx *cli.Context) error {
|
||||||
|
flags.MigrateGlobalFlags(ctx)
|
||||||
|
return debug.Setup(ctx)
|
||||||
|
}
|
||||||
|
app.After = func(ctx *cli.Context) error {
|
||||||
|
debug.Exit()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
app.Action = sync
|
app.Action = sync
|
||||||
|
|
||||||
@@ -78,14 +68,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func sync(ctx *cli.Context) error {
|
func sync(ctx *cli.Context) error {
|
||||||
usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
|
|
||||||
output := io.Writer(os.Stderr)
|
|
||||||
if usecolor {
|
|
||||||
output = colorable.NewColorable(os.Stderr)
|
|
||||||
}
|
|
||||||
verbosity := log.FromLegacyLevel(ctx.Int(verbosityFlag.Name))
|
|
||||||
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(output, verbosity, usecolor)))
|
|
||||||
|
|
||||||
// set up blsync
|
// set up blsync
|
||||||
client := blsync.NewClient(ctx)
|
client := blsync.NewClient(ctx)
|
||||||
client.SetEngineRPC(makeRPCClient(ctx))
|
client.SetEngineRPC(makeRPCClient(ctx))
|
||||||
|
|||||||
@@ -225,8 +225,8 @@ Response
|
|||||||
- `value` [number:optional]: amount of Wei to send with the transaction
|
- `value` [number:optional]: amount of Wei to send with the transaction
|
||||||
- `data` [data:optional]: input data
|
- `data` [data:optional]: input data
|
||||||
- `nonce` [number]: account nonce
|
- `nonce` [number]: account nonce
|
||||||
1. method signature [string:optional]
|
2. method signature [string:optional]
|
||||||
- The method signature, if present, is to aid decoding the calldata. Should consist of `methodname(paramtype,...)`, e.g. `transfer(uint256,address)`. The signer may use this data to parse the supplied calldata, and show the user. The data, however, is considered totally untrusted, and reliability is not expected.
|
- The method signature, if present, is to aid decoding the calldata. Should consist of `methodname(paramtype,...)`, e.g. `transfer(uint256,address)`. The signer may use this data to parse the supplied calldata, and show the user. The data, however, is considered totally untrusted, and reliability is not expected.
|
||||||
|
|
||||||
|
|
||||||
#### Result
|
#### Result
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ func rlpxPing(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("received disconnect message: %v", msg[0])
|
return fmt.Errorf("received disconnect message: %v", msg[0])
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid message code %d, expected handshake (code zero)", code)
|
return fmt.Errorf("invalid message code %d, expected handshake (code zero) or disconnect (code one)", code)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,15 +14,15 @@ The `evm t8n` tool is a stateless state transition utility. It is a utility
|
|||||||
which can
|
which can
|
||||||
|
|
||||||
1. Take a prestate, including
|
1. Take a prestate, including
|
||||||
- Accounts,
|
- Accounts,
|
||||||
- Block context information,
|
- Block context information,
|
||||||
- Previous blockshashes (*optional)
|
- Previous blockshashes (*optional)
|
||||||
2. Apply a set of transactions,
|
2. Apply a set of transactions,
|
||||||
3. Apply a mining-reward (*optional),
|
3. Apply a mining-reward (*optional),
|
||||||
4. And generate a post-state, including
|
4. And generate a post-state, including
|
||||||
- State root, transaction root, receipt root,
|
- State root, transaction root, receipt root,
|
||||||
- Information about rejected transactions,
|
- Information about rejected transactions,
|
||||||
- Optionally: a full or partial post-state dump
|
- Optionally: a full or partial post-state dump
|
||||||
|
|
||||||
### Specification
|
### Specification
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func blockTestCmd(ctx *cli.Context) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
test := tests[name]
|
test := tests[name]
|
||||||
if err := test.Run(false, rawdb.HashScheme, tracer, func(res error, chain *core.BlockChain) {
|
if err := test.Run(false, rawdb.HashScheme, false, tracer, func(res error, chain *core.BlockChain) {
|
||||||
if ctx.Bool(DumpFlag.Name) {
|
if ctx.Bool(DumpFlag.Name) {
|
||||||
if state, _ := chain.State(); state != nil {
|
if state, _ := chain.State(); state != nil {
|
||||||
fmt.Println(string(state.Dump(nil)))
|
fmt.Println(string(state.Dump(nil)))
|
||||||
|
|||||||
@@ -306,7 +306,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
if tracer.Hooks.OnTxEnd != nil {
|
if tracer.Hooks.OnTxEnd != nil {
|
||||||
tracer.Hooks.OnTxEnd(receipt, nil)
|
tracer.Hooks.OnTxEnd(receipt, nil)
|
||||||
}
|
}
|
||||||
writeTraceResult(tracer, traceOutput)
|
if err = writeTraceResult(tracer, traceOutput); err != nil {
|
||||||
|
log.Warn("Error writing tracer output", "err", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +325,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
var (
|
var (
|
||||||
blockReward = big.NewInt(miningReward)
|
blockReward = big.NewInt(miningReward)
|
||||||
minerReward = new(big.Int).Set(blockReward)
|
minerReward = new(big.Int).Set(blockReward)
|
||||||
perOmmer = new(big.Int).Div(blockReward, big.NewInt(32))
|
perOmmer = new(big.Int).Rsh(blockReward, 5)
|
||||||
)
|
)
|
||||||
for _, ommer := range pre.Env.Ommers {
|
for _, ommer := range pre.Env.Ommers {
|
||||||
// Add 1/32th for each ommer included
|
// Add 1/32th for each ommer included
|
||||||
@@ -332,7 +334,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
reward := big.NewInt(8)
|
reward := big.NewInt(8)
|
||||||
reward.Sub(reward, new(big.Int).SetUint64(ommer.Delta))
|
reward.Sub(reward, new(big.Int).SetUint64(ommer.Delta))
|
||||||
reward.Mul(reward, blockReward)
|
reward.Mul(reward, blockReward)
|
||||||
reward.Div(reward, big.NewInt(8))
|
reward.Rsh(reward, 3)
|
||||||
statedb.AddBalance(ommer.Address, uint256.MustFromBig(reward), tracing.BalanceIncreaseRewardMineUncle)
|
statedb.AddBalance(ommer.Address, uint256.MustFromBig(reward), tracing.BalanceIncreaseRewardMineUncle)
|
||||||
}
|
}
|
||||||
statedb.AddBalance(pre.Env.Coinbase, uint256.MustFromBig(minerReward), tracing.BalanceIncreaseRewardMineBlock)
|
statedb.AddBalance(pre.Env.Coinbase, uint256.MustFromBig(minerReward), tracing.BalanceIncreaseRewardMineBlock)
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ func Transition(ctx *cli.Context) error {
|
|||||||
// Set the chain id
|
// Set the chain id
|
||||||
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
|
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
|
||||||
|
|
||||||
if txIt, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil {
|
if txIt, err = loadTransactions(txStr, inputData, chainConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
|
if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Tran
|
|||||||
return signedTxs, nil
|
return signedTxs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (txIterator, error) {
|
func loadTransactions(txStr string, inputData *input, chainConfig *params.ChainConfig) (txIterator, error) {
|
||||||
var txsWithKeys []*txWithKey
|
var txsWithKeys []*txWithKey
|
||||||
if txStr != stdinSelector {
|
if txStr != stdinSelector {
|
||||||
data, err := os.ReadFile(txStr)
|
data, err := os.ReadFile(txStr)
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ 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/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
@@ -337,7 +336,7 @@ func importChain(ctx *cli.Context) error {
|
|||||||
fmt.Printf("Import done in %v.\n\n", time.Since(start))
|
fmt.Printf("Import done in %v.\n\n", time.Since(start))
|
||||||
|
|
||||||
// Output pre-compaction stats mostly to see the import trashing
|
// Output pre-compaction stats mostly to see the import trashing
|
||||||
showLeveldbStats(db)
|
showDBStats(db)
|
||||||
|
|
||||||
// Print the memory statistics used by the importing
|
// Print the memory statistics used by the importing
|
||||||
mem := new(runtime.MemStats)
|
mem := new(runtime.MemStats)
|
||||||
@@ -360,7 +359,7 @@ func importChain(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
fmt.Printf("Compaction done in %v.\n\n", time.Since(start))
|
fmt.Printf("Compaction done in %v.\n\n", time.Since(start))
|
||||||
|
|
||||||
showLeveldbStats(db)
|
showDBStats(db)
|
||||||
return importErr
|
return importErr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +515,7 @@ func importPreimages(ctx *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDumpConfig(ctx *cli.Context, stack *node.Node, db ethdb.Database) (*state.DumpConfig, common.Hash, error) {
|
func parseDumpConfig(ctx *cli.Context, db ethdb.Database) (*state.DumpConfig, common.Hash, error) {
|
||||||
var header *types.Header
|
var header *types.Header
|
||||||
if ctx.NArg() > 1 {
|
if ctx.NArg() > 1 {
|
||||||
return nil, common.Hash{}, fmt.Errorf("expected 1 argument (number or hash), got %d", ctx.NArg())
|
return nil, common.Hash{}, fmt.Errorf("expected 1 argument (number or hash), got %d", ctx.NArg())
|
||||||
@@ -580,7 +579,7 @@ func dump(ctx *cli.Context) error {
|
|||||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
conf, root, err := parseDumpConfig(ctx, stack, db)
|
conf, root, err := parseDumpConfig(ctx, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -407,17 +407,13 @@ func checkStateContent(ctx *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func showLeveldbStats(db ethdb.KeyValueStater) {
|
func showDBStats(db ethdb.KeyValueStater) {
|
||||||
if stats, err := db.Stat("leveldb.stats"); err != nil {
|
stats, err := db.Stat()
|
||||||
|
if err != nil {
|
||||||
log.Warn("Failed to read database stats", "error", err)
|
log.Warn("Failed to read database stats", "error", err)
|
||||||
} else {
|
return
|
||||||
fmt.Println(stats)
|
|
||||||
}
|
|
||||||
if ioStats, err := db.Stat("leveldb.iostats"); err != nil {
|
|
||||||
log.Warn("Failed to read database iostats", "error", err)
|
|
||||||
} else {
|
|
||||||
fmt.Println(ioStats)
|
|
||||||
}
|
}
|
||||||
|
fmt.Println(stats)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dbStats(ctx *cli.Context) error {
|
func dbStats(ctx *cli.Context) error {
|
||||||
@@ -427,7 +423,7 @@ func dbStats(ctx *cli.Context) error {
|
|||||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
showLeveldbStats(db)
|
showDBStats(db)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +435,7 @@ func dbCompact(ctx *cli.Context) error {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
log.Info("Stats before compaction")
|
log.Info("Stats before compaction")
|
||||||
showLeveldbStats(db)
|
showDBStats(db)
|
||||||
|
|
||||||
log.Info("Triggering compaction")
|
log.Info("Triggering compaction")
|
||||||
if err := db.Compact(nil, nil); err != nil {
|
if err := db.Compact(nil, nil); err != nil {
|
||||||
@@ -447,7 +443,7 @@ func dbCompact(ctx *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Info("Stats after compaction")
|
log.Info("Stats after compaction")
|
||||||
showLeveldbStats(db)
|
showDBStats(db)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ var (
|
|||||||
utils.BeaconGenesisRootFlag,
|
utils.BeaconGenesisRootFlag,
|
||||||
utils.BeaconGenesisTimeFlag,
|
utils.BeaconGenesisTimeFlag,
|
||||||
utils.BeaconCheckpointFlag,
|
utils.BeaconCheckpointFlag,
|
||||||
|
utils.CollectWitnessFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags)
|
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||||
|
|
||||||
rpcFlags = []cli.Flag{
|
rpcFlags = []cli.Flag{
|
||||||
|
|||||||
@@ -544,7 +544,7 @@ func dumpState(ctx *cli.Context) error {
|
|||||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
conf, root, err := parseDumpConfig(ctx, stack, db)
|
conf, root, err := parseDumpConfig(ctx, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -604,6 +604,11 @@ var (
|
|||||||
Usage: "Disables db compaction after import",
|
Usage: "Disables db compaction after import",
|
||||||
Category: flags.LoggingCategory,
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
|
CollectWitnessFlag = &cli.BoolFlag{
|
||||||
|
Name: "collectwitness",
|
||||||
|
Usage: "Enable state witness generation during block execution. Work in progress flag, don't use.",
|
||||||
|
Category: flags.MiscCategory,
|
||||||
|
}
|
||||||
|
|
||||||
// MISC settings
|
// MISC settings
|
||||||
SyncTargetFlag = &cli.StringFlag{
|
SyncTargetFlag = &cli.StringFlag{
|
||||||
@@ -1760,6 +1765,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||||||
// TODO(fjl): force-enable this in --dev mode
|
// TODO(fjl): force-enable this in --dev mode
|
||||||
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
||||||
}
|
}
|
||||||
|
if ctx.IsSet(CollectWitnessFlag.Name) {
|
||||||
|
cfg.EnableWitnessCollection = ctx.Bool(CollectWitnessFlag.Name)
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
|
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
|
||||||
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
|
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
|
||||||
@@ -2190,7 +2198,10 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
|||||||
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
|
cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
||||||
}
|
}
|
||||||
vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)}
|
vmcfg := vm.Config{
|
||||||
|
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
|
||||||
|
EnableWitnessCollection: ctx.Bool(CollectWitnessFlag.Name),
|
||||||
|
}
|
||||||
if ctx.IsSet(VMTraceFlag.Name) {
|
if ctx.IsSet(VMTraceFlag.Name) {
|
||||||
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
||||||
var config json.RawMessage
|
var config json.RawMessage
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func NewHexOrDecimal256(x int64) *HexOrDecimal256 {
|
|||||||
// It is similar to UnmarshalText, but allows parsing real decimals too, not just
|
// It is similar to UnmarshalText, but allows parsing real decimals too, not just
|
||||||
// quoted decimal strings.
|
// quoted decimal strings.
|
||||||
func (i *HexOrDecimal256) UnmarshalJSON(input []byte) error {
|
func (i *HexOrDecimal256) UnmarshalJSON(input []byte) error {
|
||||||
if len(input) > 0 && input[0] == '"' {
|
if len(input) > 1 && input[0] == '"' {
|
||||||
input = input[1 : len(input)-1]
|
input = input[1 : len(input)-1]
|
||||||
}
|
}
|
||||||
return i.UnmarshalText(input)
|
return i.UnmarshalText(input)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ type HexOrDecimal64 uint64
|
|||||||
// It is similar to UnmarshalText, but allows parsing real decimals too, not just
|
// It is similar to UnmarshalText, but allows parsing real decimals too, not just
|
||||||
// quoted decimal strings.
|
// quoted decimal strings.
|
||||||
func (i *HexOrDecimal64) UnmarshalJSON(input []byte) error {
|
func (i *HexOrDecimal64) UnmarshalJSON(input []byte) error {
|
||||||
if len(input) > 0 && input[0] == '"' {
|
if len(input) > 1 && input[0] == '"' {
|
||||||
input = input[1 : len(input)-1]
|
input = input[1 : len(input)-1]
|
||||||
}
|
}
|
||||||
return i.UnmarshalText(input)
|
return i.UnmarshalText(input)
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ func (d *Decimal) UnmarshalJSON(input []byte) error {
|
|||||||
if !isString(input) {
|
if !isString(input) {
|
||||||
return &json.UnmarshalTypeError{Value: "non-string", Type: reflect.TypeOf(uint64(0))}
|
return &json.UnmarshalTypeError{Value: "non-string", Type: reflect.TypeOf(uint64(0))}
|
||||||
}
|
}
|
||||||
if i, err := strconv.ParseInt(string(input[1:len(input)-1]), 10, 64); err == nil {
|
if i, err := strconv.ParseUint(string(input[1:len(input)-1]), 10, 64); err == nil {
|
||||||
*d = Decimal(i)
|
*d = Decimal(i)
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -595,3 +596,29 @@ func BenchmarkPrettyDuration(b *testing.B) {
|
|||||||
}
|
}
|
||||||
b.Logf("Post %s", a)
|
b.Logf("Post %s", a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDecimalUnmarshalJSON(t *testing.T) {
|
||||||
|
// These should error
|
||||||
|
for _, tc := range []string{``, `"`, `""`, `"-1"`} {
|
||||||
|
if err := new(Decimal).UnmarshalJSON([]byte(tc)); err == nil {
|
||||||
|
t.Errorf("input %s should cause error", tc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// These should succeed
|
||||||
|
for _, tc := range []struct {
|
||||||
|
input string
|
||||||
|
want uint64
|
||||||
|
}{
|
||||||
|
{`"0"`, 0},
|
||||||
|
{`"9223372036854775807"`, math.MaxInt64},
|
||||||
|
{`"18446744073709551615"`, math.MaxUint64},
|
||||||
|
} {
|
||||||
|
have := new(Decimal)
|
||||||
|
if err := have.UnmarshalJSON([]byte(tc.input)); err != nil {
|
||||||
|
t.Errorf("input %q triggered error: %v", tc.input, err)
|
||||||
|
}
|
||||||
|
if uint64(*have) != tc.want {
|
||||||
|
t.Errorf("input %q, have %d want %d", tc.input, *have, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -562,12 +562,6 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
|
|||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some weird constants to avoid constant memory allocs for them.
|
|
||||||
var (
|
|
||||||
u256_8 = uint256.NewInt(8)
|
|
||||||
u256_32 = uint256.NewInt(32)
|
|
||||||
)
|
|
||||||
|
|
||||||
// accumulateRewards credits the coinbase of the given block with the mining
|
// accumulateRewards credits the coinbase of the given block with the mining
|
||||||
// reward. The total reward consists of the static block reward and rewards for
|
// reward. The total reward consists of the static block reward and rewards for
|
||||||
// included uncles. The coinbase of each uncle block is also rewarded.
|
// included uncles. The coinbase of each uncle block is also rewarded.
|
||||||
@@ -589,10 +583,10 @@ func accumulateRewards(config *params.ChainConfig, stateDB *state.StateDB, heade
|
|||||||
r.AddUint64(uNum, 8)
|
r.AddUint64(uNum, 8)
|
||||||
r.Sub(r, hNum)
|
r.Sub(r, hNum)
|
||||||
r.Mul(r, blockReward)
|
r.Mul(r, blockReward)
|
||||||
r.Div(r, u256_8)
|
r.Rsh(r, 3)
|
||||||
stateDB.AddBalance(uncle.Coinbase, r, tracing.BalanceIncreaseRewardMineUncle)
|
stateDB.AddBalance(uncle.Coinbase, r, tracing.BalanceIncreaseRewardMineUncle)
|
||||||
|
|
||||||
r.Div(blockReward, u256_32)
|
r.Rsh(blockReward, 5)
|
||||||
reward.Add(reward, r)
|
reward.Add(reward, r)
|
||||||
}
|
}
|
||||||
stateDB.AddBalance(header.Coinbase, reward, tracing.BalanceIncreaseRewardMineBlock)
|
stateDB.AddBalance(header.Coinbase, reward, tracing.BalanceIncreaseRewardMineBlock)
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/stateless"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
@@ -34,14 +36,12 @@ import (
|
|||||||
type BlockValidator struct {
|
type BlockValidator struct {
|
||||||
config *params.ChainConfig // Chain configuration options
|
config *params.ChainConfig // Chain configuration options
|
||||||
bc *BlockChain // Canonical block chain
|
bc *BlockChain // Canonical block chain
|
||||||
engine consensus.Engine // Consensus engine used for validating
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockValidator returns a new block validator which is safe for re-use
|
// NewBlockValidator returns a new block validator which is safe for re-use
|
||||||
func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine) *BlockValidator {
|
func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain) *BlockValidator {
|
||||||
validator := &BlockValidator{
|
validator := &BlockValidator{
|
||||||
config: config,
|
config: config,
|
||||||
engine: engine,
|
|
||||||
bc: blockchain,
|
bc: blockchain,
|
||||||
}
|
}
|
||||||
return validator
|
return validator
|
||||||
@@ -59,7 +59,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
|||||||
// Header validity is known at this point. Here we verify that uncles, transactions
|
// Header validity is known at this point. Here we verify that uncles, transactions
|
||||||
// and withdrawals given in the block body match the header.
|
// and withdrawals given in the block body match the header.
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
if err := v.engine.VerifyUncles(v.bc, block); err != nil {
|
if err := v.bc.engine.VerifyUncles(v.bc, block); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
|
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
|
||||||
@@ -121,7 +121,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
|||||||
|
|
||||||
// ValidateState validates the various changes that happen after a state transition,
|
// ValidateState validates the various changes that happen after a state transition,
|
||||||
// such as amount of used gas, the receipt roots and the state root itself.
|
// such as amount of used gas, the receipt roots and the state root itself.
|
||||||
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
|
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, stateless bool) error {
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
if block.GasUsed() != usedGas {
|
if block.GasUsed() != usedGas {
|
||||||
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
|
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
|
||||||
@@ -132,6 +132,11 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
if rbloom != header.Bloom {
|
if rbloom != header.Bloom {
|
||||||
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
||||||
}
|
}
|
||||||
|
// In stateless mode, return early because the receipt and state root are not
|
||||||
|
// provided through the witness, rather the cross validator needs to return it.
|
||||||
|
if stateless {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// The receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
|
// The receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
|
||||||
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
|
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
|
||||||
if receiptSha != header.ReceiptHash {
|
if receiptSha != header.ReceiptHash {
|
||||||
@@ -145,6 +150,28 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateWitness cross validates a block execution with stateless remote clients.
|
||||||
|
//
|
||||||
|
// Normally we'd distribute the block witness to remote cross validators, wait
|
||||||
|
// for them to respond and then merge the results. For now, however, it's only
|
||||||
|
// Geth, so do an internal stateless run.
|
||||||
|
func (v *BlockValidator) ValidateWitness(witness *stateless.Witness, receiptRoot common.Hash, stateRoot common.Hash) error {
|
||||||
|
// Run the cross client stateless execution
|
||||||
|
// TODO(karalabe): Self-stateless for now, swap with other clients
|
||||||
|
crossReceiptRoot, crossStateRoot, err := ExecuteStateless(v.config, witness)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("stateless execution failed: %v", err)
|
||||||
|
}
|
||||||
|
// Stateless cross execution suceeeded, validate the withheld computed fields
|
||||||
|
if crossReceiptRoot != receiptRoot {
|
||||||
|
return fmt.Errorf("cross validator receipt root mismatch (cross: %x local: %x)", crossReceiptRoot, receiptRoot)
|
||||||
|
}
|
||||||
|
if crossStateRoot != stateRoot {
|
||||||
|
return fmt.Errorf("cross validator state root mismatch (cross: %x local: %x)", crossStateRoot, stateRoot)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
||||||
// to keep the baseline gas close to the provided target, and increase it towards
|
// to keep the baseline gas close to the provided target, and increase it towards
|
||||||
// the target if the baseline gas is lower.
|
// the target if the baseline gas is lower.
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ 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/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
|
"github.com/ethereum/go-ethereum/core/stateless"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"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"
|
||||||
@@ -302,18 +303,18 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||||||
vmConfig: vmConfig,
|
vmConfig: vmConfig,
|
||||||
logger: vmConfig.Tracer,
|
logger: vmConfig.Tracer,
|
||||||
}
|
}
|
||||||
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
|
||||||
bc.forker = NewForkChoice(bc, shouldPreserve)
|
|
||||||
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
|
||||||
bc.validator = NewBlockValidator(chainConfig, bc, engine)
|
|
||||||
bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine)
|
|
||||||
bc.processor = NewStateProcessor(chainConfig, bc, engine)
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
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.forker = NewForkChoice(bc, shouldPreserve)
|
||||||
|
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
||||||
|
bc.validator = NewBlockValidator(chainConfig, bc)
|
||||||
|
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
||||||
|
bc.processor = NewStateProcessor(chainConfig, bc.hc)
|
||||||
|
|
||||||
bc.genesisBlock = bc.GetBlockByNumber(0)
|
bc.genesisBlock = bc.GetBlockByNumber(0)
|
||||||
if bc.genesisBlock == nil {
|
if bc.genesisBlock == nil {
|
||||||
return nil, ErrNoGenesis
|
return nil, ErrNoGenesis
|
||||||
@@ -1809,7 +1810,14 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
|||||||
// while processing transactions. Before Byzantium the prefetcher is mostly
|
// while processing transactions. Before Byzantium the prefetcher is mostly
|
||||||
// useless due to the intermediate root hashing after each transaction.
|
// useless due to the intermediate root hashing after each transaction.
|
||||||
if bc.chainConfig.IsByzantium(block.Number()) {
|
if bc.chainConfig.IsByzantium(block.Number()) {
|
||||||
statedb.StartPrefetcher("chain")
|
var witness *stateless.Witness
|
||||||
|
if bc.vmConfig.EnableWitnessCollection {
|
||||||
|
witness, err = stateless.NewWitness(bc, block)
|
||||||
|
if err != nil {
|
||||||
|
return it.index, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statedb.StartPrefetcher("chain", witness)
|
||||||
}
|
}
|
||||||
activeState = statedb
|
activeState = statedb
|
||||||
|
|
||||||
@@ -1924,11 +1932,18 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
|||||||
ptime := time.Since(pstart)
|
ptime := time.Since(pstart)
|
||||||
|
|
||||||
vstart := time.Now()
|
vstart := time.Now()
|
||||||
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
|
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas, false); err != nil {
|
||||||
bc.reportBlock(block, receipts, err)
|
bc.reportBlock(block, receipts, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
vtime := time.Since(vstart)
|
vtime := time.Since(vstart)
|
||||||
|
|
||||||
|
if witness := statedb.Witness(); witness != nil {
|
||||||
|
if err = bc.validator.ValidateWitness(witness, block.ReceiptHash(), block.Root()); err != nil {
|
||||||
|
bc.reportBlock(block, receipts, err)
|
||||||
|
return nil, fmt.Errorf("cross verification failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
proctime := time.Since(start) // processing + validation
|
proctime := time.Since(start) // processing + validation
|
||||||
|
|
||||||
// Update the metrics touched during block processing and validation
|
// Update the metrics touched during block processing and validation
|
||||||
|
|||||||
@@ -168,8 +168,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
|
|||||||
blockchain.reportBlock(block, receipts, err)
|
blockchain.reportBlock(block, receipts, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas)
|
if err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, false); err != nil {
|
||||||
if err != nil {
|
|
||||||
blockchain.reportBlock(block, receipts, err)
|
blockchain.reportBlock(block, receipts, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -594,7 +594,7 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
|
|||||||
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
|
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
|
||||||
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
||||||
// Pre-deploy EIP-4788 system contract
|
// Pre-deploy EIP-4788 system contract
|
||||||
params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode},
|
params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if faucet != nil {
|
if faucet != nil {
|
||||||
|
|||||||
@@ -147,9 +147,9 @@ func (t *table) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns a particular internal stat of the database.
|
// Stat returns the statistic data of the database.
|
||||||
func (t *table) Stat(property string) (string, error) {
|
func (t *table) Stat() (string, error) {
|
||||||
return t.db.Stat(property)
|
return t.db.Stat()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact flattens the underlying data store for the given key range. In essence,
|
// Compact flattens the underlying data store for the given key range. In essence,
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ func TestAccountHeaderGas(t *testing.T) {
|
|||||||
|
|
||||||
// Check cold read cost
|
// Check cold read cost
|
||||||
gas := ae.VersionGas(testAddr, false)
|
gas := ae.VersionGas(testAddr, false)
|
||||||
if gas != params.WitnessBranchReadCost+params.WitnessChunkReadCost {
|
if want := params.WitnessBranchReadCost + params.WitnessChunkReadCost; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchReadCost+params.WitnessChunkReadCost)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check warm read cost
|
// Check warm read cost
|
||||||
@@ -71,8 +71,8 @@ func TestAccountHeaderGas(t *testing.T) {
|
|||||||
|
|
||||||
// Check cold write cost
|
// Check cold write cost
|
||||||
gas = ae.VersionGas(testAddr, true)
|
gas = ae.VersionGas(testAddr, true)
|
||||||
if gas != params.WitnessBranchWriteCost+params.WitnessChunkWriteCost {
|
if want := params.WitnessBranchWriteCost + params.WitnessChunkWriteCost; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchReadCost+params.WitnessBranchWriteCost)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check warm write cost
|
// Check warm write cost
|
||||||
@@ -83,8 +83,8 @@ func TestAccountHeaderGas(t *testing.T) {
|
|||||||
|
|
||||||
// Check a write without a read charges both read and write costs
|
// Check a write without a read charges both read and write costs
|
||||||
gas = ae.BalanceGas(testAddr2, true)
|
gas = ae.BalanceGas(testAddr2, true)
|
||||||
if gas != params.WitnessBranchReadCost+params.WitnessBranchWriteCost+params.WitnessChunkWriteCost+params.WitnessChunkReadCost {
|
if want := params.WitnessBranchReadCost + params.WitnessBranchWriteCost + params.WitnessChunkWriteCost + params.WitnessChunkReadCost; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchReadCost+params.WitnessBranchWriteCost+params.WitnessChunkWriteCost+params.WitnessChunkReadCost)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that a write followed by a read charges nothing
|
// Check that a write followed by a read charges nothing
|
||||||
@@ -113,8 +113,8 @@ func TestContractCreateInitGas(t *testing.T) {
|
|||||||
|
|
||||||
// Check cold read cost, without a value
|
// Check cold read cost, without a value
|
||||||
gas := ae.ContractCreateInitGas(testAddr, false)
|
gas := ae.ContractCreateInitGas(testAddr, false)
|
||||||
if gas != params.WitnessBranchWriteCost+params.WitnessBranchReadCost+params.WitnessChunkWriteCost*2+params.WitnessChunkReadCost*2 {
|
if want := params.WitnessBranchWriteCost + params.WitnessBranchReadCost + params.WitnessChunkWriteCost*2 + params.WitnessChunkReadCost*2; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchWriteCost+params.WitnessBranchReadCost+params.WitnessChunkWriteCost*3)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check warm read cost
|
// Check warm read cost
|
||||||
@@ -131,8 +131,8 @@ func TestMessageCallGas(t *testing.T) {
|
|||||||
|
|
||||||
// Check cold read cost, without a value
|
// Check cold read cost, without a value
|
||||||
gas := ae.MessageCallGas(testAddr)
|
gas := ae.MessageCallGas(testAddr)
|
||||||
if gas != params.WitnessBranchReadCost+params.WitnessChunkReadCost*2 {
|
if want := params.WitnessBranchReadCost + params.WitnessChunkReadCost*2; gas != want {
|
||||||
t.Fatalf("incorrect gas computed, got %d, want %d", gas, params.WitnessBranchReadCost+params.WitnessChunkReadCost*2)
|
t.Fatalf("incorrect gas computed, got %d, want %d", gas, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that reading the version and code size of the same account does not incur the branch read cost
|
// Check that reading the version and code size of the same account does not incur the branch read cost
|
||||||
|
|||||||
@@ -60,11 +60,11 @@ func newAccessList() *accessList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy creates an independent copy of an accessList.
|
// Copy creates an independent copy of an accessList.
|
||||||
func (a *accessList) Copy() *accessList {
|
func (al *accessList) Copy() *accessList {
|
||||||
cp := newAccessList()
|
cp := newAccessList()
|
||||||
cp.addresses = maps.Clone(a.addresses)
|
cp.addresses = maps.Clone(al.addresses)
|
||||||
cp.slots = make([]map[common.Hash]struct{}, len(a.slots))
|
cp.slots = make([]map[common.Hash]struct{}, len(al.slots))
|
||||||
for i, slotMap := range a.slots {
|
for i, slotMap := range al.slots {
|
||||||
cp.slots[i] = maps.Clone(slotMap)
|
cp.slots[i] = maps.Clone(slotMap)
|
||||||
}
|
}
|
||||||
return cp
|
return cp
|
||||||
|
|||||||
@@ -123,7 +123,11 @@ type Trie interface {
|
|||||||
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
||||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||||
// be created with new root and updated trie database for following usage
|
// be created with new root and updated trie database for following usage
|
||||||
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
|
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet)
|
||||||
|
|
||||||
|
// Witness returns a set containing all trie nodes that have been accessed.
|
||||||
|
// The returned map could be nil if the witness is empty.
|
||||||
|
Witness() map[string]struct{}
|
||||||
|
|
||||||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
||||||
// starts at the key after the given start key. And error will be returned
|
// starts at the key after the given start key. And error will be returned
|
||||||
|
|||||||
@@ -360,10 +360,7 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
|
|||||||
for i, key := range result.keys {
|
for i, key := range result.keys {
|
||||||
snapTrie.Update(key, result.vals[i])
|
snapTrie.Update(key, result.vals[i])
|
||||||
}
|
}
|
||||||
root, nodes, err := snapTrie.Commit(false)
|
root, nodes := snapTrie.Commit(false)
|
||||||
if err != nil {
|
|
||||||
return false, nil, err
|
|
||||||
}
|
|
||||||
if nodes != nil {
|
if nodes != nil {
|
||||||
tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
||||||
tdb.Commit(root, false)
|
tdb.Commit(root, false)
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ func (t *testHelper) makeStorageTrie(owner common.Hash, keys []string, vals []st
|
|||||||
if !commit {
|
if !commit {
|
||||||
return stTrie.Hash()
|
return stTrie.Hash()
|
||||||
}
|
}
|
||||||
root, nodes, _ := stTrie.Commit(false)
|
root, nodes := stTrie.Commit(false)
|
||||||
if nodes != nil {
|
if nodes != nil {
|
||||||
t.nodes.Merge(nodes)
|
t.nodes.Merge(nodes)
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ func (t *testHelper) makeStorageTrie(owner common.Hash, keys []string, vals []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *testHelper) Commit() common.Hash {
|
func (t *testHelper) Commit() common.Hash {
|
||||||
root, nodes, _ := t.accTrie.Commit(true)
|
root, nodes := t.accTrie.Commit(true)
|
||||||
if nodes != nil {
|
if nodes != nil {
|
||||||
t.nodes.Merge(nodes)
|
t.nodes.Merge(nodes)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -815,7 +815,7 @@ func TestStorageIteratorDeletions(t *testing.T) {
|
|||||||
verifyIterator(t, 2, snaps.Snapshot(common.HexToHash("0x06")).(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage)
|
verifyIterator(t, 2, snaps.Snapshot(common.HexToHash("0x06")).(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BenchmarkAccountIteratorTraversal is a bit a bit notorious -- all layers contain the
|
// BenchmarkAccountIteratorTraversal is a bit notorious -- all layers contain the
|
||||||
// exact same 200 accounts. That means that we need to process 2000 items, but
|
// exact same 200 accounts. That means that we need to process 2000 items, but
|
||||||
// only spit out 200 values eventually.
|
// only spit out 200 values eventually.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -666,6 +666,9 @@ func diffToDisk(bottom *diffLayer) *diskLayer {
|
|||||||
|
|
||||||
// Release releases resources
|
// Release releases resources
|
||||||
func (t *Tree) Release() {
|
func (t *Tree) Release() {
|
||||||
|
t.lock.RLock()
|
||||||
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
if dl := t.disklayer(); dl != nil {
|
if dl := t.disklayer(); dl != nil {
|
||||||
dl.Release()
|
dl.Release()
|
||||||
}
|
}
|
||||||
@@ -829,6 +832,8 @@ func (t *Tree) disklayer() *diskLayer {
|
|||||||
case *diskLayer:
|
case *diskLayer:
|
||||||
return layer
|
return layer
|
||||||
case *diffLayer:
|
case *diffLayer:
|
||||||
|
layer.lock.RLock()
|
||||||
|
defer layer.lock.RUnlock()
|
||||||
return layer.origin
|
return layer.origin
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("%T: undefined layer", snap))
|
panic(fmt.Sprintf("%T: undefined layer", snap))
|
||||||
@@ -848,8 +853,8 @@ func (t *Tree) diskRoot() common.Hash {
|
|||||||
// generating is an internal helper function which reports whether the snapshot
|
// generating is an internal helper function which reports whether the snapshot
|
||||||
// is still under the construction.
|
// is still under the construction.
|
||||||
func (t *Tree) generating() (bool, error) {
|
func (t *Tree) generating() (bool, error) {
|
||||||
t.lock.Lock()
|
t.lock.RLock()
|
||||||
defer t.lock.Unlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
layer := t.disklayer()
|
layer := t.disklayer()
|
||||||
if layer == nil {
|
if layer == nil {
|
||||||
@@ -860,10 +865,10 @@ func (t *Tree) generating() (bool, error) {
|
|||||||
return layer.genMarker != nil, nil
|
return layer.genMarker != nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskRoot is a external helper function to return the disk layer root.
|
// DiskRoot is an external helper function to return the disk layer root.
|
||||||
func (t *Tree) DiskRoot() common.Hash {
|
func (t *Tree) DiskRoot() common.Hash {
|
||||||
t.lock.Lock()
|
t.lock.RLock()
|
||||||
defer t.lock.Unlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
return t.diskRoot()
|
return t.diskRoot()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,6 +230,14 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
|||||||
}
|
}
|
||||||
value.SetBytes(val)
|
value.SetBytes(val)
|
||||||
}
|
}
|
||||||
|
// Independent of where we loaded the data from, add it to the prefetcher.
|
||||||
|
// Whilst this would be a bit weird if snapshots are disabled, but we still
|
||||||
|
// want the trie nodes to end up in the prefetcher too, so just push through.
|
||||||
|
if s.db.prefetcher != nil && s.data.Root != types.EmptyRootHash {
|
||||||
|
if err = s.db.prefetcher.prefetch(s.addrHash, s.origin.Root, s.address, [][]byte{key[:]}, true); err != nil {
|
||||||
|
log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
s.originStorage[key] = value
|
s.originStorage[key] = value
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
@@ -293,7 +301,7 @@ func (s *stateObject) finalise() {
|
|||||||
s.pendingStorage[key] = value
|
s.pendingStorage[key] = value
|
||||||
}
|
}
|
||||||
if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash {
|
if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash {
|
||||||
if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, slotsToPrefetch); err != nil {
|
if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, slotsToPrefetch, false); err != nil {
|
||||||
log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err)
|
log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,11 +323,17 @@ func (s *stateObject) finalise() {
|
|||||||
//
|
//
|
||||||
// It assumes all the dirty storage slots have been finalized before.
|
// It assumes all the dirty storage slots have been finalized before.
|
||||||
func (s *stateObject) updateTrie() (Trie, error) {
|
func (s *stateObject) updateTrie() (Trie, error) {
|
||||||
// Short circuit if nothing changed, don't bother with hashing anything
|
// Short circuit if nothing was accessed, don't trigger a prefetcher warning
|
||||||
if len(s.uncommittedStorage) == 0 {
|
if len(s.uncommittedStorage) == 0 {
|
||||||
return s.trie, nil
|
// Nothing was written, so we could stop early. Unless we have both reads
|
||||||
|
// and witness collection enabled, in which case we need to fetch the trie.
|
||||||
|
if s.db.witness == nil || len(s.originStorage) == 0 {
|
||||||
|
return s.trie, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Retrieve a pretecher populated trie, or fall back to the database
|
// Retrieve a pretecher populated trie, or fall back to the database. This will
|
||||||
|
// block until all prefetch tasks are done, which are needed for witnesses even
|
||||||
|
// for unmodified state objects.
|
||||||
tr := s.getPrefetchedTrie()
|
tr := s.getPrefetchedTrie()
|
||||||
if tr != nil {
|
if tr != nil {
|
||||||
// Prefetcher returned a live trie, swap it out for the current one
|
// Prefetcher returned a live trie, swap it out for the current one
|
||||||
@@ -333,6 +347,10 @@ func (s *stateObject) updateTrie() (Trie, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Short circuit if nothing changed, don't bother with hashing anything
|
||||||
|
if len(s.uncommittedStorage) == 0 {
|
||||||
|
return s.trie, nil
|
||||||
|
}
|
||||||
// Perform trie updates before deletions. This prevents resolution of unnecessary trie nodes
|
// Perform trie updates before deletions. This prevents resolution of unnecessary trie nodes
|
||||||
// in circumstances similar to the following:
|
// in circumstances similar to the following:
|
||||||
//
|
//
|
||||||
@@ -462,10 +480,7 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
|
|||||||
s.origin = s.data.Copy()
|
s.origin = s.data.Copy()
|
||||||
return op, nil, nil
|
return op, nil, nil
|
||||||
}
|
}
|
||||||
root, nodes, err := s.trie.Commit(false)
|
root, nodes := s.trie.Commit(false)
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
s.data.Root = root
|
s.data.Root = root
|
||||||
s.origin = s.data.Copy()
|
s.origin = s.data.Copy()
|
||||||
return op, nodes, nil
|
return op, nodes, nil
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
|
"github.com/ethereum/go-ethereum/core/stateless"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
@@ -105,7 +106,7 @@ type StateDB struct {
|
|||||||
// resurrection. The account value is tracked as the original value
|
// resurrection. The account value is tracked as the original value
|
||||||
// before the transition. This map is populated at the transaction
|
// before the transition. This map is populated at the transaction
|
||||||
// boundaries.
|
// boundaries.
|
||||||
stateObjectsDestruct map[common.Address]*types.StateAccount
|
stateObjectsDestruct map[common.Address]*stateObject
|
||||||
|
|
||||||
// This map tracks the account mutations that occurred during the
|
// This map tracks the account mutations that occurred during the
|
||||||
// transition. Uncommitted mutations belonging to the same account
|
// transition. Uncommitted mutations belonging to the same account
|
||||||
@@ -146,6 +147,9 @@ type StateDB struct {
|
|||||||
validRevisions []revision
|
validRevisions []revision
|
||||||
nextRevisionId int
|
nextRevisionId int
|
||||||
|
|
||||||
|
// State witness if cross validation is needed
|
||||||
|
witness *stateless.Witness
|
||||||
|
|
||||||
// Measurements gathered during execution for debugging purposes
|
// Measurements gathered during execution for debugging purposes
|
||||||
AccountReads time.Duration
|
AccountReads time.Duration
|
||||||
AccountHashes time.Duration
|
AccountHashes time.Duration
|
||||||
@@ -177,7 +181,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
|
|||||||
originalRoot: root,
|
originalRoot: root,
|
||||||
snaps: snaps,
|
snaps: snaps,
|
||||||
stateObjects: make(map[common.Address]*stateObject),
|
stateObjects: make(map[common.Address]*stateObject),
|
||||||
stateObjectsDestruct: make(map[common.Address]*types.StateAccount),
|
stateObjectsDestruct: make(map[common.Address]*stateObject),
|
||||||
mutations: make(map[common.Address]*mutation),
|
mutations: make(map[common.Address]*mutation),
|
||||||
logs: make(map[common.Hash][]*types.Log),
|
logs: make(map[common.Hash][]*types.Log),
|
||||||
preimages: make(map[common.Hash][]byte),
|
preimages: make(map[common.Hash][]byte),
|
||||||
@@ -200,14 +204,19 @@ func (s *StateDB) SetLogger(l *tracing.Hooks) {
|
|||||||
// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
|
// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
|
||||||
// state trie concurrently while the state is mutated so that when we reach the
|
// state trie concurrently while the state is mutated so that when we reach the
|
||||||
// commit phase, most of the needed data is already hot.
|
// commit phase, most of the needed data is already hot.
|
||||||
func (s *StateDB) StartPrefetcher(namespace string) {
|
func (s *StateDB) StartPrefetcher(namespace string, witness *stateless.Witness) {
|
||||||
|
// Terminate any previously running prefetcher
|
||||||
if s.prefetcher != nil {
|
if s.prefetcher != nil {
|
||||||
s.prefetcher.terminate(false)
|
s.prefetcher.terminate(false)
|
||||||
s.prefetcher.report()
|
s.prefetcher.report()
|
||||||
s.prefetcher = nil
|
s.prefetcher = nil
|
||||||
}
|
}
|
||||||
|
// Enable witness collection if requested
|
||||||
|
s.witness = witness
|
||||||
|
|
||||||
|
// If snapshots are enabled, start prefethers explicitly
|
||||||
if s.snap != nil {
|
if s.snap != nil {
|
||||||
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace)
|
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace, witness == nil)
|
||||||
|
|
||||||
// With the switch to the Proof-of-Stake consensus algorithm, block production
|
// With the switch to the Proof-of-Stake consensus algorithm, block production
|
||||||
// rewards are now handled at the consensus layer. Consequently, a block may
|
// rewards are now handled at the consensus layer. Consequently, a block may
|
||||||
@@ -218,7 +227,7 @@ func (s *StateDB) StartPrefetcher(namespace string) {
|
|||||||
// To prevent this, the account trie is always scheduled for prefetching once
|
// To prevent this, the account trie is always scheduled for prefetching once
|
||||||
// the prefetcher is constructed. For more details, see:
|
// the prefetcher is constructed. For more details, see:
|
||||||
// https://github.com/ethereum/go-ethereum/issues/29880
|
// https://github.com/ethereum/go-ethereum/issues/29880
|
||||||
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, nil); err != nil {
|
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, nil, false); err != nil {
|
||||||
log.Error("Failed to prefetch account trie", "root", s.originalRoot, "err", err)
|
log.Error("Failed to prefetch account trie", "root", s.originalRoot, "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -582,7 +591,6 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
|
|||||||
start := time.Now()
|
start := time.Now()
|
||||||
acc, err := s.snap.Account(crypto.HashData(s.hasher, addr.Bytes()))
|
acc, err := s.snap.Account(crypto.HashData(s.hasher, addr.Bytes()))
|
||||||
s.SnapshotAccountReads += time.Since(start)
|
s.SnapshotAccountReads += time.Since(start)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -616,6 +624,14 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Independent of where we loaded the data from, add it to the prefetcher.
|
||||||
|
// Whilst this would be a bit weird if snapshots are disabled, but we still
|
||||||
|
// want the trie nodes to end up in the prefetcher too, so just push through.
|
||||||
|
if s.prefetcher != nil {
|
||||||
|
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, [][]byte{addr[:]}, true); err != nil {
|
||||||
|
log.Error("Failed to prefetch account", "addr", addr, "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Insert into the live set
|
// Insert into the live set
|
||||||
obj := newObject(s, addr, data)
|
obj := newObject(s, addr, data)
|
||||||
s.setStateObject(obj)
|
s.setStateObject(obj)
|
||||||
@@ -675,7 +691,7 @@ func (s *StateDB) Copy() *StateDB {
|
|||||||
hasher: crypto.NewKeccakState(),
|
hasher: crypto.NewKeccakState(),
|
||||||
originalRoot: s.originalRoot,
|
originalRoot: s.originalRoot,
|
||||||
stateObjects: make(map[common.Address]*stateObject, len(s.stateObjects)),
|
stateObjects: make(map[common.Address]*stateObject, len(s.stateObjects)),
|
||||||
stateObjectsDestruct: maps.Clone(s.stateObjectsDestruct),
|
stateObjectsDestruct: make(map[common.Address]*stateObject, len(s.stateObjectsDestruct)),
|
||||||
mutations: make(map[common.Address]*mutation, len(s.mutations)),
|
mutations: make(map[common.Address]*mutation, len(s.mutations)),
|
||||||
dbErr: s.dbErr,
|
dbErr: s.dbErr,
|
||||||
refund: s.refund,
|
refund: s.refund,
|
||||||
@@ -695,10 +711,17 @@ func (s *StateDB) Copy() *StateDB {
|
|||||||
snaps: s.snaps,
|
snaps: s.snaps,
|
||||||
snap: s.snap,
|
snap: s.snap,
|
||||||
}
|
}
|
||||||
|
if s.witness != nil {
|
||||||
|
state.witness = s.witness.Copy()
|
||||||
|
}
|
||||||
// Deep copy cached state objects.
|
// Deep copy cached state objects.
|
||||||
for addr, obj := range s.stateObjects {
|
for addr, obj := range s.stateObjects {
|
||||||
state.stateObjects[addr] = obj.deepCopy(state)
|
state.stateObjects[addr] = obj.deepCopy(state)
|
||||||
}
|
}
|
||||||
|
// Deep copy destructed state objects.
|
||||||
|
for addr, obj := range s.stateObjectsDestruct {
|
||||||
|
state.stateObjectsDestruct[addr] = obj.deepCopy(state)
|
||||||
|
}
|
||||||
// Deep copy the object state markers.
|
// Deep copy the object state markers.
|
||||||
for addr, op := range s.mutations {
|
for addr, op := range s.mutations {
|
||||||
state.mutations[addr] = op.copy()
|
state.mutations[addr] = op.copy()
|
||||||
@@ -780,7 +803,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
|||||||
// set indefinitely). Note only the first occurred self-destruct
|
// set indefinitely). Note only the first occurred self-destruct
|
||||||
// event is tracked.
|
// event is tracked.
|
||||||
if _, ok := s.stateObjectsDestruct[obj.address]; !ok {
|
if _, ok := s.stateObjectsDestruct[obj.address]; !ok {
|
||||||
s.stateObjectsDestruct[obj.address] = obj.origin
|
s.stateObjectsDestruct[obj.address] = obj
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
obj.finalise()
|
obj.finalise()
|
||||||
@@ -792,7 +815,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
|||||||
addressesToPrefetch = append(addressesToPrefetch, common.CopyBytes(addr[:])) // Copy needed for closure
|
addressesToPrefetch = append(addressesToPrefetch, common.CopyBytes(addr[:])) // Copy needed for closure
|
||||||
}
|
}
|
||||||
if s.prefetcher != nil && len(addressesToPrefetch) > 0 {
|
if s.prefetcher != nil && len(addressesToPrefetch) > 0 {
|
||||||
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, addressesToPrefetch); err != nil {
|
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, addressesToPrefetch, false); err != nil {
|
||||||
log.Error("Failed to prefetch addresses", "addresses", len(addressesToPrefetch), "err", err)
|
log.Error("Failed to prefetch addresses", "addresses", len(addressesToPrefetch), "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -838,9 +861,46 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
|||||||
obj := s.stateObjects[addr] // closure for the task runner below
|
obj := s.stateObjects[addr] // closure for the task runner below
|
||||||
workers.Go(func() error {
|
workers.Go(func() error {
|
||||||
obj.updateRoot()
|
obj.updateRoot()
|
||||||
|
|
||||||
|
// If witness building is enabled and the state object has a trie,
|
||||||
|
// gather the witnesses for its specific storage trie
|
||||||
|
if s.witness != nil && obj.trie != nil {
|
||||||
|
s.witness.AddState(obj.trie.Witness())
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// If witness building is enabled, gather all the read-only accesses
|
||||||
|
if s.witness != nil {
|
||||||
|
// Pull in anything that has been accessed before destruction
|
||||||
|
for _, obj := range s.stateObjectsDestruct {
|
||||||
|
// Skip any objects that haven't touched their storage
|
||||||
|
if len(obj.originStorage) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if trie := obj.getPrefetchedTrie(); trie != nil {
|
||||||
|
s.witness.AddState(trie.Witness())
|
||||||
|
} else if obj.trie != nil {
|
||||||
|
s.witness.AddState(obj.trie.Witness())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Pull in only-read and non-destructed trie witnesses
|
||||||
|
for _, obj := range s.stateObjects {
|
||||||
|
// Skip any objects that have been updated
|
||||||
|
if _, ok := s.mutations[obj.address]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Skip any objects that haven't touched their storage
|
||||||
|
if len(obj.originStorage) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if trie := obj.getPrefetchedTrie(); trie != nil {
|
||||||
|
s.witness.AddState(trie.Witness())
|
||||||
|
} else if obj.trie != nil {
|
||||||
|
s.witness.AddState(obj.trie.Witness())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
workers.Wait()
|
workers.Wait()
|
||||||
s.StorageUpdates += time.Since(start)
|
s.StorageUpdates += time.Since(start)
|
||||||
|
|
||||||
@@ -896,7 +956,13 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
|||||||
// Track the amount of time wasted on hashing the account trie
|
// Track the amount of time wasted on hashing the account trie
|
||||||
defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now())
|
defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now())
|
||||||
|
|
||||||
return s.trie.Hash()
|
hash := s.trie.Hash()
|
||||||
|
|
||||||
|
// If witness building is enabled, gather the account trie witness
|
||||||
|
if s.witness != nil {
|
||||||
|
s.witness.AddState(s.trie.Witness())
|
||||||
|
}
|
||||||
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTxContext sets the current transaction hash and index which are
|
// SetTxContext sets the current transaction hash and index which are
|
||||||
@@ -1052,7 +1118,9 @@ func (s *StateDB) handleDestruction() (map[common.Hash]*accountDelete, []*trieno
|
|||||||
buf = crypto.NewKeccakState()
|
buf = crypto.NewKeccakState()
|
||||||
deletes = make(map[common.Hash]*accountDelete)
|
deletes = make(map[common.Hash]*accountDelete)
|
||||||
)
|
)
|
||||||
for addr, prev := range s.stateObjectsDestruct {
|
for addr, prevObj := range s.stateObjectsDestruct {
|
||||||
|
prev := prevObj.origin
|
||||||
|
|
||||||
// The account was non-existent, and it's marked as destructed in the scope
|
// The account was non-existent, and it's marked as destructed in the scope
|
||||||
// of block. It can be either case (a) or (b) and will be interpreted as
|
// of block. It can be either case (a) or (b) and will be interpreted as
|
||||||
// null->null state transition.
|
// null->null state transition.
|
||||||
@@ -1171,10 +1239,7 @@ func (s *StateDB) commit(deleteEmptyObjects bool) (*stateUpdate, error) {
|
|||||||
// code didn't anticipate for.
|
// code didn't anticipate for.
|
||||||
workers.Go(func() error {
|
workers.Go(func() error {
|
||||||
// Write the account trie changes, measuring the amount of wasted time
|
// Write the account trie changes, measuring the amount of wasted time
|
||||||
newroot, set, err := s.trie.Commit(true)
|
newroot, set := s.trie.Commit(true)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
root = newroot
|
root = newroot
|
||||||
|
|
||||||
if err := merge(set); err != nil {
|
if err := merge(set); err != nil {
|
||||||
@@ -1234,7 +1299,7 @@ func (s *StateDB) commit(deleteEmptyObjects bool) (*stateUpdate, error) {
|
|||||||
|
|
||||||
// Clear all internal flags and update state root at the end.
|
// Clear all internal flags and update state root at the end.
|
||||||
s.mutations = make(map[common.Address]*mutation)
|
s.mutations = make(map[common.Address]*mutation)
|
||||||
s.stateObjectsDestruct = make(map[common.Address]*types.StateAccount)
|
s.stateObjectsDestruct = make(map[common.Address]*stateObject)
|
||||||
|
|
||||||
origin := s.originalRoot
|
origin := s.originalRoot
|
||||||
s.originalRoot = root
|
s.originalRoot = root
|
||||||
@@ -1407,3 +1472,8 @@ func (s *StateDB) markUpdate(addr common.Address) {
|
|||||||
func (s *StateDB) PointCache() *utils.PointCache {
|
func (s *StateDB) PointCache() *utils.PointCache {
|
||||||
return s.db.PointCache()
|
return s.db.PointCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Witness retrieves the current state witness being collected.
|
||||||
|
func (s *StateDB) Witness() *stateless.Witness {
|
||||||
|
return s.witness
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,31 +44,49 @@ type triePrefetcher struct {
|
|||||||
root common.Hash // Root hash of the account trie for metrics
|
root common.Hash // Root hash of the account trie for metrics
|
||||||
fetchers map[string]*subfetcher // Subfetchers for each trie
|
fetchers map[string]*subfetcher // Subfetchers for each trie
|
||||||
term chan struct{} // Channel to signal interruption
|
term chan struct{} // Channel to signal interruption
|
||||||
|
noreads bool // Whether to ignore state-read-only prefetch requests
|
||||||
|
|
||||||
deliveryMissMeter metrics.Meter
|
deliveryMissMeter metrics.Meter
|
||||||
accountLoadMeter metrics.Meter
|
|
||||||
accountDupMeter metrics.Meter
|
accountLoadReadMeter metrics.Meter
|
||||||
accountWasteMeter metrics.Meter
|
accountLoadWriteMeter metrics.Meter
|
||||||
storageLoadMeter metrics.Meter
|
accountDupReadMeter metrics.Meter
|
||||||
storageDupMeter metrics.Meter
|
accountDupWriteMeter metrics.Meter
|
||||||
storageWasteMeter metrics.Meter
|
accountDupCrossMeter metrics.Meter
|
||||||
|
accountWasteMeter metrics.Meter
|
||||||
|
|
||||||
|
storageLoadReadMeter metrics.Meter
|
||||||
|
storageLoadWriteMeter metrics.Meter
|
||||||
|
storageDupReadMeter metrics.Meter
|
||||||
|
storageDupWriteMeter metrics.Meter
|
||||||
|
storageDupCrossMeter metrics.Meter
|
||||||
|
storageWasteMeter metrics.Meter
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTriePrefetcher(db Database, root common.Hash, namespace string) *triePrefetcher {
|
func newTriePrefetcher(db Database, root common.Hash, namespace string, noreads bool) *triePrefetcher {
|
||||||
prefix := triePrefetchMetricsPrefix + namespace
|
prefix := triePrefetchMetricsPrefix + namespace
|
||||||
return &triePrefetcher{
|
return &triePrefetcher{
|
||||||
db: db,
|
db: db,
|
||||||
root: root,
|
root: root,
|
||||||
fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map
|
fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map
|
||||||
term: make(chan struct{}),
|
term: make(chan struct{}),
|
||||||
|
noreads: noreads,
|
||||||
|
|
||||||
deliveryMissMeter: metrics.GetOrRegisterMeter(prefix+"/deliverymiss", nil),
|
deliveryMissMeter: metrics.GetOrRegisterMeter(prefix+"/deliverymiss", nil),
|
||||||
accountLoadMeter: metrics.GetOrRegisterMeter(prefix+"/account/load", nil),
|
|
||||||
accountDupMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup", nil),
|
accountLoadReadMeter: metrics.GetOrRegisterMeter(prefix+"/account/load/read", nil),
|
||||||
accountWasteMeter: metrics.GetOrRegisterMeter(prefix+"/account/waste", nil),
|
accountLoadWriteMeter: metrics.GetOrRegisterMeter(prefix+"/account/load/write", nil),
|
||||||
storageLoadMeter: metrics.GetOrRegisterMeter(prefix+"/storage/load", nil),
|
accountDupReadMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup/read", nil),
|
||||||
storageDupMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup", nil),
|
accountDupWriteMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup/write", nil),
|
||||||
storageWasteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/waste", nil),
|
accountDupCrossMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup/cross", nil),
|
||||||
|
accountWasteMeter: metrics.GetOrRegisterMeter(prefix+"/account/waste", nil),
|
||||||
|
|
||||||
|
storageLoadReadMeter: metrics.GetOrRegisterMeter(prefix+"/storage/load/read", nil),
|
||||||
|
storageLoadWriteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/load/write", nil),
|
||||||
|
storageDupReadMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup/read", nil),
|
||||||
|
storageDupWriteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup/write", nil),
|
||||||
|
storageDupCrossMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup/cross", nil),
|
||||||
|
storageWasteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/waste", nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,19 +116,31 @@ func (p *triePrefetcher) report() {
|
|||||||
fetcher.wait() // ensure the fetcher's idle before poking in its internals
|
fetcher.wait() // ensure the fetcher's idle before poking in its internals
|
||||||
|
|
||||||
if fetcher.root == p.root {
|
if fetcher.root == p.root {
|
||||||
p.accountLoadMeter.Mark(int64(len(fetcher.seen)))
|
p.accountLoadReadMeter.Mark(int64(len(fetcher.seenRead)))
|
||||||
p.accountDupMeter.Mark(int64(fetcher.dups))
|
p.accountLoadWriteMeter.Mark(int64(len(fetcher.seenWrite)))
|
||||||
|
|
||||||
|
p.accountDupReadMeter.Mark(int64(fetcher.dupsRead))
|
||||||
|
p.accountDupWriteMeter.Mark(int64(fetcher.dupsWrite))
|
||||||
|
p.accountDupCrossMeter.Mark(int64(fetcher.dupsCross))
|
||||||
|
|
||||||
for _, key := range fetcher.used {
|
for _, key := range fetcher.used {
|
||||||
delete(fetcher.seen, string(key))
|
delete(fetcher.seenRead, string(key))
|
||||||
|
delete(fetcher.seenWrite, string(key))
|
||||||
}
|
}
|
||||||
p.accountWasteMeter.Mark(int64(len(fetcher.seen)))
|
p.accountWasteMeter.Mark(int64(len(fetcher.seenRead) + len(fetcher.seenWrite)))
|
||||||
} else {
|
} else {
|
||||||
p.storageLoadMeter.Mark(int64(len(fetcher.seen)))
|
p.storageLoadReadMeter.Mark(int64(len(fetcher.seenRead)))
|
||||||
p.storageDupMeter.Mark(int64(fetcher.dups))
|
p.storageLoadWriteMeter.Mark(int64(len(fetcher.seenWrite)))
|
||||||
|
|
||||||
|
p.storageDupReadMeter.Mark(int64(fetcher.dupsRead))
|
||||||
|
p.storageDupWriteMeter.Mark(int64(fetcher.dupsWrite))
|
||||||
|
p.storageDupCrossMeter.Mark(int64(fetcher.dupsCross))
|
||||||
|
|
||||||
for _, key := range fetcher.used {
|
for _, key := range fetcher.used {
|
||||||
delete(fetcher.seen, string(key))
|
delete(fetcher.seenRead, string(key))
|
||||||
|
delete(fetcher.seenWrite, string(key))
|
||||||
}
|
}
|
||||||
p.storageWasteMeter.Mark(int64(len(fetcher.seen)))
|
p.storageWasteMeter.Mark(int64(len(fetcher.seenRead) + len(fetcher.seenWrite)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +156,11 @@ func (p *triePrefetcher) report() {
|
|||||||
// upon the same contract, the parameters invoking this method may be
|
// upon the same contract, the parameters invoking this method may be
|
||||||
// repeated.
|
// repeated.
|
||||||
// 2. Finalize of the main account trie. This happens only once per block.
|
// 2. Finalize of the main account trie. This happens only once per block.
|
||||||
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte) error {
|
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte, read bool) error {
|
||||||
|
// If the state item is only being read, but reads are disabled, return
|
||||||
|
if read && p.noreads {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Ensure the subfetcher is still alive
|
// Ensure the subfetcher is still alive
|
||||||
select {
|
select {
|
||||||
case <-p.term:
|
case <-p.term:
|
||||||
@@ -139,7 +173,7 @@ func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr comm
|
|||||||
fetcher = newSubfetcher(p.db, p.root, owner, root, addr)
|
fetcher = newSubfetcher(p.db, p.root, owner, root, addr)
|
||||||
p.fetchers[id] = fetcher
|
p.fetchers[id] = fetcher
|
||||||
}
|
}
|
||||||
return fetcher.schedule(keys)
|
return fetcher.schedule(keys, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
// trie returns the trie matching the root hash, blocking until the fetcher of
|
// trie returns the trie matching the root hash, blocking until the fetcher of
|
||||||
@@ -186,38 +220,51 @@ type subfetcher struct {
|
|||||||
addr common.Address // Address of the account that the trie belongs to
|
addr common.Address // Address of the account that the trie belongs to
|
||||||
trie Trie // Trie being populated with nodes
|
trie Trie // Trie being populated with nodes
|
||||||
|
|
||||||
tasks [][]byte // Items queued up for retrieval
|
tasks []*subfetcherTask // Items queued up for retrieval
|
||||||
lock sync.Mutex // Lock protecting the task queue
|
lock sync.Mutex // Lock protecting the task queue
|
||||||
|
|
||||||
wake chan struct{} // Wake channel if a new task is scheduled
|
wake chan struct{} // Wake channel if a new task is scheduled
|
||||||
stop chan struct{} // Channel to interrupt processing
|
stop chan struct{} // Channel to interrupt processing
|
||||||
term chan struct{} // Channel to signal interruption
|
term chan struct{} // Channel to signal interruption
|
||||||
|
|
||||||
seen map[string]struct{} // Tracks the entries already loaded
|
seenRead map[string]struct{} // Tracks the entries already loaded via read operations
|
||||||
dups int // Number of duplicate preload tasks
|
seenWrite map[string]struct{} // Tracks the entries already loaded via write operations
|
||||||
used [][]byte // Tracks the entries used in the end
|
|
||||||
|
dupsRead int // Number of duplicate preload tasks via reads only
|
||||||
|
dupsWrite int // Number of duplicate preload tasks via writes only
|
||||||
|
dupsCross int // Number of duplicate preload tasks via read-write-crosses
|
||||||
|
|
||||||
|
used [][]byte // Tracks the entries used in the end
|
||||||
|
}
|
||||||
|
|
||||||
|
// subfetcherTask is a trie path to prefetch, tagged with whether it originates
|
||||||
|
// from a read or a write request.
|
||||||
|
type subfetcherTask struct {
|
||||||
|
read bool
|
||||||
|
key []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// newSubfetcher creates a goroutine to prefetch state items belonging to a
|
// newSubfetcher creates a goroutine to prefetch state items belonging to a
|
||||||
// particular root hash.
|
// particular root hash.
|
||||||
func newSubfetcher(db Database, state common.Hash, owner common.Hash, root common.Hash, addr common.Address) *subfetcher {
|
func newSubfetcher(db Database, state common.Hash, owner common.Hash, root common.Hash, addr common.Address) *subfetcher {
|
||||||
sf := &subfetcher{
|
sf := &subfetcher{
|
||||||
db: db,
|
db: db,
|
||||||
state: state,
|
state: state,
|
||||||
owner: owner,
|
owner: owner,
|
||||||
root: root,
|
root: root,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
wake: make(chan struct{}, 1),
|
wake: make(chan struct{}, 1),
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
term: make(chan struct{}),
|
term: make(chan struct{}),
|
||||||
seen: make(map[string]struct{}),
|
seenRead: make(map[string]struct{}),
|
||||||
|
seenWrite: make(map[string]struct{}),
|
||||||
}
|
}
|
||||||
go sf.loop()
|
go sf.loop()
|
||||||
return sf
|
return sf
|
||||||
}
|
}
|
||||||
|
|
||||||
// schedule adds a batch of trie keys to the queue to prefetch.
|
// schedule adds a batch of trie keys to the queue to prefetch.
|
||||||
func (sf *subfetcher) schedule(keys [][]byte) error {
|
func (sf *subfetcher) schedule(keys [][]byte, read bool) error {
|
||||||
// Ensure the subfetcher is still alive
|
// Ensure the subfetcher is still alive
|
||||||
select {
|
select {
|
||||||
case <-sf.term:
|
case <-sf.term:
|
||||||
@@ -226,7 +273,10 @@ func (sf *subfetcher) schedule(keys [][]byte) error {
|
|||||||
}
|
}
|
||||||
// Append the tasks to the current queue
|
// Append the tasks to the current queue
|
||||||
sf.lock.Lock()
|
sf.lock.Lock()
|
||||||
sf.tasks = append(sf.tasks, keys...)
|
for _, key := range keys {
|
||||||
|
key := key // closure for the append below
|
||||||
|
sf.tasks = append(sf.tasks, &subfetcherTask{read: read, key: key})
|
||||||
|
}
|
||||||
sf.lock.Unlock()
|
sf.lock.Unlock()
|
||||||
|
|
||||||
// Notify the background thread to execute scheduled tasks
|
// Notify the background thread to execute scheduled tasks
|
||||||
@@ -303,16 +353,36 @@ func (sf *subfetcher) loop() {
|
|||||||
sf.lock.Unlock()
|
sf.lock.Unlock()
|
||||||
|
|
||||||
for _, task := range tasks {
|
for _, task := range tasks {
|
||||||
if _, ok := sf.seen[string(task)]; ok {
|
key := string(task.key)
|
||||||
sf.dups++
|
if task.read {
|
||||||
continue
|
if _, ok := sf.seenRead[key]; ok {
|
||||||
}
|
sf.dupsRead++
|
||||||
if len(task) == common.AddressLength {
|
continue
|
||||||
sf.trie.GetAccount(common.BytesToAddress(task))
|
}
|
||||||
|
if _, ok := sf.seenWrite[key]; ok {
|
||||||
|
sf.dupsCross++
|
||||||
|
continue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sf.trie.GetStorage(sf.addr, task)
|
if _, ok := sf.seenRead[key]; ok {
|
||||||
|
sf.dupsCross++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := sf.seenWrite[key]; ok {
|
||||||
|
sf.dupsWrite++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(task.key) == common.AddressLength {
|
||||||
|
sf.trie.GetAccount(common.BytesToAddress(task.key))
|
||||||
|
} else {
|
||||||
|
sf.trie.GetStorage(sf.addr, task.key)
|
||||||
|
}
|
||||||
|
if task.read {
|
||||||
|
sf.seenRead[key] = struct{}{}
|
||||||
|
} else {
|
||||||
|
sf.seenWrite[key] = struct{}{}
|
||||||
}
|
}
|
||||||
sf.seen[string(task)] = struct{}{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-sf.stop:
|
case <-sf.stop:
|
||||||
|
|||||||
@@ -47,15 +47,15 @@ func filledStateDB() *StateDB {
|
|||||||
|
|
||||||
func TestUseAfterTerminate(t *testing.T) {
|
func TestUseAfterTerminate(t *testing.T) {
|
||||||
db := filledStateDB()
|
db := filledStateDB()
|
||||||
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "")
|
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "", true)
|
||||||
skey := common.HexToHash("aaa")
|
skey := common.HexToHash("aaa")
|
||||||
|
|
||||||
if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}); err != nil {
|
if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}, false); err != nil {
|
||||||
t.Errorf("Prefetch failed before terminate: %v", err)
|
t.Errorf("Prefetch failed before terminate: %v", err)
|
||||||
}
|
}
|
||||||
prefetcher.terminate(false)
|
prefetcher.terminate(false)
|
||||||
|
|
||||||
if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}); err == nil {
|
if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}, false); err == nil {
|
||||||
t.Errorf("Prefetch succeeded after terminate: %v", err)
|
t.Errorf("Prefetch succeeded after terminate: %v", err)
|
||||||
}
|
}
|
||||||
if tr := prefetcher.trie(common.Hash{}, db.originalRoot); tr == nil {
|
if tr := prefetcher.trie(common.Hash{}, db.originalRoot); tr == nil {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package core
|
|||||||
import (
|
import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
|
||||||
"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/core/vm"
|
||||||
@@ -31,16 +30,14 @@ import (
|
|||||||
// data from disk before the main block processor start executing.
|
// data from disk before the main block processor start executing.
|
||||||
type statePrefetcher struct {
|
type statePrefetcher struct {
|
||||||
config *params.ChainConfig // Chain configuration options
|
config *params.ChainConfig // Chain configuration options
|
||||||
bc *BlockChain // Canonical block chain
|
chain *HeaderChain // Canonical block chain
|
||||||
engine consensus.Engine // Consensus engine used for block rewards
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newStatePrefetcher initialises a new statePrefetcher.
|
// newStatePrefetcher initialises a new statePrefetcher.
|
||||||
func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *statePrefetcher {
|
func newStatePrefetcher(config *params.ChainConfig, chain *HeaderChain) *statePrefetcher {
|
||||||
return &statePrefetcher{
|
return &statePrefetcher{
|
||||||
config: config,
|
config: config,
|
||||||
bc: bc,
|
chain: chain,
|
||||||
engine: engine,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +48,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
|
|||||||
var (
|
var (
|
||||||
header = block.Header()
|
header = block.Header()
|
||||||
gaspool = new(GasPool).AddGas(block.GasLimit())
|
gaspool = new(GasPool).AddGas(block.GasLimit())
|
||||||
blockContext = NewEVMBlockContext(header, p.bc, nil)
|
blockContext = NewEVMBlockContext(header, p.chain, nil)
|
||||||
evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
|
evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
|
||||||
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"math/big"
|
"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/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
"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"
|
||||||
@@ -37,16 +36,14 @@ import (
|
|||||||
// StateProcessor implements Processor.
|
// StateProcessor implements Processor.
|
||||||
type StateProcessor struct {
|
type StateProcessor struct {
|
||||||
config *params.ChainConfig // Chain configuration options
|
config *params.ChainConfig // Chain configuration options
|
||||||
bc *BlockChain // Canonical block chain
|
chain *HeaderChain // Canonical header chain
|
||||||
engine consensus.Engine // Consensus engine used for block rewards
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStateProcessor initialises a new StateProcessor.
|
// NewStateProcessor initialises a new StateProcessor.
|
||||||
func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *StateProcessor {
|
func NewStateProcessor(config *params.ChainConfig, chain *HeaderChain) *StateProcessor {
|
||||||
return &StateProcessor{
|
return &StateProcessor{
|
||||||
config: config,
|
config: config,
|
||||||
bc: bc,
|
chain: chain,
|
||||||
engine: engine,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,10 +70,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
context = NewEVMBlockContext(header, p.bc, nil)
|
context vm.BlockContext
|
||||||
vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
|
||||||
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||||
)
|
)
|
||||||
|
context = NewEVMBlockContext(header, p.chain, nil)
|
||||||
|
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
||||||
}
|
}
|
||||||
@@ -101,7 +99,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||||||
return nil, nil, 0, errors.New("withdrawals before shanghai")
|
return nil, nil, 0, errors.New("withdrawals before shanghai")
|
||||||
}
|
}
|
||||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||||
p.engine.Finalize(p.bc, header, statedb, block.Body())
|
p.chain.engine.Finalize(p.chain, header, statedb, block.Body())
|
||||||
|
|
||||||
return receipts, allLogs, *usedGas, nil
|
return receipts, allLogs, *usedGas, nil
|
||||||
}
|
}
|
||||||
|
|||||||
73
core/stateless.go
Normal file
73
core/stateless.go
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/stateless"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExecuteStateless runs a stateless execution based on a witness, verifies
|
||||||
|
// everything it can locally and returns the two computed fields that need the
|
||||||
|
// other side to explicitly check.
|
||||||
|
//
|
||||||
|
// This method is a bit of a sore thumb here, but:
|
||||||
|
// - It cannot be placed in core/stateless, because state.New prodces a circular dep
|
||||||
|
// - It cannot be placed outside of core, because it needs to construct a dud headerchain
|
||||||
|
//
|
||||||
|
// TODO(karalabe): Would be nice to resolve both issues above somehow and move it.
|
||||||
|
func ExecuteStateless(config *params.ChainConfig, witness *stateless.Witness) (common.Hash, common.Hash, error) {
|
||||||
|
// Create and populate the state database to serve as the stateless backend
|
||||||
|
memdb := witness.MakeHashDB()
|
||||||
|
|
||||||
|
db, err := state.New(witness.Root(), state.NewDatabaseWithConfig(memdb, triedb.HashDefaults), nil)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, common.Hash{}, err
|
||||||
|
}
|
||||||
|
// Create a blockchain that is idle, but can be used to access headers through
|
||||||
|
chain := &HeaderChain{
|
||||||
|
config: config,
|
||||||
|
chainDb: memdb,
|
||||||
|
headerCache: lru.NewCache[common.Hash, *types.Header](256),
|
||||||
|
engine: beacon.New(ethash.NewFaker()),
|
||||||
|
}
|
||||||
|
processor := NewStateProcessor(config, chain)
|
||||||
|
validator := NewBlockValidator(config, nil) // No chain, we only validate the state, not the block
|
||||||
|
|
||||||
|
// Run the stateless blocks processing and self-validate certain fields
|
||||||
|
receipts, _, usedGas, err := processor.Process(witness.Block, db, vm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, common.Hash{}, err
|
||||||
|
}
|
||||||
|
if err = validator.ValidateState(witness.Block, db, receipts, usedGas, true); err != nil {
|
||||||
|
return common.Hash{}, common.Hash{}, err
|
||||||
|
}
|
||||||
|
// Almost everything validated, but receipt and state root needs to be returned
|
||||||
|
receiptRoot := types.DeriveSha(receipts, trie.NewStackTrie(nil))
|
||||||
|
stateRoot := db.IntermediateRoot(config.IsEIP158(witness.Block.Number()))
|
||||||
|
|
||||||
|
return receiptRoot, stateRoot, nil
|
||||||
|
}
|
||||||
60
core/stateless/database.go
Normal file
60
core/stateless/database.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package stateless
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MakeHashDB imports tries, codes and block hashes from a witness into a new
|
||||||
|
// hash-based memory db. We could eventually rewrite this into a pathdb, but
|
||||||
|
// simple is better for now.
|
||||||
|
func (w *Witness) MakeHashDB() ethdb.Database {
|
||||||
|
var (
|
||||||
|
memdb = rawdb.NewMemoryDatabase()
|
||||||
|
hasher = crypto.NewKeccakState()
|
||||||
|
hash = make([]byte, 32)
|
||||||
|
)
|
||||||
|
// Inject all the "block hashes" (i.e. headers) into the ephemeral database
|
||||||
|
for _, header := range w.Headers {
|
||||||
|
rawdb.WriteHeader(memdb, header)
|
||||||
|
}
|
||||||
|
// Inject all the bytecodes into the ephemeral database
|
||||||
|
for code := range w.Codes {
|
||||||
|
blob := []byte(code)
|
||||||
|
|
||||||
|
hasher.Reset()
|
||||||
|
hasher.Write(blob)
|
||||||
|
hasher.Read(hash)
|
||||||
|
|
||||||
|
rawdb.WriteCode(memdb, common.BytesToHash(hash), blob)
|
||||||
|
}
|
||||||
|
// Inject all the MPT trie nodes into the ephemeral database
|
||||||
|
for node := range w.State {
|
||||||
|
blob := []byte(node)
|
||||||
|
|
||||||
|
hasher.Reset()
|
||||||
|
hasher.Write(blob)
|
||||||
|
hasher.Read(hash)
|
||||||
|
|
||||||
|
rawdb.WriteLegacyTrieNode(memdb, common.BytesToHash(hash), blob)
|
||||||
|
}
|
||||||
|
return memdb
|
||||||
|
}
|
||||||
129
core/stateless/encoding.go
Normal file
129
core/stateless/encoding.go
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package stateless
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run github.com/fjl/gencodec -type extWitness -field-override extWitnessMarshalling -out gen_encoding_json.go
|
||||||
|
|
||||||
|
// toExtWitness converts our internal witness representation to the consensus one.
|
||||||
|
func (w *Witness) toExtWitness() *extWitness {
|
||||||
|
ext := &extWitness{
|
||||||
|
Block: w.Block,
|
||||||
|
Headers: w.Headers,
|
||||||
|
}
|
||||||
|
ext.Codes = make([][]byte, 0, len(w.Codes))
|
||||||
|
for code := range w.Codes {
|
||||||
|
ext.Codes = append(ext.Codes, []byte(code))
|
||||||
|
}
|
||||||
|
slices.SortFunc(ext.Codes, bytes.Compare)
|
||||||
|
|
||||||
|
ext.State = make([][]byte, 0, len(w.State))
|
||||||
|
for node := range w.State {
|
||||||
|
ext.State = append(ext.State, []byte(node))
|
||||||
|
}
|
||||||
|
slices.SortFunc(ext.State, bytes.Compare)
|
||||||
|
return ext
|
||||||
|
}
|
||||||
|
|
||||||
|
// fromExtWitness converts the consensus witness format into our internal one.
|
||||||
|
func (w *Witness) fromExtWitness(ext *extWitness) error {
|
||||||
|
w.Block, w.Headers = ext.Block, ext.Headers
|
||||||
|
|
||||||
|
w.Codes = make(map[string]struct{}, len(ext.Codes))
|
||||||
|
for _, code := range ext.Codes {
|
||||||
|
w.Codes[string(code)] = struct{}{}
|
||||||
|
}
|
||||||
|
w.State = make(map[string]struct{}, len(ext.State))
|
||||||
|
for _, node := range ext.State {
|
||||||
|
w.State[string(node)] = struct{}{}
|
||||||
|
}
|
||||||
|
return w.sanitize()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON marshals a witness as JSON.
|
||||||
|
func (w *Witness) MarshalJSON() ([]byte, error) {
|
||||||
|
return w.toExtWitness().MarshalJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeRLP serializes a witness as RLP.
|
||||||
|
func (w *Witness) EncodeRLP(wr io.Writer) error {
|
||||||
|
return rlp.Encode(wr, w.toExtWitness())
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
|
func (w *Witness) UnmarshalJSON(input []byte) error {
|
||||||
|
var ext extWitness
|
||||||
|
if err := ext.UnmarshalJSON(input); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return w.fromExtWitness(&ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeRLP decodes a witness from RLP.
|
||||||
|
func (w *Witness) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
var ext extWitness
|
||||||
|
if err := s.Decode(&ext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return w.fromExtWitness(&ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanitize checks for some mandatory fields in the witness after decoding so
|
||||||
|
// the rest of the code can assume invariants and doesn't have to deal with
|
||||||
|
// corrupted data.
|
||||||
|
func (w *Witness) sanitize() error {
|
||||||
|
// Verify that the "parent" header (i.e. index 0) is available, and is the
|
||||||
|
// true parent of the block-to-be executed, since we use that to link the
|
||||||
|
// current block to the pre-state.
|
||||||
|
if len(w.Headers) == 0 {
|
||||||
|
return errors.New("parent header (for pre-root hash) missing")
|
||||||
|
}
|
||||||
|
for i, header := range w.Headers {
|
||||||
|
if header == nil {
|
||||||
|
return fmt.Errorf("witness header nil at position %d", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if w.Headers[0].Hash() != w.Block.ParentHash() {
|
||||||
|
return fmt.Errorf("parent hash different: witness %v, block parent %v", w.Headers[0].Hash(), w.Block.ParentHash())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// extWitness is a witness RLP encoding for transferring across clients.
|
||||||
|
type extWitness struct {
|
||||||
|
Block *types.Block `json:"block" gencodec:"required"`
|
||||||
|
Headers []*types.Header `json:"headers" gencodec:"required"`
|
||||||
|
Codes [][]byte `json:"codes"`
|
||||||
|
State [][]byte `json:"state"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// extWitnessMarshalling defines the hex marshalling types for a witness.
|
||||||
|
type extWitnessMarshalling struct {
|
||||||
|
Codes []hexutil.Bytes
|
||||||
|
State []hexutil.Bytes
|
||||||
|
}
|
||||||
74
core/stateless/gen_encoding_json.go
Normal file
74
core/stateless/gen_encoding_json.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package stateless
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*extWitnessMarshalling)(nil)
|
||||||
|
|
||||||
|
// MarshalJSON marshals as JSON.
|
||||||
|
func (e extWitness) MarshalJSON() ([]byte, error) {
|
||||||
|
type extWitness struct {
|
||||||
|
Block *types.Block `json:"block" gencodec:"required"`
|
||||||
|
Headers []*types.Header `json:"headers" gencodec:"required"`
|
||||||
|
Codes []hexutil.Bytes `json:"codes"`
|
||||||
|
State []hexutil.Bytes `json:"state"`
|
||||||
|
}
|
||||||
|
var enc extWitness
|
||||||
|
enc.Block = e.Block
|
||||||
|
enc.Headers = e.Headers
|
||||||
|
if e.Codes != nil {
|
||||||
|
enc.Codes = make([]hexutil.Bytes, len(e.Codes))
|
||||||
|
for k, v := range e.Codes {
|
||||||
|
enc.Codes[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e.State != nil {
|
||||||
|
enc.State = make([]hexutil.Bytes, len(e.State))
|
||||||
|
for k, v := range e.State {
|
||||||
|
enc.State[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
|
func (e *extWitness) UnmarshalJSON(input []byte) error {
|
||||||
|
type extWitness struct {
|
||||||
|
Block *types.Block `json:"block" gencodec:"required"`
|
||||||
|
Headers []*types.Header `json:"headers" gencodec:"required"`
|
||||||
|
Codes []hexutil.Bytes `json:"codes"`
|
||||||
|
State []hexutil.Bytes `json:"state"`
|
||||||
|
}
|
||||||
|
var dec extWitness
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.Block == nil {
|
||||||
|
return errors.New("missing required field 'block' for extWitness")
|
||||||
|
}
|
||||||
|
e.Block = dec.Block
|
||||||
|
if dec.Headers == nil {
|
||||||
|
return errors.New("missing required field 'headers' for extWitness")
|
||||||
|
}
|
||||||
|
e.Headers = dec.Headers
|
||||||
|
if dec.Codes != nil {
|
||||||
|
e.Codes = make([][]byte, len(dec.Codes))
|
||||||
|
for k, v := range dec.Codes {
|
||||||
|
e.Codes[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dec.State != nil {
|
||||||
|
e.State = make([][]byte, len(dec.State))
|
||||||
|
for k, v := range dec.State {
|
||||||
|
e.State[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
159
core/stateless/witness.go
Normal file
159
core/stateless/witness.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package stateless
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"maps"
|
||||||
|
"slices"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HeaderReader is an interface to pull in headers in place of block hashes for
|
||||||
|
// the witness.
|
||||||
|
type HeaderReader interface {
|
||||||
|
// GetHeader retrieves a block header from the database by hash and number,
|
||||||
|
GetHeader(hash common.Hash, number uint64) *types.Header
|
||||||
|
}
|
||||||
|
|
||||||
|
// Witness encompasses a block, state and any other chain data required to apply
|
||||||
|
// a set of transactions and derive a post state/receipt root.
|
||||||
|
type Witness struct {
|
||||||
|
Block *types.Block // Current block with rootHash and receiptHash zeroed out
|
||||||
|
Headers []*types.Header // Past headers in reverse order (0=parent, 1=parent's-parent, etc). First *must* be set.
|
||||||
|
Codes map[string]struct{} // Set of bytecodes ran or accessed
|
||||||
|
State map[string]struct{} // Set of MPT state trie nodes (account and storage together)
|
||||||
|
|
||||||
|
chain HeaderReader // Chain reader to convert block hash ops to header proofs
|
||||||
|
lock sync.Mutex // Lock to allow concurrent state insertions
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWitness creates an empty witness ready for population.
|
||||||
|
func NewWitness(chain HeaderReader, block *types.Block) (*Witness, error) {
|
||||||
|
// Zero out the result fields to avoid accidentally sending them to the verifier
|
||||||
|
header := block.Header()
|
||||||
|
header.Root = common.Hash{}
|
||||||
|
header.ReceiptHash = common.Hash{}
|
||||||
|
|
||||||
|
// Retrieve the parent header, which will *always* be included to act as a
|
||||||
|
// trustless pre-root hash container
|
||||||
|
parent := chain.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
||||||
|
if parent == nil {
|
||||||
|
return nil, errors.New("failed to retrieve parent header")
|
||||||
|
}
|
||||||
|
// Create the wtness with a reconstructed gutted out block
|
||||||
|
return &Witness{
|
||||||
|
Block: types.NewBlockWithHeader(header).WithBody(*block.Body()),
|
||||||
|
Codes: make(map[string]struct{}),
|
||||||
|
State: make(map[string]struct{}),
|
||||||
|
Headers: []*types.Header{parent},
|
||||||
|
chain: chain,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddBlockHash adds a "blockhash" to the witness with the designated offset from
|
||||||
|
// chain head. Under the hood, this method actually pulls in enough headers from
|
||||||
|
// the chain to cover the block being added.
|
||||||
|
func (w *Witness) AddBlockHash(number uint64) {
|
||||||
|
// Keep pulling in headers until this hash is populated
|
||||||
|
for int(w.Block.NumberU64()-number) > len(w.Headers) {
|
||||||
|
tail := w.Block.Header()
|
||||||
|
if len(w.Headers) > 0 {
|
||||||
|
tail = w.Headers[len(w.Headers)-1]
|
||||||
|
}
|
||||||
|
w.Headers = append(w.Headers, w.chain.GetHeader(tail.ParentHash, tail.Number.Uint64()-1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCode adds a bytecode blob to the witness.
|
||||||
|
func (w *Witness) AddCode(code []byte) {
|
||||||
|
if len(code) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Codes[string(code)] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddState inserts a batch of MPT trie nodes into the witness.
|
||||||
|
func (w *Witness) AddState(nodes map[string]struct{}) {
|
||||||
|
if len(nodes) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.lock.Lock()
|
||||||
|
defer w.lock.Unlock()
|
||||||
|
|
||||||
|
for node := range nodes {
|
||||||
|
w.State[node] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy deep-copies the witness object. Witness.Block isn't deep-copied as it
|
||||||
|
// is never mutated by Witness
|
||||||
|
func (w *Witness) Copy() *Witness {
|
||||||
|
return &Witness{
|
||||||
|
Block: w.Block,
|
||||||
|
Headers: slices.Clone(w.Headers),
|
||||||
|
Codes: maps.Clone(w.Codes),
|
||||||
|
State: maps.Clone(w.State),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String prints a human-readable summary containing the total size of the
|
||||||
|
// witness and the sizes of the underlying components
|
||||||
|
func (w *Witness) String() string {
|
||||||
|
blob, _ := rlp.EncodeToBytes(w)
|
||||||
|
bytesTotal := len(blob)
|
||||||
|
|
||||||
|
blob, _ = rlp.EncodeToBytes(w.Block)
|
||||||
|
bytesBlock := len(blob)
|
||||||
|
|
||||||
|
bytesHeaders := 0
|
||||||
|
for _, header := range w.Headers {
|
||||||
|
blob, _ = rlp.EncodeToBytes(header)
|
||||||
|
bytesHeaders += len(blob)
|
||||||
|
}
|
||||||
|
bytesCodes := 0
|
||||||
|
for code := range w.Codes {
|
||||||
|
bytesCodes += len(code)
|
||||||
|
}
|
||||||
|
bytesState := 0
|
||||||
|
for node := range w.State {
|
||||||
|
bytesState += len(node)
|
||||||
|
}
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
|
fmt.Fprintf(buf, "Witness #%d: %v\n", w.Block.Number(), common.StorageSize(bytesTotal))
|
||||||
|
fmt.Fprintf(buf, " block (%4d txs): %10v\n", len(w.Block.Transactions()), common.StorageSize(bytesBlock))
|
||||||
|
fmt.Fprintf(buf, "%4d headers: %10v\n", len(w.Headers), common.StorageSize(bytesHeaders))
|
||||||
|
fmt.Fprintf(buf, "%4d trie nodes: %10v\n", len(w.State), common.StorageSize(bytesState))
|
||||||
|
fmt.Fprintf(buf, "%4d codes: %10v\n", len(w.Codes), common.StorageSize(bytesCodes))
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root returns the pre-state root from the first header.
|
||||||
|
//
|
||||||
|
// Note, this method will panic in case of a bad witness (but RLP decoding will
|
||||||
|
// sanitize it and fail before that).
|
||||||
|
func (w *Witness) Root() common.Hash {
|
||||||
|
return w.Headers[0].Root
|
||||||
|
}
|
||||||
@@ -199,7 +199,7 @@ type Hooks struct {
|
|||||||
// for tracing and reporting.
|
// for tracing and reporting.
|
||||||
type BalanceChangeReason byte
|
type BalanceChangeReason byte
|
||||||
|
|
||||||
//go:generate stringer -type=BalanceChangeReason -output gen_balance_change_reason_stringer.go
|
//go:generate go run golang.org/x/tools/cmd/stringer -type=BalanceChangeReason -output gen_balance_change_reason_stringer.go
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BalanceChangeUnspecified BalanceChangeReason = 0
|
BalanceChangeUnspecified BalanceChangeReason = 0
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserve txpool.Addres
|
|||||||
if p.head.ExcessBlobGas != nil {
|
if p.head.ExcessBlobGas != nil {
|
||||||
blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(*p.head.ExcessBlobGas))
|
blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(*p.head.ExcessBlobGas))
|
||||||
}
|
}
|
||||||
p.evict = newPriceHeap(basefee, blobfee, &p.index)
|
p.evict = newPriceHeap(basefee, blobfee, p.index)
|
||||||
|
|
||||||
// Pool initialized, attach the blob limbo to it to track blobs included
|
// Pool initialized, attach the blob limbo to it to track blobs included
|
||||||
// recently but not yet finalized
|
// recently but not yet finalized
|
||||||
@@ -1598,8 +1598,8 @@ func (p *BlobPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool
|
|||||||
// Nonce returns the next nonce of an account, with all transactions executable
|
// Nonce returns the next nonce of an account, with all transactions executable
|
||||||
// by the pool already applied on top.
|
// by the pool already applied on top.
|
||||||
func (p *BlobPool) Nonce(addr common.Address) uint64 {
|
func (p *BlobPool) Nonce(addr common.Address) uint64 {
|
||||||
p.lock.Lock()
|
p.lock.RLock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.RUnlock()
|
||||||
|
|
||||||
if txs, ok := p.index[addr]; ok {
|
if txs, ok := p.index[addr]; ok {
|
||||||
return txs[len(txs)-1].nonce + 1
|
return txs[len(txs)-1].nonce + 1
|
||||||
@@ -1610,8 +1610,8 @@ func (p *BlobPool) Nonce(addr common.Address) uint64 {
|
|||||||
// Stats retrieves the current pool stats, namely the number of pending and the
|
// Stats retrieves the current pool stats, namely the number of pending and the
|
||||||
// number of queued (non-executable) transactions.
|
// number of queued (non-executable) transactions.
|
||||||
func (p *BlobPool) Stats() (int, int) {
|
func (p *BlobPool) Stats() (int, int) {
|
||||||
p.lock.Lock()
|
p.lock.RLock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.RUnlock()
|
||||||
|
|
||||||
var pending int
|
var pending int
|
||||||
for _, txs := range p.index {
|
for _, txs := range p.index {
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ func (bc *testBlockChain) CurrentFinalBlock() *types.Header {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bt *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
|
func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,13 @@
|
|||||||
package blobpool
|
package blobpool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"container/heap"
|
"container/heap"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"slices"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
// evictHeap is a helper data structure to keep track of the cheapest bottleneck
|
// evictHeap is a helper data structure to keep track of the cheapest bottleneck
|
||||||
@@ -35,7 +35,7 @@ import (
|
|||||||
// The goal of the heap is to decide which account has the worst bottleneck to
|
// The goal of the heap is to decide which account has the worst bottleneck to
|
||||||
// evict transactions from.
|
// evict transactions from.
|
||||||
type evictHeap struct {
|
type evictHeap struct {
|
||||||
metas *map[common.Address][]*blobTxMeta // Pointer to the blob pool's index for price retrievals
|
metas map[common.Address][]*blobTxMeta // Pointer to the blob pool's index for price retrievals
|
||||||
|
|
||||||
basefeeJumps float64 // Pre-calculated absolute dynamic fee jumps for the base fee
|
basefeeJumps float64 // Pre-calculated absolute dynamic fee jumps for the base fee
|
||||||
blobfeeJumps float64 // Pre-calculated absolute dynamic fee jumps for the blob fee
|
blobfeeJumps float64 // Pre-calculated absolute dynamic fee jumps for the blob fee
|
||||||
@@ -46,23 +46,18 @@ type evictHeap struct {
|
|||||||
|
|
||||||
// newPriceHeap creates a new heap of cheapest accounts in the blob pool to evict
|
// newPriceHeap creates a new heap of cheapest accounts in the blob pool to evict
|
||||||
// from in case of over saturation.
|
// from in case of over saturation.
|
||||||
func newPriceHeap(basefee *uint256.Int, blobfee *uint256.Int, index *map[common.Address][]*blobTxMeta) *evictHeap {
|
func newPriceHeap(basefee *uint256.Int, blobfee *uint256.Int, index map[common.Address][]*blobTxMeta) *evictHeap {
|
||||||
heap := &evictHeap{
|
heap := &evictHeap{
|
||||||
metas: index,
|
metas: index,
|
||||||
index: make(map[common.Address]int),
|
index: make(map[common.Address]int, len(index)),
|
||||||
}
|
}
|
||||||
// Populate the heap in account sort order. Not really needed in practice,
|
// Populate the heap in account sort order. Not really needed in practice,
|
||||||
// but it makes the heap initialization deterministic and less annoying to
|
// but it makes the heap initialization deterministic and less annoying to
|
||||||
// test in unit tests.
|
// test in unit tests.
|
||||||
addrs := make([]common.Address, 0, len(*index))
|
heap.addrs = maps.Keys(index)
|
||||||
for addr := range *index {
|
slices.SortFunc(heap.addrs, common.Address.Cmp)
|
||||||
addrs = append(addrs, addr)
|
for i, addr := range heap.addrs {
|
||||||
}
|
heap.index[addr] = i
|
||||||
sort.Slice(addrs, func(i, j int) bool { return bytes.Compare(addrs[i][:], addrs[j][:]) < 0 })
|
|
||||||
|
|
||||||
for _, addr := range addrs {
|
|
||||||
heap.index[addr] = len(heap.addrs)
|
|
||||||
heap.addrs = append(heap.addrs, addr)
|
|
||||||
}
|
}
|
||||||
heap.reinit(basefee, blobfee, true)
|
heap.reinit(basefee, blobfee, true)
|
||||||
return heap
|
return heap
|
||||||
@@ -94,8 +89,8 @@ func (h *evictHeap) Len() int {
|
|||||||
// Less implements sort.Interface as part of heap.Interface, returning which of
|
// Less implements sort.Interface as part of heap.Interface, returning which of
|
||||||
// the two requested accounts has a cheaper bottleneck.
|
// the two requested accounts has a cheaper bottleneck.
|
||||||
func (h *evictHeap) Less(i, j int) bool {
|
func (h *evictHeap) Less(i, j int) bool {
|
||||||
txsI := (*(h.metas))[h.addrs[i]]
|
txsI := h.metas[h.addrs[i]]
|
||||||
txsJ := (*(h.metas))[h.addrs[j]]
|
txsJ := h.metas[h.addrs[j]]
|
||||||
|
|
||||||
lastI := txsI[len(txsI)-1]
|
lastI := txsI[len(txsI)-1]
|
||||||
lastJ := txsJ[len(txsJ)-1]
|
lastJ := txsJ[len(txsJ)-1]
|
||||||
|
|||||||
@@ -37,17 +37,17 @@ func verifyHeapInternals(t *testing.T, evict *evictHeap) {
|
|||||||
seen := make(map[common.Address]struct{})
|
seen := make(map[common.Address]struct{})
|
||||||
for i, addr := range evict.addrs {
|
for i, addr := range evict.addrs {
|
||||||
seen[addr] = struct{}{}
|
seen[addr] = struct{}{}
|
||||||
if _, ok := (*evict.metas)[addr]; !ok {
|
if _, ok := evict.metas[addr]; !ok {
|
||||||
t.Errorf("heap contains unexpected address at slot %d: %v", i, addr)
|
t.Errorf("heap contains unexpected address at slot %d: %v", i, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for addr := range *evict.metas {
|
for addr := range evict.metas {
|
||||||
if _, ok := seen[addr]; !ok {
|
if _, ok := seen[addr]; !ok {
|
||||||
t.Errorf("heap is missing required address %v", addr)
|
t.Errorf("heap is missing required address %v", addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(evict.addrs) != len(*evict.metas) {
|
if len(evict.addrs) != len(evict.metas) {
|
||||||
t.Errorf("heap size %d mismatches metadata size %d", len(evict.addrs), len(*evict.metas))
|
t.Errorf("heap size %d mismatches metadata size %d", len(evict.addrs), len(evict.metas))
|
||||||
}
|
}
|
||||||
// Ensure that all accounts are present in the heap order index and no extras
|
// Ensure that all accounts are present in the heap order index and no extras
|
||||||
have := make([]common.Address, len(evict.index))
|
have := make([]common.Address, len(evict.index))
|
||||||
@@ -159,7 +159,7 @@ func TestPriceHeapSorting(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
// Create a price heap and check the pop order
|
// Create a price heap and check the pop order
|
||||||
priceheap := newPriceHeap(uint256.NewInt(tt.basefee), uint256.NewInt(tt.blobfee), &index)
|
priceheap := newPriceHeap(uint256.NewInt(tt.basefee), uint256.NewInt(tt.blobfee), index)
|
||||||
verifyHeapInternals(t, priceheap)
|
verifyHeapInternals(t, priceheap)
|
||||||
|
|
||||||
for j := 0; j < len(tt.order); j++ {
|
for j := 0; j < len(tt.order); j++ {
|
||||||
@@ -218,7 +218,7 @@ func benchmarkPriceHeapReinit(b *testing.B, datacap uint64) {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
// Create a price heap and reinit it over and over
|
// Create a price heap and reinit it over and over
|
||||||
heap := newPriceHeap(uint256.NewInt(rand.Uint64()), uint256.NewInt(rand.Uint64()), &index)
|
heap := newPriceHeap(uint256.NewInt(rand.Uint64()), uint256.NewInt(rand.Uint64()), index)
|
||||||
|
|
||||||
basefees := make([]*uint256.Int, b.N)
|
basefees := make([]*uint256.Int, b.N)
|
||||||
blobfees := make([]*uint256.Int, b.N)
|
blobfees := make([]*uint256.Int, b.N)
|
||||||
@@ -278,7 +278,7 @@ func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
// Create a price heap and overflow it over and over
|
// Create a price heap and overflow it over and over
|
||||||
evict := newPriceHeap(uint256.NewInt(rand.Uint64()), uint256.NewInt(rand.Uint64()), &index)
|
evict := newPriceHeap(uint256.NewInt(rand.Uint64()), uint256.NewInt(rand.Uint64()), index)
|
||||||
var (
|
var (
|
||||||
addrs = make([]common.Address, b.N)
|
addrs = make([]common.Address, b.N)
|
||||||
metas = make([]*blobTxMeta, b.N)
|
metas = make([]*blobTxMeta, b.N)
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ package core
|
|||||||
import (
|
import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/stateless"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@@ -33,7 +35,10 @@ type Validator interface {
|
|||||||
|
|
||||||
// ValidateState validates the given statedb and optionally the receipts and
|
// ValidateState validates the given statedb and optionally the receipts and
|
||||||
// gas used.
|
// gas used.
|
||||||
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
|
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64, stateless bool) error
|
||||||
|
|
||||||
|
// ValidateWitness cross validates a block execution with stateless remote clients.
|
||||||
|
ValidateWitness(witness *stateless.Witness, receiptRoot common.Hash, stateRoot common.Hash) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefetcher is an interface for pre-caching transaction signatures and state.
|
// Prefetcher is an interface for pre-caching transaction signatures and state.
|
||||||
|
|||||||
@@ -459,11 +459,11 @@ func (s EIP155Signer) Hash(tx *Transaction) common.Hash {
|
|||||||
// homestead rules.
|
// homestead rules.
|
||||||
type HomesteadSigner struct{ FrontierSigner }
|
type HomesteadSigner struct{ FrontierSigner }
|
||||||
|
|
||||||
func (s HomesteadSigner) ChainID() *big.Int {
|
func (hs HomesteadSigner) ChainID() *big.Int {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s HomesteadSigner) Equal(s2 Signer) bool {
|
func (hs HomesteadSigner) Equal(s2 Signer) bool {
|
||||||
_, ok := s2.(HomesteadSigner)
|
_, ok := s2.(HomesteadSigner)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
@@ -486,11 +486,11 @@ func (hs HomesteadSigner) Sender(tx *Transaction) (common.Address, error) {
|
|||||||
// frontier rules.
|
// frontier rules.
|
||||||
type FrontierSigner struct{}
|
type FrontierSigner struct{}
|
||||||
|
|
||||||
func (s FrontierSigner) ChainID() *big.Int {
|
func (fs FrontierSigner) ChainID() *big.Int {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s FrontierSigner) Equal(s2 Signer) bool {
|
func (fs FrontierSigner) Equal(s2 Signer) bool {
|
||||||
_, ok := s2.(FrontierSigner)
|
_, ok := s2.(FrontierSigner)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
@@ -572,6 +572,6 @@ func deriveChainId(v *big.Int) *big.Int {
|
|||||||
}
|
}
|
||||||
return new(big.Int).SetUint64((v - 35) / 2)
|
return new(big.Int).SetUint64((v - 35) / 2)
|
||||||
}
|
}
|
||||||
v = new(big.Int).Sub(v, big.NewInt(35))
|
v.Sub(v, big.NewInt(35))
|
||||||
return v.Div(v, big.NewInt(2))
|
return v.Rsh(v, 1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,10 +296,7 @@ type bigModExp struct {
|
|||||||
var (
|
var (
|
||||||
big1 = big.NewInt(1)
|
big1 = big.NewInt(1)
|
||||||
big3 = big.NewInt(3)
|
big3 = big.NewInt(3)
|
||||||
big4 = big.NewInt(4)
|
|
||||||
big7 = big.NewInt(7)
|
big7 = big.NewInt(7)
|
||||||
big8 = big.NewInt(8)
|
|
||||||
big16 = big.NewInt(16)
|
|
||||||
big20 = big.NewInt(20)
|
big20 = big.NewInt(20)
|
||||||
big32 = big.NewInt(32)
|
big32 = big.NewInt(32)
|
||||||
big64 = big.NewInt(64)
|
big64 = big.NewInt(64)
|
||||||
@@ -325,13 +322,13 @@ func modexpMultComplexity(x *big.Int) *big.Int {
|
|||||||
case x.Cmp(big1024) <= 0:
|
case x.Cmp(big1024) <= 0:
|
||||||
// (x ** 2 // 4 ) + ( 96 * x - 3072)
|
// (x ** 2 // 4 ) + ( 96 * x - 3072)
|
||||||
x = new(big.Int).Add(
|
x = new(big.Int).Add(
|
||||||
new(big.Int).Div(new(big.Int).Mul(x, x), big4),
|
new(big.Int).Rsh(new(big.Int).Mul(x, x), 2),
|
||||||
new(big.Int).Sub(new(big.Int).Mul(big96, x), big3072),
|
new(big.Int).Sub(new(big.Int).Mul(big96, x), big3072),
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
// (x ** 2 // 16) + (480 * x - 199680)
|
// (x ** 2 // 16) + (480 * x - 199680)
|
||||||
x = new(big.Int).Add(
|
x = new(big.Int).Add(
|
||||||
new(big.Int).Div(new(big.Int).Mul(x, x), big16),
|
new(big.Int).Rsh(new(big.Int).Mul(x, x), 4),
|
||||||
new(big.Int).Sub(new(big.Int).Mul(big480, x), big199680),
|
new(big.Int).Sub(new(big.Int).Mul(big480, x), big199680),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -369,7 +366,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
|
|||||||
adjExpLen := new(big.Int)
|
adjExpLen := new(big.Int)
|
||||||
if expLen.Cmp(big32) > 0 {
|
if expLen.Cmp(big32) > 0 {
|
||||||
adjExpLen.Sub(expLen, big32)
|
adjExpLen.Sub(expLen, big32)
|
||||||
adjExpLen.Mul(big8, adjExpLen)
|
adjExpLen.Lsh(adjExpLen, 3)
|
||||||
}
|
}
|
||||||
adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
|
adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
|
||||||
// Calculate the gas cost of the operation
|
// Calculate the gas cost of the operation
|
||||||
@@ -383,8 +380,8 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
|
|||||||
// ceiling(x/8)^2
|
// ceiling(x/8)^2
|
||||||
//
|
//
|
||||||
//where is x is max(length_of_MODULUS, length_of_BASE)
|
//where is x is max(length_of_MODULUS, length_of_BASE)
|
||||||
gas = gas.Add(gas, big7)
|
gas.Add(gas, big7)
|
||||||
gas = gas.Div(gas, big8)
|
gas.Rsh(gas, 3)
|
||||||
gas.Mul(gas, gas)
|
gas.Mul(gas, gas)
|
||||||
|
|
||||||
gas.Mul(gas, math.BigMax(adjExpLen, big1))
|
gas.Mul(gas, math.BigMax(adjExpLen, big1))
|
||||||
|
|||||||
@@ -231,6 +231,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||||
// The contract is a scoped environment for this execution context only.
|
// The contract is a scoped environment for this execution context only.
|
||||||
code := evm.StateDB.GetCode(addr)
|
code := evm.StateDB.GetCode(addr)
|
||||||
|
if witness := evm.StateDB.Witness(); witness != nil {
|
||||||
|
witness.AddCode(code)
|
||||||
|
}
|
||||||
if len(code) == 0 {
|
if len(code) == 0 {
|
||||||
ret, err = nil, nil // gas is unchanged
|
ret, err = nil, nil // gas is unchanged
|
||||||
} else {
|
} else {
|
||||||
@@ -298,6 +301,9 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
|
|||||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||||
// The contract is a scoped environment for this execution context only.
|
// The contract is a scoped environment for this execution context only.
|
||||||
contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
|
contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
|
||||||
|
if witness := evm.StateDB.Witness(); witness != nil {
|
||||||
|
witness.AddCode(evm.StateDB.GetCode(addrCopy))
|
||||||
|
}
|
||||||
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
|
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
|
||||||
ret, err = evm.interpreter.Run(contract, input, false)
|
ret, err = evm.interpreter.Run(contract, input, false)
|
||||||
gas = contract.Gas
|
gas = contract.Gas
|
||||||
@@ -345,6 +351,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
|||||||
addrCopy := addr
|
addrCopy := addr
|
||||||
// Initialise a new contract and make initialise the delegate values
|
// Initialise a new contract and make initialise the delegate values
|
||||||
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
|
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
|
||||||
|
if witness := evm.StateDB.Witness(); witness != nil {
|
||||||
|
witness.AddCode(evm.StateDB.GetCode(addrCopy))
|
||||||
|
}
|
||||||
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
|
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
|
||||||
ret, err = evm.interpreter.Run(contract, input, false)
|
ret, err = evm.interpreter.Run(contract, input, false)
|
||||||
gas = contract.Gas
|
gas = contract.Gas
|
||||||
@@ -400,6 +409,9 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
|
|||||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||||
// The contract is a scoped environment for this execution context only.
|
// The contract is a scoped environment for this execution context only.
|
||||||
contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas)
|
contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas)
|
||||||
|
if witness := evm.StateDB.Witness(); witness != nil {
|
||||||
|
witness.AddCode(evm.StateDB.GetCode(addrCopy))
|
||||||
|
}
|
||||||
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
|
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
|
||||||
// When an error was returned by the EVM or when setting the creation code
|
// When an error was returned by the EVM or when setting the creation code
|
||||||
// above we revert to the snapshot and consume any gas remaining. Additionally
|
// above we revert to the snapshot and consume any gas remaining. Additionally
|
||||||
|
|||||||
@@ -340,6 +340,10 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
|||||||
|
|
||||||
func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
slot := scope.Stack.peek()
|
slot := scope.Stack.peek()
|
||||||
|
address := slot.Bytes20()
|
||||||
|
if witness := interpreter.evm.StateDB.Witness(); witness != nil {
|
||||||
|
witness.AddCode(interpreter.evm.StateDB.GetCode(address))
|
||||||
|
}
|
||||||
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20())))
|
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20())))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -378,7 +382,11 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||||||
uint64CodeOffset = math.MaxUint64
|
uint64CodeOffset = math.MaxUint64
|
||||||
}
|
}
|
||||||
addr := common.Address(a.Bytes20())
|
addr := common.Address(a.Bytes20())
|
||||||
codeCopy := getData(interpreter.evm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64())
|
code := interpreter.evm.StateDB.GetCode(addr)
|
||||||
|
if witness := interpreter.evm.StateDB.Witness(); witness != nil {
|
||||||
|
witness.AddCode(code)
|
||||||
|
}
|
||||||
|
codeCopy := getData(code, uint64CodeOffset, length.Uint64())
|
||||||
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
|
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -443,7 +451,11 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
|
|||||||
lower = upper - 256
|
lower = upper - 256
|
||||||
}
|
}
|
||||||
if num64 >= lower && num64 < upper {
|
if num64 >= lower && num64 < upper {
|
||||||
num.SetBytes(interpreter.evm.Context.GetHash(num64).Bytes())
|
res := interpreter.evm.Context.GetHash(num64)
|
||||||
|
if witness := interpreter.evm.StateDB.Witness(); witness != nil {
|
||||||
|
witness.AddBlockHash(num64)
|
||||||
|
}
|
||||||
|
num.SetBytes(res[:])
|
||||||
} else {
|
} else {
|
||||||
num.Clear()
|
num.Clear()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/stateless"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
@@ -87,6 +88,8 @@ type StateDB interface {
|
|||||||
|
|
||||||
AddLog(*types.Log)
|
AddLog(*types.Log)
|
||||||
AddPreimage(common.Hash, []byte)
|
AddPreimage(common.Hash, []byte)
|
||||||
|
|
||||||
|
Witness() *stateless.Witness
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Config struct {
|
|||||||
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
||||||
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
||||||
ExtraEips []int // Additional EIPS that are to be enabled
|
ExtraEips []int // Additional EIPS that are to be enabled
|
||||||
|
EnableWitnessCollection bool // true if witness collection is enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScopeContext contains the things that are per-call, such as stack and memory,
|
// ScopeContext contains the things that are per-call, such as stack and memory,
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||||||
var (
|
var (
|
||||||
vmConfig = vm.Config{
|
vmConfig = vm.Config{
|
||||||
EnablePreimageRecording: config.EnablePreimageRecording,
|
EnablePreimageRecording: config.EnablePreimageRecording,
|
||||||
|
EnableWitnessCollection: config.EnableWitnessCollection,
|
||||||
}
|
}
|
||||||
cacheConfig = &core.CacheConfig{
|
cacheConfig = &core.CacheConfig{
|
||||||
TrieCleanLimit: config.TrieCleanCache,
|
TrieCleanLimit: config.TrieCleanCache,
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ type Config struct {
|
|||||||
// Enables tracking of SHA3 preimages in the VM
|
// Enables tracking of SHA3 preimages in the VM
|
||||||
EnablePreimageRecording bool
|
EnablePreimageRecording bool
|
||||||
|
|
||||||
|
// Enables prefetching trie nodes for read operations too
|
||||||
|
EnableWitnessCollection bool `toml:"-"`
|
||||||
|
|
||||||
// Enables VM tracing
|
// Enables VM tracing
|
||||||
VMTrace string
|
VMTrace string
|
||||||
VMTraceJsonConfig string
|
VMTraceJsonConfig string
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
|||||||
BlobPool blobpool.Config
|
BlobPool blobpool.Config
|
||||||
GPO gasprice.Config
|
GPO gasprice.Config
|
||||||
EnablePreimageRecording bool
|
EnablePreimageRecording bool
|
||||||
|
EnableWitnessCollection bool `toml:"-"`
|
||||||
VMTrace string
|
VMTrace string
|
||||||
VMTraceJsonConfig string
|
VMTraceJsonConfig string
|
||||||
DocRoot string `toml:"-"`
|
DocRoot string `toml:"-"`
|
||||||
@@ -93,6 +94,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
|||||||
enc.BlobPool = c.BlobPool
|
enc.BlobPool = c.BlobPool
|
||||||
enc.GPO = c.GPO
|
enc.GPO = c.GPO
|
||||||
enc.EnablePreimageRecording = c.EnablePreimageRecording
|
enc.EnablePreimageRecording = c.EnablePreimageRecording
|
||||||
|
enc.EnableWitnessCollection = c.EnableWitnessCollection
|
||||||
enc.VMTrace = c.VMTrace
|
enc.VMTrace = c.VMTrace
|
||||||
enc.VMTraceJsonConfig = c.VMTraceJsonConfig
|
enc.VMTraceJsonConfig = c.VMTraceJsonConfig
|
||||||
enc.DocRoot = c.DocRoot
|
enc.DocRoot = c.DocRoot
|
||||||
@@ -140,6 +142,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
|||||||
BlobPool *blobpool.Config
|
BlobPool *blobpool.Config
|
||||||
GPO *gasprice.Config
|
GPO *gasprice.Config
|
||||||
EnablePreimageRecording *bool
|
EnablePreimageRecording *bool
|
||||||
|
EnableWitnessCollection *bool `toml:"-"`
|
||||||
VMTrace *string
|
VMTrace *string
|
||||||
VMTraceJsonConfig *string
|
VMTraceJsonConfig *string
|
||||||
DocRoot *string `toml:"-"`
|
DocRoot *string `toml:"-"`
|
||||||
@@ -252,6 +255,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
|||||||
if dec.EnablePreimageRecording != nil {
|
if dec.EnablePreimageRecording != nil {
|
||||||
c.EnablePreimageRecording = *dec.EnablePreimageRecording
|
c.EnablePreimageRecording = *dec.EnablePreimageRecording
|
||||||
}
|
}
|
||||||
|
if dec.EnableWitnessCollection != nil {
|
||||||
|
c.EnableWitnessCollection = *dec.EnableWitnessCollection
|
||||||
|
}
|
||||||
if dec.VMTrace != nil {
|
if dec.VMTrace != nil {
|
||||||
c.VMTrace = *dec.VMTrace
|
c.VMTrace = *dec.VMTrace
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -332,11 +332,7 @@ func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePac
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var proofs [][]byte
|
return accounts, proof.List()
|
||||||
for _, blob := range proof.List() {
|
|
||||||
proofs = append(proofs, blob)
|
|
||||||
}
|
|
||||||
return accounts, proofs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesPacket) ([][]*StorageData, [][]byte) {
|
func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesPacket) ([][]*StorageData, [][]byte) {
|
||||||
@@ -438,9 +434,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, blob := range proof.List() {
|
proofs = append(proofs, proof.List()...)
|
||||||
proofs = append(proofs, blob)
|
|
||||||
}
|
|
||||||
// Proof terminates the reply as proofs are only added if a node
|
// Proof terminates the reply as proofs are only added if a node
|
||||||
// refuses to serve more data (exception when a contract fetch is
|
// refuses to serve more data (exception when a contract fetch is
|
||||||
// finishing, but that's that).
|
// finishing, but that's that).
|
||||||
|
|||||||
@@ -286,10 +286,7 @@ func createAccountRequestResponse(t *testPeer, root common.Hash, origin common.H
|
|||||||
t.logger.Error("Could not prove last item", "error", err)
|
t.logger.Error("Could not prove last item", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, blob := range proof.List() {
|
return keys, vals, proof.List()
|
||||||
proofs = append(proofs, blob)
|
|
||||||
}
|
|
||||||
return keys, vals, proofs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultStorageRequestHandler is a well-behaving storage request handler
|
// defaultStorageRequestHandler is a well-behaving storage request handler
|
||||||
@@ -371,9 +368,7 @@ func createStorageRequestResponse(t *testPeer, root common.Hash, accounts []comm
|
|||||||
t.logger.Error("Could not prove last item", "error", err)
|
t.logger.Error("Could not prove last item", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, blob := range proof.List() {
|
proofs = append(proofs, proof.List()...)
|
||||||
proofs = append(proofs, blob)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,9 +425,7 @@ func createStorageRequestResponseAlwaysProve(t *testPeer, root common.Hash, acco
|
|||||||
t.logger.Error("Could not prove last item", "error", err)
|
t.logger.Error("Could not prove last item", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, blob := range proof.List() {
|
proofs = append(proofs, proof.List()...)
|
||||||
proofs = append(proofs, blob)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -586,9 +579,8 @@ func testSyncBloatedProof(t *testing.T, scheme string) {
|
|||||||
|
|
||||||
source.accountRequestHandler = func(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error {
|
source.accountRequestHandler = func(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error {
|
||||||
var (
|
var (
|
||||||
proofs [][]byte
|
keys []common.Hash
|
||||||
keys []common.Hash
|
vals [][]byte
|
||||||
vals [][]byte
|
|
||||||
)
|
)
|
||||||
// The values
|
// The values
|
||||||
for _, entry := range t.accountValues {
|
for _, entry := range t.accountValues {
|
||||||
@@ -618,10 +610,7 @@ func testSyncBloatedProof(t *testing.T, scheme string) {
|
|||||||
keys = append(keys[:1], keys[2:]...)
|
keys = append(keys[:1], keys[2:]...)
|
||||||
vals = append(vals[:1], vals[2:]...)
|
vals = append(vals[:1], vals[2:]...)
|
||||||
}
|
}
|
||||||
for _, blob := range proof.List() {
|
if err := t.remote.OnAccounts(t, requestId, keys, vals, proof.List()); err != nil {
|
||||||
proofs = append(proofs, blob)
|
|
||||||
}
|
|
||||||
if err := t.remote.OnAccounts(t, requestId, keys, vals, proofs); err != nil {
|
|
||||||
t.logger.Info("remote error on delivery (as expected)", "error", err)
|
t.logger.Info("remote error on delivery (as expected)", "error", err)
|
||||||
t.term()
|
t.term()
|
||||||
// This is actually correct, signal to exit the test successfully
|
// This is actually correct, signal to exit the test successfully
|
||||||
@@ -1525,7 +1514,7 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv)
|
|||||||
|
|
||||||
// Commit the state changes into db and re-create the trie
|
// Commit the state changes into db and re-create the trie
|
||||||
// for accessing later.
|
// for accessing later.
|
||||||
root, nodes, _ := accTrie.Commit(false)
|
root, nodes := accTrie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
||||||
|
|
||||||
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
||||||
@@ -1587,7 +1576,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
|
|||||||
|
|
||||||
// Commit the state changes into db and re-create the trie
|
// Commit the state changes into db and re-create the trie
|
||||||
// for accessing later.
|
// for accessing later.
|
||||||
root, nodes, _ := accTrie.Commit(false)
|
root, nodes := accTrie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
||||||
|
|
||||||
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
||||||
@@ -1633,7 +1622,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
|
|||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
|
|
||||||
// Commit account trie
|
// Commit account trie
|
||||||
root, set, _ := accTrie.Commit(true)
|
root, set := accTrie.Commit(true)
|
||||||
nodes.Merge(set)
|
nodes.Merge(set)
|
||||||
|
|
||||||
// Commit gathered dirty nodes into database
|
// Commit gathered dirty nodes into database
|
||||||
@@ -1700,7 +1689,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
|
|||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
|
|
||||||
// Commit account trie
|
// Commit account trie
|
||||||
root, set, _ := accTrie.Commit(true)
|
root, set := accTrie.Commit(true)
|
||||||
nodes.Merge(set)
|
nodes.Merge(set)
|
||||||
|
|
||||||
// Commit gathered dirty nodes into database
|
// Commit gathered dirty nodes into database
|
||||||
@@ -1742,7 +1731,7 @@ func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *triedb.Datab
|
|||||||
entries = append(entries, elem)
|
entries = append(entries, elem)
|
||||||
}
|
}
|
||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
return root, nodes, entries
|
return root, nodes, entries
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1793,7 +1782,7 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *triedb.Database) (com
|
|||||||
entries = append(entries, elem)
|
entries = append(entries, elem)
|
||||||
}
|
}
|
||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
return root, nodes, entries
|
return root, nodes, entries
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1825,7 +1814,7 @@ func makeUnevenStorageTrie(owner common.Hash, slots int, db *triedb.Database) (c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
root, nodes, _ := tr.Commit(false)
|
root, nodes := tr.Commit(false)
|
||||||
return root, nodes, entries
|
return root, nodes, entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -204,12 +204,10 @@ func (s *supply) internalTxsHandler(call *supplyTxCallstack) {
|
|||||||
s.delta.Burn.Misc.Add(s.delta.Burn.Misc, call.burn)
|
s.delta.Burn.Misc.Add(s.delta.Burn.Misc, call.burn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(call.calls) > 0 {
|
// Recursively handle internal calls
|
||||||
// Recursively handle internal calls
|
for _, call := range call.calls {
|
||||||
for _, call := range call.calls {
|
callCopy := call
|
||||||
callCopy := call
|
s.internalTxsHandler(&callCopy)
|
||||||
s.internalTxsHandler(&callCopy)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -274,16 +274,14 @@ func flatFromNested(input *callFrame, traceAddress []int, convertErrs bool, ctx
|
|||||||
}
|
}
|
||||||
|
|
||||||
output = append(output, *frame)
|
output = append(output, *frame)
|
||||||
if len(input.Calls) > 0 {
|
for i, childCall := range input.Calls {
|
||||||
for i, childCall := range input.Calls {
|
childAddr := childTraceAddress(traceAddress, i)
|
||||||
childAddr := childTraceAddress(traceAddress, i)
|
childCallCopy := childCall
|
||||||
childCallCopy := childCall
|
flat, err := flatFromNested(&childCallCopy, childAddr, convertErrs, ctx)
|
||||||
flat, err := flatFromNested(&childCallCopy, childAddr, convertErrs, ctx)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
output = append(output, flat...)
|
|
||||||
}
|
}
|
||||||
|
output = append(output, flat...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output, nil
|
return output, nil
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ type KeyValueWriter interface {
|
|||||||
|
|
||||||
// KeyValueStater wraps the Stat method of a backing data store.
|
// KeyValueStater wraps the Stat method of a backing data store.
|
||||||
type KeyValueStater interface {
|
type KeyValueStater interface {
|
||||||
// Stat returns a particular internal stat of the database.
|
// Stat returns the statistic data of the database.
|
||||||
Stat(property string) (string, error)
|
Stat() (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compacter wraps the Compact method of a backing data store.
|
// Compacter wraps the Compact method of a backing data store.
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ package leveldb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -244,14 +243,53 @@ func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
|
|||||||
return &snapshot{db: snap}, nil
|
return &snapshot{db: snap}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns a particular internal stat of the database.
|
// Stat returns the statistic data of the database.
|
||||||
func (db *Database) Stat(property string) (string, error) {
|
func (db *Database) Stat() (string, error) {
|
||||||
if property == "" {
|
var stats leveldb.DBStats
|
||||||
property = "leveldb.stats"
|
if err := db.db.Stats(&stats); err != nil {
|
||||||
} else if !strings.HasPrefix(property, "leveldb.") {
|
return "", err
|
||||||
property = "leveldb." + property
|
|
||||||
}
|
}
|
||||||
return db.db.GetProperty(property)
|
var (
|
||||||
|
message string
|
||||||
|
totalRead int64
|
||||||
|
totalWrite int64
|
||||||
|
totalSize int64
|
||||||
|
totalTables int
|
||||||
|
totalDuration time.Duration
|
||||||
|
)
|
||||||
|
if len(stats.LevelSizes) > 0 {
|
||||||
|
message += " Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB)\n" +
|
||||||
|
"-------+------------+---------------+---------------+---------------+---------------\n"
|
||||||
|
for level, size := range stats.LevelSizes {
|
||||||
|
read := stats.LevelRead[level]
|
||||||
|
write := stats.LevelWrite[level]
|
||||||
|
duration := stats.LevelDurations[level]
|
||||||
|
tables := stats.LevelTablesCounts[level]
|
||||||
|
|
||||||
|
if tables == 0 && duration == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
totalTables += tables
|
||||||
|
totalSize += size
|
||||||
|
totalRead += read
|
||||||
|
totalWrite += write
|
||||||
|
totalDuration += duration
|
||||||
|
message += fmt.Sprintf(" %3d | %10d | %13.5f | %13.5f | %13.5f | %13.5f\n",
|
||||||
|
level, tables, float64(size)/1048576.0, duration.Seconds(),
|
||||||
|
float64(read)/1048576.0, float64(write)/1048576.0)
|
||||||
|
}
|
||||||
|
message += "-------+------------+---------------+---------------+---------------+---------------\n"
|
||||||
|
message += fmt.Sprintf(" Total | %10d | %13.5f | %13.5f | %13.5f | %13.5f\n",
|
||||||
|
totalTables, float64(totalSize)/1048576.0, totalDuration.Seconds(),
|
||||||
|
float64(totalRead)/1048576.0, float64(totalWrite)/1048576.0)
|
||||||
|
message += "-------+------------+---------------+---------------+---------------+---------------\n\n"
|
||||||
|
}
|
||||||
|
message += fmt.Sprintf("Read(MB):%.5f Write(MB):%.5f\n", float64(stats.IORead)/1048576.0, float64(stats.IOWrite)/1048576.0)
|
||||||
|
message += fmt.Sprintf("BlockCache(MB):%.5f FileCache:%d\n", float64(stats.BlockCacheSize)/1048576.0, stats.OpenedTablesCount)
|
||||||
|
message += fmt.Sprintf("MemoryCompaction:%d Level0Compaction:%d NonLevel0Compaction:%d SeekCompaction:%d\n", stats.MemComp, stats.Level0Comp, stats.NonLevel0Comp, stats.SeekComp)
|
||||||
|
message += fmt.Sprintf("WriteDelayCount:%d WriteDelayDuration:%s Paused:%t\n", stats.WriteDelayCount, common.PrettyDuration(stats.WriteDelayDuration), stats.WritePaused)
|
||||||
|
message += fmt.Sprintf("Snapshots:%d Iterators:%d\n", stats.AliveSnapshots, stats.AliveIterators)
|
||||||
|
return message, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact flattens the underlying data store for the given key range. In essence,
|
// Compact flattens the underlying data store for the given key range. In essence,
|
||||||
|
|||||||
@@ -182,9 +182,9 @@ func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
|
|||||||
return newSnapshot(db), nil
|
return newSnapshot(db), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns a particular internal stat of the database.
|
// Stat returns the statistic data of the database.
|
||||||
func (db *Database) Stat(property string) (string, error) {
|
func (db *Database) Stat() (string, error) {
|
||||||
return "", errors.New("unknown property")
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact is not supported on a memory database, but there's no need either as
|
// Compact is not supported on a memory database, but there's no need either as
|
||||||
|
|||||||
@@ -416,10 +416,8 @@ func upperBound(prefix []byte) (limit []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns the internal metrics of Pebble in a text format. It's a developer
|
// Stat returns the internal metrics of Pebble in a text format. It's a developer
|
||||||
// method to read everything there is to read independent of Pebble version.
|
// method to read everything there is to read, independent of Pebble version.
|
||||||
//
|
func (d *Database) Stat() (string, error) {
|
||||||
// The property is unused in Pebble as there's only one thing to retrieve.
|
|
||||||
func (d *Database) Stat(property string) (string, error) {
|
|
||||||
return d.db.Metrics().String(), nil
|
return d.db.Metrics().String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,8 +126,8 @@ func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
|
|||||||
panic("not supported")
|
panic("not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) Stat(property string) (string, error) {
|
func (db *Database) Stat() (string, error) {
|
||||||
panic("not supported")
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) AncientDatadir() (string, error) {
|
func (db *Database) AncientDatadir() (string, error) {
|
||||||
|
|||||||
13
go.mod
13
go.mod
@@ -13,7 +13,7 @@ require (
|
|||||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0
|
github.com/btcsuite/btcd/btcec/v2 v2.2.0
|
||||||
github.com/cespare/cp v0.1.0
|
github.com/cespare/cp v0.1.0
|
||||||
github.com/cloudflare/cloudflare-go v0.79.0
|
github.com/cloudflare/cloudflare-go v0.79.0
|
||||||
github.com/cockroachdb/pebble v1.1.0
|
github.com/cockroachdb/pebble v1.1.1
|
||||||
github.com/consensys/gnark-crypto v0.12.1
|
github.com/consensys/gnark-crypto v0.12.1
|
||||||
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c
|
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c
|
||||||
github.com/crate-crypto/go-kzg-4844 v1.0.0
|
github.com/crate-crypto/go-kzg-4844 v1.0.0
|
||||||
@@ -61,13 +61,14 @@ require (
|
|||||||
github.com/rs/cors v1.7.0
|
github.com/rs/cors v1.7.0
|
||||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
||||||
github.com/status-im/keycard-go v0.2.0
|
github.com/status-im/keycard-go v0.2.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/supranational/blst v0.3.11
|
github.com/supranational/blst v0.3.11
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||||
github.com/tyler-smith/go-bip39 v1.1.0
|
github.com/tyler-smith/go-bip39 v1.1.0
|
||||||
github.com/urfave/cli/v2 v2.25.7
|
github.com/urfave/cli/v2 v2.25.7
|
||||||
go.uber.org/automaxprocs v1.5.2
|
go.uber.org/automaxprocs v1.5.2
|
||||||
golang.org/x/crypto v0.22.0
|
golang.org/x/crypto v0.22.0
|
||||||
|
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
|
||||||
golang.org/x/sync v0.7.0
|
golang.org/x/sync v0.7.0
|
||||||
golang.org/x/sys v0.20.0
|
golang.org/x/sys v0.20.0
|
||||||
golang.org/x/text v0.14.0
|
golang.org/x/text v0.14.0
|
||||||
@@ -94,7 +95,8 @@ require (
|
|||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.10.0 // indirect
|
github.com/bits-and-blooms/bitset v1.10.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/cockroachdb/errors v1.11.1 // indirect
|
github.com/cockroachdb/errors v1.11.3 // indirect
|
||||||
|
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
|
||||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
||||||
github.com/cockroachdb/redact v1.1.5 // indirect
|
github.com/cockroachdb/redact v1.1.5 // indirect
|
||||||
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
|
||||||
@@ -104,7 +106,7 @@ require (
|
|||||||
github.com/deepmap/oapi-codegen v1.6.0 // indirect
|
github.com/deepmap/oapi-codegen v1.6.0 // indirect
|
||||||
github.com/dlclark/regexp2 v1.7.0 // indirect
|
github.com/dlclark/regexp2 v1.7.0 // indirect
|
||||||
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect
|
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect
|
||||||
github.com/getsentry/sentry-go v0.18.0 // indirect
|
github.com/getsentry/sentry-go v0.27.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
@@ -115,7 +117,7 @@ require (
|
|||||||
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
|
||||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
|
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/klauspost/compress v1.15.15 // indirect
|
github.com/klauspost/compress v1.16.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
@@ -139,7 +141,6 @@ require (
|
|||||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/net v0.24.0 // indirect
|
golang.org/x/net v0.24.0 // indirect
|
||||||
google.golang.org/protobuf v1.33.0 // indirect
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
|
|||||||
22
go.sum
22
go.sum
@@ -116,12 +116,14 @@ github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8
|
|||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
|
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
|
||||||
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
|
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
|
||||||
github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8=
|
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
|
||||||
github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw=
|
github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
|
||||||
|
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
|
||||||
|
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
|
||||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
|
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
|
||||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
||||||
github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4=
|
github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw=
|
||||||
github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E=
|
github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU=
|
||||||
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
|
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
|
||||||
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
||||||
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
|
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
|
||||||
@@ -187,8 +189,8 @@ github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILD
|
|||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
||||||
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||||
github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
|
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
||||||
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
|
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
@@ -347,8 +349,8 @@ github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4
|
|||||||
github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig=
|
github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
||||||
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
|
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
@@ -494,8 +496,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
|
github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
|
||||||
github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||||
|
|||||||
@@ -272,17 +272,22 @@ func extractFile(arpath string, armode os.FileMode, data io.Reader, dest string)
|
|||||||
return fmt.Errorf("path %q escapes archive destination", target)
|
return fmt.Errorf("path %q escapes archive destination", target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the destination directory exists.
|
// Remove the preivously-extracted file if it exists
|
||||||
|
if err := os.RemoveAll(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recreate the destination directory
|
||||||
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
|
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy file data.
|
// Copy file data.
|
||||||
file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, armode)
|
file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY, armode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := io.Copy(file, data); err != nil {
|
if _, err = io.Copy(file, data); err != nil {
|
||||||
file.Close()
|
file.Close()
|
||||||
os.Remove(target)
|
os.Remove(target)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -231,9 +231,9 @@ func Setup(ctx *cli.Context) error {
|
|||||||
case ctx.Bool(logjsonFlag.Name):
|
case ctx.Bool(logjsonFlag.Name):
|
||||||
// Retain backwards compatibility with `--log.json` flag if `--log.format` not set
|
// Retain backwards compatibility with `--log.json` flag if `--log.format` not set
|
||||||
defer log.Warn("The flag '--log.json' is deprecated, please use '--log.format=json' instead")
|
defer log.Warn("The flag '--log.json' is deprecated, please use '--log.format=json' instead")
|
||||||
handler = log.JSONHandlerWithLevel(output, log.LevelInfo)
|
handler = log.JSONHandler(output)
|
||||||
case logFmtFlag == "json":
|
case logFmtFlag == "json":
|
||||||
handler = log.JSONHandlerWithLevel(output, log.LevelInfo)
|
handler = log.JSONHandler(output)
|
||||||
case logFmtFlag == "logfmt":
|
case logFmtFlag == "logfmt":
|
||||||
handler = log.LogfmtHandler(output)
|
handler = log.LogfmtHandler(output)
|
||||||
case logFmtFlag == "", logFmtFlag == "terminal":
|
case logFmtFlag == "", logFmtFlag == "terminal":
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -263,7 +263,6 @@ web3._extend({
|
|||||||
new web3._extend.Method({
|
new web3._extend.Method({
|
||||||
name: 'chaindbProperty',
|
name: 'chaindbProperty',
|
||||||
call: 'debug_chaindbProperty',
|
call: 'debug_chaindbProperty',
|
||||||
params: 1,
|
|
||||||
outputFormatter: console.log
|
outputFormatter: console.log
|
||||||
}),
|
}),
|
||||||
new web3._extend.Method({
|
new web3._extend.Method({
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ func (h *TerminalHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ResetFieldPadding zeroes the field-padding for all attribute pairs.
|
// ResetFieldPadding zeroes the field-padding for all attribute pairs.
|
||||||
func (t *TerminalHandler) ResetFieldPadding() {
|
func (h *TerminalHandler) ResetFieldPadding() {
|
||||||
t.mu.Lock()
|
h.mu.Lock()
|
||||||
t.fieldPadding = make(map[string]int)
|
h.fieldPadding = make(map[string]int)
|
||||||
t.mu.Unlock()
|
h.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
type leveler struct{ minLevel slog.Level }
|
type leveler struct{ minLevel slog.Level }
|
||||||
|
|||||||
@@ -139,11 +139,15 @@ func (h *GlogHandler) Vmodule(ruleset string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enabled implements slog.Handler, reporting whether the handler handles records
|
||||||
|
// at the given level.
|
||||||
func (h *GlogHandler) Enabled(ctx context.Context, lvl slog.Level) bool {
|
func (h *GlogHandler) Enabled(ctx context.Context, lvl slog.Level) bool {
|
||||||
// fast-track skipping logging if override not enabled and the provided verbosity is above configured
|
// fast-track skipping logging if override not enabled and the provided verbosity is above configured
|
||||||
return h.override.Load() || slog.Level(h.level.Load()) <= lvl
|
return h.override.Load() || slog.Level(h.level.Load()) <= lvl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithAttrs implements slog.Handler, returning a new Handler whose attributes
|
||||||
|
// consist of both the receiver's attributes and the arguments.
|
||||||
func (h *GlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
func (h *GlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||||
h.lock.RLock()
|
h.lock.RLock()
|
||||||
siteCache := maps.Clone(h.siteCache)
|
siteCache := maps.Clone(h.siteCache)
|
||||||
@@ -164,12 +168,16 @@ func (h *GlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
|||||||
return &res
|
return &res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithGroup implements slog.Handler, returning a new Handler with the given
|
||||||
|
// group appended to the receiver's existing groups.
|
||||||
|
//
|
||||||
|
// Note, this function is not implemented.
|
||||||
func (h *GlogHandler) WithGroup(name string) slog.Handler {
|
func (h *GlogHandler) WithGroup(name string) slog.Handler {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log implements Handler.Log, filtering a log record through the global, local
|
// Handle implements slog.Handler, filtering a log record through the global,
|
||||||
// and backtrace filters, finally emitting it if either allow it through.
|
// local and backtrace filters, finally emitting it if either allow it through.
|
||||||
func (h *GlogHandler) Handle(_ context.Context, r slog.Record) error {
|
func (h *GlogHandler) Handle(_ context.Context, r slog.Record) error {
|
||||||
// If the global log level allows, fast track logging
|
// If the global log level allows, fast track logging
|
||||||
if slog.Level(h.level.Load()) <= r.Level {
|
if slog.Level(h.level.Load()) <= r.Level {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const (
|
|||||||
LvlDebug = LevelDebug
|
LvlDebug = LevelDebug
|
||||||
)
|
)
|
||||||
|
|
||||||
// convert from old Geth verbosity level constants
|
// FromLegacyLevel converts from old Geth verbosity level constants
|
||||||
// to levels defined by slog
|
// to levels defined by slog
|
||||||
func FromLegacyLevel(lvl int) slog.Level {
|
func FromLegacyLevel(lvl int) slog.Level {
|
||||||
switch lvl {
|
switch lvl {
|
||||||
@@ -107,7 +107,7 @@ type Logger interface {
|
|||||||
// With returns a new Logger that has this logger's attributes plus the given attributes
|
// With returns a new Logger that has this logger's attributes plus the given attributes
|
||||||
With(ctx ...interface{}) Logger
|
With(ctx ...interface{}) Logger
|
||||||
|
|
||||||
// With returns a new Logger that has this logger's attributes plus the given attributes. Identical to 'With'.
|
// New returns a new Logger that has this logger's attributes plus the given attributes. Identical to 'With'.
|
||||||
New(ctx ...interface{}) Logger
|
New(ctx ...interface{}) Logger
|
||||||
|
|
||||||
// Log logs a message at the specified level with context key/value pairs
|
// Log logs a message at the specified level with context key/value pairs
|
||||||
@@ -156,7 +156,7 @@ func (l *logger) Handler() slog.Handler {
|
|||||||
return l.inner.Handler()
|
return l.inner.Handler()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write logs a message at the specified level:
|
// Write logs a message at the specified level.
|
||||||
func (l *logger) Write(level slog.Level, msg string, attrs ...any) {
|
func (l *logger) Write(level slog.Level, msg string, attrs ...any) {
|
||||||
if !l.inner.Enabled(context.Background(), level) {
|
if !l.inner.Enabled(context.Background(), level) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -452,7 +452,9 @@ func (tab *Table) loadSeedNodes() {
|
|||||||
addr, _ := seed.UDPEndpoint()
|
addr, _ := seed.UDPEndpoint()
|
||||||
tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", addr, "age", age)
|
tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", addr, "age", age)
|
||||||
}
|
}
|
||||||
|
tab.mutex.Lock()
|
||||||
tab.handleAddNode(addNodeOp{node: seed, isInbound: false})
|
tab.handleAddNode(addNodeOp{node: seed, isInbound: false})
|
||||||
|
tab.mutex.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func waitForRevalidationPing(t *testing.T, transport *pingRecorder, tab *Table,
|
|||||||
simclock.Run(tab.cfg.PingInterval * slowRevalidationFactor)
|
simclock.Run(tab.cfg.PingInterval * slowRevalidationFactor)
|
||||||
p := transport.waitPing(2 * time.Second)
|
p := transport.waitPing(2 * time.Second)
|
||||||
if p == nil {
|
if p == nil {
|
||||||
t.Fatal("Table did not send revalidation ping")
|
continue
|
||||||
}
|
}
|
||||||
if id == (enode.ID{}) || p.ID() == id {
|
if id == (enode.ID{}) || p.ID() == id {
|
||||||
return p
|
return p
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user