mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 22:56:43 +00:00
Merge remote-tracking branch 'origin/master' into eof-opcodes
This commit is contained in:
commit
3927f6bfa6
224 changed files with 13847 additions and 5521 deletions
13
.gitignore
vendored
13
.gitignore
vendored
|
|
@ -43,3 +43,16 @@ profile.cov
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
tests/spec-tests/
|
tests/spec-tests/
|
||||||
|
|
||||||
|
# binaries
|
||||||
|
cmd/abidump/abidump
|
||||||
|
cmd/abigen/abigen
|
||||||
|
cmd/blsync/blsync
|
||||||
|
cmd/clef/clef
|
||||||
|
cmd/devp2p/devp2p
|
||||||
|
cmd/era/era
|
||||||
|
cmd/ethkey/ethkey
|
||||||
|
cmd/evm/evm
|
||||||
|
cmd/geth/geth
|
||||||
|
cmd/rlpdump/rlpdump
|
||||||
|
cmd/workload/workload
|
||||||
23
.travis.yml
23
.travis.yml
|
|
@ -2,12 +2,6 @@ language: go
|
||||||
go_import_path: github.com/ethereum/go-ethereum
|
go_import_path: github.com/ethereum/go-ethereum
|
||||||
sudo: false
|
sudo: false
|
||||||
jobs:
|
jobs:
|
||||||
allow_failures:
|
|
||||||
- stage: build
|
|
||||||
os: osx
|
|
||||||
env:
|
|
||||||
- azure-osx
|
|
||||||
|
|
||||||
include:
|
include:
|
||||||
# This builder create and push the Docker images for all architectures
|
# This builder create and push the Docker images for all architectures
|
||||||
- stage: build
|
- stage: build
|
||||||
|
|
@ -62,23 +56,6 @@ jobs:
|
||||||
- go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
|
- go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
|
||||||
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
||||||
|
|
||||||
# This builder does the OSX Azure uploads
|
|
||||||
- stage: build
|
|
||||||
if: type = push
|
|
||||||
os: osx
|
|
||||||
osx_image: xcode14.2
|
|
||||||
go: 1.23.1 # See https://github.com/ethereum/go-ethereum/pull/30478
|
|
||||||
env:
|
|
||||||
- azure-osx
|
|
||||||
git:
|
|
||||||
submodules: false # avoid cloning ethereum/tests
|
|
||||||
script:
|
|
||||||
- ln -sf /Users/travis/gopath/bin/go1.23.1 /usr/local/bin/go # Work around travis go-setup bug
|
|
||||||
- go run build/ci.go install -dlgo
|
|
||||||
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
|
||||||
- go run build/ci.go install -dlgo -arch arm64
|
|
||||||
- go run build/ci.go archive -arch arm64 -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
|
||||||
|
|
||||||
# These builders run the tests
|
# These builders run the tests
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = push
|
if: type = push
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Package bind generates Ethereum contract Go bindings.
|
// Package abigen generates Ethereum contract Go bindings.
|
||||||
//
|
//
|
||||||
// Detailed usage document and tutorial available on the go-ethereum Wiki page:
|
// Detailed usage document and tutorial available on the go-ethereum Wiki page:
|
||||||
// https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts
|
// https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings
|
||||||
package bind
|
package abigen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -33,13 +33,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Lang is a target programming language selector to generate bindings for.
|
|
||||||
type Lang int
|
|
||||||
|
|
||||||
const (
|
|
||||||
LangGo Lang = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
func isKeyWord(arg string) bool {
|
func isKeyWord(arg string) bool {
|
||||||
switch arg {
|
switch arg {
|
||||||
case "break":
|
case "break":
|
||||||
|
|
@ -81,7 +74,7 @@ func isKeyWord(arg string) bool {
|
||||||
// to be used as is in client code, but rather as an intermediate struct which
|
// to be used as is in client code, but rather as an intermediate struct which
|
||||||
// enforces compile time type safety and naming convention as opposed to having to
|
// enforces compile time type safety and naming convention as opposed to having to
|
||||||
// manually maintain hard coded strings that break on runtime.
|
// manually maintain hard coded strings that break on runtime.
|
||||||
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string, aliases map[string]string) (string, error) {
|
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, libs map[string]string, aliases map[string]string) (string, error) {
|
||||||
var (
|
var (
|
||||||
// contracts is the map of each individual contract requested binding
|
// contracts is the map of each individual contract requested binding
|
||||||
contracts = make(map[string]*tmplContract)
|
contracts = make(map[string]*tmplContract)
|
||||||
|
|
@ -125,14 +118,14 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
|
|
||||||
for _, input := range evmABI.Constructor.Inputs {
|
for _, input := range evmABI.Constructor.Inputs {
|
||||||
if hasStruct(input.Type) {
|
if hasStruct(input.Type) {
|
||||||
bindStructType[lang](input.Type, structs)
|
bindStructType(input.Type, structs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, original := range evmABI.Methods {
|
for _, original := range evmABI.Methods {
|
||||||
// Normalize the method for capital cases and non-anonymous inputs/outputs
|
// Normalize the method for capital cases and non-anonymous inputs/outputs
|
||||||
normalized := original
|
normalized := original
|
||||||
normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
|
normalizedName := abi.ToCamelCase(alias(aliases, original.Name))
|
||||||
// Ensure there is no duplicated identifier
|
// Ensure there is no duplicated identifier
|
||||||
var identifiers = callIdentifiers
|
var identifiers = callIdentifiers
|
||||||
if !original.IsConstant() {
|
if !original.IsConstant() {
|
||||||
|
|
@ -159,17 +152,17 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
|
normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
|
||||||
}
|
}
|
||||||
if hasStruct(input.Type) {
|
if hasStruct(input.Type) {
|
||||||
bindStructType[lang](input.Type, structs)
|
bindStructType(input.Type, structs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
normalized.Outputs = make([]abi.Argument, len(original.Outputs))
|
normalized.Outputs = make([]abi.Argument, len(original.Outputs))
|
||||||
copy(normalized.Outputs, original.Outputs)
|
copy(normalized.Outputs, original.Outputs)
|
||||||
for j, output := range normalized.Outputs {
|
for j, output := range normalized.Outputs {
|
||||||
if output.Name != "" {
|
if output.Name != "" {
|
||||||
normalized.Outputs[j].Name = capitalise(output.Name)
|
normalized.Outputs[j].Name = abi.ToCamelCase(output.Name)
|
||||||
}
|
}
|
||||||
if hasStruct(output.Type) {
|
if hasStruct(output.Type) {
|
||||||
bindStructType[lang](output.Type, structs)
|
bindStructType(output.Type, structs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Append the methods to the call or transact lists
|
// Append the methods to the call or transact lists
|
||||||
|
|
@ -188,7 +181,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
normalized := original
|
normalized := original
|
||||||
|
|
||||||
// Ensure there is no duplicated identifier
|
// Ensure there is no duplicated identifier
|
||||||
normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
|
normalizedName := abi.ToCamelCase(alias(aliases, original.Name))
|
||||||
// Name shouldn't start with a digit. It will make the generated code invalid.
|
// Name shouldn't start with a digit. It will make the generated code invalid.
|
||||||
if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) {
|
if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) {
|
||||||
normalizedName = fmt.Sprintf("E%s", normalizedName)
|
normalizedName = fmt.Sprintf("E%s", normalizedName)
|
||||||
|
|
@ -213,14 +206,14 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
// Event is a bit special, we need to define event struct in binding,
|
// Event is a bit special, we need to define event struct in binding,
|
||||||
// ensure there is no camel-case-style name conflict.
|
// ensure there is no camel-case-style name conflict.
|
||||||
for index := 0; ; index++ {
|
for index := 0; ; index++ {
|
||||||
if !used[capitalise(normalized.Inputs[j].Name)] {
|
if !used[abi.ToCamelCase(normalized.Inputs[j].Name)] {
|
||||||
used[capitalise(normalized.Inputs[j].Name)] = true
|
used[abi.ToCamelCase(normalized.Inputs[j].Name)] = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
normalized.Inputs[j].Name = fmt.Sprintf("%s%d", normalized.Inputs[j].Name, index)
|
normalized.Inputs[j].Name = fmt.Sprintf("%s%d", normalized.Inputs[j].Name, index)
|
||||||
}
|
}
|
||||||
if hasStruct(input.Type) {
|
if hasStruct(input.Type) {
|
||||||
bindStructType[lang](input.Type, structs)
|
bindStructType(input.Type, structs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Append the event to the accumulator list
|
// Append the event to the accumulator list
|
||||||
|
|
@ -233,8 +226,9 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
if evmABI.HasReceive() {
|
if evmABI.HasReceive() {
|
||||||
receive = &tmplMethod{Original: evmABI.Receive}
|
receive = &tmplMethod{Original: evmABI.Receive}
|
||||||
}
|
}
|
||||||
|
|
||||||
contracts[types[i]] = &tmplContract{
|
contracts[types[i]] = &tmplContract{
|
||||||
Type: capitalise(types[i]),
|
Type: abi.ToCamelCase(types[i]),
|
||||||
InputABI: strings.ReplaceAll(strippedABI, "\"", "\\\""),
|
InputABI: strings.ReplaceAll(strippedABI, "\"", "\\\""),
|
||||||
InputBin: strings.TrimPrefix(strings.TrimSpace(bytecodes[i]), "0x"),
|
InputBin: strings.TrimPrefix(strings.TrimSpace(bytecodes[i]), "0x"),
|
||||||
Constructor: evmABI.Constructor,
|
Constructor: evmABI.Constructor,
|
||||||
|
|
@ -245,6 +239,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
Events: events,
|
Events: events,
|
||||||
Libraries: make(map[string]string),
|
Libraries: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function 4-byte signatures are stored in the same sequence
|
// Function 4-byte signatures are stored in the same sequence
|
||||||
// as types, if available.
|
// as types, if available.
|
||||||
if len(fsigs) > i {
|
if len(fsigs) > i {
|
||||||
|
|
@ -270,6 +265,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
_, ok := isLib[types[i]]
|
_, ok := isLib[types[i]]
|
||||||
contracts[types[i]].Library = ok
|
contracts[types[i]].Library = ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the contract template data content and render it
|
// Generate the contract template data content and render it
|
||||||
data := &tmplData{
|
data := &tmplData{
|
||||||
Package: pkg,
|
Package: pkg,
|
||||||
|
|
@ -280,36 +276,25 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
|
|
||||||
funcs := map[string]interface{}{
|
funcs := map[string]interface{}{
|
||||||
"bindtype": bindType[lang],
|
"bindtype": bindType,
|
||||||
"bindtopictype": bindTopicType[lang],
|
"bindtopictype": bindTopicType,
|
||||||
"namedtype": namedType[lang],
|
"capitalise": abi.ToCamelCase,
|
||||||
"capitalise": capitalise,
|
|
||||||
"decapitalise": decapitalise,
|
"decapitalise": decapitalise,
|
||||||
}
|
}
|
||||||
tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSource[lang]))
|
tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSource))
|
||||||
if err := tmpl.Execute(buffer, data); err != nil {
|
if err := tmpl.Execute(buffer, data); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
// For Go bindings pass the code through gofmt to clean it up
|
// Pass the code through gofmt to clean it up
|
||||||
if lang == LangGo {
|
code, err := format.Source(buffer.Bytes())
|
||||||
code, err := format.Source(buffer.Bytes())
|
if err != nil {
|
||||||
if err != nil {
|
return "", fmt.Errorf("%v\n%s", err, buffer)
|
||||||
return "", fmt.Errorf("%v\n%s", err, buffer)
|
|
||||||
}
|
|
||||||
return string(code), nil
|
|
||||||
}
|
}
|
||||||
// For all others just return as is for now
|
return string(code), nil
|
||||||
return buffer.String(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bindType is a set of type binders that convert Solidity types to some supported
|
// bindBasicType converts basic solidity types(except array, slice and tuple) to Go ones.
|
||||||
// programming language types.
|
func bindBasicType(kind abi.Type) string {
|
||||||
var bindType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
|
|
||||||
LangGo: bindTypeGo,
|
|
||||||
}
|
|
||||||
|
|
||||||
// bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go ones.
|
|
||||||
func bindBasicTypeGo(kind abi.Type) string {
|
|
||||||
switch kind.T {
|
switch kind.T {
|
||||||
case abi.AddressTy:
|
case abi.AddressTy:
|
||||||
return "common.Address"
|
return "common.Address"
|
||||||
|
|
@ -332,32 +317,26 @@ func bindBasicTypeGo(kind abi.Type) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bindTypeGo converts solidity types to Go ones. Since there is no clear mapping
|
// bindType converts solidity types to Go ones. Since there is no clear mapping
|
||||||
// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
|
// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly
|
||||||
// mapped will use an upscaled type (e.g. BigDecimal).
|
// mapped will use an upscaled type (e.g. BigDecimal).
|
||||||
func bindTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
func bindType(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||||
switch kind.T {
|
switch kind.T {
|
||||||
case abi.TupleTy:
|
case abi.TupleTy:
|
||||||
return structs[kind.TupleRawName+kind.String()].Name
|
return structs[kind.TupleRawName+kind.String()].Name
|
||||||
case abi.ArrayTy:
|
case abi.ArrayTy:
|
||||||
return fmt.Sprintf("[%d]", kind.Size) + bindTypeGo(*kind.Elem, structs)
|
return fmt.Sprintf("[%d]", kind.Size) + bindType(*kind.Elem, structs)
|
||||||
case abi.SliceTy:
|
case abi.SliceTy:
|
||||||
return "[]" + bindTypeGo(*kind.Elem, structs)
|
return "[]" + bindType(*kind.Elem, structs)
|
||||||
default:
|
default:
|
||||||
return bindBasicTypeGo(kind)
|
return bindBasicType(kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bindTopicType is a set of type binders that convert Solidity types to some
|
// bindTopicType converts a Solidity topic type to a Go one. It is almost the same
|
||||||
// supported programming language topic types.
|
|
||||||
var bindTopicType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
|
|
||||||
LangGo: bindTopicTypeGo,
|
|
||||||
}
|
|
||||||
|
|
||||||
// bindTopicTypeGo converts a Solidity topic type to a Go one. It is almost the same
|
|
||||||
// functionality as for simple types, but dynamic types get converted to hashes.
|
// functionality as for simple types, but dynamic types get converted to hashes.
|
||||||
func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
func bindTopicType(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||||
bound := bindTypeGo(kind, structs)
|
bound := bindType(kind, structs)
|
||||||
|
|
||||||
// todo(rjl493456442) according solidity documentation, indexed event
|
// todo(rjl493456442) according solidity documentation, indexed event
|
||||||
// parameters that are not value types i.e. arrays and structs are not
|
// parameters that are not value types i.e. arrays and structs are not
|
||||||
|
|
@ -371,16 +350,10 @@ func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||||
return bound
|
return bound
|
||||||
}
|
}
|
||||||
|
|
||||||
// bindStructType is a set of type binders that convert Solidity tuple types to some supported
|
// bindStructType converts a Solidity tuple type to a Go one and records the mapping
|
||||||
// programming language struct definition.
|
// in the given map. Notably, this function will resolve and record nested struct
|
||||||
var bindStructType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
|
// recursively.
|
||||||
LangGo: bindStructTypeGo,
|
func bindStructType(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||||
}
|
|
||||||
|
|
||||||
// bindStructTypeGo converts a Solidity tuple type to a Go one and records the mapping
|
|
||||||
// in the given map.
|
|
||||||
// Notably, this function will resolve and record nested struct recursively.
|
|
||||||
func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
|
||||||
switch kind.T {
|
switch kind.T {
|
||||||
case abi.TupleTy:
|
case abi.TupleTy:
|
||||||
// We compose a raw struct name and a canonical parameter expression
|
// We compose a raw struct name and a canonical parameter expression
|
||||||
|
|
@ -398,16 +371,20 @@ func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||||
fields []*tmplField
|
fields []*tmplField
|
||||||
)
|
)
|
||||||
for i, elem := range kind.TupleElems {
|
for i, elem := range kind.TupleElems {
|
||||||
name := capitalise(kind.TupleRawNames[i])
|
name := abi.ToCamelCase(kind.TupleRawNames[i])
|
||||||
name = abi.ResolveNameConflict(name, func(s string) bool { return names[s] })
|
name = abi.ResolveNameConflict(name, func(s string) bool { return names[s] })
|
||||||
names[name] = true
|
names[name] = true
|
||||||
fields = append(fields, &tmplField{Type: bindStructTypeGo(*elem, structs), Name: name, SolKind: *elem})
|
fields = append(fields, &tmplField{
|
||||||
|
Type: bindStructType(*elem, structs),
|
||||||
|
Name: name,
|
||||||
|
SolKind: *elem,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
name := kind.TupleRawName
|
name := kind.TupleRawName
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = fmt.Sprintf("Struct%d", len(structs))
|
name = fmt.Sprintf("Struct%d", len(structs))
|
||||||
}
|
}
|
||||||
name = capitalise(name)
|
name = abi.ToCamelCase(name)
|
||||||
|
|
||||||
structs[id] = &tmplStruct{
|
structs[id] = &tmplStruct{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
|
@ -415,20 +392,14 @@ func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||||
}
|
}
|
||||||
return name
|
return name
|
||||||
case abi.ArrayTy:
|
case abi.ArrayTy:
|
||||||
return fmt.Sprintf("[%d]", kind.Size) + bindStructTypeGo(*kind.Elem, structs)
|
return fmt.Sprintf("[%d]", kind.Size) + bindStructType(*kind.Elem, structs)
|
||||||
case abi.SliceTy:
|
case abi.SliceTy:
|
||||||
return "[]" + bindStructTypeGo(*kind.Elem, structs)
|
return "[]" + bindStructType(*kind.Elem, structs)
|
||||||
default:
|
default:
|
||||||
return bindBasicTypeGo(kind)
|
return bindBasicType(kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// namedType is a set of functions that transform language specific types to
|
|
||||||
// named versions that may be used inside method names.
|
|
||||||
var namedType = map[Lang]func(string, abi.Type) string{
|
|
||||||
LangGo: func(string, abi.Type) string { panic("this shouldn't be needed") },
|
|
||||||
}
|
|
||||||
|
|
||||||
// alias returns an alias of the given string based on the aliasing rules
|
// alias returns an alias of the given string based on the aliasing rules
|
||||||
// or returns itself if no rule is matched.
|
// or returns itself if no rule is matched.
|
||||||
func alias(aliases map[string]string, n string) string {
|
func alias(aliases map[string]string, n string) string {
|
||||||
|
|
@ -438,21 +409,11 @@ func alias(aliases map[string]string, n string) string {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// methodNormalizer is a name transformer that modifies Solidity method names to
|
|
||||||
// conform to target language naming conventions.
|
|
||||||
var methodNormalizer = map[Lang]func(string) string{
|
|
||||||
LangGo: abi.ToCamelCase,
|
|
||||||
}
|
|
||||||
|
|
||||||
// capitalise makes a camel-case string which starts with an upper case character.
|
|
||||||
var capitalise = abi.ToCamelCase
|
|
||||||
|
|
||||||
// decapitalise makes a camel-case string which starts with a lower case character.
|
// decapitalise makes a camel-case string which starts with a lower case character.
|
||||||
func decapitalise(input string) string {
|
func decapitalise(input string) string {
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
||||||
goForm := abi.ToCamelCase(input)
|
goForm := abi.ToCamelCase(input)
|
||||||
return strings.ToLower(goForm[:1]) + goForm[1:]
|
return strings.ToLower(goForm[:1]) + goForm[1:]
|
||||||
}
|
}
|
||||||
|
|
@ -471,7 +432,7 @@ func structured(args abi.Arguments) bool {
|
||||||
}
|
}
|
||||||
// If the field name is empty when normalized or collides (var, Var, _var, _Var),
|
// If the field name is empty when normalized or collides (var, Var, _var, _Var),
|
||||||
// we can't organize into a struct
|
// we can't organize into a struct
|
||||||
field := capitalise(out.Name)
|
field := abi.ToCamelCase(out.Name)
|
||||||
if field == "" || exists[field] {
|
if field == "" || exists[field] {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package bind
|
package abigen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -541,7 +541,7 @@ var bindTests = []struct {
|
||||||
struct A {
|
struct A {
|
||||||
bytes32 B;
|
bytes32 B;
|
||||||
}
|
}
|
||||||
|
|
||||||
function F() public view returns (A[] memory a, uint256[] memory c, bool[] memory d) {
|
function F() public view returns (A[] memory a, uint256[] memory c, bool[] memory d) {
|
||||||
A[] memory a = new A[](2);
|
A[] memory a = new A[](2);
|
||||||
a[0].B = bytes32(uint256(1234) << 96);
|
a[0].B = bytes32(uint256(1234) << 96);
|
||||||
|
|
@ -549,7 +549,7 @@ var bindTests = []struct {
|
||||||
bool[] memory d;
|
bool[] memory d;
|
||||||
return (a, c, d);
|
return (a, c, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
function G() public view returns (A[] memory a) {
|
function G() public view returns (A[] memory a) {
|
||||||
A[] memory a = new A[](2);
|
A[] memory a = new A[](2);
|
||||||
a[0].B = bytes32(uint256(1234) << 96);
|
a[0].B = bytes32(uint256(1234) << 96);
|
||||||
|
|
@ -571,10 +571,10 @@ var bindTests = []struct {
|
||||||
// Generate a new random account and a funded simulator
|
// Generate a new random account and a funded simulator
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||||
|
|
||||||
sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
|
sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000)
|
||||||
defer sim.Close()
|
defer sim.Close()
|
||||||
|
|
||||||
// Deploy a structs method invoker contract and execute its default method
|
// Deploy a structs method invoker contract and execute its default method
|
||||||
_, _, structs, err := DeployStructs(auth, sim)
|
_, _, structs, err := DeployStructs(auth, sim)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1701,13 +1701,13 @@ var bindTests = []struct {
|
||||||
`NewFallbacks`,
|
`NewFallbacks`,
|
||||||
`
|
`
|
||||||
pragma solidity >=0.6.0 <0.7.0;
|
pragma solidity >=0.6.0 <0.7.0;
|
||||||
|
|
||||||
contract NewFallbacks {
|
contract NewFallbacks {
|
||||||
event Fallback(bytes data);
|
event Fallback(bytes data);
|
||||||
fallback() external {
|
fallback() external {
|
||||||
emit Fallback(msg.data);
|
emit Fallback(msg.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
event Received(address addr, uint value);
|
event Received(address addr, uint value);
|
||||||
receive() external payable {
|
receive() external payable {
|
||||||
emit Received(msg.sender, msg.value);
|
emit Received(msg.sender, msg.value);
|
||||||
|
|
@ -1719,7 +1719,7 @@ var bindTests = []struct {
|
||||||
`
|
`
|
||||||
"bytes"
|
"bytes"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
@ -1728,22 +1728,22 @@ var bindTests = []struct {
|
||||||
`
|
`
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
||||||
sim := backends.NewSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 1000000)
|
sim := backends.NewSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 1000000)
|
||||||
defer sim.Close()
|
defer sim.Close()
|
||||||
|
|
||||||
opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||||
_, _, c, err := DeployNewFallbacks(opts, sim)
|
_, _, c, err := DeployNewFallbacks(opts, sim)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to deploy contract: %v", err)
|
t.Fatalf("Failed to deploy contract: %v", err)
|
||||||
}
|
}
|
||||||
sim.Commit()
|
sim.Commit()
|
||||||
|
|
||||||
// Test receive function
|
// Test receive function
|
||||||
opts.Value = big.NewInt(100)
|
opts.Value = big.NewInt(100)
|
||||||
c.Receive(opts)
|
c.Receive(opts)
|
||||||
sim.Commit()
|
sim.Commit()
|
||||||
|
|
||||||
var gotEvent bool
|
var gotEvent bool
|
||||||
iter, _ := c.FilterReceived(nil)
|
iter, _ := c.FilterReceived(nil)
|
||||||
defer iter.Close()
|
defer iter.Close()
|
||||||
|
|
@ -1760,14 +1760,14 @@ var bindTests = []struct {
|
||||||
if !gotEvent {
|
if !gotEvent {
|
||||||
t.Fatal("Expect to receive event emitted by receive")
|
t.Fatal("Expect to receive event emitted by receive")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test fallback function
|
// Test fallback function
|
||||||
gotEvent = false
|
gotEvent = false
|
||||||
opts.Value = nil
|
opts.Value = nil
|
||||||
calldata := []byte{0x01, 0x02, 0x03}
|
calldata := []byte{0x01, 0x02, 0x03}
|
||||||
c.Fallback(opts, calldata)
|
c.Fallback(opts, calldata)
|
||||||
sim.Commit()
|
sim.Commit()
|
||||||
|
|
||||||
iter2, _ := c.FilterFallback(nil)
|
iter2, _ := c.FilterFallback(nil)
|
||||||
defer iter2.Close()
|
defer iter2.Close()
|
||||||
for iter2.Next() {
|
for iter2.Next() {
|
||||||
|
|
@ -1806,7 +1806,9 @@ var bindTests = []struct {
|
||||||
[]string{"608060405234801561001057600080fd5b50610113806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806324ec1d3f14602d575b600080fd5b60336035565b005b7fb4b2ff75e30cb4317eaae16dd8a187dd89978df17565104caa6c2797caae27d460405180604001604052806001815260200160028152506040516078919060ba565b60405180910390a1565b6040820160008201516096600085018260ad565b50602082015160a7602085018260ad565b50505050565b60b48160d3565b82525050565b600060408201905060cd60008301846082565b92915050565b600081905091905056fea26469706673582212208823628796125bf9941ce4eda18da1be3cf2931b231708ab848e1bd7151c0c9a64736f6c63430008070033"},
|
[]string{"608060405234801561001057600080fd5b50610113806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806324ec1d3f14602d575b600080fd5b60336035565b005b7fb4b2ff75e30cb4317eaae16dd8a187dd89978df17565104caa6c2797caae27d460405180604001604052806001815260200160028152506040516078919060ba565b60405180910390a1565b6040820160008201516096600085018260ad565b50602082015160a7602085018260ad565b50505050565b60b48160d3565b82525050565b600060408201905060cd60008301846082565b92915050565b600081905091905056fea26469706673582212208823628796125bf9941ce4eda18da1be3cf2931b231708ab848e1bd7151c0c9a64736f6c63430008070033"},
|
||||||
[]string{`[{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"indexed":false,"internalType":"struct Test.MyStruct","name":"s","type":"tuple"}],"name":"StructEvent","type":"event"},{"inputs":[],"name":"TestEvent","outputs":[],"stateMutability":"nonpayable","type":"function"}]`},
|
[]string{`[{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"indexed":false,"internalType":"struct Test.MyStruct","name":"s","type":"tuple"}],"name":"StructEvent","type":"event"},{"inputs":[],"name":"TestEvent","outputs":[],"stateMutability":"nonpayable","type":"function"}]`},
|
||||||
`
|
`
|
||||||
|
"context"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
||||||
|
|
@ -1828,12 +1830,23 @@ var bindTests = []struct {
|
||||||
}
|
}
|
||||||
sim.Commit()
|
sim.Commit()
|
||||||
|
|
||||||
_, err = d.TestEvent(user)
|
tx, err := d.TestEvent(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to call contract %v", err)
|
t.Fatalf("Failed to call contract %v", err)
|
||||||
}
|
}
|
||||||
sim.Commit()
|
sim.Commit()
|
||||||
|
|
||||||
|
// Wait for the transaction to be mined
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
receipt, err := bind.WaitMined(ctx, sim, tx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to wait for tx to be mined: %v", err)
|
||||||
|
}
|
||||||
|
if receipt.Status != types.ReceiptStatusSuccessful {
|
||||||
|
t.Fatal("Transaction failed")
|
||||||
|
}
|
||||||
|
|
||||||
it, err := d.FilterStructEvent(nil)
|
it, err := d.FilterStructEvent(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to filter contract event %v", err)
|
t.Fatalf("Failed to filter contract event %v", err)
|
||||||
|
|
@ -1862,7 +1875,7 @@ var bindTests = []struct {
|
||||||
`NewErrors`,
|
`NewErrors`,
|
||||||
`
|
`
|
||||||
pragma solidity >0.8.4;
|
pragma solidity >0.8.4;
|
||||||
|
|
||||||
contract NewErrors {
|
contract NewErrors {
|
||||||
error MyError(uint256);
|
error MyError(uint256);
|
||||||
error MyError1(uint256);
|
error MyError1(uint256);
|
||||||
|
|
@ -1878,7 +1891,7 @@ var bindTests = []struct {
|
||||||
`
|
`
|
||||||
"context"
|
"context"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
@ -1892,7 +1905,7 @@ var bindTests = []struct {
|
||||||
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
|
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
|
||||||
)
|
)
|
||||||
defer sim.Close()
|
defer sim.Close()
|
||||||
|
|
||||||
_, tx, contract, err := DeployNewErrors(user, sim)
|
_, tx, contract, err := DeployNewErrors(user, sim)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -1917,12 +1930,12 @@ var bindTests = []struct {
|
||||||
name: `ConstructorWithStructParam`,
|
name: `ConstructorWithStructParam`,
|
||||||
contract: `
|
contract: `
|
||||||
pragma solidity >=0.8.0 <0.9.0;
|
pragma solidity >=0.8.0 <0.9.0;
|
||||||
|
|
||||||
contract ConstructorWithStructParam {
|
contract ConstructorWithStructParam {
|
||||||
struct StructType {
|
struct StructType {
|
||||||
uint256 field;
|
uint256 field;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(StructType memory st) {}
|
constructor(StructType memory st) {}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
|
@ -1951,7 +1964,7 @@ var bindTests = []struct {
|
||||||
t.Fatalf("DeployConstructorWithStructParam() got err %v; want nil err", err)
|
t.Fatalf("DeployConstructorWithStructParam() got err %v; want nil err", err)
|
||||||
}
|
}
|
||||||
sim.Commit()
|
sim.Commit()
|
||||||
|
|
||||||
if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
|
if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
|
||||||
t.Logf("Deployment tx: %+v", tx)
|
t.Logf("Deployment tx: %+v", tx)
|
||||||
t.Errorf("bind.WaitDeployed(nil, %T, <deployment tx>) got err %v; want nil err", sim, err)
|
t.Errorf("bind.WaitDeployed(nil, %T, <deployment tx>) got err %v; want nil err", sim, err)
|
||||||
|
|
@ -2000,7 +2013,7 @@ var bindTests = []struct {
|
||||||
t.Fatalf("DeployNameConflict() got err %v; want nil err", err)
|
t.Fatalf("DeployNameConflict() got err %v; want nil err", err)
|
||||||
}
|
}
|
||||||
sim.Commit()
|
sim.Commit()
|
||||||
|
|
||||||
if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
|
if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil {
|
||||||
t.Logf("Deployment tx: %+v", tx)
|
t.Logf("Deployment tx: %+v", tx)
|
||||||
t.Errorf("bind.WaitDeployed(nil, %T, <deployment tx>) got err %v; want nil err", sim, err)
|
t.Errorf("bind.WaitDeployed(nil, %T, <deployment tx>) got err %v; want nil err", sim, err)
|
||||||
|
|
@ -2072,20 +2085,22 @@ var bindTests = []struct {
|
||||||
|
|
||||||
// Tests that packages generated by the binder can be successfully compiled and
|
// Tests that packages generated by the binder can be successfully compiled and
|
||||||
// the requested tester run against it.
|
// the requested tester run against it.
|
||||||
func TestGolangBindings(t *testing.T) {
|
func TestBindings(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// Skip the test if no Go command can be found
|
// Skip the test if no Go command can be found
|
||||||
gocmd := runtime.GOROOT() + "/bin/go"
|
gocmd := runtime.GOROOT() + "/bin/go"
|
||||||
if !common.FileExist(gocmd) {
|
if !common.FileExist(gocmd) {
|
||||||
t.Skip("go sdk not found for testing")
|
t.Skip("go sdk not found for testing")
|
||||||
}
|
}
|
||||||
// Create a temporary workspace for the test suite
|
|
||||||
ws := t.TempDir()
|
|
||||||
|
|
||||||
pkg := filepath.Join(ws, "bindtest")
|
// Create a temporary workspace for the test suite
|
||||||
|
path := t.TempDir()
|
||||||
|
pkg := filepath.Join(path, "bindtest")
|
||||||
if err := os.MkdirAll(pkg, 0700); err != nil {
|
if err := os.MkdirAll(pkg, 0700); err != nil {
|
||||||
t.Fatalf("failed to create package: %v", err)
|
t.Fatalf("failed to create package: %v", err)
|
||||||
}
|
}
|
||||||
|
t.Log("tmpdir", pkg)
|
||||||
|
|
||||||
// Generate the test suite for all the contracts
|
// Generate the test suite for all the contracts
|
||||||
for i, tt := range bindTests {
|
for i, tt := range bindTests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
@ -2096,7 +2111,7 @@ func TestGolangBindings(t *testing.T) {
|
||||||
types = []string{tt.name}
|
types = []string{tt.name}
|
||||||
}
|
}
|
||||||
// Generate the binding and create a Go source file in the workspace
|
// Generate the binding and create a Go source file in the workspace
|
||||||
bind, err := Bind(types, tt.abi, tt.bytecode, tt.fsigs, "bindtest", LangGo, tt.libs, tt.aliases)
|
bind, err := Bind(types, tt.abi, tt.bytecode, tt.fsigs, "bindtest", tt.libs, tt.aliases)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test %d: failed to generate binding: %v", i, err)
|
t.Fatalf("test %d: failed to generate binding: %v", i, err)
|
||||||
}
|
}
|
||||||
373
accounts/abi/abigen/bindv2.go
Normal file
373
accounts/abi/abigen/bindv2.go
Normal file
|
|
@ -0,0 +1,373 @@
|
||||||
|
// 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 abigen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"slices"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// underlyingBindType returns a string representation of the Go type
|
||||||
|
// that corresponds to the given ABI type, panicking if it is not a
|
||||||
|
// pointer.
|
||||||
|
func underlyingBindType(typ abi.Type) string {
|
||||||
|
goType := typ.GetType()
|
||||||
|
if goType.Kind() != reflect.Pointer {
|
||||||
|
panic("trying to retrieve underlying bind type of non-pointer type.")
|
||||||
|
}
|
||||||
|
return goType.Elem().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// isPointerType returns true if the underlying type is a pointer.
|
||||||
|
func isPointerType(typ abi.Type) bool {
|
||||||
|
return typ.GetType().Kind() == reflect.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// OLD:
|
||||||
|
// binder is used during the conversion of an ABI definition into Go bindings
|
||||||
|
// (as part of the execution of BindV2). In contrast to contractBinder, binder
|
||||||
|
// contains binding-generation-state that is shared between contracts:
|
||||||
|
//
|
||||||
|
// a global struct map of structs emitted by all contracts is tracked and expanded.
|
||||||
|
// Structs generated in the bindings are not prefixed with the contract name
|
||||||
|
// that uses them (to keep the generated bindings less verbose).
|
||||||
|
//
|
||||||
|
// This contrasts to other per-contract state (constructor/method/event/error,
|
||||||
|
// pack/unpack methods) which are guaranteed to be unique because of their
|
||||||
|
// association with the uniquely-named owning contract (whether prefixed in the
|
||||||
|
// generated symbol name, or as a member method on a contract struct).
|
||||||
|
//
|
||||||
|
// In addition, binder contains the input alias map. In BindV2, a binder is
|
||||||
|
// instantiated to produce a set of tmplContractV2 and tmplStruct objects from
|
||||||
|
// the provided ABI definition. These are used as part of the input to rendering
|
||||||
|
// the binding template.
|
||||||
|
|
||||||
|
// NEW:
|
||||||
|
// binder is used to translate an ABI definition into a set of data-structures
|
||||||
|
// that will be used to render the template and produce Go bindings. This can
|
||||||
|
// be thought of as the "backend" that sanitizes the ABI definition to a format
|
||||||
|
// that can be directly rendered with minimal complexity in the template.
|
||||||
|
//
|
||||||
|
// The input data to the template rendering consists of:
|
||||||
|
// - the set of all contracts requested for binding, each containing
|
||||||
|
// methods/events/errors to emit pack/unpack methods for.
|
||||||
|
// - the set of structures defined by the contracts, and created
|
||||||
|
// as part of the binding process.
|
||||||
|
type binder struct {
|
||||||
|
// contracts is the map of each individual contract requested binding.
|
||||||
|
// It is keyed by the contract name provided in the ABI definition.
|
||||||
|
contracts map[string]*tmplContractV2
|
||||||
|
|
||||||
|
// structs is the map of all emitted structs from contracts being bound.
|
||||||
|
// it is keyed by a unique identifier generated from the name of the owning contract
|
||||||
|
// and the solidity type signature of the struct
|
||||||
|
structs map[string]*tmplStruct
|
||||||
|
|
||||||
|
// aliases is a map for renaming instances of named events/functions/errors
|
||||||
|
// to specified values. it is keyed by source symbol name, and values are
|
||||||
|
// what the replacement name should be.
|
||||||
|
aliases map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindStructType registers the type to be emitted as a struct in the
|
||||||
|
// bindings.
|
||||||
|
func (b *binder) BindStructType(typ abi.Type) {
|
||||||
|
bindStructType(typ, b.structs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// contractBinder holds state for binding of a single contract. It is a type
|
||||||
|
// registry for compiling maps of identifiers that will be emitted in generated
|
||||||
|
// bindings.
|
||||||
|
type contractBinder struct {
|
||||||
|
binder *binder
|
||||||
|
|
||||||
|
// all maps are keyed by the original (non-normalized) name of the symbol in question
|
||||||
|
// from the provided ABI definition.
|
||||||
|
calls map[string]*tmplMethod
|
||||||
|
events map[string]*tmplEvent
|
||||||
|
errors map[string]*tmplError
|
||||||
|
callIdentifiers map[string]bool
|
||||||
|
eventIdentifiers map[string]bool
|
||||||
|
errorIdentifiers map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newContractBinder(binder *binder) *contractBinder {
|
||||||
|
return &contractBinder{
|
||||||
|
binder,
|
||||||
|
make(map[string]*tmplMethod),
|
||||||
|
make(map[string]*tmplEvent),
|
||||||
|
make(map[string]*tmplError),
|
||||||
|
make(map[string]bool),
|
||||||
|
make(map[string]bool),
|
||||||
|
make(map[string]bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// registerIdentifier applies alias renaming, name normalization (conversion
|
||||||
|
// from snake to camel-case), and registers the normalized name in the specified identifier map.
|
||||||
|
// It returns an error if the normalized name already exists in the map.
|
||||||
|
func (cb *contractBinder) registerIdentifier(identifiers map[string]bool, original string) (normalized string, err error) {
|
||||||
|
normalized = abi.ToCamelCase(alias(cb.binder.aliases, original))
|
||||||
|
|
||||||
|
// Name shouldn't start with a digit. It will make the generated code invalid.
|
||||||
|
if len(normalized) > 0 && unicode.IsDigit(rune(normalized[0])) {
|
||||||
|
normalized = fmt.Sprintf("E%s", normalized)
|
||||||
|
normalized = abi.ResolveNameConflict(normalized, func(name string) bool {
|
||||||
|
_, ok := identifiers[name]
|
||||||
|
return ok
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if _, ok := identifiers[normalized]; ok {
|
||||||
|
return "", fmt.Errorf("duplicate symbol '%s'", normalized)
|
||||||
|
}
|
||||||
|
identifiers[normalized] = true
|
||||||
|
return normalized, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindMethod registers a method to be emitted in the bindings. The name, inputs
|
||||||
|
// and outputs are normalized. If any inputs are struct-type their structs are
|
||||||
|
// registered to be emitted in the bindings. Any methods that return more than
|
||||||
|
// one output have their results gathered into a struct.
|
||||||
|
func (cb *contractBinder) bindMethod(original abi.Method) error {
|
||||||
|
normalized := original
|
||||||
|
normalizedName, err := cb.registerIdentifier(cb.callIdentifiers, original.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
normalized.Name = normalizedName
|
||||||
|
|
||||||
|
normalized.Inputs = normalizeArgs(original.Inputs)
|
||||||
|
for _, input := range normalized.Inputs {
|
||||||
|
if hasStruct(input.Type) {
|
||||||
|
cb.binder.BindStructType(input.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
normalized.Outputs = normalizeArgs(original.Outputs)
|
||||||
|
for _, output := range normalized.Outputs {
|
||||||
|
if hasStruct(output.Type) {
|
||||||
|
cb.binder.BindStructType(output.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isStructured bool
|
||||||
|
// If the call returns multiple values, gather them into a struct
|
||||||
|
if len(normalized.Outputs) > 1 {
|
||||||
|
isStructured = true
|
||||||
|
}
|
||||||
|
cb.calls[original.Name] = &tmplMethod{
|
||||||
|
Original: original,
|
||||||
|
Normalized: normalized,
|
||||||
|
Structured: isStructured,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize a set of arguments by stripping underscores, giving a generic name
|
||||||
|
// in the case where the arg name collides with a reserved Go keyword, and finally
|
||||||
|
// converting to camel-case.
|
||||||
|
func normalizeArgs(args abi.Arguments) abi.Arguments {
|
||||||
|
args = slices.Clone(args)
|
||||||
|
used := make(map[string]bool)
|
||||||
|
|
||||||
|
for i, input := range args {
|
||||||
|
if isKeyWord(input.Name) {
|
||||||
|
args[i].Name = fmt.Sprintf("arg%d", i)
|
||||||
|
}
|
||||||
|
args[i].Name = abi.ToCamelCase(args[i].Name)
|
||||||
|
if args[i].Name == "" {
|
||||||
|
args[i].Name = fmt.Sprintf("arg%d", i)
|
||||||
|
} else {
|
||||||
|
args[i].Name = strings.ToLower(args[i].Name[:1]) + args[i].Name[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
for index := 0; ; index++ {
|
||||||
|
if !used[args[i].Name] {
|
||||||
|
used[args[i].Name] = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
args[i].Name = fmt.Sprintf("%s%d", args[i].Name, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizeErrorOrEventFields normalizes errors/events for emitting through
|
||||||
|
// bindings: Any anonymous fields are given generated names.
|
||||||
|
func (cb *contractBinder) normalizeErrorOrEventFields(originalInputs abi.Arguments) abi.Arguments {
|
||||||
|
normalizedArguments := normalizeArgs(originalInputs)
|
||||||
|
for _, input := range normalizedArguments {
|
||||||
|
if hasStruct(input.Type) {
|
||||||
|
cb.binder.BindStructType(input.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return normalizedArguments
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindEvent normalizes an event and registers it to be emitted in the bindings.
|
||||||
|
func (cb *contractBinder) bindEvent(original abi.Event) error {
|
||||||
|
// Skip anonymous events as they don't support explicit filtering
|
||||||
|
if original.Anonymous {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
normalizedName, err := cb.registerIdentifier(cb.eventIdentifiers, original.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized := original
|
||||||
|
normalized.Name = normalizedName
|
||||||
|
normalized.Inputs = cb.normalizeErrorOrEventFields(original.Inputs)
|
||||||
|
cb.events[original.Name] = &tmplEvent{Original: original, Normalized: normalized}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// bindError normalizes an error and registers it to be emitted in the bindings.
|
||||||
|
func (cb *contractBinder) bindError(original abi.Error) error {
|
||||||
|
normalizedName, err := cb.registerIdentifier(cb.errorIdentifiers, original.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized := original
|
||||||
|
normalized.Name = normalizedName
|
||||||
|
normalized.Inputs = cb.normalizeErrorOrEventFields(original.Inputs)
|
||||||
|
cb.errors[original.Name] = &tmplError{Original: original, Normalized: normalized}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseLibraryDeps extracts references to library dependencies from the unlinked
|
||||||
|
// hex string deployment bytecode.
|
||||||
|
func parseLibraryDeps(unlinkedCode string) (res []string) {
|
||||||
|
reMatchSpecificPattern, err := regexp.Compile(`__\$([a-f0-9]+)\$__`)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, match := range reMatchSpecificPattern.FindAllStringSubmatch(unlinkedCode, -1) {
|
||||||
|
res = append(res, match[1])
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterSorted iterates the map in the lexicographic order of the keys calling
|
||||||
|
// onItem on each. If the callback returns an error, iteration is halted and
|
||||||
|
// the error is returned from iterSorted.
|
||||||
|
func iterSorted[V any](inp map[string]V, onItem func(string, V) error) error {
|
||||||
|
var sortedKeys []string
|
||||||
|
for key := range inp {
|
||||||
|
sortedKeys = append(sortedKeys, key)
|
||||||
|
}
|
||||||
|
sort.Strings(sortedKeys)
|
||||||
|
|
||||||
|
for _, key := range sortedKeys {
|
||||||
|
if err := onItem(key, inp[key]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindV2 generates a Go wrapper around a contract ABI. This wrapper isn't meant
|
||||||
|
// to be used as is in client code, but rather as an intermediate struct which
|
||||||
|
// enforces compile time type safety and naming convention as opposed to having to
|
||||||
|
// manually maintain hard coded strings that break on runtime.
|
||||||
|
func BindV2(types []string, abis []string, bytecodes []string, pkg string, libs map[string]string, aliases map[string]string) (string, error) {
|
||||||
|
b := binder{
|
||||||
|
contracts: make(map[string]*tmplContractV2),
|
||||||
|
structs: make(map[string]*tmplStruct),
|
||||||
|
aliases: aliases,
|
||||||
|
}
|
||||||
|
for i := 0; i < len(types); i++ {
|
||||||
|
// Parse the actual ABI to generate the binding for
|
||||||
|
evmABI, err := abi.JSON(strings.NewReader(abis[i]))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, input := range evmABI.Constructor.Inputs {
|
||||||
|
if hasStruct(input.Type) {
|
||||||
|
bindStructType(input.Type, b.structs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb := newContractBinder(&b)
|
||||||
|
err = iterSorted(evmABI.Methods, func(_ string, original abi.Method) error {
|
||||||
|
return cb.bindMethod(original)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = iterSorted(evmABI.Events, func(_ string, original abi.Event) error {
|
||||||
|
return cb.bindEvent(original)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = iterSorted(evmABI.Errors, func(_ string, original abi.Error) error {
|
||||||
|
return cb.bindError(original)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
b.contracts[types[i]] = newTmplContractV2(types[i], abis[i], bytecodes[i], evmABI.Constructor, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
invertedLibs := make(map[string]string)
|
||||||
|
for pattern, name := range libs {
|
||||||
|
invertedLibs[name] = pattern
|
||||||
|
}
|
||||||
|
data := tmplDataV2{
|
||||||
|
Package: pkg,
|
||||||
|
Contracts: b.contracts,
|
||||||
|
Libraries: invertedLibs,
|
||||||
|
Structs: b.structs,
|
||||||
|
}
|
||||||
|
|
||||||
|
for typ, contract := range data.Contracts {
|
||||||
|
for _, depPattern := range parseLibraryDeps(contract.InputBin) {
|
||||||
|
data.Contracts[typ].Libraries[libs[depPattern]] = depPattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer := new(bytes.Buffer)
|
||||||
|
funcs := map[string]interface{}{
|
||||||
|
"bindtype": bindType,
|
||||||
|
"bindtopictype": bindTopicType,
|
||||||
|
"capitalise": abi.ToCamelCase,
|
||||||
|
"decapitalise": decapitalise,
|
||||||
|
"ispointertype": isPointerType,
|
||||||
|
"underlyingbindtype": underlyingBindType,
|
||||||
|
}
|
||||||
|
tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSourceV2))
|
||||||
|
if err := tmpl.Execute(buffer, data); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// Pass the code through gofmt to clean it up
|
||||||
|
code, err := format.Source(buffer.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("%v\n%s", err, buffer)
|
||||||
|
}
|
||||||
|
return string(code), nil
|
||||||
|
}
|
||||||
342
accounts/abi/abigen/bindv2_test.go
Normal file
342
accounts/abi/abigen/bindv2_test.go
Normal file
File diff suppressed because one or more lines are too long
238
accounts/abi/abigen/source2.go.tpl
Normal file
238
accounts/abi/abigen/source2.go.tpl
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package {{.Package}}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math/big"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = 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}}
|
||||||
|
{{capitalise $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 (index $.Libraries .Type) -}}
|
||||||
|
ID: "{{index $.Libraries .Type}}",
|
||||||
|
{{ else -}}
|
||||||
|
ID: "{{.Type}}",
|
||||||
|
{{end -}}
|
||||||
|
{{if .InputBin -}}
|
||||||
|
Bin: "0x{{.InputBin}}",
|
||||||
|
{{end -}}
|
||||||
|
{{if .Libraries -}}
|
||||||
|
Deps: []*bind.MetaData{
|
||||||
|
{{- range $name, $pattern := .Libraries}}
|
||||||
|
&{{$name}}MetaData,
|
||||||
|
{{- end}}
|
||||||
|
},
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// {{.Type}} is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type {{.Type}} struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// New{{.Type}} creates a new instance of {{.Type}}.
|
||||||
|
func New{{.Type}}() *{{.Type}} {
|
||||||
|
parsed, err := {{.Type}}MetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &{{.Type}}{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *{{.Type}}) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ if .Constructor.Inputs }}
|
||||||
|
// PackConstructor is the Go binding used to pack the parameters required for
|
||||||
|
// contract deployment.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Constructor.String}}
|
||||||
|
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) PackConstructor({{range .Constructor.Inputs}} {{.Name}} {{bindtype .Type $structs}}, {{end}}) []byte {
|
||||||
|
enc, err := {{ decapitalise $contract.Type}}.abi.Pack("" {{range .Constructor.Inputs}}, {{.Name}}{{end}})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{range .Calls}}
|
||||||
|
// Pack{{.Normalized.Name}} is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Pack{{.Normalized.Name}}({{range .Normalized.Inputs}} {{.Name}} {{bindtype .Type $structs}}, {{end}}) []byte {
|
||||||
|
enc, err := {{ decapitalise $contract.Type}}.abi.Pack("{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/* Unpack method is needed only when there are return args */}}
|
||||||
|
{{if .Normalized.Outputs }}
|
||||||
|
{{ if .Structured }}
|
||||||
|
// {{.Normalized.Name}}Output serves as a container for the return parameters of contract
|
||||||
|
// method {{ .Normalized.Name }}.
|
||||||
|
type {{.Normalized.Name}}Output struct {
|
||||||
|
{{range .Normalized.Outputs}}
|
||||||
|
{{capitalise .Name}} {{bindtype .Type $structs}}{{end}}
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
// Unpack{{.Normalized.Name}} is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x{{printf "%x" .Original.ID}}.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}(data []byte) (
|
||||||
|
{{- if .Structured}} {{.Normalized.Name}}Output,{{else}}
|
||||||
|
{{- range .Normalized.Outputs}} {{bindtype .Type $structs}},{{- end }}
|
||||||
|
{{- end }} error) {
|
||||||
|
out, err := {{ decapitalise $contract.Type}}.abi.Unpack("{{.Original.Name}}", data)
|
||||||
|
{{- if .Structured}}
|
||||||
|
outstruct := new({{.Normalized.Name}}Output)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
{{- range $i, $t := .Normalized.Outputs}}
|
||||||
|
{{- if ispointertype .Type}}
|
||||||
|
outstruct.{{capitalise .Name}} = abi.ConvertType(out[{{$i}}], new({{underlyingbindtype .Type }})).({{bindtype .Type $structs}})
|
||||||
|
{{- else }}
|
||||||
|
outstruct.{{capitalise .Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}})
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
return *outstruct, err
|
||||||
|
{{else}}
|
||||||
|
if err != nil {
|
||||||
|
return {{range $i, $_ := .Normalized.Outputs}}{{if ispointertype .Type}}new({{underlyingbindtype .Type }}), {{else}}*new({{bindtype .Type $structs}}), {{end}}{{end}} err
|
||||||
|
}
|
||||||
|
{{- range $i, $t := .Normalized.Outputs}}
|
||||||
|
{{- if ispointertype .Type }}
|
||||||
|
out{{$i}} := abi.ConvertType(out[{{$i}}], new({{underlyingbindtype .Type}})).({{bindtype .Type $structs}})
|
||||||
|
{{- else }}
|
||||||
|
out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}})
|
||||||
|
{{- end }}
|
||||||
|
{{- end}}
|
||||||
|
return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err
|
||||||
|
{{- end}}
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{range .Events}}
|
||||||
|
// {{$contract.Type}}{{.Normalized.Name}} represents a {{.Original.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
|
||||||
|
}
|
||||||
|
|
||||||
|
const {{$contract.Type}}{{.Normalized.Name}}EventName = "{{.Original.Name}}"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func ({{$contract.Type}}{{.Normalized.Name}}) ContractEventName() string {
|
||||||
|
return {{$contract.Type}}{{.Normalized.Name}}EventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpack{{.Normalized.Name}}Event is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}Event(log *types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
||||||
|
event := "{{.Original.Name}}"
|
||||||
|
if log.Topics[0] != {{ decapitalise $contract.Type}}.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new({{$contract.Type}}{{.Normalized.Name}})
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := {{ decapitalise $contract.Type}}.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range {{ decapitalise $contract.Type}}.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{ if .Errors }}
|
||||||
|
// UnpackError attempts to decode the provided error data using user-defined
|
||||||
|
// error definitions.
|
||||||
|
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) UnpackError(raw []byte) (any, error) {
|
||||||
|
{{- range $k, $v := .Errors}}
|
||||||
|
if bytes.Equal(raw[:4], {{ decapitalise $contract.Type}}.abi.Errors["{{.Normalized.Name}}"].ID.Bytes()[:4]) {
|
||||||
|
return {{ decapitalise $contract.Type}}.Unpack{{.Normalized.Name}}Error(raw[4:])
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
|
return nil, errors.New("Unknown error")
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{range .Errors}}
|
||||||
|
// {{$contract.Type}}{{.Normalized.Name}} represents a {{.Original.Name}} error 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}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorID returns the hash of canonical representation of the error's signature.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func {{$contract.Type}}{{.Normalized.Name}}ErrorID() common.Hash {
|
||||||
|
return common.HexToHash("{{.Original.ID}}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpack{{.Normalized.Name}}Error is the Go binding used to decode the provided
|
||||||
|
// error data into the corresponding Go error struct.
|
||||||
|
//
|
||||||
|
// Solidity: {{.Original.String}}
|
||||||
|
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}Error(raw []byte) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
||||||
|
out := new({{$contract.Type}}{{.Normalized.Name}})
|
||||||
|
if err := {{ decapitalise $contract.Type}}.abi.UnpackIntoInterface(out, "{{.Normalized.Name}}", raw); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
|
@ -14,10 +14,12 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package bind
|
package abigen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
)
|
)
|
||||||
|
|
@ -42,10 +44,48 @@ type tmplContract struct {
|
||||||
Fallback *tmplMethod // Additional special fallback function
|
Fallback *tmplMethod // Additional special fallback function
|
||||||
Receive *tmplMethod // Additional special receive function
|
Receive *tmplMethod // Additional special receive function
|
||||||
Events map[string]*tmplEvent // Contract events accessors
|
Events map[string]*tmplEvent // Contract events accessors
|
||||||
Libraries map[string]string // Same as tmplData, but filtered to only keep what the contract needs
|
Libraries map[string]string // Same as tmplData, but filtered to only keep direct deps that the contract needs
|
||||||
Library bool // Indicator whether the contract is a library
|
Library bool // Indicator whether the contract is a library
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type tmplContractV2 struct {
|
||||||
|
Type string // Type name of the main contract binding
|
||||||
|
InputABI string // JSON ABI used as the input to generate the binding from
|
||||||
|
InputBin string // Optional EVM bytecode used to generate deploy code from
|
||||||
|
Constructor abi.Method // Contract constructor for deploy parametrization
|
||||||
|
Calls map[string]*tmplMethod // All contract methods (excluding fallback, receive)
|
||||||
|
Events map[string]*tmplEvent // Contract events accessors
|
||||||
|
Libraries map[string]string // all direct library dependencies
|
||||||
|
Errors map[string]*tmplError // all errors defined
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTmplContractV2(typ string, abiStr string, bytecode string, constructor abi.Method, cb *contractBinder) *tmplContractV2 {
|
||||||
|
// Strip any whitespace from the JSON ABI
|
||||||
|
strippedABI := strings.Map(func(r rune) rune {
|
||||||
|
if unicode.IsSpace(r) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}, abiStr)
|
||||||
|
return &tmplContractV2{
|
||||||
|
abi.ToCamelCase(typ),
|
||||||
|
strings.ReplaceAll(strippedABI, "\"", "\\\""),
|
||||||
|
strings.TrimPrefix(strings.TrimSpace(bytecode), "0x"),
|
||||||
|
constructor,
|
||||||
|
cb.calls,
|
||||||
|
cb.events,
|
||||||
|
make(map[string]string),
|
||||||
|
cb.errors,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type tmplDataV2 struct {
|
||||||
|
Package string // Name of the package to use for the generated bindings
|
||||||
|
Contracts map[string]*tmplContractV2 // Contracts that will be emitted in the bindings (keyed by contract name)
|
||||||
|
Libraries map[string]string // Map of the contract's name to link pattern
|
||||||
|
Structs map[string]*tmplStruct // Contract struct type definitions
|
||||||
|
}
|
||||||
|
|
||||||
// tmplMethod is a wrapper around an abi.Method that contains a few preprocessed
|
// tmplMethod is a wrapper around an abi.Method that contains a few preprocessed
|
||||||
// and cached data fields.
|
// and cached data fields.
|
||||||
type tmplMethod struct {
|
type tmplMethod struct {
|
||||||
|
|
@ -61,6 +101,13 @@ type tmplEvent struct {
|
||||||
Normalized abi.Event // Normalized version of the parsed fields
|
Normalized abi.Event // Normalized version of the parsed fields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tmplError is a wrapper around an abi.Error that contains a few preprocessed
|
||||||
|
// and cached data fields.
|
||||||
|
type tmplError struct {
|
||||||
|
Original abi.Error
|
||||||
|
Normalized abi.Error
|
||||||
|
}
|
||||||
|
|
||||||
// tmplField is a wrapper around a struct field with binding language
|
// tmplField is a wrapper around a struct field with binding language
|
||||||
// struct type definition and relative filed name.
|
// struct type definition and relative filed name.
|
||||||
type tmplField struct {
|
type tmplField struct {
|
||||||
|
|
@ -76,14 +123,14 @@ type tmplStruct struct {
|
||||||
Fields []*tmplField // Struct fields definition depends on the binding language.
|
Fields []*tmplField // Struct fields definition depends on the binding language.
|
||||||
}
|
}
|
||||||
|
|
||||||
// tmplSource is language to template mapping containing all the supported
|
// tmplSource is the Go source template that the generated Go contract binding
|
||||||
// programming languages the package can generate to.
|
|
||||||
var tmplSource = map[Lang]string{
|
|
||||||
LangGo: tmplSourceGo,
|
|
||||||
}
|
|
||||||
|
|
||||||
// tmplSourceGo is the Go source template that the generated Go contract binding
|
|
||||||
// is based on.
|
// is based on.
|
||||||
//
|
//
|
||||||
//go:embed source.go.tpl
|
//go:embed source.go.tpl
|
||||||
var tmplSourceGo string
|
var tmplSource string
|
||||||
|
|
||||||
|
// tmplSourceV2 is the Go source template that the generated Go contract binding
|
||||||
|
// for abigen v2 is based on.
|
||||||
|
//
|
||||||
|
//go:embed source2.go.tpl
|
||||||
|
var tmplSourceV2 string
|
||||||
64
accounts/abi/abigen/testdata/v2/callbackparam.go.txt
vendored
Normal file
64
accounts/abi/abigen/testdata/v2/callbackparam.go.txt
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// CallbackParamMetaData contains all meta data concerning the CallbackParam contract.
|
||||||
|
var CallbackParamMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":false,\"inputs\":[{\"name\":\"callback\",\"type\":\"function\"}],\"name\":\"test\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
|
||||||
|
ID: "949f96f86d3c2e1bcc15563ad898beaaca",
|
||||||
|
Bin: "0x608060405234801561001057600080fd5b5061015e806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063d7a5aba214610040575b600080fd5b34801561004c57600080fd5b506100be6004803603602081101561006357600080fd5b810190808035806c0100000000000000000000000090049068010000000000000000900463ffffffff1677ffffffffffffffffffffffffffffffffffffffffffffffff169091602001919093929190939291905050506100c0565b005b818160016040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561011657600080fd5b505af115801561012a573d6000803e3d6000fd5b50505050505056fea165627a7a7230582062f87455ff84be90896dbb0c4e4ddb505c600d23089f8e80a512548440d7e2580029",
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallbackParam is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type CallbackParam struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCallbackParam creates a new instance of CallbackParam.
|
||||||
|
func NewCallbackParam() *CallbackParam {
|
||||||
|
parsed, err := CallbackParamMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &CallbackParam{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *CallbackParam) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTest is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xd7a5aba2.
|
||||||
|
//
|
||||||
|
// Solidity: function test(function callback) returns()
|
||||||
|
func (callbackParam *CallbackParam) PackTest(callback [24]byte) []byte {
|
||||||
|
enc, err := callbackParam.abi.Pack("test", callback)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
304
accounts/abi/abigen/testdata/v2/crowdsale.go.txt
vendored
Normal file
304
accounts/abi/abigen/testdata/v2/crowdsale.go.txt
vendored
Normal file
|
|
@ -0,0 +1,304 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// CrowdsaleMetaData contains all meta data concerning the Crowdsale contract.
|
||||||
|
var CrowdsaleMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":false,\"inputs\":[],\"name\":\"checkGoalReached\",\"outputs\":[],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"deadline\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"tokenReward\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"fundingGoal\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"amountRaised\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"price\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"funders\",\"outputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"inputs\":[{\"name\":\"ifSuccessfulSendTo\",\"type\":\"address\"},{\"name\":\"fundingGoalInEthers\",\"type\":\"uint256\"},{\"name\":\"durationInMinutes\",\"type\":\"uint256\"},{\"name\":\"etherCostOfEachToken\",\"type\":\"uint256\"},{\"name\":\"addressOfTokenUsedAsReward\",\"type\":\"address\"}],\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"backer\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"isContribution\",\"type\":\"bool\"}],\"name\":\"FundTransfer\",\"type\":\"event\"}]",
|
||||||
|
ID: "84d7e935785c5c648282d326307bb8fa0d",
|
||||||
|
Bin: "0x606060408190526007805460ff1916905560a0806105a883396101006040529051608051915160c05160e05160008054600160a060020a03199081169095178155670de0b6b3a7640000958602600155603c9093024201600355930260045560058054909216909217905561052f90819061007990396000f36060604052361561006c5760e060020a600035046301cb3b20811461008257806329dcb0cf1461014457806338af3eed1461014d5780636e66f6e91461015f5780637a3a0e84146101715780637b3e5e7b1461017a578063a035b1fe14610183578063dc0d3dff1461018c575b61020060075460009060ff161561032357610002565b61020060035460009042106103205760025460015490106103cb576002548154600160a060020a0316908290606082818181858883f150915460025460408051600160a060020a039390931683526020830191909152818101869052517fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf6945090819003909201919050a15b60405160008054600160a060020a039081169230909116319082818181858883f150506007805460ff1916600117905550505050565b6103a160035481565b6103ab600054600160a060020a031681565b6103ab600554600160a060020a031681565b6103a160015481565b6103a160025481565b6103a160045481565b6103be60043560068054829081101561000257506000526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f8101547ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d409190910154600160a060020a03919091169082565b005b505050815481101561000257906000526020600020906002020160005060008201518160000160006101000a815481600160a060020a030219169083021790555060208201518160010160005055905050806002600082828250540192505081905550600560009054906101000a9004600160a060020a0316600160a060020a031663a9059cbb3360046000505484046040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506000604051808303816000876161da5a03f11561000257505060408051600160a060020a03331681526020810184905260018183015290517fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf692509081900360600190a15b50565b5060a0604052336060908152346080819052600680546001810180835592939282908280158290116102025760020281600202836000526020600020918201910161020291905b8082111561039d57805473ffffffffffffffffffffffffffffffffffffffff19168155600060019190910190815561036a565b5090565b6060908152602090f35b600160a060020a03166060908152602090f35b6060918252608052604090f35b5b60065481101561010e576006805482908110156100025760009182526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0190600680549254600160a060020a0316928490811015610002576002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40015460405190915082818181858883f19350505050507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf660066000508281548110156100025760008290526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01548154600160a060020a039190911691908490811015610002576002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40015460408051600160a060020a0394909416845260208401919091526000838201525191829003606001919050a16001016103cc56",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crowdsale is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Crowdsale struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCrowdsale creates a new instance of Crowdsale.
|
||||||
|
func NewCrowdsale() *Crowdsale {
|
||||||
|
parsed, err := CrowdsaleMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Crowdsale{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Crowdsale) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackConstructor is the Go binding used to pack the parameters required for
|
||||||
|
// contract deployment.
|
||||||
|
//
|
||||||
|
// Solidity: constructor(address ifSuccessfulSendTo, uint256 fundingGoalInEthers, uint256 durationInMinutes, uint256 etherCostOfEachToken, address addressOfTokenUsedAsReward) returns()
|
||||||
|
func (crowdsale *Crowdsale) PackConstructor(ifSuccessfulSendTo common.Address, fundingGoalInEthers *big.Int, durationInMinutes *big.Int, etherCostOfEachToken *big.Int, addressOfTokenUsedAsReward common.Address) []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("", ifSuccessfulSendTo, fundingGoalInEthers, durationInMinutes, etherCostOfEachToken, addressOfTokenUsedAsReward)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackAmountRaised is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x7b3e5e7b.
|
||||||
|
//
|
||||||
|
// Solidity: function amountRaised() returns(uint256)
|
||||||
|
func (crowdsale *Crowdsale) PackAmountRaised() []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("amountRaised")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackAmountRaised is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x7b3e5e7b.
|
||||||
|
//
|
||||||
|
// Solidity: function amountRaised() returns(uint256)
|
||||||
|
func (crowdsale *Crowdsale) UnpackAmountRaised(data []byte) (*big.Int, error) {
|
||||||
|
out, err := crowdsale.abi.Unpack("amountRaised", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackBeneficiary is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x38af3eed.
|
||||||
|
//
|
||||||
|
// Solidity: function beneficiary() returns(address)
|
||||||
|
func (crowdsale *Crowdsale) PackBeneficiary() []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("beneficiary")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBeneficiary is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x38af3eed.
|
||||||
|
//
|
||||||
|
// Solidity: function beneficiary() returns(address)
|
||||||
|
func (crowdsale *Crowdsale) UnpackBeneficiary(data []byte) (common.Address, error) {
|
||||||
|
out, err := crowdsale.abi.Unpack("beneficiary", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(common.Address), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackCheckGoalReached is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x01cb3b20.
|
||||||
|
//
|
||||||
|
// Solidity: function checkGoalReached() returns()
|
||||||
|
func (crowdsale *Crowdsale) PackCheckGoalReached() []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("checkGoalReached")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDeadline is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x29dcb0cf.
|
||||||
|
//
|
||||||
|
// Solidity: function deadline() returns(uint256)
|
||||||
|
func (crowdsale *Crowdsale) PackDeadline() []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("deadline")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDeadline is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x29dcb0cf.
|
||||||
|
//
|
||||||
|
// Solidity: function deadline() returns(uint256)
|
||||||
|
func (crowdsale *Crowdsale) UnpackDeadline(data []byte) (*big.Int, error) {
|
||||||
|
out, err := crowdsale.abi.Unpack("deadline", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackFunders is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xdc0d3dff.
|
||||||
|
//
|
||||||
|
// Solidity: function funders(uint256 ) returns(address addr, uint256 amount)
|
||||||
|
func (crowdsale *Crowdsale) PackFunders(arg0 *big.Int) []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("funders", arg0)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// FundersOutput serves as a container for the return parameters of contract
|
||||||
|
// method Funders.
|
||||||
|
type FundersOutput struct {
|
||||||
|
Addr common.Address
|
||||||
|
Amount *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackFunders is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xdc0d3dff.
|
||||||
|
//
|
||||||
|
// Solidity: function funders(uint256 ) returns(address addr, uint256 amount)
|
||||||
|
func (crowdsale *Crowdsale) UnpackFunders(data []byte) (FundersOutput, error) {
|
||||||
|
out, err := crowdsale.abi.Unpack("funders", data)
|
||||||
|
outstruct := new(FundersOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Addr = *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
|
||||||
|
outstruct.Amount = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackFundingGoal is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x7a3a0e84.
|
||||||
|
//
|
||||||
|
// Solidity: function fundingGoal() returns(uint256)
|
||||||
|
func (crowdsale *Crowdsale) PackFundingGoal() []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("fundingGoal")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackFundingGoal is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x7a3a0e84.
|
||||||
|
//
|
||||||
|
// Solidity: function fundingGoal() returns(uint256)
|
||||||
|
func (crowdsale *Crowdsale) UnpackFundingGoal(data []byte) (*big.Int, error) {
|
||||||
|
out, err := crowdsale.abi.Unpack("fundingGoal", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackPrice is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xa035b1fe.
|
||||||
|
//
|
||||||
|
// Solidity: function price() returns(uint256)
|
||||||
|
func (crowdsale *Crowdsale) PackPrice() []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("price")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackPrice is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xa035b1fe.
|
||||||
|
//
|
||||||
|
// Solidity: function price() returns(uint256)
|
||||||
|
func (crowdsale *Crowdsale) UnpackPrice(data []byte) (*big.Int, error) {
|
||||||
|
out, err := crowdsale.abi.Unpack("price", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTokenReward is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x6e66f6e9.
|
||||||
|
//
|
||||||
|
// Solidity: function tokenReward() returns(address)
|
||||||
|
func (crowdsale *Crowdsale) PackTokenReward() []byte {
|
||||||
|
enc, err := crowdsale.abi.Pack("tokenReward")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackTokenReward is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x6e66f6e9.
|
||||||
|
//
|
||||||
|
// Solidity: function tokenReward() returns(address)
|
||||||
|
func (crowdsale *Crowdsale) UnpackTokenReward(data []byte) (common.Address, error) {
|
||||||
|
out, err := crowdsale.abi.Unpack("tokenReward", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(common.Address), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CrowdsaleFundTransfer represents a FundTransfer event raised by the Crowdsale contract.
|
||||||
|
type CrowdsaleFundTransfer struct {
|
||||||
|
Backer common.Address
|
||||||
|
Amount *big.Int
|
||||||
|
IsContribution bool
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const CrowdsaleFundTransferEventName = "FundTransfer"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (CrowdsaleFundTransfer) ContractEventName() string {
|
||||||
|
return CrowdsaleFundTransferEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackFundTransferEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event FundTransfer(address backer, uint256 amount, bool isContribution)
|
||||||
|
func (crowdsale *Crowdsale) UnpackFundTransferEvent(log *types.Log) (*CrowdsaleFundTransfer, error) {
|
||||||
|
event := "FundTransfer"
|
||||||
|
if log.Topics[0] != crowdsale.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(CrowdsaleFundTransfer)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := crowdsale.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range crowdsale.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
655
accounts/abi/abigen/testdata/v2/dao.go.txt
vendored
Normal file
655
accounts/abi/abigen/testdata/v2/dao.go.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
114
accounts/abi/abigen/testdata/v2/deeplynestedarray.go.txt
vendored
Normal file
114
accounts/abi/abigen/testdata/v2/deeplynestedarray.go.txt
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeeplyNestedArrayMetaData contains all meta data concerning the DeeplyNestedArray contract.
|
||||||
|
var DeeplyNestedArrayMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":false,\"inputs\":[{\"name\":\"arr\",\"type\":\"uint64[3][4][5]\"}],\"name\":\"storeDeepUintArray\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"retrieveDeepArray\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64[3][4][5]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"deepUint64Array\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
|
||||||
|
ID: "3a44c26b21f02743d5dbeb02d24a67bf41",
|
||||||
|
Bin: "0x6060604052341561000f57600080fd5b6106438061001e6000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063344248551461005c5780638ed4573a1461011457806398ed1856146101ab575b600080fd5b341561006757600080fd5b610112600480806107800190600580602002604051908101604052809291906000905b828210156101055783826101800201600480602002604051908101604052809291906000905b828210156100f25783826060020160038060200260405190810160405280929190826003602002808284378201915050505050815260200190600101906100b0565b505050508152602001906001019061008a565b5050505091905050610208565b005b341561011f57600080fd5b61012761021d565b604051808260056000925b8184101561019b578284602002015160046000925b8184101561018d5782846020020151600360200280838360005b8381101561017c578082015181840152602081019050610161565b505050509050019260010192610147565b925050509260010192610132565b9250505091505060405180910390f35b34156101b657600080fd5b6101de6004808035906020019091908035906020019091908035906020019091905050610309565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b80600090600561021992919061035f565b5050565b6102256103b0565b6000600580602002604051908101604052809291906000905b8282101561030057838260040201600480602002604051908101604052809291906000905b828210156102ed578382016003806020026040519081016040528092919082600380156102d9576020028201916000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff16815260200190600801906020826007010492830192600103820291508084116102945790505b505050505081526020019060010190610263565b505050508152602001906001019061023e565b50505050905090565b60008360058110151561031857fe5b600402018260048110151561032957fe5b018160038110151561033757fe5b6004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b826005600402810192821561039f579160200282015b8281111561039e5782518290600461038e9291906103df565b5091602001919060040190610375565b5b5090506103ac919061042d565b5090565b610780604051908101604052806005905b6103c9610459565b8152602001906001900390816103c15790505090565b826004810192821561041c579160200282015b8281111561041b5782518290600361040b929190610488565b50916020019190600101906103f2565b5b5090506104299190610536565b5090565b61045691905b8082111561045257600081816104499190610562565b50600401610433565b5090565b90565b610180604051908101604052806004905b6104726105a7565b81526020019060019003908161046a5790505090565b82600380016004900481019282156105255791602002820160005b838211156104ef57835183826101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555092602001926008016020816007010492830192600103026104a3565b80156105235782816101000a81549067ffffffffffffffff02191690556008016020816007010492830192600103026104ef565b505b50905061053291906105d9565b5090565b61055f91905b8082111561055b57600081816105529190610610565b5060010161053c565b5090565b90565b50600081816105719190610610565b50600101600081816105839190610610565b50600101600081816105959190610610565b5060010160006105a59190610610565b565b6060604051908101604052806003905b600067ffffffffffffffff168152602001906001900390816105b75790505090565b61060d91905b8082111561060957600081816101000a81549067ffffffffffffffff0219169055506001016105df565b5090565b90565b50600090555600a165627a7a7230582087e5a43f6965ab6ef7a4ff056ab80ed78fd8c15cff57715a1bf34ec76a93661c0029",
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeeplyNestedArray is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type DeeplyNestedArray struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDeeplyNestedArray creates a new instance of DeeplyNestedArray.
|
||||||
|
func NewDeeplyNestedArray() *DeeplyNestedArray {
|
||||||
|
parsed, err := DeeplyNestedArrayMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &DeeplyNestedArray{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *DeeplyNestedArray) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDeepUint64Array is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x98ed1856.
|
||||||
|
//
|
||||||
|
// Solidity: function deepUint64Array(uint256 , uint256 , uint256 ) view returns(uint64)
|
||||||
|
func (deeplyNestedArray *DeeplyNestedArray) PackDeepUint64Array(arg0 *big.Int, arg1 *big.Int, arg2 *big.Int) []byte {
|
||||||
|
enc, err := deeplyNestedArray.abi.Pack("deepUint64Array", arg0, arg1, arg2)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDeepUint64Array is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x98ed1856.
|
||||||
|
//
|
||||||
|
// Solidity: function deepUint64Array(uint256 , uint256 , uint256 ) view returns(uint64)
|
||||||
|
func (deeplyNestedArray *DeeplyNestedArray) UnpackDeepUint64Array(data []byte) (uint64, error) {
|
||||||
|
out, err := deeplyNestedArray.abi.Unpack("deepUint64Array", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(uint64), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackRetrieveDeepArray is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x8ed4573a.
|
||||||
|
//
|
||||||
|
// Solidity: function retrieveDeepArray() view returns(uint64[3][4][5])
|
||||||
|
func (deeplyNestedArray *DeeplyNestedArray) PackRetrieveDeepArray() []byte {
|
||||||
|
enc, err := deeplyNestedArray.abi.Pack("retrieveDeepArray")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackRetrieveDeepArray is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x8ed4573a.
|
||||||
|
//
|
||||||
|
// Solidity: function retrieveDeepArray() view returns(uint64[3][4][5])
|
||||||
|
func (deeplyNestedArray *DeeplyNestedArray) UnpackRetrieveDeepArray(data []byte) ([5][4][3]uint64, error) {
|
||||||
|
out, err := deeplyNestedArray.abi.Unpack("retrieveDeepArray", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new([5][4][3]uint64), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new([5][4][3]uint64)).(*[5][4][3]uint64)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackStoreDeepUintArray is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x34424855.
|
||||||
|
//
|
||||||
|
// Solidity: function storeDeepUintArray(uint64[3][4][5] arr) returns()
|
||||||
|
func (deeplyNestedArray *DeeplyNestedArray) PackStoreDeepUintArray(arr [5][4][3]uint64) []byte {
|
||||||
|
enc, err := deeplyNestedArray.abi.Pack("storeDeepUintArray", arr)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
52
accounts/abi/abigen/testdata/v2/empty.go.txt
vendored
Normal file
52
accounts/abi/abigen/testdata/v2/empty.go.txt
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// EmptyMetaData contains all meta data concerning the Empty contract.
|
||||||
|
var EmptyMetaData = bind.MetaData{
|
||||||
|
ABI: "[]",
|
||||||
|
ID: "c4ce3210982aa6fc94dabe46dc1dbf454d",
|
||||||
|
Bin: "0x606060405260068060106000396000f3606060405200",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Empty struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEmpty creates a new instance of Empty.
|
||||||
|
func NewEmpty() *Empty {
|
||||||
|
parsed, err := EmptyMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Empty{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Empty) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
261
accounts/abi/abigen/testdata/v2/eventchecker.go.txt
vendored
Normal file
261
accounts/abi/abigen/testdata/v2/eventchecker.go.txt
vendored
Normal file
|
|
@ -0,0 +1,261 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// EventCheckerMetaData contains all meta data concerning the EventChecker contract.
|
||||||
|
var EventCheckerMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"type\":\"event\",\"name\":\"empty\",\"inputs\":[]},{\"type\":\"event\",\"name\":\"indexed\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"indexed\":true},{\"name\":\"num\",\"type\":\"int256\",\"indexed\":true}]},{\"type\":\"event\",\"name\":\"mixed\",\"inputs\":[{\"name\":\"addr\",\"type\":\"address\",\"indexed\":true},{\"name\":\"num\",\"type\":\"int256\"}]},{\"type\":\"event\",\"name\":\"anonymous\",\"anonymous\":true,\"inputs\":[]},{\"type\":\"event\",\"name\":\"dynamic\",\"inputs\":[{\"name\":\"idxStr\",\"type\":\"string\",\"indexed\":true},{\"name\":\"idxDat\",\"type\":\"bytes\",\"indexed\":true},{\"name\":\"str\",\"type\":\"string\"},{\"name\":\"dat\",\"type\":\"bytes\"}]},{\"type\":\"event\",\"name\":\"unnamed\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":true},{\"name\":\"\",\"type\":\"uint256\",\"indexed\":true}]}]",
|
||||||
|
ID: "253d421f98e29b25315bde79c1251ab27c",
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventChecker is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type EventChecker struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEventChecker creates a new instance of EventChecker.
|
||||||
|
func NewEventChecker() *EventChecker {
|
||||||
|
parsed, err := EventCheckerMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &EventChecker{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *EventChecker) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventCheckerDynamic represents a dynamic event raised by the EventChecker contract.
|
||||||
|
type EventCheckerDynamic struct {
|
||||||
|
IdxStr common.Hash
|
||||||
|
IdxDat common.Hash
|
||||||
|
Str string
|
||||||
|
Dat []byte
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const EventCheckerDynamicEventName = "dynamic"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (EventCheckerDynamic) ContractEventName() string {
|
||||||
|
return EventCheckerDynamicEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDynamicEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event dynamic(string indexed idxStr, bytes indexed idxDat, string str, bytes dat)
|
||||||
|
func (eventChecker *EventChecker) UnpackDynamicEvent(log *types.Log) (*EventCheckerDynamic, error) {
|
||||||
|
event := "dynamic"
|
||||||
|
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(EventCheckerDynamic)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range eventChecker.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventCheckerEmpty represents a empty event raised by the EventChecker contract.
|
||||||
|
type EventCheckerEmpty struct {
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const EventCheckerEmptyEventName = "empty"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (EventCheckerEmpty) ContractEventName() string {
|
||||||
|
return EventCheckerEmptyEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackEmptyEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event empty()
|
||||||
|
func (eventChecker *EventChecker) UnpackEmptyEvent(log *types.Log) (*EventCheckerEmpty, error) {
|
||||||
|
event := "empty"
|
||||||
|
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(EventCheckerEmpty)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range eventChecker.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventCheckerIndexed represents a indexed event raised by the EventChecker contract.
|
||||||
|
type EventCheckerIndexed struct {
|
||||||
|
Addr common.Address
|
||||||
|
Num *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const EventCheckerIndexedEventName = "indexed"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (EventCheckerIndexed) ContractEventName() string {
|
||||||
|
return EventCheckerIndexedEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackIndexedEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event indexed(address indexed addr, int256 indexed num)
|
||||||
|
func (eventChecker *EventChecker) UnpackIndexedEvent(log *types.Log) (*EventCheckerIndexed, error) {
|
||||||
|
event := "indexed"
|
||||||
|
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(EventCheckerIndexed)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range eventChecker.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventCheckerMixed represents a mixed event raised by the EventChecker contract.
|
||||||
|
type EventCheckerMixed struct {
|
||||||
|
Addr common.Address
|
||||||
|
Num *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const EventCheckerMixedEventName = "mixed"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (EventCheckerMixed) ContractEventName() string {
|
||||||
|
return EventCheckerMixedEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackMixedEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event mixed(address indexed addr, int256 num)
|
||||||
|
func (eventChecker *EventChecker) UnpackMixedEvent(log *types.Log) (*EventCheckerMixed, error) {
|
||||||
|
event := "mixed"
|
||||||
|
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(EventCheckerMixed)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range eventChecker.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventCheckerUnnamed represents a unnamed event raised by the EventChecker contract.
|
||||||
|
type EventCheckerUnnamed struct {
|
||||||
|
Arg0 *big.Int
|
||||||
|
Arg1 *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const EventCheckerUnnamedEventName = "unnamed"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (EventCheckerUnnamed) ContractEventName() string {
|
||||||
|
return EventCheckerUnnamedEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackUnnamedEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event unnamed(uint256 indexed arg0, uint256 indexed arg1)
|
||||||
|
func (eventChecker *EventChecker) UnpackUnnamedEvent(log *types.Log) (*EventCheckerUnnamed, error) {
|
||||||
|
event := "unnamed"
|
||||||
|
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(EventCheckerUnnamed)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := eventChecker.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range eventChecker.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
89
accounts/abi/abigen/testdata/v2/getter.go.txt
vendored
Normal file
89
accounts/abi/abigen/testdata/v2/getter.go.txt
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetterMetaData contains all meta data concerning the Getter contract.
|
||||||
|
var GetterMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"getter\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"int256\"},{\"name\":\"\",\"type\":\"bytes32\"}],\"type\":\"function\"}]",
|
||||||
|
ID: "e23a74c8979fe93c9fff15e4f51535ad54",
|
||||||
|
Bin: "0x606060405260dc8060106000396000f3606060405260e060020a6000350463993a04b78114601a575b005b600060605260c0604052600260809081527f486900000000000000000000000000000000000000000000000000000000000060a05260017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060e0829052610100819052606060c0908152600261012081905281906101409060a09080838184600060046012f1505081517fffff000000000000000000000000000000000000000000000000000000000000169091525050604051610160819003945092505050f3",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Getter struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetter creates a new instance of Getter.
|
||||||
|
func NewGetter() *Getter {
|
||||||
|
parsed, err := GetterMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Getter{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Getter) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackGetter is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x993a04b7.
|
||||||
|
//
|
||||||
|
// Solidity: function getter() returns(string, int256, bytes32)
|
||||||
|
func (getter *Getter) PackGetter() []byte {
|
||||||
|
enc, err := getter.abi.Pack("getter")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetterOutput serves as a container for the return parameters of contract
|
||||||
|
// method Getter.
|
||||||
|
type GetterOutput struct {
|
||||||
|
Arg0 string
|
||||||
|
Arg1 *big.Int
|
||||||
|
Arg2 [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackGetter is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x993a04b7.
|
||||||
|
//
|
||||||
|
// Solidity: function getter() returns(string, int256, bytes32)
|
||||||
|
func (getter *Getter) UnpackGetter(data []byte) (GetterOutput, error) {
|
||||||
|
out, err := getter.abi.Unpack("getter", data)
|
||||||
|
outstruct := new(GetterOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Arg2 = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
102
accounts/abi/abigen/testdata/v2/identifiercollision.go.txt
vendored
Normal file
102
accounts/abi/abigen/testdata/v2/identifiercollision.go.txt
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// IdentifierCollisionMetaData contains all meta data concerning the IdentifierCollision contract.
|
||||||
|
var IdentifierCollisionMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"MyVar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_myVar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
|
||||||
|
ID: "1863c5622f8ac2c09c42f063ca883fe438",
|
||||||
|
Bin: "0x60806040523480156100115760006000fd5b50610017565b60c3806100256000396000f3fe608060405234801560105760006000fd5b506004361060365760003560e01c806301ad4d8714603c5780634ef1f0ad146058576036565b60006000fd5b60426074565b6040518082815260200191505060405180910390f35b605e607d565b6040518082815260200191505060405180910390f35b60006000505481565b60006000600050549050608b565b9056fea265627a7a7231582067c8d84688b01c4754ba40a2a871cede94ea1f28b5981593ab2a45b46ac43af664736f6c634300050c0032",
|
||||||
|
}
|
||||||
|
|
||||||
|
// IdentifierCollision is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type IdentifierCollision struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIdentifierCollision creates a new instance of IdentifierCollision.
|
||||||
|
func NewIdentifierCollision() *IdentifierCollision {
|
||||||
|
parsed, err := IdentifierCollisionMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &IdentifierCollision{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *IdentifierCollision) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackMyVar is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x4ef1f0ad.
|
||||||
|
//
|
||||||
|
// Solidity: function MyVar() view returns(uint256)
|
||||||
|
func (identifierCollision *IdentifierCollision) PackMyVar() []byte {
|
||||||
|
enc, err := identifierCollision.abi.Pack("MyVar")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackMyVar is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x4ef1f0ad.
|
||||||
|
//
|
||||||
|
// Solidity: function MyVar() view returns(uint256)
|
||||||
|
func (identifierCollision *IdentifierCollision) UnpackMyVar(data []byte) (*big.Int, error) {
|
||||||
|
out, err := identifierCollision.abi.Unpack("MyVar", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackPubVar is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x01ad4d87.
|
||||||
|
//
|
||||||
|
// Solidity: function _myVar() view returns(uint256)
|
||||||
|
func (identifierCollision *IdentifierCollision) PackPubVar() []byte {
|
||||||
|
enc, err := identifierCollision.abi.Pack("_myVar")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackPubVar is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x01ad4d87.
|
||||||
|
//
|
||||||
|
// Solidity: function _myVar() view returns(uint256)
|
||||||
|
func (identifierCollision *IdentifierCollision) UnpackPubVar(data []byte) (*big.Int, error) {
|
||||||
|
out, err := identifierCollision.abi.Unpack("_myVar", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
123
accounts/abi/abigen/testdata/v2/inputchecker.go.txt
vendored
Normal file
123
accounts/abi/abigen/testdata/v2/inputchecker.go.txt
vendored
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// InputCheckerMetaData contains all meta data concerning the InputChecker contract.
|
||||||
|
var InputCheckerMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"type\":\"function\",\"name\":\"noInput\",\"constant\":true,\"inputs\":[],\"outputs\":[]},{\"type\":\"function\",\"name\":\"namedInput\",\"constant\":true,\"inputs\":[{\"name\":\"str\",\"type\":\"string\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"anonInput\",\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"string\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"namedInputs\",\"constant\":true,\"inputs\":[{\"name\":\"str1\",\"type\":\"string\"},{\"name\":\"str2\",\"type\":\"string\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"anonInputs\",\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"string\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"mixedInputs\",\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"str\",\"type\":\"string\"}],\"outputs\":[]}]",
|
||||||
|
ID: "e551ce092312e54f54f45ffdf06caa4cdc",
|
||||||
|
}
|
||||||
|
|
||||||
|
// InputChecker is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type InputChecker struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInputChecker creates a new instance of InputChecker.
|
||||||
|
func NewInputChecker() *InputChecker {
|
||||||
|
parsed, err := InputCheckerMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &InputChecker{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *InputChecker) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackAnonInput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x3e708e82.
|
||||||
|
//
|
||||||
|
// Solidity: function anonInput(string ) returns()
|
||||||
|
func (inputChecker *InputChecker) PackAnonInput(arg0 string) []byte {
|
||||||
|
enc, err := inputChecker.abi.Pack("anonInput", arg0)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackAnonInputs is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x28160527.
|
||||||
|
//
|
||||||
|
// Solidity: function anonInputs(string , string ) returns()
|
||||||
|
func (inputChecker *InputChecker) PackAnonInputs(arg0 string, arg1 string) []byte {
|
||||||
|
enc, err := inputChecker.abi.Pack("anonInputs", arg0, arg1)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackMixedInputs is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xc689ebdc.
|
||||||
|
//
|
||||||
|
// Solidity: function mixedInputs(string , string str) returns()
|
||||||
|
func (inputChecker *InputChecker) PackMixedInputs(arg0 string, str string) []byte {
|
||||||
|
enc, err := inputChecker.abi.Pack("mixedInputs", arg0, str)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackNamedInput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x0d402005.
|
||||||
|
//
|
||||||
|
// Solidity: function namedInput(string str) returns()
|
||||||
|
func (inputChecker *InputChecker) PackNamedInput(str string) []byte {
|
||||||
|
enc, err := inputChecker.abi.Pack("namedInput", str)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackNamedInputs is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x63c796ed.
|
||||||
|
//
|
||||||
|
// Solidity: function namedInputs(string str1, string str2) returns()
|
||||||
|
func (inputChecker *InputChecker) PackNamedInputs(str1 string, str2 string) []byte {
|
||||||
|
enc, err := inputChecker.abi.Pack("namedInputs", str1, str2)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackNoInput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x53539029.
|
||||||
|
//
|
||||||
|
// Solidity: function noInput() returns()
|
||||||
|
func (inputChecker *InputChecker) PackNoInput() []byte {
|
||||||
|
enc, err := inputChecker.abi.Pack("noInput")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
126
accounts/abi/abigen/testdata/v2/interactor.go.txt
vendored
Normal file
126
accounts/abi/abigen/testdata/v2/interactor.go.txt
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// InteractorMetaData contains all meta data concerning the Interactor contract.
|
||||||
|
var InteractorMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"transactString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"deployString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"str\",\"type\":\"string\"}],\"name\":\"transact\",\"outputs\":[],\"type\":\"function\"},{\"inputs\":[{\"name\":\"str\",\"type\":\"string\"}],\"type\":\"constructor\"}]",
|
||||||
|
ID: "f63980878028f3242c9033fdc30fd21a81",
|
||||||
|
Bin: "0x6060604052604051610328380380610328833981016040528051018060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10608d57805160ff19168380011785555b50607c9291505b8082111560ba57838155600101606b565b50505061026a806100be6000396000f35b828001600101855582156064579182015b828111156064578251826000505591602001919060010190609e565b509056606060405260e060020a60003504630d86a0e181146100315780636874e8091461008d578063d736c513146100ea575b005b610190600180546020600282841615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156102295780601f106101fe57610100808354040283529160200191610229565b61019060008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156102295780601f106101fe57610100808354040283529160200191610229565b60206004803580820135601f81018490049093026080908101604052606084815261002f946024939192918401918190838280828437509496505050505050508060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061023157805160ff19168380011785555b506102619291505b808211156102665760008155830161017d565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156101f05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b820191906000526020600020905b81548152906001019060200180831161020c57829003601f168201915b505050505081565b82800160010185558215610175579182015b82811115610175578251826000505591602001919060010190610243565b505050565b509056",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interactor is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Interactor struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInteractor creates a new instance of Interactor.
|
||||||
|
func NewInteractor() *Interactor {
|
||||||
|
parsed, err := InteractorMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Interactor{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Interactor) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackConstructor is the Go binding used to pack the parameters required for
|
||||||
|
// contract deployment.
|
||||||
|
//
|
||||||
|
// Solidity: constructor(string str) returns()
|
||||||
|
func (interactor *Interactor) PackConstructor(str string) []byte {
|
||||||
|
enc, err := interactor.abi.Pack("", str)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDeployString is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x6874e809.
|
||||||
|
//
|
||||||
|
// Solidity: function deployString() returns(string)
|
||||||
|
func (interactor *Interactor) PackDeployString() []byte {
|
||||||
|
enc, err := interactor.abi.Pack("deployString")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDeployString is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x6874e809.
|
||||||
|
//
|
||||||
|
// Solidity: function deployString() returns(string)
|
||||||
|
func (interactor *Interactor) UnpackDeployString(data []byte) (string, error) {
|
||||||
|
out, err := interactor.abi.Unpack("deployString", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(string), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTransact is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xd736c513.
|
||||||
|
//
|
||||||
|
// Solidity: function transact(string str) returns()
|
||||||
|
func (interactor *Interactor) PackTransact(str string) []byte {
|
||||||
|
enc, err := interactor.abi.Pack("transact", str)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTransactString is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x0d86a0e1.
|
||||||
|
//
|
||||||
|
// Solidity: function transactString() returns(string)
|
||||||
|
func (interactor *Interactor) PackTransactString() []byte {
|
||||||
|
enc, err := interactor.abi.Pack("transactString")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackTransactString is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x0d86a0e1.
|
||||||
|
//
|
||||||
|
// Solidity: function transactString() returns(string)
|
||||||
|
func (interactor *Interactor) UnpackTransactString(data []byte) (string, error) {
|
||||||
|
out, err := interactor.abi.Unpack("transactString", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(string), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
137
accounts/abi/abigen/testdata/v2/nameconflict.go.txt
vendored
Normal file
137
accounts/abi/abigen/testdata/v2/nameconflict.go.txt
vendored
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// Oraclerequest is an auto generated low-level Go binding around an user-defined struct.
|
||||||
|
type Oraclerequest struct {
|
||||||
|
Data []byte
|
||||||
|
Data0 []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameConflictMetaData contains all meta data concerning the NameConflict contract.
|
||||||
|
var NameConflictMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"msg\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"_msg\",\"type\":\"int256\"}],\"name\":\"log\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"internalType\":\"structoracle.request\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"addRequest\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"internalType\":\"structoracle.request\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "8f6e2703b307244ae6bd61ed94ce959cf9",
|
||||||
|
Bin: "0x608060405234801561001057600080fd5b5061042b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063c2bb515f1461003b578063cce7b04814610059575b600080fd5b610043610075565b60405161005091906101af565b60405180910390f35b610073600480360381019061006e91906103ac565b6100b5565b005b61007d6100b8565b604051806040016040528060405180602001604052806000815250815260200160405180602001604052806000815250815250905090565b50565b604051806040016040528060608152602001606081525090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561010c5780820151818401526020810190506100f1565b8381111561011b576000848401525b50505050565b6000601f19601f8301169050919050565b600061013d826100d2565b61014781856100dd565b93506101578185602086016100ee565b61016081610121565b840191505092915050565b600060408301600083015184820360008601526101888282610132565b915050602083015184820360208601526101a28282610132565b9150508091505092915050565b600060208201905081810360008301526101c9818461016b565b905092915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61022282610121565b810181811067ffffffffffffffff82111715610241576102406101ea565b5b80604052505050565b60006102546101d1565b90506102608282610219565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff82111561028f5761028e6101ea565b5b61029882610121565b9050602081019050919050565b82818337600083830152505050565b60006102c76102c284610274565b61024a565b9050828152602081018484840111156102e3576102e261026f565b5b6102ee8482856102a5565b509392505050565b600082601f83011261030b5761030a61026a565b5b813561031b8482602086016102b4565b91505092915050565b60006040828403121561033a576103396101e5565b5b610344604061024a565b9050600082013567ffffffffffffffff81111561036457610363610265565b5b610370848285016102f6565b600083015250602082013567ffffffffffffffff81111561039457610393610265565b5b6103a0848285016102f6565b60208301525092915050565b6000602082840312156103c2576103c16101db565b5b600082013567ffffffffffffffff8111156103e0576103df6101e0565b5b6103ec84828501610324565b9150509291505056fea264697066735822122033bca1606af9b6aeba1673f98c52003cec19338539fb44b86690ce82c51483b564736f6c634300080e0033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameConflict is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type NameConflict struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNameConflict creates a new instance of NameConflict.
|
||||||
|
func NewNameConflict() *NameConflict {
|
||||||
|
parsed, err := NameConflictMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &NameConflict{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *NameConflict) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackAddRequest is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xcce7b048.
|
||||||
|
//
|
||||||
|
// Solidity: function addRequest((bytes,bytes) req) pure returns()
|
||||||
|
func (nameConflict *NameConflict) PackAddRequest(req Oraclerequest) []byte {
|
||||||
|
enc, err := nameConflict.abi.Pack("addRequest", req)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackGetRequest is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xc2bb515f.
|
||||||
|
//
|
||||||
|
// Solidity: function getRequest() pure returns((bytes,bytes))
|
||||||
|
func (nameConflict *NameConflict) PackGetRequest() []byte {
|
||||||
|
enc, err := nameConflict.abi.Pack("getRequest")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackGetRequest is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xc2bb515f.
|
||||||
|
//
|
||||||
|
// Solidity: function getRequest() pure returns((bytes,bytes))
|
||||||
|
func (nameConflict *NameConflict) UnpackGetRequest(data []byte) (Oraclerequest, error) {
|
||||||
|
out, err := nameConflict.abi.Unpack("getRequest", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(Oraclerequest), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(Oraclerequest)).(*Oraclerequest)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameConflictLog represents a log event raised by the NameConflict contract.
|
||||||
|
type NameConflictLog struct {
|
||||||
|
Msg *big.Int
|
||||||
|
Msg0 *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const NameConflictLogEventName = "log"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (NameConflictLog) ContractEventName() string {
|
||||||
|
return NameConflictLogEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackLogEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event log(int256 msg, int256 _msg)
|
||||||
|
func (nameConflict *NameConflict) UnpackLogEvent(log *types.Log) (*NameConflictLog, error) {
|
||||||
|
event := "log"
|
||||||
|
if log.Topics[0] != nameConflict.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(NameConflictLog)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := nameConflict.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range nameConflict.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
129
accounts/abi/abigen/testdata/v2/numericmethodname.go.txt
vendored
Normal file
129
accounts/abi/abigen/testdata/v2/numericmethodname.go.txt
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// NumericMethodNameMetaData contains all meta data concerning the NumericMethodName contract.
|
||||||
|
var NumericMethodNameMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_param\",\"type\":\"address\"}],\"name\":\"_1TestEvent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"_1test\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"__1test\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"__2test\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "a691b347afbc44b90dd9a1dfbc65661904",
|
||||||
|
Bin: "0x6080604052348015600f57600080fd5b5060958061001e6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80639d993132146041578063d02767c7146049578063ffa02795146051575b600080fd5b60476059565b005b604f605b565b005b6057605d565b005b565b565b56fea26469706673582212200382ca602dff96a7e2ba54657985e2b4ac423a56abe4a1f0667bc635c4d4371f64736f6c63430008110033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumericMethodName is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type NumericMethodName struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNumericMethodName creates a new instance of NumericMethodName.
|
||||||
|
func NewNumericMethodName() *NumericMethodName {
|
||||||
|
parsed, err := NumericMethodNameMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &NumericMethodName{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *NumericMethodName) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackE1test is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xffa02795.
|
||||||
|
//
|
||||||
|
// Solidity: function _1test() pure returns()
|
||||||
|
func (numericMethodName *NumericMethodName) PackE1test() []byte {
|
||||||
|
enc, err := numericMethodName.abi.Pack("_1test")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackE1test0 is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xd02767c7.
|
||||||
|
//
|
||||||
|
// Solidity: function __1test() pure returns()
|
||||||
|
func (numericMethodName *NumericMethodName) PackE1test0() []byte {
|
||||||
|
enc, err := numericMethodName.abi.Pack("__1test")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackE2test is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x9d993132.
|
||||||
|
//
|
||||||
|
// Solidity: function __2test() pure returns()
|
||||||
|
func (numericMethodName *NumericMethodName) PackE2test() []byte {
|
||||||
|
enc, err := numericMethodName.abi.Pack("__2test")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumericMethodNameE1TestEvent represents a _1TestEvent event raised by the NumericMethodName contract.
|
||||||
|
type NumericMethodNameE1TestEvent struct {
|
||||||
|
Param common.Address
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const NumericMethodNameE1TestEventEventName = "_1TestEvent"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (NumericMethodNameE1TestEvent) ContractEventName() string {
|
||||||
|
return NumericMethodNameE1TestEventEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackE1TestEventEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event _1TestEvent(address _param)
|
||||||
|
func (numericMethodName *NumericMethodName) UnpackE1TestEventEvent(log *types.Log) (*NumericMethodNameE1TestEvent, error) {
|
||||||
|
event := "_1TestEvent"
|
||||||
|
if log.Topics[0] != numericMethodName.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(NumericMethodNameE1TestEvent)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := numericMethodName.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range numericMethodName.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
253
accounts/abi/abigen/testdata/v2/outputchecker.go.txt
vendored
Normal file
253
accounts/abi/abigen/testdata/v2/outputchecker.go.txt
vendored
Normal file
|
|
@ -0,0 +1,253 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// OutputCheckerMetaData contains all meta data concerning the OutputChecker contract.
|
||||||
|
var OutputCheckerMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"type\":\"function\",\"name\":\"noOutput\",\"constant\":true,\"inputs\":[],\"outputs\":[]},{\"type\":\"function\",\"name\":\"namedOutput\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"str\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"anonOutput\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"namedOutputs\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"str1\",\"type\":\"string\"},{\"name\":\"str2\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"collidingOutputs\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"str\",\"type\":\"string\"},{\"name\":\"Str\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"anonOutputs\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"string\"}]},{\"type\":\"function\",\"name\":\"mixedOutputs\",\"constant\":true,\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\"},{\"name\":\"str\",\"type\":\"string\"}]}]",
|
||||||
|
ID: "cc1d4e235801a590b506d5130b0cca90a1",
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutputChecker is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type OutputChecker struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOutputChecker creates a new instance of OutputChecker.
|
||||||
|
func NewOutputChecker() *OutputChecker {
|
||||||
|
parsed, err := OutputCheckerMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &OutputChecker{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *OutputChecker) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackAnonOutput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x008bda05.
|
||||||
|
//
|
||||||
|
// Solidity: function anonOutput() returns(string)
|
||||||
|
func (outputChecker *OutputChecker) PackAnonOutput() []byte {
|
||||||
|
enc, err := outputChecker.abi.Pack("anonOutput")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackAnonOutput is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x008bda05.
|
||||||
|
//
|
||||||
|
// Solidity: function anonOutput() returns(string)
|
||||||
|
func (outputChecker *OutputChecker) UnpackAnonOutput(data []byte) (string, error) {
|
||||||
|
out, err := outputChecker.abi.Unpack("anonOutput", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(string), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackAnonOutputs is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x3c401115.
|
||||||
|
//
|
||||||
|
// Solidity: function anonOutputs() returns(string, string)
|
||||||
|
func (outputChecker *OutputChecker) PackAnonOutputs() []byte {
|
||||||
|
enc, err := outputChecker.abi.Pack("anonOutputs")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnonOutputsOutput serves as a container for the return parameters of contract
|
||||||
|
// method AnonOutputs.
|
||||||
|
type AnonOutputsOutput struct {
|
||||||
|
Arg0 string
|
||||||
|
Arg1 string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackAnonOutputs is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x3c401115.
|
||||||
|
//
|
||||||
|
// Solidity: function anonOutputs() returns(string, string)
|
||||||
|
func (outputChecker *OutputChecker) UnpackAnonOutputs(data []byte) (AnonOutputsOutput, error) {
|
||||||
|
out, err := outputChecker.abi.Unpack("anonOutputs", data)
|
||||||
|
outstruct := new(AnonOutputsOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
outstruct.Arg1 = *abi.ConvertType(out[1], new(string)).(*string)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackCollidingOutputs is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xeccbc1ee.
|
||||||
|
//
|
||||||
|
// Solidity: function collidingOutputs() returns(string str, string Str)
|
||||||
|
func (outputChecker *OutputChecker) PackCollidingOutputs() []byte {
|
||||||
|
enc, err := outputChecker.abi.Pack("collidingOutputs")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollidingOutputsOutput serves as a container for the return parameters of contract
|
||||||
|
// method CollidingOutputs.
|
||||||
|
type CollidingOutputsOutput struct {
|
||||||
|
Str string
|
||||||
|
Str0 string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackCollidingOutputs is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xeccbc1ee.
|
||||||
|
//
|
||||||
|
// Solidity: function collidingOutputs() returns(string str, string Str)
|
||||||
|
func (outputChecker *OutputChecker) UnpackCollidingOutputs(data []byte) (CollidingOutputsOutput, error) {
|
||||||
|
out, err := outputChecker.abi.Unpack("collidingOutputs", data)
|
||||||
|
outstruct := new(CollidingOutputsOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Str = *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
outstruct.Str0 = *abi.ConvertType(out[1], new(string)).(*string)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackMixedOutputs is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x21b77b44.
|
||||||
|
//
|
||||||
|
// Solidity: function mixedOutputs() returns(string, string str)
|
||||||
|
func (outputChecker *OutputChecker) PackMixedOutputs() []byte {
|
||||||
|
enc, err := outputChecker.abi.Pack("mixedOutputs")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// MixedOutputsOutput serves as a container for the return parameters of contract
|
||||||
|
// method MixedOutputs.
|
||||||
|
type MixedOutputsOutput struct {
|
||||||
|
Arg0 string
|
||||||
|
Str string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackMixedOutputs is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x21b77b44.
|
||||||
|
//
|
||||||
|
// Solidity: function mixedOutputs() returns(string, string str)
|
||||||
|
func (outputChecker *OutputChecker) UnpackMixedOutputs(data []byte) (MixedOutputsOutput, error) {
|
||||||
|
out, err := outputChecker.abi.Unpack("mixedOutputs", data)
|
||||||
|
outstruct := new(MixedOutputsOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Arg0 = *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
outstruct.Str = *abi.ConvertType(out[1], new(string)).(*string)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackNamedOutput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x5e632bd5.
|
||||||
|
//
|
||||||
|
// Solidity: function namedOutput() returns(string str)
|
||||||
|
func (outputChecker *OutputChecker) PackNamedOutput() []byte {
|
||||||
|
enc, err := outputChecker.abi.Pack("namedOutput")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackNamedOutput is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x5e632bd5.
|
||||||
|
//
|
||||||
|
// Solidity: function namedOutput() returns(string str)
|
||||||
|
func (outputChecker *OutputChecker) UnpackNamedOutput(data []byte) (string, error) {
|
||||||
|
out, err := outputChecker.abi.Unpack("namedOutput", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(string), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackNamedOutputs is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x7970a189.
|
||||||
|
//
|
||||||
|
// Solidity: function namedOutputs() returns(string str1, string str2)
|
||||||
|
func (outputChecker *OutputChecker) PackNamedOutputs() []byte {
|
||||||
|
enc, err := outputChecker.abi.Pack("namedOutputs")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamedOutputsOutput serves as a container for the return parameters of contract
|
||||||
|
// method NamedOutputs.
|
||||||
|
type NamedOutputsOutput struct {
|
||||||
|
Str1 string
|
||||||
|
Str2 string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackNamedOutputs is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x7970a189.
|
||||||
|
//
|
||||||
|
// Solidity: function namedOutputs() returns(string str1, string str2)
|
||||||
|
func (outputChecker *OutputChecker) UnpackNamedOutputs(data []byte) (NamedOutputsOutput, error) {
|
||||||
|
out, err := outputChecker.abi.Unpack("namedOutputs", data)
|
||||||
|
outstruct := new(NamedOutputsOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Str1 = *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
outstruct.Str2 = *abi.ConvertType(out[1], new(string)).(*string)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackNoOutput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x625f0306.
|
||||||
|
//
|
||||||
|
// Solidity: function noOutput() returns()
|
||||||
|
func (outputChecker *OutputChecker) PackNoOutput() []byte {
|
||||||
|
enc, err := outputChecker.abi.Pack("noOutput")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
159
accounts/abi/abigen/testdata/v2/overload.go.txt
vendored
Normal file
159
accounts/abi/abigen/testdata/v2/overload.go.txt
vendored
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// OverloadMetaData contains all meta data concerning the Overload contract.
|
||||||
|
var OverloadMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"},{\"name\":\"j\",\"type\":\"uint256\"}],\"name\":\"foo\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"foo\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"bar\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"i\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"j\",\"type\":\"uint256\"}],\"name\":\"bar\",\"type\":\"event\"}]",
|
||||||
|
ID: "f49f0ff7ed407de5c37214f49309072aec",
|
||||||
|
Bin: "0x608060405234801561001057600080fd5b50610153806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806304bc52f81461003b5780632fbebd3814610073575b600080fd5b6100716004803603604081101561005157600080fd5b8101908080359060200190929190803590602001909291905050506100a1565b005b61009f6004803603602081101561008957600080fd5b81019080803590602001909291905050506100e4565b005b7fae42e9514233792a47a1e4554624e83fe852228e1503f63cd383e8a431f4f46d8282604051808381526020018281526020019250505060405180910390a15050565b7f0423a1321222a0a8716c22b92fac42d85a45a612b696a461784d9fa537c81e5c816040518082815260200191505060405180910390a15056fea265627a7a72305820e22b049858b33291cbe67eeaece0c5f64333e439d27032ea8337d08b1de18fe864736f6c634300050a0032",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overload is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Overload struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOverload creates a new instance of Overload.
|
||||||
|
func NewOverload() *Overload {
|
||||||
|
parsed, err := OverloadMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Overload{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Overload) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackFoo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x04bc52f8.
|
||||||
|
//
|
||||||
|
// Solidity: function foo(uint256 i, uint256 j) returns()
|
||||||
|
func (overload *Overload) PackFoo(i *big.Int, j *big.Int) []byte {
|
||||||
|
enc, err := overload.abi.Pack("foo", i, j)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackFoo0 is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2fbebd38.
|
||||||
|
//
|
||||||
|
// Solidity: function foo(uint256 i) returns()
|
||||||
|
func (overload *Overload) PackFoo0(i *big.Int) []byte {
|
||||||
|
enc, err := overload.abi.Pack("foo0", i)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// OverloadBar represents a bar event raised by the Overload contract.
|
||||||
|
type OverloadBar struct {
|
||||||
|
I *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const OverloadBarEventName = "bar"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (OverloadBar) ContractEventName() string {
|
||||||
|
return OverloadBarEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBarEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event bar(uint256 i)
|
||||||
|
func (overload *Overload) UnpackBarEvent(log *types.Log) (*OverloadBar, error) {
|
||||||
|
event := "bar"
|
||||||
|
if log.Topics[0] != overload.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(OverloadBar)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := overload.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range overload.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OverloadBar0 represents a bar0 event raised by the Overload contract.
|
||||||
|
type OverloadBar0 struct {
|
||||||
|
I *big.Int
|
||||||
|
J *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const OverloadBar0EventName = "bar0"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (OverloadBar0) ContractEventName() string {
|
||||||
|
return OverloadBar0EventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBar0Event is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event bar(uint256 i, uint256 j)
|
||||||
|
func (overload *Overload) UnpackBar0Event(log *types.Log) (*OverloadBar0, error) {
|
||||||
|
event := "bar0"
|
||||||
|
if log.Topics[0] != overload.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(OverloadBar0)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := overload.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range overload.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
64
accounts/abi/abigen/testdata/v2/rangekeyword.go.txt
vendored
Normal file
64
accounts/abi/abigen/testdata/v2/rangekeyword.go.txt
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// RangeKeywordMetaData contains all meta data concerning the RangeKeyword contract.
|
||||||
|
var RangeKeywordMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"range\",\"type\":\"uint256\"}],\"name\":\"functionWithKeywordParameter\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "cec8c872ba06feb1b8f0a00e7b237eb226",
|
||||||
|
Bin: "0x608060405234801561001057600080fd5b5060dc8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063527a119f14602d575b600080fd5b60436004803603810190603f9190605b565b6045565b005b50565b6000813590506055816092565b92915050565b600060208284031215606e57606d608d565b5b6000607a848285016048565b91505092915050565b6000819050919050565b600080fd5b6099816083565b811460a357600080fd5b5056fea2646970667358221220d4f4525e2615516394055d369fb17df41c359e5e962734f27fd683ea81fd9db164736f6c63430008070033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeKeyword is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type RangeKeyword struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRangeKeyword creates a new instance of RangeKeyword.
|
||||||
|
func NewRangeKeyword() *RangeKeyword {
|
||||||
|
parsed, err := RangeKeywordMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &RangeKeyword{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *RangeKeyword) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackFunctionWithKeywordParameter is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x527a119f.
|
||||||
|
//
|
||||||
|
// Solidity: function functionWithKeywordParameter(uint256 range) pure returns()
|
||||||
|
func (rangeKeyword *RangeKeyword) PackFunctionWithKeywordParameter(arg0 *big.Int) []byte {
|
||||||
|
enc, err := rangeKeyword.abi.Pack("functionWithKeywordParameter", arg0)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
152
accounts/abi/abigen/testdata/v2/slicer.go.txt
vendored
Normal file
152
accounts/abi/abigen/testdata/v2/slicer.go.txt
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// SlicerMetaData contains all meta data concerning the Slicer contract.
|
||||||
|
var SlicerMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":true,\"inputs\":[{\"name\":\"input\",\"type\":\"address[]\"}],\"name\":\"echoAddresses\",\"outputs\":[{\"name\":\"output\",\"type\":\"address[]\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"input\",\"type\":\"uint24[23]\"}],\"name\":\"echoFancyInts\",\"outputs\":[{\"name\":\"output\",\"type\":\"uint24[23]\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"input\",\"type\":\"int256[]\"}],\"name\":\"echoInts\",\"outputs\":[{\"name\":\"output\",\"type\":\"int256[]\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"input\",\"type\":\"bool[]\"}],\"name\":\"echoBools\",\"outputs\":[{\"name\":\"output\",\"type\":\"bool[]\"}],\"type\":\"function\"}]",
|
||||||
|
ID: "082c0740ab6537c7169cb573d097c52112",
|
||||||
|
Bin: "0x606060405261015c806100126000396000f3606060405260e060020a6000350463be1127a3811461003c578063d88becc014610092578063e15a3db71461003c578063f637e5891461003c575b005b604080516020600480358082013583810285810185019096528085526100ee959294602494909392850192829185019084908082843750949650505050505050604080516020810190915260009052805b919050565b604080516102e0818101909252610138916004916102e491839060179083908390808284375090955050505050506102e0604051908101604052806017905b60008152602001906001900390816100d15790505081905061008d565b60405180806020018281038252838181518152602001915080519060200190602002808383829060006004602084601f0104600f02600301f1509050019250505060405180910390f35b60405180826102e0808381846000600461015cf15090500191505060405180910390f3",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slicer is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Slicer struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSlicer creates a new instance of Slicer.
|
||||||
|
func NewSlicer() *Slicer {
|
||||||
|
parsed, err := SlicerMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Slicer{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Slicer) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackEchoAddresses is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xbe1127a3.
|
||||||
|
//
|
||||||
|
// Solidity: function echoAddresses(address[] input) returns(address[] output)
|
||||||
|
func (slicer *Slicer) PackEchoAddresses(input []common.Address) []byte {
|
||||||
|
enc, err := slicer.abi.Pack("echoAddresses", input)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackEchoAddresses is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xbe1127a3.
|
||||||
|
//
|
||||||
|
// Solidity: function echoAddresses(address[] input) returns(address[] output)
|
||||||
|
func (slicer *Slicer) UnpackEchoAddresses(data []byte) ([]common.Address, error) {
|
||||||
|
out, err := slicer.abi.Unpack("echoAddresses", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new([]common.Address), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackEchoBools is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xf637e589.
|
||||||
|
//
|
||||||
|
// Solidity: function echoBools(bool[] input) returns(bool[] output)
|
||||||
|
func (slicer *Slicer) PackEchoBools(input []bool) []byte {
|
||||||
|
enc, err := slicer.abi.Pack("echoBools", input)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackEchoBools is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xf637e589.
|
||||||
|
//
|
||||||
|
// Solidity: function echoBools(bool[] input) returns(bool[] output)
|
||||||
|
func (slicer *Slicer) UnpackEchoBools(data []byte) ([]bool, error) {
|
||||||
|
out, err := slicer.abi.Unpack("echoBools", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new([]bool), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new([]bool)).(*[]bool)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackEchoFancyInts is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xd88becc0.
|
||||||
|
//
|
||||||
|
// Solidity: function echoFancyInts(uint24[23] input) returns(uint24[23] output)
|
||||||
|
func (slicer *Slicer) PackEchoFancyInts(input [23]*big.Int) []byte {
|
||||||
|
enc, err := slicer.abi.Pack("echoFancyInts", input)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackEchoFancyInts is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xd88becc0.
|
||||||
|
//
|
||||||
|
// Solidity: function echoFancyInts(uint24[23] input) returns(uint24[23] output)
|
||||||
|
func (slicer *Slicer) UnpackEchoFancyInts(data []byte) ([23]*big.Int, error) {
|
||||||
|
out, err := slicer.abi.Unpack("echoFancyInts", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new([23]*big.Int), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new([23]*big.Int)).(*[23]*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackEchoInts is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xe15a3db7.
|
||||||
|
//
|
||||||
|
// Solidity: function echoInts(int256[] input) returns(int256[] output)
|
||||||
|
func (slicer *Slicer) PackEchoInts(input []*big.Int) []byte {
|
||||||
|
enc, err := slicer.abi.Pack("echoInts", input)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackEchoInts is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xe15a3db7.
|
||||||
|
//
|
||||||
|
// Solidity: function echoInts(int256[] input) returns(int256[] output)
|
||||||
|
func (slicer *Slicer) UnpackEchoInts(data []byte) ([]*big.Int, error) {
|
||||||
|
out, err := slicer.abi.Unpack("echoInts", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new([]*big.Int), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
116
accounts/abi/abigen/testdata/v2/structs-abi.go.txt
vendored
Normal file
116
accounts/abi/abigen/testdata/v2/structs-abi.go.txt
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package v1bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// Struct0 is an auto generated low-level Go binding around an user-defined struct.
|
||||||
|
type Struct0 struct {
|
||||||
|
B [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// StructsMetaData contains all meta data concerning the Structs contract.
|
||||||
|
var StructsMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[],\"name\":\"F\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[]\",\"name\":\"c\",\"type\":\"uint256[]\"},{\"internalType\":\"bool[]\",\"name\":\"d\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"G\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
|
||||||
|
ID: "Structs",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Structs is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Structs struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStructs creates a new instance of Structs.
|
||||||
|
func NewStructs() *Structs {
|
||||||
|
parsed, err := StructsMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Structs{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
<<<<<<< HEAD
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Structs) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
=======
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call,
|
||||||
|
// Transact, etc.
|
||||||
|
func (c *Structs) Instance(backend bind.ContractBackend, addr common.Address) bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(backend, addr, c.abi)
|
||||||
|
>>>>>>> 854c25e086 (accounts/abi/abigen: improve v2 template)
|
||||||
|
}
|
||||||
|
|
||||||
|
// F is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method 0x28811f59.
|
||||||
|
//
|
||||||
|
// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
|
||||||
|
func (structs *Structs) PackF() ([]byte, error) {
|
||||||
|
return structs.abi.Pack("F")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FOutput serves as a container for the return parameters of contract
|
||||||
|
// method F.
|
||||||
|
type FOutput struct {
|
||||||
|
A []Struct0
|
||||||
|
C []*big.Int
|
||||||
|
D []bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackF is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x28811f59.
|
||||||
|
//
|
||||||
|
// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
|
||||||
|
func (structs *Structs) UnpackF(data []byte) (*FOutput, error) {
|
||||||
|
out, err := structs.abi.Unpack("F", data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := new(FOutput)
|
||||||
|
ret.A = *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
|
||||||
|
ret.C = *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int)
|
||||||
|
ret.D = *abi.ConvertType(out[2], new([]bool)).(*[]bool)
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// G is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method 0x6fecb623.
|
||||||
|
//
|
||||||
|
// Solidity: function G() view returns((bytes32)[] a)
|
||||||
|
func (structs *Structs) PackG() ([]byte, error) {
|
||||||
|
return structs.abi.Pack("G")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackG is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x6fecb623.
|
||||||
|
//
|
||||||
|
// Solidity: function G() view returns((bytes32)[] a)
|
||||||
|
func (structs *Structs) UnpackG(data []byte) (*[]Struct0, error) {
|
||||||
|
out, err := structs.abi.Unpack("G", data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
|
||||||
|
return &out0, nil
|
||||||
|
}
|
||||||
119
accounts/abi/abigen/testdata/v2/structs.go.txt
vendored
Normal file
119
accounts/abi/abigen/testdata/v2/structs.go.txt
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// Struct0 is an auto generated low-level Go binding around an user-defined struct.
|
||||||
|
type Struct0 struct {
|
||||||
|
B [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// StructsMetaData contains all meta data concerning the Structs contract.
|
||||||
|
var StructsMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[],\"name\":\"F\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[]\",\"name\":\"c\",\"type\":\"uint256[]\"},{\"internalType\":\"bool[]\",\"name\":\"d\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"G\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
|
||||||
|
ID: "920a35318e7581766aec7a17218628a91d",
|
||||||
|
Bin: "0x608060405234801561001057600080fd5b50610278806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806328811f591461003b5780636fecb6231461005b575b600080fd5b610043610070565b604051610052939291906101a0565b60405180910390f35b6100636100d6565b6040516100529190610186565b604080516002808252606082810190935282918291829190816020015b610095610131565b81526020019060019003908161008d575050805190915061026960611b9082906000906100be57fe5b60209081029190910101515293606093508392509050565b6040805160028082526060828101909352829190816020015b6100f7610131565b8152602001906001900390816100ef575050805190915061026960611b90829060009061012057fe5b602090810291909101015152905090565b60408051602081019091526000815290565b815260200190565b6000815180845260208085019450808401835b8381101561017b578151518752958201959082019060010161015e565b509495945050505050565b600060208252610199602083018461014b565b9392505050565b6000606082526101b3606083018661014b565b6020838203818501528186516101c98185610239565b91508288019350845b818110156101f3576101e5838651610143565b9484019492506001016101d2565b505084810360408601528551808252908201925081860190845b8181101561022b57825115158552938301939183019160010161020d565b509298975050505050505050565b9081526020019056fea2646970667358221220eb85327e285def14230424c52893aebecec1e387a50bb6b75fc4fdbed647f45f64736f6c63430006050033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Structs is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Structs struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStructs creates a new instance of Structs.
|
||||||
|
func NewStructs() *Structs {
|
||||||
|
parsed, err := StructsMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Structs{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Structs) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackF is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x28811f59.
|
||||||
|
//
|
||||||
|
// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
|
||||||
|
func (structs *Structs) PackF() []byte {
|
||||||
|
enc, err := structs.abi.Pack("F")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// FOutput serves as a container for the return parameters of contract
|
||||||
|
// method F.
|
||||||
|
type FOutput struct {
|
||||||
|
A []Struct0
|
||||||
|
C []*big.Int
|
||||||
|
D []bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackF is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x28811f59.
|
||||||
|
//
|
||||||
|
// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
|
||||||
|
func (structs *Structs) UnpackF(data []byte) (FOutput, error) {
|
||||||
|
out, err := structs.abi.Unpack("F", data)
|
||||||
|
outstruct := new(FOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.A = *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
|
||||||
|
outstruct.C = *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int)
|
||||||
|
outstruct.D = *abi.ConvertType(out[2], new([]bool)).(*[]bool)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackG is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x6fecb623.
|
||||||
|
//
|
||||||
|
// Solidity: function G() view returns((bytes32)[] a)
|
||||||
|
func (structs *Structs) PackG() []byte {
|
||||||
|
enc, err := structs.abi.Pack("G")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackG is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x6fecb623.
|
||||||
|
//
|
||||||
|
// Solidity: function G() view returns((bytes32)[] a)
|
||||||
|
func (structs *Structs) UnpackG(data []byte) ([]Struct0, error) {
|
||||||
|
out, err := structs.abi.Unpack("G", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new([]Struct0), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
319
accounts/abi/abigen/testdata/v2/token.go.txt
vendored
Normal file
319
accounts/abi/abigen/testdata/v2/token.go.txt
vendored
Normal file
|
|
@ -0,0 +1,319 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// TokenMetaData contains all meta data concerning the Token contract.
|
||||||
|
var TokenMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"spentAllowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialSupply\",\"type\":\"uint256\"},{\"name\":\"tokenName\",\"type\":\"string\"},{\"name\":\"decimalUnits\",\"type\":\"uint8\"},{\"name\":\"tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"}]",
|
||||||
|
ID: "1317f51c845ce3bfb7c268e5337a825f12",
|
||||||
|
Bin: "0x60606040526040516107fd3803806107fd83398101604052805160805160a05160c051929391820192909101600160a060020a0333166000908152600360209081526040822086905581548551838052601f6002600019610100600186161502019093169290920482018390047f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56390810193919290918801908390106100e857805160ff19168380011785555b506101189291505b8082111561017157600081556001016100b4565b50506002805460ff19168317905550505050610658806101a56000396000f35b828001600101855582156100ac579182015b828111156100ac5782518260005055916020019190600101906100fa565b50508060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017557805160ff19168380011785555b506100c89291506100b4565b5090565b82800160010185558215610165579182015b8281111561016557825182600050559160200191906001019061018756606060405236156100775760e060020a600035046306fdde03811461007f57806323b872dd146100dc578063313ce5671461010e57806370a082311461011a57806395d89b4114610132578063a9059cbb1461018e578063cae9ca51146101bd578063dc3080f21461031c578063dd62ed3e14610341575b610365610002565b61036760008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156104eb5780601f106104c0576101008083540402835291602001916104eb565b6103d5600435602435604435600160a060020a038316600090815260036020526040812054829010156104f357610002565b6103e760025460ff1681565b6103d560043560036020526000908152604090205481565b610367600180546020600282841615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156104eb5780601f106104c0576101008083540402835291602001916104eb565b610365600435602435600160a060020a033316600090815260036020526040902054819010156103f157610002565b60806020604435600481810135601f8101849004909302840160405260608381526103d5948235946024803595606494939101919081908382808284375094965050505050505060006000836004600050600033600160a060020a03168152602001908152602001600020600050600087600160a060020a031681526020019081526020016000206000508190555084905080600160a060020a0316638f4ffcb1338630876040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a03168152602001806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156102f25780820380516001836020036101000a031916815260200191505b50955050505050506000604051808303816000876161da5a03f11561000257505050509392505050565b6005602090815260043560009081526040808220909252602435815220546103d59081565b60046020818152903560009081526040808220909252602435815220546103d59081565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156103c75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a03821660009081526040902054808201101561041357610002565b806003600050600033600160a060020a03168152602001908152602001600020600082828250540392505081905550806003600050600084600160a060020a0316815260200190815260200160002060008282825054019250508190555081600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b820191906000526020600020905b8154815290600101906020018083116104ce57829003601f168201915b505050505081565b600160a060020a03831681526040812054808301101561051257610002565b600160a060020a0380851680835260046020908152604080852033949094168086529382528085205492855260058252808520938552929052908220548301111561055c57610002565b816003600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816003600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816005600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054019250508190555082600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3939250505056",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Token is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Token struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewToken creates a new instance of Token.
|
||||||
|
func NewToken() *Token {
|
||||||
|
parsed, err := TokenMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Token{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Token) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackConstructor is the Go binding used to pack the parameters required for
|
||||||
|
// contract deployment.
|
||||||
|
//
|
||||||
|
// Solidity: constructor(uint256 initialSupply, string tokenName, uint8 decimalUnits, string tokenSymbol) returns()
|
||||||
|
func (token *Token) PackConstructor(initialSupply *big.Int, tokenName string, decimalUnits uint8, tokenSymbol string) []byte {
|
||||||
|
enc, err := token.abi.Pack("", initialSupply, tokenName, decimalUnits, tokenSymbol)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackAllowance is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xdd62ed3e.
|
||||||
|
//
|
||||||
|
// Solidity: function allowance(address , address ) returns(uint256)
|
||||||
|
func (token *Token) PackAllowance(arg0 common.Address, arg1 common.Address) []byte {
|
||||||
|
enc, err := token.abi.Pack("allowance", arg0, arg1)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackAllowance is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xdd62ed3e.
|
||||||
|
//
|
||||||
|
// Solidity: function allowance(address , address ) returns(uint256)
|
||||||
|
func (token *Token) UnpackAllowance(data []byte) (*big.Int, error) {
|
||||||
|
out, err := token.abi.Unpack("allowance", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackApproveAndCall is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xcae9ca51.
|
||||||
|
//
|
||||||
|
// Solidity: function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns(bool success)
|
||||||
|
func (token *Token) PackApproveAndCall(spender common.Address, value *big.Int, extraData []byte) []byte {
|
||||||
|
enc, err := token.abi.Pack("approveAndCall", spender, value, extraData)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackApproveAndCall is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xcae9ca51.
|
||||||
|
//
|
||||||
|
// Solidity: function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns(bool success)
|
||||||
|
func (token *Token) UnpackApproveAndCall(data []byte) (bool, error) {
|
||||||
|
out, err := token.abi.Unpack("approveAndCall", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(bool), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackBalanceOf is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x70a08231.
|
||||||
|
//
|
||||||
|
// Solidity: function balanceOf(address ) returns(uint256)
|
||||||
|
func (token *Token) PackBalanceOf(arg0 common.Address) []byte {
|
||||||
|
enc, err := token.abi.Pack("balanceOf", arg0)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBalanceOf is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x70a08231.
|
||||||
|
//
|
||||||
|
// Solidity: function balanceOf(address ) returns(uint256)
|
||||||
|
func (token *Token) UnpackBalanceOf(data []byte) (*big.Int, error) {
|
||||||
|
out, err := token.abi.Unpack("balanceOf", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDecimals is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x313ce567.
|
||||||
|
//
|
||||||
|
// Solidity: function decimals() returns(uint8)
|
||||||
|
func (token *Token) PackDecimals() []byte {
|
||||||
|
enc, err := token.abi.Pack("decimals")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDecimals is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x313ce567.
|
||||||
|
//
|
||||||
|
// Solidity: function decimals() returns(uint8)
|
||||||
|
func (token *Token) UnpackDecimals(data []byte) (uint8, error) {
|
||||||
|
out, err := token.abi.Unpack("decimals", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(uint8), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackName is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x06fdde03.
|
||||||
|
//
|
||||||
|
// Solidity: function name() returns(string)
|
||||||
|
func (token *Token) PackName() []byte {
|
||||||
|
enc, err := token.abi.Pack("name")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackName is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x06fdde03.
|
||||||
|
//
|
||||||
|
// Solidity: function name() returns(string)
|
||||||
|
func (token *Token) UnpackName(data []byte) (string, error) {
|
||||||
|
out, err := token.abi.Unpack("name", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(string), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackSpentAllowance is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xdc3080f2.
|
||||||
|
//
|
||||||
|
// Solidity: function spentAllowance(address , address ) returns(uint256)
|
||||||
|
func (token *Token) PackSpentAllowance(arg0 common.Address, arg1 common.Address) []byte {
|
||||||
|
enc, err := token.abi.Pack("spentAllowance", arg0, arg1)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackSpentAllowance is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xdc3080f2.
|
||||||
|
//
|
||||||
|
// Solidity: function spentAllowance(address , address ) returns(uint256)
|
||||||
|
func (token *Token) UnpackSpentAllowance(data []byte) (*big.Int, error) {
|
||||||
|
out, err := token.abi.Unpack("spentAllowance", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackSymbol is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x95d89b41.
|
||||||
|
//
|
||||||
|
// Solidity: function symbol() returns(string)
|
||||||
|
func (token *Token) PackSymbol() []byte {
|
||||||
|
enc, err := token.abi.Pack("symbol")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackSymbol is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x95d89b41.
|
||||||
|
//
|
||||||
|
// Solidity: function symbol() returns(string)
|
||||||
|
func (token *Token) UnpackSymbol(data []byte) (string, error) {
|
||||||
|
out, err := token.abi.Unpack("symbol", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(string), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTransfer is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xa9059cbb.
|
||||||
|
//
|
||||||
|
// Solidity: function transfer(address _to, uint256 _value) returns()
|
||||||
|
func (token *Token) PackTransfer(to common.Address, value *big.Int) []byte {
|
||||||
|
enc, err := token.abi.Pack("transfer", to, value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTransferFrom is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x23b872dd.
|
||||||
|
//
|
||||||
|
// Solidity: function transferFrom(address _from, address _to, uint256 _value) returns(bool success)
|
||||||
|
func (token *Token) PackTransferFrom(from common.Address, to common.Address, value *big.Int) []byte {
|
||||||
|
enc, err := token.abi.Pack("transferFrom", from, to, value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackTransferFrom is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x23b872dd.
|
||||||
|
//
|
||||||
|
// Solidity: function transferFrom(address _from, address _to, uint256 _value) returns(bool success)
|
||||||
|
func (token *Token) UnpackTransferFrom(data []byte) (bool, error) {
|
||||||
|
out, err := token.abi.Unpack("transferFrom", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(bool), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TokenTransfer represents a Transfer event raised by the Token contract.
|
||||||
|
type TokenTransfer struct {
|
||||||
|
From common.Address
|
||||||
|
To common.Address
|
||||||
|
Value *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const TokenTransferEventName = "Transfer"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (TokenTransfer) ContractEventName() string {
|
||||||
|
return TokenTransferEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackTransferEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
|
||||||
|
func (token *Token) UnpackTransferEvent(log *types.Log) (*TokenTransfer, error) {
|
||||||
|
event := "Transfer"
|
||||||
|
if log.Topics[0] != token.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(TokenTransfer)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := token.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range token.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
228
accounts/abi/abigen/testdata/v2/tuple.go.txt
vendored
Normal file
228
accounts/abi/abigen/testdata/v2/tuple.go.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
89
accounts/abi/abigen/testdata/v2/tupler.go.txt
vendored
Normal file
89
accounts/abi/abigen/testdata/v2/tupler.go.txt
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// TuplerMetaData contains all meta data concerning the Tupler contract.
|
||||||
|
var TuplerMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"tuple\",\"outputs\":[{\"name\":\"a\",\"type\":\"string\"},{\"name\":\"b\",\"type\":\"int256\"},{\"name\":\"c\",\"type\":\"bytes32\"}],\"type\":\"function\"}]",
|
||||||
|
ID: "a8f4d2061f55c712cfae266c426a1cd568",
|
||||||
|
Bin: "0x606060405260dc8060106000396000f3606060405260e060020a60003504633175aae28114601a575b005b600060605260c0604052600260809081527f486900000000000000000000000000000000000000000000000000000000000060a05260017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060e0829052610100819052606060c0908152600261012081905281906101409060a09080838184600060046012f1505081517fffff000000000000000000000000000000000000000000000000000000000000169091525050604051610160819003945092505050f3",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tupler is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Tupler struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTupler creates a new instance of Tupler.
|
||||||
|
func NewTupler() *Tupler {
|
||||||
|
parsed, err := TuplerMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Tupler{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Tupler) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackTuple is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x3175aae2.
|
||||||
|
//
|
||||||
|
// Solidity: function tuple() returns(string a, int256 b, bytes32 c)
|
||||||
|
func (tupler *Tupler) PackTuple() []byte {
|
||||||
|
enc, err := tupler.abi.Pack("tuple")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// TupleOutput serves as a container for the return parameters of contract
|
||||||
|
// method Tuple.
|
||||||
|
type TupleOutput struct {
|
||||||
|
A string
|
||||||
|
B *big.Int
|
||||||
|
C [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackTuple is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x3175aae2.
|
||||||
|
//
|
||||||
|
// Solidity: function tuple() returns(string a, int256 b, bytes32 c)
|
||||||
|
func (tupler *Tupler) UnpackTuple(data []byte) (TupleOutput, error) {
|
||||||
|
out, err := tupler.abi.Unpack("tuple", data)
|
||||||
|
outstruct := new(TupleOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.A = *abi.ConvertType(out[0], new(string)).(*string)
|
||||||
|
outstruct.B = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.C = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
322
accounts/abi/abigen/testdata/v2/underscorer.go.txt
vendored
Normal file
322
accounts/abi/abigen/testdata/v2/underscorer.go.txt
vendored
Normal file
|
|
@ -0,0 +1,322 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package bindtests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnderscorerMetaData contains all meta data concerning the Underscorer contract.
|
||||||
|
var UnderscorerMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"constant\":true,\"inputs\":[],\"name\":\"LowerUpperCollision\",\"outputs\":[{\"name\":\"_res\",\"type\":\"int256\"},{\"name\":\"Res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_under_scored_func\",\"outputs\":[{\"name\":\"_int\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"UnderscoredOutput\",\"outputs\":[{\"name\":\"_int\",\"type\":\"int256\"},{\"name\":\"_string\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"PurelyUnderscoredOutput\",\"outputs\":[{\"name\":\"_\",\"type\":\"int256\"},{\"name\":\"res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"UpperLowerCollision\",\"outputs\":[{\"name\":\"_Res\",\"type\":\"int256\"},{\"name\":\"res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"AllPurelyUnderscoredOutput\",\"outputs\":[{\"name\":\"_\",\"type\":\"int256\"},{\"name\":\"__\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"UpperUpperCollision\",\"outputs\":[{\"name\":\"_Res\",\"type\":\"int256\"},{\"name\":\"Res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"LowerLowerCollision\",\"outputs\":[{\"name\":\"_res\",\"type\":\"int256\"},{\"name\":\"res\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
|
||||||
|
ID: "5873a90ab43c925dfced86ad53f871f01d",
|
||||||
|
Bin: "0x6060604052341561000f57600080fd5b6103858061001e6000396000f30060606040526004361061008e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303a592131461009357806346546dbe146100c357806367e6633d146100ec5780639df4848514610181578063af7486ab146101b1578063b564b34d146101e1578063e02ab24d14610211578063e409ca4514610241575b600080fd5b341561009e57600080fd5b6100a6610271565b604051808381526020018281526020019250505060405180910390f35b34156100ce57600080fd5b6100d6610286565b6040518082815260200191505060405180910390f35b34156100f757600080fd5b6100ff61028e565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561014557808201518184015260208101905061012a565b50505050905090810190601f1680156101725780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561018c57600080fd5b6101946102dc565b604051808381526020018281526020019250505060405180910390f35b34156101bc57600080fd5b6101c46102f1565b604051808381526020018281526020019250505060405180910390f35b34156101ec57600080fd5b6101f4610306565b604051808381526020018281526020019250505060405180910390f35b341561021c57600080fd5b61022461031b565b604051808381526020018281526020019250505060405180910390f35b341561024c57600080fd5b610254610330565b604051808381526020018281526020019250505060405180910390f35b60008060016002819150809050915091509091565b600080905090565b6000610298610345565b61013a8090506040805190810160405280600281526020017f7069000000000000000000000000000000000000000000000000000000000000815250915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b6020604051908101604052806000815250905600a165627a7a72305820d1a53d9de9d1e3d55cb3dc591900b63c4f1ded79114f7b79b332684840e186a40029",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Underscorer is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type Underscorer struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUnderscorer creates a new instance of Underscorer.
|
||||||
|
func NewUnderscorer() *Underscorer {
|
||||||
|
parsed, err := UnderscorerMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &Underscorer{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *Underscorer) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackAllPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xb564b34d.
|
||||||
|
//
|
||||||
|
// Solidity: function AllPurelyUnderscoredOutput() view returns(int256 _, int256 __)
|
||||||
|
func (underscorer *Underscorer) PackAllPurelyUnderscoredOutput() []byte {
|
||||||
|
enc, err := underscorer.abi.Pack("AllPurelyUnderscoredOutput")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllPurelyUnderscoredOutputOutput serves as a container for the return parameters of contract
|
||||||
|
// method AllPurelyUnderscoredOutput.
|
||||||
|
type AllPurelyUnderscoredOutputOutput struct {
|
||||||
|
Arg0 *big.Int
|
||||||
|
Arg1 *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackAllPurelyUnderscoredOutput is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xb564b34d.
|
||||||
|
//
|
||||||
|
// Solidity: function AllPurelyUnderscoredOutput() view returns(int256 _, int256 __)
|
||||||
|
func (underscorer *Underscorer) UnpackAllPurelyUnderscoredOutput(data []byte) (AllPurelyUnderscoredOutputOutput, error) {
|
||||||
|
out, err := underscorer.abi.Unpack("AllPurelyUnderscoredOutput", data)
|
||||||
|
outstruct := new(AllPurelyUnderscoredOutputOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackLowerLowerCollision is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xe409ca45.
|
||||||
|
//
|
||||||
|
// Solidity: function LowerLowerCollision() view returns(int256 _res, int256 res)
|
||||||
|
func (underscorer *Underscorer) PackLowerLowerCollision() []byte {
|
||||||
|
enc, err := underscorer.abi.Pack("LowerLowerCollision")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// LowerLowerCollisionOutput serves as a container for the return parameters of contract
|
||||||
|
// method LowerLowerCollision.
|
||||||
|
type LowerLowerCollisionOutput struct {
|
||||||
|
Res *big.Int
|
||||||
|
Res0 *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackLowerLowerCollision is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xe409ca45.
|
||||||
|
//
|
||||||
|
// Solidity: function LowerLowerCollision() view returns(int256 _res, int256 res)
|
||||||
|
func (underscorer *Underscorer) UnpackLowerLowerCollision(data []byte) (LowerLowerCollisionOutput, error) {
|
||||||
|
out, err := underscorer.abi.Unpack("LowerLowerCollision", data)
|
||||||
|
outstruct := new(LowerLowerCollisionOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackLowerUpperCollision is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x03a59213.
|
||||||
|
//
|
||||||
|
// Solidity: function LowerUpperCollision() view returns(int256 _res, int256 Res)
|
||||||
|
func (underscorer *Underscorer) PackLowerUpperCollision() []byte {
|
||||||
|
enc, err := underscorer.abi.Pack("LowerUpperCollision")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// LowerUpperCollisionOutput serves as a container for the return parameters of contract
|
||||||
|
// method LowerUpperCollision.
|
||||||
|
type LowerUpperCollisionOutput struct {
|
||||||
|
Res *big.Int
|
||||||
|
Res0 *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackLowerUpperCollision is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x03a59213.
|
||||||
|
//
|
||||||
|
// Solidity: function LowerUpperCollision() view returns(int256 _res, int256 Res)
|
||||||
|
func (underscorer *Underscorer) UnpackLowerUpperCollision(data []byte) (LowerUpperCollisionOutput, error) {
|
||||||
|
out, err := underscorer.abi.Unpack("LowerUpperCollision", data)
|
||||||
|
outstruct := new(LowerUpperCollisionOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackPurelyUnderscoredOutput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x9df48485.
|
||||||
|
//
|
||||||
|
// Solidity: function PurelyUnderscoredOutput() view returns(int256 _, int256 res)
|
||||||
|
func (underscorer *Underscorer) PackPurelyUnderscoredOutput() []byte {
|
||||||
|
enc, err := underscorer.abi.Pack("PurelyUnderscoredOutput")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PurelyUnderscoredOutputOutput serves as a container for the return parameters of contract
|
||||||
|
// method PurelyUnderscoredOutput.
|
||||||
|
type PurelyUnderscoredOutputOutput struct {
|
||||||
|
Arg0 *big.Int
|
||||||
|
Res *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackPurelyUnderscoredOutput is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x9df48485.
|
||||||
|
//
|
||||||
|
// Solidity: function PurelyUnderscoredOutput() view returns(int256 _, int256 res)
|
||||||
|
func (underscorer *Underscorer) UnpackPurelyUnderscoredOutput(data []byte) (PurelyUnderscoredOutputOutput, error) {
|
||||||
|
out, err := underscorer.abi.Unpack("PurelyUnderscoredOutput", data)
|
||||||
|
outstruct := new(PurelyUnderscoredOutputOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Res = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackUnderscoredOutput is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x67e6633d.
|
||||||
|
//
|
||||||
|
// Solidity: function UnderscoredOutput() view returns(int256 _int, string _string)
|
||||||
|
func (underscorer *Underscorer) PackUnderscoredOutput() []byte {
|
||||||
|
enc, err := underscorer.abi.Pack("UnderscoredOutput")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnderscoredOutputOutput serves as a container for the return parameters of contract
|
||||||
|
// method UnderscoredOutput.
|
||||||
|
type UnderscoredOutputOutput struct {
|
||||||
|
Int *big.Int
|
||||||
|
String string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackUnderscoredOutput is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x67e6633d.
|
||||||
|
//
|
||||||
|
// Solidity: function UnderscoredOutput() view returns(int256 _int, string _string)
|
||||||
|
func (underscorer *Underscorer) UnpackUnderscoredOutput(data []byte) (UnderscoredOutputOutput, error) {
|
||||||
|
out, err := underscorer.abi.Unpack("UnderscoredOutput", data)
|
||||||
|
outstruct := new(UnderscoredOutputOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Int = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.String = *abi.ConvertType(out[1], new(string)).(*string)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackUpperLowerCollision is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xaf7486ab.
|
||||||
|
//
|
||||||
|
// Solidity: function UpperLowerCollision() view returns(int256 _Res, int256 res)
|
||||||
|
func (underscorer *Underscorer) PackUpperLowerCollision() []byte {
|
||||||
|
enc, err := underscorer.abi.Pack("UpperLowerCollision")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpperLowerCollisionOutput serves as a container for the return parameters of contract
|
||||||
|
// method UpperLowerCollision.
|
||||||
|
type UpperLowerCollisionOutput struct {
|
||||||
|
Res *big.Int
|
||||||
|
Res0 *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackUpperLowerCollision is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xaf7486ab.
|
||||||
|
//
|
||||||
|
// Solidity: function UpperLowerCollision() view returns(int256 _Res, int256 res)
|
||||||
|
func (underscorer *Underscorer) UnpackUpperLowerCollision(data []byte) (UpperLowerCollisionOutput, error) {
|
||||||
|
out, err := underscorer.abi.Unpack("UpperLowerCollision", data)
|
||||||
|
outstruct := new(UpperLowerCollisionOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackUpperUpperCollision is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xe02ab24d.
|
||||||
|
//
|
||||||
|
// Solidity: function UpperUpperCollision() view returns(int256 _Res, int256 Res)
|
||||||
|
func (underscorer *Underscorer) PackUpperUpperCollision() []byte {
|
||||||
|
enc, err := underscorer.abi.Pack("UpperUpperCollision")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpperUpperCollisionOutput serves as a container for the return parameters of contract
|
||||||
|
// method UpperUpperCollision.
|
||||||
|
type UpperUpperCollisionOutput struct {
|
||||||
|
Res *big.Int
|
||||||
|
Res0 *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackUpperUpperCollision is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xe02ab24d.
|
||||||
|
//
|
||||||
|
// Solidity: function UpperUpperCollision() view returns(int256 _Res, int256 Res)
|
||||||
|
func (underscorer *Underscorer) UnpackUpperUpperCollision(data []byte) (UpperUpperCollisionOutput, error) {
|
||||||
|
out, err := underscorer.abi.Unpack("UpperUpperCollision", data)
|
||||||
|
outstruct := new(UpperUpperCollisionOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Res = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Res0 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackUnderScoredFunc is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x46546dbe.
|
||||||
|
//
|
||||||
|
// Solidity: function _under_scored_func() view returns(int256 _int)
|
||||||
|
func (underscorer *Underscorer) PackUnderScoredFunc() []byte {
|
||||||
|
enc, err := underscorer.abi.Pack("_under_scored_func")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackUnderScoredFunc is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x46546dbe.
|
||||||
|
//
|
||||||
|
// Solidity: function _under_scored_func() view returns(int256 _int)
|
||||||
|
func (underscorer *Underscorer) UnpackUnderScoredFunc(data []byte) (*big.Int, error) {
|
||||||
|
out, err := underscorer.abi.Unpack("_under_scored_func", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
@ -77,18 +77,18 @@ func (arguments Arguments) isTuple() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack performs the operation hexdata -> Go format.
|
// Unpack performs the operation hexdata -> Go format.
|
||||||
func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) {
|
func (arguments Arguments) Unpack(data []byte) ([]any, error) {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
if len(arguments.NonIndexed()) != 0 {
|
if len(arguments.NonIndexed()) != 0 {
|
||||||
return nil, errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
|
return nil, errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
|
||||||
}
|
}
|
||||||
return make([]interface{}, 0), nil
|
return make([]any, 0), nil
|
||||||
}
|
}
|
||||||
return arguments.UnpackValues(data)
|
return arguments.UnpackValues(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value.
|
// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value.
|
||||||
func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error {
|
func (arguments Arguments) UnpackIntoMap(v map[string]any, data []byte) error {
|
||||||
// Make sure map is not nil
|
// Make sure map is not nil
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return errors.New("abi: cannot unpack into a nil map")
|
return errors.New("abi: cannot unpack into a nil map")
|
||||||
|
|
@ -110,7 +110,7 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy performs the operation go format -> provided struct.
|
// Copy performs the operation go format -> provided struct.
|
||||||
func (arguments Arguments) Copy(v interface{}, values []interface{}) error {
|
func (arguments Arguments) Copy(v any, values []any) error {
|
||||||
// make sure the passed value is arguments pointer
|
// make sure the passed value is arguments pointer
|
||||||
if reflect.Ptr != reflect.ValueOf(v).Kind() {
|
if reflect.Ptr != reflect.ValueOf(v).Kind() {
|
||||||
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
|
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
|
||||||
|
|
@ -128,7 +128,7 @@ func (arguments Arguments) Copy(v interface{}, values []interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyAtomic copies ( hexdata -> go ) a single value
|
// copyAtomic copies ( hexdata -> go ) a single value
|
||||||
func (arguments Arguments) copyAtomic(v interface{}, marshalledValues interface{}) error {
|
func (arguments Arguments) copyAtomic(v any, marshalledValues any) error {
|
||||||
dst := reflect.ValueOf(v).Elem()
|
dst := reflect.ValueOf(v).Elem()
|
||||||
src := reflect.ValueOf(marshalledValues)
|
src := reflect.ValueOf(marshalledValues)
|
||||||
|
|
||||||
|
|
@ -139,7 +139,7 @@ func (arguments Arguments) copyAtomic(v interface{}, marshalledValues interface{
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyTuple copies a batch of values from marshalledValues to v.
|
// copyTuple copies a batch of values from marshalledValues to v.
|
||||||
func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface{}) error {
|
func (arguments Arguments) copyTuple(v any, marshalledValues []any) error {
|
||||||
value := reflect.ValueOf(v).Elem()
|
value := reflect.ValueOf(v).Elem()
|
||||||
nonIndexedArgs := arguments.NonIndexed()
|
nonIndexedArgs := arguments.NonIndexed()
|
||||||
|
|
||||||
|
|
@ -181,11 +181,17 @@ func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface
|
||||||
// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
|
// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
|
||||||
// without supplying a struct to unpack into. Instead, this method returns a list containing the
|
// without supplying a struct to unpack into. Instead, this method returns a list containing the
|
||||||
// values. An atomic argument will be a list with one element.
|
// values. An atomic argument will be a list with one element.
|
||||||
func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
|
func (arguments Arguments) UnpackValues(data []byte) ([]any, error) {
|
||||||
nonIndexedArgs := arguments.NonIndexed()
|
var (
|
||||||
retval := make([]interface{}, 0, len(nonIndexedArgs))
|
retval = make([]any, 0)
|
||||||
virtualArgs := 0
|
virtualArgs = 0
|
||||||
for index, arg := range nonIndexedArgs {
|
index = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, arg := range arguments {
|
||||||
|
if arg.Indexed {
|
||||||
|
continue
|
||||||
|
}
|
||||||
marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
|
marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -208,18 +214,19 @@ func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
|
||||||
virtualArgs += getTypeSize(arg.Type)/32 - 1
|
virtualArgs += getTypeSize(arg.Type)/32 - 1
|
||||||
}
|
}
|
||||||
retval = append(retval, marshalledValue)
|
retval = append(retval, marshalledValue)
|
||||||
|
index++
|
||||||
}
|
}
|
||||||
return retval, nil
|
return retval, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackValues performs the operation Go format -> Hexdata.
|
// PackValues performs the operation Go format -> Hexdata.
|
||||||
// It is the semantic opposite of UnpackValues.
|
// It is the semantic opposite of UnpackValues.
|
||||||
func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
|
func (arguments Arguments) PackValues(args []any) ([]byte, error) {
|
||||||
return arguments.Pack(args...)
|
return arguments.Pack(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pack performs the operation Go format -> Hexdata.
|
// Pack performs the operation Go format -> Hexdata.
|
||||||
func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
|
func (arguments Arguments) Pack(args ...any) ([]byte, error) {
|
||||||
// Make sure arguments match up and pack them
|
// Make sure arguments match up and pack them
|
||||||
abiArgs := arguments
|
abiArgs := arguments
|
||||||
if len(args) != len(abiArgs) {
|
if len(args) != len(abiArgs) {
|
||||||
|
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
// Copyright 2016 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 bind
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/external"
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrNoChainID is returned whenever the user failed to specify a chain id.
|
|
||||||
var ErrNoChainID = errors.New("no chain id specified")
|
|
||||||
|
|
||||||
// ErrNotAuthorized is returned when an account is not properly unlocked.
|
|
||||||
var ErrNotAuthorized = errors.New("not authorized to sign this account")
|
|
||||||
|
|
||||||
// NewTransactor is a utility method to easily create a transaction signer from
|
|
||||||
// an encrypted json key stream and the associated passphrase.
|
|
||||||
//
|
|
||||||
// Deprecated: Use NewTransactorWithChainID instead.
|
|
||||||
func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
|
|
||||||
log.Warn("WARNING: NewTransactor has been deprecated in favour of NewTransactorWithChainID")
|
|
||||||
json, err := io.ReadAll(keyin)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
key, err := keystore.DecryptKey(json, passphrase)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return NewKeyedTransactor(key.PrivateKey), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
|
|
||||||
// a decrypted key from a keystore.
|
|
||||||
//
|
|
||||||
// Deprecated: Use NewKeyStoreTransactorWithChainID instead.
|
|
||||||
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
|
|
||||||
log.Warn("WARNING: NewKeyStoreTransactor has been deprecated in favour of NewTransactorWithChainID")
|
|
||||||
signer := types.HomesteadSigner{}
|
|
||||||
return &TransactOpts{
|
|
||||||
From: account.Address,
|
|
||||||
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
|
||||||
if address != account.Address {
|
|
||||||
return nil, ErrNotAuthorized
|
|
||||||
}
|
|
||||||
signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tx.WithSignature(signer, signature)
|
|
||||||
},
|
|
||||||
Context: context.Background(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewKeyedTransactor is a utility method to easily create a transaction signer
|
|
||||||
// from a single private key.
|
|
||||||
//
|
|
||||||
// Deprecated: Use NewKeyedTransactorWithChainID instead.
|
|
||||||
func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
|
|
||||||
log.Warn("WARNING: NewKeyedTransactor has been deprecated in favour of NewKeyedTransactorWithChainID")
|
|
||||||
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
|
|
||||||
signer := types.HomesteadSigner{}
|
|
||||||
return &TransactOpts{
|
|
||||||
From: keyAddr,
|
|
||||||
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
|
||||||
if address != keyAddr {
|
|
||||||
return nil, ErrNotAuthorized
|
|
||||||
}
|
|
||||||
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tx.WithSignature(signer, signature)
|
|
||||||
},
|
|
||||||
Context: context.Background(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTransactorWithChainID is a utility method to easily create a transaction signer from
|
|
||||||
// an encrypted json key stream and the associated passphrase.
|
|
||||||
func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.Int) (*TransactOpts, error) {
|
|
||||||
json, err := io.ReadAll(keyin)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
key, err := keystore.DecryptKey(json, passphrase)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return NewKeyedTransactorWithChainID(key.PrivateKey, chainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewKeyStoreTransactorWithChainID is a utility method to easily create a transaction signer from
|
|
||||||
// a decrypted key from a keystore.
|
|
||||||
func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) (*TransactOpts, error) {
|
|
||||||
if chainID == nil {
|
|
||||||
return nil, ErrNoChainID
|
|
||||||
}
|
|
||||||
signer := types.LatestSignerForChainID(chainID)
|
|
||||||
return &TransactOpts{
|
|
||||||
From: account.Address,
|
|
||||||
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
|
||||||
if address != account.Address {
|
|
||||||
return nil, ErrNotAuthorized
|
|
||||||
}
|
|
||||||
signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tx.WithSignature(signer, signature)
|
|
||||||
},
|
|
||||||
Context: context.Background(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewKeyedTransactorWithChainID is a utility method to easily create a transaction signer
|
|
||||||
// from a single private key.
|
|
||||||
func NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *big.Int) (*TransactOpts, error) {
|
|
||||||
if chainID == nil {
|
|
||||||
return nil, ErrNoChainID
|
|
||||||
}
|
|
||||||
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
|
|
||||||
signer := types.LatestSignerForChainID(chainID)
|
|
||||||
return &TransactOpts{
|
|
||||||
From: keyAddr,
|
|
||||||
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
|
||||||
if address != keyAddr {
|
|
||||||
return nil, ErrNotAuthorized
|
|
||||||
}
|
|
||||||
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tx.WithSignature(signer, signature)
|
|
||||||
},
|
|
||||||
Context: context.Background(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClefTransactor is a utility method to easily create a transaction signer
|
|
||||||
// with a clef backend.
|
|
||||||
func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts {
|
|
||||||
return &TransactOpts{
|
|
||||||
From: account.Address,
|
|
||||||
Signer: func(address common.Address, transaction *types.Transaction) (*types.Transaction, error) {
|
|
||||||
if address != account.Address {
|
|
||||||
return nil, ErrNotAuthorized
|
|
||||||
}
|
|
||||||
return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id
|
|
||||||
},
|
|
||||||
Context: context.Background(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
294
accounts/abi/bind/old.go
Normal file
294
accounts/abi/bind/old.go
Normal file
|
|
@ -0,0 +1,294 @@
|
||||||
|
// Copyright 2016 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 bind is the runtime for abigen v1 generated contract bindings.
|
||||||
|
// Deprecated: please use github.com/ethereum/go-ethereum/bind/v2
|
||||||
|
package bind
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/abigen"
|
||||||
|
bind2 "github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/external"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bind generates a v1 contract binding.
|
||||||
|
// Deprecated: binding generation has moved to github.com/ethereum/go-ethereum/accounts/abi/abigen
|
||||||
|
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, libs map[string]string, aliases map[string]string) (string, error) {
|
||||||
|
return abigen.Bind(types, abis, bytecodes, fsigs, pkg, libs, aliases)
|
||||||
|
}
|
||||||
|
|
||||||
|
// auth.go
|
||||||
|
|
||||||
|
// ErrNoChainID is returned whenever the user failed to specify a chain id.
|
||||||
|
var ErrNoChainID = errors.New("no chain id specified")
|
||||||
|
|
||||||
|
// ErrNotAuthorized is returned when an account is not properly unlocked.
|
||||||
|
var ErrNotAuthorized = bind2.ErrNotAuthorized
|
||||||
|
|
||||||
|
// NewTransactor is a utility method to easily create a transaction signer from
|
||||||
|
// an encrypted json key stream and the associated passphrase.
|
||||||
|
//
|
||||||
|
// Deprecated: Use NewTransactorWithChainID instead.
|
||||||
|
func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
|
||||||
|
log.Warn("WARNING: NewTransactor has been deprecated in favour of NewTransactorWithChainID")
|
||||||
|
json, err := io.ReadAll(keyin)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key, err := keystore.DecryptKey(json, passphrase)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewKeyedTransactor(key.PrivateKey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
|
||||||
|
// a decrypted key from a keystore.
|
||||||
|
//
|
||||||
|
// Deprecated: Use NewKeyStoreTransactorWithChainID instead.
|
||||||
|
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
|
||||||
|
log.Warn("WARNING: NewKeyStoreTransactor has been deprecated in favour of NewTransactorWithChainID")
|
||||||
|
signer := types.HomesteadSigner{}
|
||||||
|
return &TransactOpts{
|
||||||
|
From: account.Address,
|
||||||
|
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
||||||
|
if address != account.Address {
|
||||||
|
return nil, ErrNotAuthorized
|
||||||
|
}
|
||||||
|
signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tx.WithSignature(signer, signature)
|
||||||
|
},
|
||||||
|
Context: context.Background(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKeyedTransactor is a utility method to easily create a transaction signer
|
||||||
|
// from a single private key.
|
||||||
|
//
|
||||||
|
// Deprecated: Use NewKeyedTransactorWithChainID instead.
|
||||||
|
func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
|
||||||
|
log.Warn("WARNING: NewKeyedTransactor has been deprecated in favour of NewKeyedTransactorWithChainID")
|
||||||
|
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
signer := types.HomesteadSigner{}
|
||||||
|
return &TransactOpts{
|
||||||
|
From: keyAddr,
|
||||||
|
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
||||||
|
if address != keyAddr {
|
||||||
|
return nil, ErrNotAuthorized
|
||||||
|
}
|
||||||
|
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tx.WithSignature(signer, signature)
|
||||||
|
},
|
||||||
|
Context: context.Background(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTransactorWithChainID is a utility method to easily create a transaction signer from
|
||||||
|
// an encrypted json key stream and the associated passphrase.
|
||||||
|
func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.Int) (*TransactOpts, error) {
|
||||||
|
json, err := io.ReadAll(keyin)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key, err := keystore.DecryptKey(json, passphrase)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewKeyedTransactorWithChainID(key.PrivateKey, chainID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKeyStoreTransactorWithChainID is a utility method to easily create a transaction signer from
|
||||||
|
// a decrypted key from a keystore.
|
||||||
|
func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) (*TransactOpts, error) {
|
||||||
|
// New version panics for chainID == nil, catch it here.
|
||||||
|
if chainID == nil {
|
||||||
|
return nil, ErrNoChainID
|
||||||
|
}
|
||||||
|
return bind2.NewKeyStoreTransactor(keystore, account, chainID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKeyedTransactorWithChainID is a utility method to easily create a transaction signer
|
||||||
|
// from a single private key.
|
||||||
|
func NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *big.Int) (*TransactOpts, error) {
|
||||||
|
// New version panics for chainID == nil, catch it here.
|
||||||
|
if chainID == nil {
|
||||||
|
return nil, ErrNoChainID
|
||||||
|
}
|
||||||
|
return bind2.NewKeyedTransactor(key, chainID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClefTransactor is a utility method to easily create a transaction signer
|
||||||
|
// with a clef backend.
|
||||||
|
func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts {
|
||||||
|
return bind2.NewClefTransactor(clef, account)
|
||||||
|
}
|
||||||
|
|
||||||
|
// backend.go
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNoCode is returned by call and transact operations for which the requested
|
||||||
|
// recipient contract to operate on does not exist in the state db or does not
|
||||||
|
// have any code associated with it (i.e. self-destructed).
|
||||||
|
ErrNoCode = bind2.ErrNoCode
|
||||||
|
|
||||||
|
// ErrNoPendingState is raised when attempting to perform a pending state action
|
||||||
|
// on a backend that doesn't implement PendingContractCaller.
|
||||||
|
ErrNoPendingState = bind2.ErrNoPendingState
|
||||||
|
|
||||||
|
// ErrNoBlockHashState is raised when attempting to perform a block hash action
|
||||||
|
// on a backend that doesn't implement BlockHashContractCaller.
|
||||||
|
ErrNoBlockHashState = bind2.ErrNoBlockHashState
|
||||||
|
|
||||||
|
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
|
||||||
|
// an empty contract behind.
|
||||||
|
ErrNoCodeAfterDeploy = bind2.ErrNoCodeAfterDeploy
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContractCaller defines the methods needed to allow operating with a contract on a read
|
||||||
|
// only basis.
|
||||||
|
type ContractCaller = bind2.ContractCaller
|
||||||
|
|
||||||
|
// PendingContractCaller defines methods to perform contract calls on the pending state.
|
||||||
|
// Call will try to discover this interface when access to the pending state is requested.
|
||||||
|
// If the backend does not support the pending state, Call returns ErrNoPendingState.
|
||||||
|
type PendingContractCaller = bind2.PendingContractCaller
|
||||||
|
|
||||||
|
// BlockHashContractCaller defines methods to perform contract calls on a specific block hash.
|
||||||
|
// Call will try to discover this interface when access to a block by hash is requested.
|
||||||
|
// If the backend does not support the block hash state, Call returns ErrNoBlockHashState.
|
||||||
|
type BlockHashContractCaller = bind2.BlockHashContractCaller
|
||||||
|
|
||||||
|
// ContractTransactor defines the methods needed to allow operating with a contract
|
||||||
|
// on a write only basis. Besides the transacting method, the remainder are helpers
|
||||||
|
// used when the user does not provide some needed values, but rather leaves it up
|
||||||
|
// to the transactor to decide.
|
||||||
|
type ContractTransactor = bind2.ContractTransactor
|
||||||
|
|
||||||
|
// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
|
||||||
|
type DeployBackend = bind2.DeployBackend
|
||||||
|
|
||||||
|
// ContractFilterer defines the methods needed to access log events using one-off
|
||||||
|
// queries or continuous event subscriptions.
|
||||||
|
type ContractFilterer = bind2.ContractFilterer
|
||||||
|
|
||||||
|
// ContractBackend defines the methods needed to work with contracts on a read-write basis.
|
||||||
|
type ContractBackend = bind2.ContractBackend
|
||||||
|
|
||||||
|
// base.go
|
||||||
|
|
||||||
|
type SignerFn = bind2.SignerFn
|
||||||
|
|
||||||
|
type CallOpts = bind2.CallOpts
|
||||||
|
|
||||||
|
type TransactOpts = bind2.TransactOpts
|
||||||
|
|
||||||
|
type FilterOpts = bind2.FilterOpts
|
||||||
|
|
||||||
|
type WatchOpts = bind2.WatchOpts
|
||||||
|
|
||||||
|
type BoundContract = bind2.BoundContract
|
||||||
|
|
||||||
|
func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller, transactor ContractTransactor, filterer ContractFilterer) *BoundContract {
|
||||||
|
return bind2.NewBoundContract(address, abi, caller, transactor, filterer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend ContractBackend, params ...interface{}) (common.Address, *types.Transaction, *BoundContract, error) {
|
||||||
|
packed, err := abi.Pack("", params...)
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, nil, err
|
||||||
|
}
|
||||||
|
addr, tx, err := bind2.DeployContract(opts, bytecode, backend, packed)
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, nil, err
|
||||||
|
}
|
||||||
|
contract := NewBoundContract(addr, abi, backend, backend, backend)
|
||||||
|
return addr, tx, contract, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetaData collects all metadata for a bound contract.
|
||||||
|
type MetaData struct {
|
||||||
|
Bin string // runtime bytecode (as a hex string)
|
||||||
|
ABI string // the raw ABI definition (JSON)
|
||||||
|
Sigs map[string]string // 4byte identifier -> function signature
|
||||||
|
mu sync.Mutex
|
||||||
|
parsedABI *abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAbi returns the parsed ABI definition.
|
||||||
|
func (m *MetaData) GetAbi() (*abi.ABI, error) {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
if m.parsedABI != nil {
|
||||||
|
return m.parsedABI, nil
|
||||||
|
}
|
||||||
|
if parsed, err := abi.JSON(strings.NewReader(m.ABI)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
m.parsedABI = &parsed
|
||||||
|
}
|
||||||
|
return m.parsedABI, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// util.go
|
||||||
|
|
||||||
|
// WaitMined waits for tx to be mined on the blockchain.
|
||||||
|
// It stops waiting when the context is canceled.
|
||||||
|
func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) {
|
||||||
|
return bind2.WaitMined(ctx, b, tx.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitMinedHash waits for a transaction with the provided hash to be mined on the blockchain.
|
||||||
|
// It stops waiting when the context is canceled.
|
||||||
|
func WaitMinedHash(ctx context.Context, b DeployBackend, hash common.Hash) (*types.Receipt, error) {
|
||||||
|
return bind2.WaitMined(ctx, b, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitDeployed waits for a contract deployment transaction and returns the on-chain
|
||||||
|
// contract address when it is mined. It stops waiting when ctx is canceled.
|
||||||
|
func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) {
|
||||||
|
if tx.To() != nil {
|
||||||
|
return common.Address{}, errors.New("tx is not contract creation")
|
||||||
|
}
|
||||||
|
return bind2.WaitDeployed(ctx, b, tx.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitDeployedHash waits for a contract deployment transaction with the provided hash and returns the on-chain
|
||||||
|
// contract address when it is mined. It stops waiting when ctx is canceled.
|
||||||
|
func WaitDeployedHash(ctx context.Context, b DeployBackend, hash common.Hash) (common.Address, error) {
|
||||||
|
return bind2.WaitDeployed(ctx, b, hash)
|
||||||
|
}
|
||||||
96
accounts/abi/bind/v2/auth.go
Normal file
96
accounts/abi/bind/v2/auth.go
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
// Copyright 2016 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 bind
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/external"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrNotAuthorized is returned when an account is not properly unlocked.
|
||||||
|
var ErrNotAuthorized = errors.New("not authorized to sign this account")
|
||||||
|
|
||||||
|
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
|
||||||
|
// a decrypted key from a keystore.
|
||||||
|
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) *TransactOpts {
|
||||||
|
if chainID == nil {
|
||||||
|
panic("nil chainID")
|
||||||
|
}
|
||||||
|
signer := types.LatestSignerForChainID(chainID)
|
||||||
|
return &TransactOpts{
|
||||||
|
From: account.Address,
|
||||||
|
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
||||||
|
if address != account.Address {
|
||||||
|
return nil, ErrNotAuthorized
|
||||||
|
}
|
||||||
|
signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tx.WithSignature(signer, signature)
|
||||||
|
},
|
||||||
|
Context: context.Background(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKeyedTransactor is a utility method to easily create a transaction signer
|
||||||
|
// from a single private key.
|
||||||
|
func NewKeyedTransactor(key *ecdsa.PrivateKey, chainID *big.Int) *TransactOpts {
|
||||||
|
if chainID == nil {
|
||||||
|
panic("nil chainID")
|
||||||
|
}
|
||||||
|
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
signer := types.LatestSignerForChainID(chainID)
|
||||||
|
return &TransactOpts{
|
||||||
|
From: keyAddr,
|
||||||
|
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
||||||
|
if address != keyAddr {
|
||||||
|
return nil, ErrNotAuthorized
|
||||||
|
}
|
||||||
|
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tx.WithSignature(signer, signature)
|
||||||
|
},
|
||||||
|
Context: context.Background(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClefTransactor is a utility method to easily create a transaction signer
|
||||||
|
// with a clef backend.
|
||||||
|
func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts {
|
||||||
|
return &TransactOpts{
|
||||||
|
From: account.Address,
|
||||||
|
Signer: func(address common.Address, transaction *types.Transaction) (*types.Transaction, error) {
|
||||||
|
if address != account.Address {
|
||||||
|
return nil, ErrNotAuthorized
|
||||||
|
}
|
||||||
|
return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id
|
||||||
|
},
|
||||||
|
Context: context.Background(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,11 @@ var (
|
||||||
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
|
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
|
||||||
// an empty contract behind.
|
// an empty contract behind.
|
||||||
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
|
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
|
||||||
|
|
||||||
|
// ErrNoAddressInReceipt is returned by WaitDeployed when the receipt for the
|
||||||
|
// transaction hash does not contain a contract address. This error may indicate
|
||||||
|
// that the transaction hash was not a CREATE transaction.
|
||||||
|
ErrNoAddressInReceipt = errors.New("no contract address in receipt")
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContractCaller defines the methods needed to allow operating with a contract on a read
|
// ContractCaller defines the methods needed to allow operating with a contract on a read
|
||||||
|
|
@ -118,3 +123,11 @@ type ContractBackend interface {
|
||||||
ContractTransactor
|
ContractTransactor
|
||||||
ContractFilterer
|
ContractFilterer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Backend combines all backend methods used in this package. This type is provided for
|
||||||
|
// convenience. It is meant to be used when you need to hold a reference to a backend that
|
||||||
|
// is used for both deployment and contract interaction.
|
||||||
|
type Backend interface {
|
||||||
|
DeployBackend
|
||||||
|
ContractBackend
|
||||||
|
}
|
||||||
|
|
@ -25,10 +25,10 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"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/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -89,25 +89,42 @@ type WatchOpts struct {
|
||||||
|
|
||||||
// MetaData collects all metadata for a bound contract.
|
// MetaData collects all metadata for a bound contract.
|
||||||
type MetaData struct {
|
type MetaData struct {
|
||||||
mu sync.Mutex
|
Bin string // deployer bytecode (as a hex string)
|
||||||
Sigs map[string]string
|
ABI string // the raw ABI definition (JSON)
|
||||||
Bin string
|
Deps []*MetaData // library dependencies of the contract
|
||||||
ABI string
|
|
||||||
ab *abi.ABI
|
// For bindings that were compiled from combined-json ID is the Solidity
|
||||||
|
// library pattern: a 34 character prefix of the hex encoding of the keccak256
|
||||||
|
// hash of the fully qualified 'library name', i.e. the path of the source file.
|
||||||
|
//
|
||||||
|
// For contracts compiled from the ABI definition alone, this is the type name
|
||||||
|
// of the contract (as specified in the ABI definition or overridden via the
|
||||||
|
// --type flag).
|
||||||
|
//
|
||||||
|
// This is a unique identifier of a contract within a compilation unit. When
|
||||||
|
// used as part of a multi-contract deployment with library dependencies, the
|
||||||
|
// ID is used to link contracts during deployment using [LinkAndDeploy].
|
||||||
|
ID string
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
parsedABI *abi.ABI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MetaData) GetAbi() (*abi.ABI, error) {
|
// ParseABI returns the parsed ABI specification, or an error if the string
|
||||||
|
// representation of the ABI set in the MetaData instance could not be parsed.
|
||||||
|
func (m *MetaData) ParseABI() (*abi.ABI, error) {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
if m.ab != nil {
|
|
||||||
return m.ab, nil
|
if m.parsedABI != nil {
|
||||||
|
return m.parsedABI, nil
|
||||||
}
|
}
|
||||||
if parsed, err := abi.JSON(strings.NewReader(m.ABI)); err != nil {
|
if parsed, err := abi.JSON(strings.NewReader(m.ABI)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
m.ab = &parsed
|
m.parsedABI = &parsed
|
||||||
}
|
}
|
||||||
return m.ab, nil
|
return m.parsedABI, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BoundContract is the base wrapper object that reflects a contract on the
|
// BoundContract is the base wrapper object that reflects a contract on the
|
||||||
|
|
@ -133,94 +150,23 @@ func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeployContract deploys a contract onto the Ethereum blockchain and binds the
|
|
||||||
// deployment address with a Go wrapper.
|
|
||||||
func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend ContractBackend, params ...interface{}) (common.Address, *types.Transaction, *BoundContract, error) {
|
|
||||||
// Otherwise try to deploy the contract
|
|
||||||
c := NewBoundContract(common.Address{}, abi, backend, backend, backend)
|
|
||||||
|
|
||||||
input, err := c.abi.Pack("", params...)
|
|
||||||
if err != nil {
|
|
||||||
return common.Address{}, nil, nil, err
|
|
||||||
}
|
|
||||||
tx, err := c.transact(opts, nil, append(bytecode, input...))
|
|
||||||
if err != nil {
|
|
||||||
return common.Address{}, nil, nil, err
|
|
||||||
}
|
|
||||||
c.address = crypto.CreateAddress(opts.From, tx.Nonce())
|
|
||||||
return c.address, tx, c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call invokes the (constant) contract method with params as input values and
|
// 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
|
// 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, a slice of interfaces for anonymous returns and a struct for named
|
||||||
// returns.
|
// returns.
|
||||||
func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method string, params ...interface{}) error {
|
func (c *BoundContract) Call(opts *CallOpts, results *[]any, method string, params ...any) error {
|
||||||
// Don't crash on a lazy user
|
|
||||||
if opts == nil {
|
|
||||||
opts = new(CallOpts)
|
|
||||||
}
|
|
||||||
if results == nil {
|
if results == nil {
|
||||||
results = new([]interface{})
|
results = new([]any)
|
||||||
}
|
}
|
||||||
// Pack the input, call and unpack the results
|
// Pack the input, call and unpack the results
|
||||||
input, err := c.abi.Pack(method, params...)
|
input, err := c.abi.Pack(method, params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var (
|
|
||||||
msg = ethereum.CallMsg{From: opts.From, To: &c.address, Data: input}
|
output, err := c.call(opts, input)
|
||||||
ctx = ensureContext(opts.Context)
|
if err != nil {
|
||||||
code []byte
|
return err
|
||||||
output []byte
|
|
||||||
)
|
|
||||||
if opts.Pending {
|
|
||||||
pb, ok := c.caller.(PendingContractCaller)
|
|
||||||
if !ok {
|
|
||||||
return ErrNoPendingState
|
|
||||||
}
|
|
||||||
output, err = pb.PendingCallContract(ctx, msg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(output) == 0 {
|
|
||||||
// Make sure we have a contract to operate on, and bail out otherwise.
|
|
||||||
if code, err = pb.PendingCodeAt(ctx, c.address); err != nil {
|
|
||||||
return err
|
|
||||||
} else if len(code) == 0 {
|
|
||||||
return ErrNoCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if opts.BlockHash != (common.Hash{}) {
|
|
||||||
bh, ok := c.caller.(BlockHashContractCaller)
|
|
||||||
if !ok {
|
|
||||||
return ErrNoBlockHashState
|
|
||||||
}
|
|
||||||
output, err = bh.CallContractAtHash(ctx, msg, opts.BlockHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(output) == 0 {
|
|
||||||
// Make sure we have a contract to operate on, and bail out otherwise.
|
|
||||||
if code, err = bh.CodeAtHash(ctx, c.address, opts.BlockHash); err != nil {
|
|
||||||
return err
|
|
||||||
} else if len(code) == 0 {
|
|
||||||
return ErrNoCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(output) == 0 {
|
|
||||||
// Make sure we have a contract to operate on, and bail out otherwise.
|
|
||||||
if code, err = c.caller.CodeAt(ctx, c.address, opts.BlockNumber); err != nil {
|
|
||||||
return err
|
|
||||||
} else if len(code) == 0 {
|
|
||||||
return ErrNoCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*results) == 0 {
|
if len(*results) == 0 {
|
||||||
|
|
@ -232,26 +178,97 @@ func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method stri
|
||||||
return c.abi.UnpackIntoInterface(res[0], method, output)
|
return c.abi.UnpackIntoInterface(res[0], method, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CallRaw executes an eth_call against the contract with the raw calldata as
|
||||||
|
// input. It returns the call's return data or an error.
|
||||||
|
func (c *BoundContract) CallRaw(opts *CallOpts, input []byte) ([]byte, error) {
|
||||||
|
return c.call(opts, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *BoundContract) call(opts *CallOpts, input []byte) ([]byte, error) {
|
||||||
|
// Don't crash on a lazy user
|
||||||
|
if opts == nil {
|
||||||
|
opts = new(CallOpts)
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
msg = ethereum.CallMsg{From: opts.From, To: &c.address, Data: input}
|
||||||
|
ctx = ensureContext(opts.Context)
|
||||||
|
code []byte
|
||||||
|
output []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if opts.Pending {
|
||||||
|
pb, ok := c.caller.(PendingContractCaller)
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrNoPendingState
|
||||||
|
}
|
||||||
|
output, err = pb.PendingCallContract(ctx, msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(output) == 0 {
|
||||||
|
// Make sure we have a contract to operate on, and bail out otherwise.
|
||||||
|
if code, err = pb.PendingCodeAt(ctx, c.address); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if len(code) == 0 {
|
||||||
|
return nil, ErrNoCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if opts.BlockHash != (common.Hash{}) {
|
||||||
|
bh, ok := c.caller.(BlockHashContractCaller)
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrNoBlockHashState
|
||||||
|
}
|
||||||
|
output, err = bh.CallContractAtHash(ctx, msg, opts.BlockHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(output) == 0 {
|
||||||
|
// Make sure we have a contract to operate on, and bail out otherwise.
|
||||||
|
if code, err = bh.CodeAtHash(ctx, c.address, opts.BlockHash); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if len(code) == 0 {
|
||||||
|
return nil, ErrNoCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(output) == 0 {
|
||||||
|
// Make sure we have a contract to operate on, and bail out otherwise.
|
||||||
|
if code, err = c.caller.CodeAt(ctx, c.address, opts.BlockNumber); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if len(code) == 0 {
|
||||||
|
return nil, ErrNoCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Transact invokes the (paid) contract method with params as input values.
|
// Transact invokes the (paid) contract method with params as input values.
|
||||||
func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...any) (*types.Transaction, error) {
|
||||||
// Otherwise pack up the parameters and invoke the contract
|
// Otherwise pack up the parameters and invoke the contract
|
||||||
input, err := c.abi.Pack(method, params...)
|
input, err := c.abi.Pack(method, params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// todo(rjl493456442) check whether the method is payable or not,
|
|
||||||
// reject invalid transaction at the first place
|
|
||||||
return c.transact(opts, &c.address, input)
|
return c.transact(opts, &c.address, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawTransact initiates a transaction with the given raw calldata as the input.
|
// RawTransact initiates a transaction with the given raw calldata as the input.
|
||||||
// It's usually used to initiate transactions for invoking **Fallback** function.
|
// It's usually used to initiate transactions for invoking **Fallback** function.
|
||||||
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
|
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
|
||||||
// todo(rjl493456442) check whether the method is payable or not,
|
|
||||||
// reject invalid transaction at the first place
|
|
||||||
return c.transact(opts, &c.address, calldata)
|
return c.transact(opts, &c.address, calldata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RawCreationTransact creates and submits a contract-creation transaction with
|
||||||
|
// the given calldata as the input.
|
||||||
|
func (c *BoundContract) RawCreationTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
|
||||||
|
return c.transact(opts, nil, calldata)
|
||||||
|
}
|
||||||
|
|
||||||
// Transfer initiates a plain transaction to move funds to the contract, calling
|
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||||
// its default method if one is available.
|
// its default method if one is available.
|
||||||
func (c *BoundContract) Transfer(opts *TransactOpts) (*types.Transaction, error) {
|
func (c *BoundContract) Transfer(opts *TransactOpts) (*types.Transaction, error) {
|
||||||
|
|
@ -366,13 +383,14 @@ func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Ad
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg := ethereum.CallMsg{
|
msg := ethereum.CallMsg{
|
||||||
From: opts.From,
|
From: opts.From,
|
||||||
To: contract,
|
To: contract,
|
||||||
GasPrice: gasPrice,
|
GasPrice: gasPrice,
|
||||||
GasTipCap: gasTipCap,
|
GasTipCap: gasTipCap,
|
||||||
GasFeeCap: gasFeeCap,
|
GasFeeCap: gasFeeCap,
|
||||||
Value: value,
|
Value: value,
|
||||||
Data: input,
|
Data: input,
|
||||||
|
AccessList: opts.AccessList,
|
||||||
}
|
}
|
||||||
return c.transactor.EstimateGas(ensureContext(opts.Context), msg)
|
return c.transactor.EstimateGas(ensureContext(opts.Context), msg)
|
||||||
}
|
}
|
||||||
|
|
@ -433,14 +451,13 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
|
||||||
|
|
||||||
// FilterLogs filters contract logs for past blocks, returning the necessary
|
// FilterLogs filters contract logs for past blocks, returning the necessary
|
||||||
// channels to construct a strongly typed bound iterator on top of them.
|
// channels to construct a strongly typed bound iterator on top of them.
|
||||||
func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]interface{}) (chan types.Log, event.Subscription, error) {
|
func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]any) (chan types.Log, event.Subscription, error) {
|
||||||
// Don't crash on a lazy user
|
// Don't crash on a lazy user
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
opts = new(FilterOpts)
|
opts = new(FilterOpts)
|
||||||
}
|
}
|
||||||
// Append the event selector to the query parameters and construct the topic set
|
// Append the event selector to the query parameters and construct the topic set
|
||||||
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
|
query = append([][]any{{c.abi.Events[name].ID}}, query...)
|
||||||
|
|
||||||
topics, err := abi.MakeTopics(query...)
|
topics, err := abi.MakeTopics(query...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|
@ -479,13 +496,13 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
|
||||||
|
|
||||||
// WatchLogs filters subscribes to contract logs for future blocks, returning a
|
// WatchLogs filters subscribes to contract logs for future blocks, returning a
|
||||||
// subscription object that can be used to tear down the watcher.
|
// subscription object that can be used to tear down the watcher.
|
||||||
func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]interface{}) (chan types.Log, event.Subscription, error) {
|
func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]any) (chan types.Log, event.Subscription, error) {
|
||||||
// Don't crash on a lazy user
|
// Don't crash on a lazy user
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
opts = new(WatchOpts)
|
opts = new(WatchOpts)
|
||||||
}
|
}
|
||||||
// Append the event selector to the query parameters and construct the topic set
|
// Append the event selector to the query parameters and construct the topic set
|
||||||
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
|
query = append([][]any{{c.abi.Events[name].ID}}, query...)
|
||||||
|
|
||||||
topics, err := abi.MakeTopics(query...)
|
topics, err := abi.MakeTopics(query...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -509,7 +526,7 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnpackLog unpacks a retrieved log into the provided output structure.
|
// UnpackLog unpacks a retrieved log into the provided output structure.
|
||||||
func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) error {
|
func (c *BoundContract) UnpackLog(out any, event string, log types.Log) error {
|
||||||
// Anonymous events are not supported.
|
// Anonymous events are not supported.
|
||||||
if len(log.Topics) == 0 {
|
if len(log.Topics) == 0 {
|
||||||
return errNoEventSignature
|
return errNoEventSignature
|
||||||
|
|
@ -532,7 +549,7 @@ func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnpackLogIntoMap unpacks a retrieved log into the provided map.
|
// UnpackLogIntoMap unpacks a retrieved log into the provided map.
|
||||||
func (c *BoundContract) UnpackLogIntoMap(out map[string]interface{}, event string, log types.Log) error {
|
func (c *BoundContract) UnpackLogIntoMap(out map[string]any, event string, log types.Log) error {
|
||||||
// Anonymous events are not supported.
|
// Anonymous events are not supported.
|
||||||
if len(log.Topics) == 0 {
|
if len(log.Topics) == 0 {
|
||||||
return errNoEventSignature
|
return errNoEventSignature
|
||||||
|
|
@ -26,7 +26,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
167
accounts/abi/bind/v2/dep_tree.go
Normal file
167
accounts/abi/bind/v2/dep_tree.go
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
// Copyright 2025 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package bind
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"maps"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeploymentParams contains parameters needed to deploy one or more contracts via LinkAndDeploy
|
||||||
|
type DeploymentParams struct {
|
||||||
|
// list of all contracts targeted for the deployment
|
||||||
|
Contracts []*MetaData
|
||||||
|
|
||||||
|
// optional map of ABI-encoded constructor inputs keyed by the MetaData.ID.
|
||||||
|
Inputs map[string][]byte
|
||||||
|
|
||||||
|
// optional map of override addresses for specifying already-deployed
|
||||||
|
// contracts. It is keyed by the MetaData.ID.
|
||||||
|
Overrides map[string]common.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate determines whether the contracts specified in the DeploymentParams
|
||||||
|
// instance have embedded deployer code in their provided MetaData instances.
|
||||||
|
func (d *DeploymentParams) validate() error {
|
||||||
|
for _, meta := range d.Contracts {
|
||||||
|
if meta.Bin == "" {
|
||||||
|
return fmt.Errorf("cannot deploy contract %s: deployer code missing from metadata", meta.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentResult contains information about the result of a pending
|
||||||
|
// deployment made by LinkAndDeploy.
|
||||||
|
type DeploymentResult struct {
|
||||||
|
// Map of contract MetaData.ID to pending deployment transaction
|
||||||
|
Txs map[string]*types.Transaction
|
||||||
|
|
||||||
|
// Map of contract MetaData.ID to the address where it will be deployed
|
||||||
|
Addresses map[string]common.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeployFn deploys a contract given a deployer and optional input. It returns
|
||||||
|
// the address and a pending transaction, or an error if the deployment failed.
|
||||||
|
type DeployFn func(input, deployer []byte) (common.Address, *types.Transaction, error)
|
||||||
|
|
||||||
|
// depTreeDeployer is responsible for taking a dependency, deploying-and-linking
|
||||||
|
// its components in the proper order. A depTreeDeployer cannot be used after
|
||||||
|
// calling LinkAndDeploy other than to retrieve the deployment result.
|
||||||
|
type depTreeDeployer struct {
|
||||||
|
deployedAddrs map[string]common.Address
|
||||||
|
deployerTxs map[string]*types.Transaction
|
||||||
|
inputs map[string][]byte // map of the root contract pattern to the constructor input (if there is any)
|
||||||
|
deployFn DeployFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDepTreeDeployer(deployParams *DeploymentParams, deployFn DeployFn) *depTreeDeployer {
|
||||||
|
deployedAddrs := maps.Clone(deployParams.Overrides)
|
||||||
|
if deployedAddrs == nil {
|
||||||
|
deployedAddrs = make(map[string]common.Address)
|
||||||
|
}
|
||||||
|
inputs := deployParams.Inputs
|
||||||
|
if inputs == nil {
|
||||||
|
inputs = make(map[string][]byte)
|
||||||
|
}
|
||||||
|
return &depTreeDeployer{
|
||||||
|
deployFn: deployFn,
|
||||||
|
deployedAddrs: deployedAddrs,
|
||||||
|
deployerTxs: make(map[string]*types.Transaction),
|
||||||
|
inputs: inputs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// linkAndDeploy deploys a contract and it's dependencies. Because libraries
|
||||||
|
// can in-turn have their own library dependencies, linkAndDeploy performs
|
||||||
|
// deployment recursively (deepest-dependency first). The address of the
|
||||||
|
// pending contract deployment for the top-level contract is returned.
|
||||||
|
func (d *depTreeDeployer) linkAndDeploy(metadata *MetaData) (common.Address, error) {
|
||||||
|
// Don't re-deploy aliased or previously-deployed contracts
|
||||||
|
if addr, ok := d.deployedAddrs[metadata.ID]; ok {
|
||||||
|
return addr, nil
|
||||||
|
}
|
||||||
|
// If this contract/library depends on other libraries deploy them
|
||||||
|
// (and their dependencies) first
|
||||||
|
deployerCode := metadata.Bin
|
||||||
|
for _, dep := range metadata.Deps {
|
||||||
|
addr, err := d.linkAndDeploy(dep)
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, err
|
||||||
|
}
|
||||||
|
// Link their deployed addresses into the bytecode to produce
|
||||||
|
deployerCode = strings.ReplaceAll(deployerCode, "__$"+dep.ID+"$__", strings.ToLower(addr.String()[2:]))
|
||||||
|
}
|
||||||
|
// Finally, deploy the top-level contract.
|
||||||
|
code, err := hex.DecodeString(deployerCode[2:])
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("error decoding contract deployer hex %s:\n%v", deployerCode[2:], err))
|
||||||
|
}
|
||||||
|
addr, tx, err := d.deployFn(d.inputs[metadata.ID], code)
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, err
|
||||||
|
}
|
||||||
|
d.deployedAddrs[metadata.ID] = addr
|
||||||
|
d.deployerTxs[metadata.ID] = tx
|
||||||
|
return addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// result returns a DeploymentResult instance referencing contracts deployed
|
||||||
|
// and not including any overrides specified for this deployment.
|
||||||
|
func (d *depTreeDeployer) result() *DeploymentResult {
|
||||||
|
// filter the override addresses from the deployed address set.
|
||||||
|
for pattern := range d.deployedAddrs {
|
||||||
|
if _, ok := d.deployerTxs[pattern]; !ok {
|
||||||
|
delete(d.deployedAddrs, pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &DeploymentResult{
|
||||||
|
Txs: d.deployerTxs,
|
||||||
|
Addresses: d.deployedAddrs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkAndDeploy performs the contract deployment specified by params using the
|
||||||
|
// provided DeployFn to create, sign and submit transactions.
|
||||||
|
//
|
||||||
|
// Contracts can depend on libraries, which in-turn can have their own library
|
||||||
|
// dependencies. Therefore, LinkAndDeploy performs the deployment recursively,
|
||||||
|
// starting with libraries (and contracts) that don't have dependencies, and
|
||||||
|
// progressing through the contracts that depend upon them.
|
||||||
|
//
|
||||||
|
// If an error is encountered, the returned DeploymentResult only contains
|
||||||
|
// entries for the contracts whose deployment submission succeeded.
|
||||||
|
//
|
||||||
|
// LinkAndDeploy performs creation and submission of creation transactions,
|
||||||
|
// but does not ensure that the contracts are included in the chain.
|
||||||
|
func LinkAndDeploy(params *DeploymentParams, deploy DeployFn) (*DeploymentResult, error) {
|
||||||
|
if err := params.validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
deployer := newDepTreeDeployer(params, deploy)
|
||||||
|
for _, contract := range params.Contracts {
|
||||||
|
if _, err := deployer.linkAndDeploy(contract); err != nil {
|
||||||
|
return deployer.result(), err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deployer.result(), nil
|
||||||
|
}
|
||||||
370
accounts/abi/bind/v2/dep_tree_test.go
Normal file
370
accounts/abi/bind/v2/dep_tree_test.go
Normal file
|
|
@ -0,0 +1,370 @@
|
||||||
|
// 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 bind
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"golang.org/x/exp/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type linkTestCase struct {
|
||||||
|
// map of pattern to unlinked bytecode (for the purposes of tests just contains the patterns of its dependencies)
|
||||||
|
libCodes map[string]string
|
||||||
|
contractCodes map[string]string
|
||||||
|
|
||||||
|
overrides map[string]common.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyMetaData(m *MetaData) *MetaData {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
var deps []*MetaData
|
||||||
|
if len(m.Deps) > 0 {
|
||||||
|
for _, dep := range m.Deps {
|
||||||
|
deps = append(deps, copyMetaData(dep))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &MetaData{
|
||||||
|
Bin: m.Bin,
|
||||||
|
ABI: m.ABI,
|
||||||
|
Deps: deps,
|
||||||
|
ID: m.ID,
|
||||||
|
parsedABI: m.parsedABI,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeLinkTestCase(input map[rune][]rune, overrides map[rune]common.Address) *linkTestCase {
|
||||||
|
codes := make(map[string]string)
|
||||||
|
libCodes := make(map[string]string)
|
||||||
|
contractCodes := make(map[string]string)
|
||||||
|
|
||||||
|
inputMap := make(map[rune]map[rune]struct{})
|
||||||
|
// set of solidity patterns for all contracts that are known to be libraries
|
||||||
|
libs := make(map[string]struct{})
|
||||||
|
|
||||||
|
// map of test contract id (rune) to the solidity library pattern (hash of that rune)
|
||||||
|
patternMap := map[rune]string{}
|
||||||
|
|
||||||
|
for contract, deps := range input {
|
||||||
|
inputMap[contract] = make(map[rune]struct{})
|
||||||
|
if _, ok := patternMap[contract]; !ok {
|
||||||
|
patternMap[contract] = crypto.Keccak256Hash([]byte(string(contract))).String()[2:36]
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dep := range deps {
|
||||||
|
if _, ok := patternMap[dep]; !ok {
|
||||||
|
patternMap[dep] = crypto.Keccak256Hash([]byte(string(dep))).String()[2:36]
|
||||||
|
}
|
||||||
|
codes[patternMap[contract]] = codes[patternMap[contract]] + fmt.Sprintf("__$%s$__", patternMap[dep])
|
||||||
|
inputMap[contract][dep] = struct{}{}
|
||||||
|
libs[patternMap[dep]] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overridesPatterns := make(map[string]common.Address)
|
||||||
|
for contractId, overrideAddr := range overrides {
|
||||||
|
pattern := crypto.Keccak256Hash([]byte(string(contractId))).String()[2:36]
|
||||||
|
overridesPatterns[pattern] = overrideAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pattern := range patternMap {
|
||||||
|
if _, ok := libs[pattern]; ok {
|
||||||
|
// if the library didn't depend on others, give it some dummy code to not bork deployment logic down-the-line
|
||||||
|
if len(codes[pattern]) == 0 {
|
||||||
|
libCodes[pattern] = "ff"
|
||||||
|
} else {
|
||||||
|
libCodes[pattern] = codes[pattern]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
contractCodes[pattern] = codes[pattern]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &linkTestCase{
|
||||||
|
libCodes,
|
||||||
|
contractCodes,
|
||||||
|
overridesPatterns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
|
||||||
|
type linkTestCaseInput struct {
|
||||||
|
input map[rune][]rune
|
||||||
|
overrides map[rune]struct{}
|
||||||
|
expectDeployed map[rune]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// linkDeps will return a set of root dependencies and their sub-dependencies connected via the Deps field
|
||||||
|
func linkDeps(deps map[string]*MetaData) []*MetaData {
|
||||||
|
roots := make(map[string]struct{})
|
||||||
|
for pattern := range deps {
|
||||||
|
roots[pattern] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedDeps := make(map[string]*MetaData)
|
||||||
|
for pattern, dep := range deps {
|
||||||
|
connectedDeps[pattern] = internalLinkDeps(dep, deps, &roots)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rootMetadatas []*MetaData
|
||||||
|
for pattern := range roots {
|
||||||
|
dep := connectedDeps[pattern]
|
||||||
|
rootMetadatas = append(rootMetadatas, dep)
|
||||||
|
}
|
||||||
|
return rootMetadatas
|
||||||
|
}
|
||||||
|
|
||||||
|
// internalLinkDeps is the internal recursing logic of linkDeps:
|
||||||
|
// It links the contract referred to by MetaData given the depMap (map of solidity
|
||||||
|
// link pattern to contract metadata object), deleting contract entries from the
|
||||||
|
// roots map if they were referenced as dependencies. It returns a new MetaData
|
||||||
|
// object which is the linked version of metadata parameter.
|
||||||
|
func internalLinkDeps(metadata *MetaData, depMap map[string]*MetaData, roots *map[string]struct{}) *MetaData {
|
||||||
|
linked := copyMetaData(metadata)
|
||||||
|
depPatterns := parseLibraryDeps(metadata.Bin)
|
||||||
|
for _, pattern := range depPatterns {
|
||||||
|
delete(*roots, pattern)
|
||||||
|
connectedDep := internalLinkDeps(depMap[pattern], depMap, roots)
|
||||||
|
linked.Deps = append(linked.Deps, connectedDep)
|
||||||
|
}
|
||||||
|
return linked
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLinkCase(tcInput linkTestCaseInput) error {
|
||||||
|
var (
|
||||||
|
testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
|
||||||
|
overridesAddrs = make(map[common.Address]struct{})
|
||||||
|
overrideAddrs = make(map[rune]common.Address)
|
||||||
|
)
|
||||||
|
// generate deterministic addresses for the override set.
|
||||||
|
rand.Seed(42)
|
||||||
|
for contract := range tcInput.overrides {
|
||||||
|
var addr common.Address
|
||||||
|
rand.Read(addr[:])
|
||||||
|
overrideAddrs[contract] = addr
|
||||||
|
overridesAddrs[addr] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
tc := makeLinkTestCase(tcInput.input, overrideAddrs)
|
||||||
|
allContracts := make(map[rune]struct{})
|
||||||
|
|
||||||
|
for contract, deps := range tcInput.input {
|
||||||
|
allContracts[contract] = struct{}{}
|
||||||
|
for _, dep := range deps {
|
||||||
|
allContracts[dep] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testAddrNonce uint64
|
||||||
|
mockDeploy := func(input []byte, deployer []byte) (common.Address, *types.Transaction, error) {
|
||||||
|
contractAddr := crypto.CreateAddress(testAddr, testAddrNonce)
|
||||||
|
testAddrNonce++
|
||||||
|
|
||||||
|
if len(deployer) >= 20 {
|
||||||
|
// assert that this contract only references libs that are known to be deployed or in the override set
|
||||||
|
for i := 0; i < len(deployer); i += 20 {
|
||||||
|
var dep common.Address
|
||||||
|
dep.SetBytes(deployer[i : i+20])
|
||||||
|
if _, ok := overridesAddrs[dep]; !ok {
|
||||||
|
return common.Address{}, nil, fmt.Errorf("reference to dependent contract that has not yet been deployed: %x\n", dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overridesAddrs[contractAddr] = struct{}{}
|
||||||
|
// we don't care about the txs themselves for the sake of the linking tests. so we can return nil for them in the mock deployer
|
||||||
|
return contractAddr, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
contracts := make(map[string]*MetaData)
|
||||||
|
overrides := make(map[string]common.Address)
|
||||||
|
|
||||||
|
for pattern, bin := range tc.contractCodes {
|
||||||
|
contracts[pattern] = &MetaData{ID: pattern, Bin: "0x" + bin}
|
||||||
|
}
|
||||||
|
for pattern, bin := range tc.libCodes {
|
||||||
|
contracts[pattern] = &MetaData{
|
||||||
|
Bin: "0x" + bin,
|
||||||
|
ID: pattern,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contractsList := linkDeps(contracts)
|
||||||
|
|
||||||
|
for pattern, override := range tc.overrides {
|
||||||
|
overrides[pattern] = override
|
||||||
|
}
|
||||||
|
|
||||||
|
deployParams := &DeploymentParams{
|
||||||
|
Contracts: contractsList,
|
||||||
|
Overrides: overrides,
|
||||||
|
}
|
||||||
|
res, err := LinkAndDeploy(deployParams, mockDeploy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res.Txs) != len(tcInput.expectDeployed) {
|
||||||
|
return fmt.Errorf("got %d deployed contracts. expected %d.\n", len(res.Addresses), len(tcInput.expectDeployed))
|
||||||
|
}
|
||||||
|
for contract := range tcInput.expectDeployed {
|
||||||
|
pattern := crypto.Keccak256Hash([]byte(string(contract))).String()[2:36]
|
||||||
|
if _, ok := res.Addresses[pattern]; !ok {
|
||||||
|
return fmt.Errorf("expected contract %s was not deployed\n", string(contract))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContractLinking(t *testing.T) {
|
||||||
|
for i, tc := range []linkTestCaseInput{
|
||||||
|
// test simple contract without any dependencies or overrides
|
||||||
|
{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {}},
|
||||||
|
map[rune]struct{}{},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}},
|
||||||
|
},
|
||||||
|
// test deployment of a contract that depends on somes libraries.
|
||||||
|
{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {'b', 'c', 'd', 'e'}},
|
||||||
|
map[rune]struct{}{},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}},
|
||||||
|
},
|
||||||
|
// test deployment of a contract that depends on some libraries,
|
||||||
|
// one of which has its own library dependencies.
|
||||||
|
{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {'b', 'c', 'd', 'e'},
|
||||||
|
'e': {'f', 'g', 'h', 'i'}},
|
||||||
|
map[rune]struct{}{},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}},
|
||||||
|
},
|
||||||
|
// test single contract only without deps
|
||||||
|
{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {}},
|
||||||
|
map[rune]struct{}{},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// test that libraries at different levels of the tree can share deps,
|
||||||
|
// and that these shared deps will only be deployed once.
|
||||||
|
{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {'b', 'c', 'd', 'e'},
|
||||||
|
'e': {'f', 'g', 'h', 'i', 'm'},
|
||||||
|
'i': {'j', 'k', 'l', 'm'}},
|
||||||
|
map[rune]struct{}{},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}, 'j': {}, 'k': {}, 'l': {}, 'm': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// test two contracts can be deployed which don't share deps
|
||||||
|
linkTestCaseInput{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {'b', 'c', 'd', 'e'},
|
||||||
|
'f': {'g', 'h', 'i', 'j'}},
|
||||||
|
map[rune]struct{}{},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}, 'j': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// test two contracts can be deployed which share deps
|
||||||
|
linkTestCaseInput{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {'b', 'c', 'd', 'e'},
|
||||||
|
'f': {'g', 'c', 'd', 'h'}},
|
||||||
|
map[rune]struct{}{},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// test one contract with overrides for all lib deps
|
||||||
|
linkTestCaseInput{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {'b', 'c', 'd', 'e'}},
|
||||||
|
map[rune]struct{}{'b': {}, 'c': {}, 'd': {}, 'e': {}},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}},
|
||||||
|
},
|
||||||
|
// test one contract with overrides for some lib deps
|
||||||
|
linkTestCaseInput{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {'b', 'c'}},
|
||||||
|
map[rune]struct{}{'b': {}, 'c': {}},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}},
|
||||||
|
},
|
||||||
|
// test deployment of a contract with overrides
|
||||||
|
linkTestCaseInput{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {}},
|
||||||
|
map[rune]struct{}{'a': {}},
|
||||||
|
map[rune]struct{}{},
|
||||||
|
},
|
||||||
|
// two contracts ('a' and 'f') share some dependencies. contract 'a' is marked as an override. expect that any of
|
||||||
|
// its depdencies that aren't shared with 'f' are not deployed.
|
||||||
|
linkTestCaseInput{map[rune][]rune{
|
||||||
|
'a': {'b', 'c', 'd', 'e'},
|
||||||
|
'f': {'g', 'c', 'd', 'h'}},
|
||||||
|
map[rune]struct{}{'a': {}},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'f': {}, 'g': {}, 'c': {}, 'd': {}, 'h': {}},
|
||||||
|
},
|
||||||
|
// test nested libraries that share deps at different levels of the tree... with override.
|
||||||
|
// same condition as above test: no sub-dependencies of
|
||||||
|
{
|
||||||
|
map[rune][]rune{
|
||||||
|
'a': {'b', 'c', 'd', 'e'},
|
||||||
|
'e': {'f', 'g', 'h', 'i', 'm'},
|
||||||
|
'i': {'j', 'k', 'l', 'm'},
|
||||||
|
'l': {'n', 'o', 'p'}},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'i': {},
|
||||||
|
},
|
||||||
|
map[rune]struct{}{
|
||||||
|
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'm': {}},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
if err := testLinkCase(tc); err != nil {
|
||||||
|
t.Fatalf("test case %d failed: %v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseLibraryDeps(unlinkedCode string) (res []string) {
|
||||||
|
reMatchSpecificPattern, err := regexp.Compile(`__\$([a-f0-9]+)\$__`)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, match := range reMatchSpecificPattern.FindAllStringSubmatch(unlinkedCode, -1) {
|
||||||
|
res = append(res, match[1])
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
102
accounts/abi/bind/v2/generate_test.go
Normal file
102
accounts/abi/bind/v2/generate_test.go
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
// 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 bind_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/abigen"
|
||||||
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
|
"github.com/ethereum/go-ethereum/common/compiler"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Run go generate to recreate the test bindings.
|
||||||
|
//
|
||||||
|
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/db/combined-abi.json -type DBStats -pkg db -out internal/contracts/db/bindings.go
|
||||||
|
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/events/combined-abi.json -type C -pkg events -out internal/contracts/events/bindings.go
|
||||||
|
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/nested_libraries/combined-abi.json -type C1 -pkg nested_libraries -out internal/contracts/nested_libraries/bindings.go
|
||||||
|
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/solc_errors/combined-abi.json -type C -pkg solc_errors -out internal/contracts/solc_errors/bindings.go
|
||||||
|
//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/uint256arrayreturn/combined-abi.json -type C -pkg uint256arrayreturn -out internal/contracts/uint256arrayreturn/bindings.go
|
||||||
|
|
||||||
|
// TestBindingGeneration tests that re-running generation of bindings does not result in
|
||||||
|
// mutations to the binding code.
|
||||||
|
func TestBindingGeneration(t *testing.T) {
|
||||||
|
matches, _ := filepath.Glob("internal/contracts/*")
|
||||||
|
var dirs []string
|
||||||
|
for _, match := range matches {
|
||||||
|
f, _ := os.Stat(match)
|
||||||
|
if f.IsDir() {
|
||||||
|
dirs = append(dirs, f.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dir := range dirs {
|
||||||
|
var (
|
||||||
|
abis []string
|
||||||
|
bins []string
|
||||||
|
types []string
|
||||||
|
libs = make(map[string]string)
|
||||||
|
)
|
||||||
|
basePath := filepath.Join("internal/contracts", dir)
|
||||||
|
combinedJsonPath := filepath.Join(basePath, "combined-abi.json")
|
||||||
|
abiBytes, err := os.ReadFile(combinedJsonPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error trying to read file %s: %v", combinedJsonPath, err)
|
||||||
|
}
|
||||||
|
contracts, err := compiler.ParseCombinedJSON(abiBytes, "", "", "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read contract information from json output: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, contract := range contracts {
|
||||||
|
// fully qualified name is of the form <solFilePath>:<type>
|
||||||
|
nameParts := strings.Split(name, ":")
|
||||||
|
typeName := nameParts[len(nameParts)-1]
|
||||||
|
abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to parse ABIs from compiler output: %v", err)
|
||||||
|
}
|
||||||
|
abis = append(abis, string(abi))
|
||||||
|
bins = append(bins, contract.Code)
|
||||||
|
types = append(types, typeName)
|
||||||
|
|
||||||
|
// Derive the library placeholder which is a 34 character prefix of the
|
||||||
|
// hex encoding of the keccak256 hash of the fully qualified library name.
|
||||||
|
// Note that the fully qualified library name is the path of its source
|
||||||
|
// file and the library name separated by ":".
|
||||||
|
libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] // the first 2 chars are 0x
|
||||||
|
libs[libPattern] = typeName
|
||||||
|
}
|
||||||
|
code, err := abigen.BindV2(types, abis, bins, dir, libs, make(map[string]string))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error creating bindings for package %s: %v", dir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
existingBindings, err := os.ReadFile(filepath.Join(basePath, "bindings.go"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ReadFile returned error: %v", err)
|
||||||
|
}
|
||||||
|
if code != string(existingBindings) {
|
||||||
|
t.Fatalf("code mismatch for %s", dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
293
accounts/abi/bind/v2/internal/contracts/db/bindings.go
Normal file
293
accounts/abi/bind/v2/internal/contracts/db/bindings.go
Normal file
|
|
@ -0,0 +1,293 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// DBStats is an auto generated low-level Go binding around an user-defined struct.
|
||||||
|
type DBStats struct {
|
||||||
|
Gets *big.Int
|
||||||
|
Inserts *big.Int
|
||||||
|
Mods *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBMetaData contains all meta data concerning the DB contract.
|
||||||
|
var DBMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"key\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"Insert\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"key\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"KeyedInsert\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"k\",\"type\":\"uint256\"}],\"name\":\"get\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNamedStatParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gets\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inserts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mods\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatParams\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStatsStruct\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gets\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inserts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mods\",\"type\":\"uint256\"}],\"internalType\":\"structDB.Stats\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"k\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"v\",\"type\":\"uint256\"}],\"name\":\"insert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]",
|
||||||
|
ID: "253cc2574e2f8b5e909644530e4934f6ac",
|
||||||
|
Bin: "0x60806040525f5f553480156011575f5ffd5b5060405180606001604052805f81526020015f81526020015f81525060035f820151815f015560208201518160010155604082015181600201559050506105f78061005b5f395ff3fe60806040526004361061004d575f3560e01c80631d834a1b146100cb5780636fcb9c70146101075780639507d39a14610133578063e369ba3b1461016f578063ee8161e01461019b5761006a565b3661006a57345f5f82825461006291906103eb565b925050819055005b348015610075575f5ffd5b505f36606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050509050915050805190602001f35b3480156100d6575f5ffd5b506100f160048036038101906100ec919061044c565b6101c5565b6040516100fe9190610499565b60405180910390f35b348015610112575f5ffd5b5061011b6102ef565b60405161012a939291906104b2565b60405180910390f35b34801561013e575f5ffd5b50610159600480360381019061015491906104e7565b61030e565b6040516101669190610499565b60405180910390f35b34801561017a575f5ffd5b50610183610341565b604051610192939291906104b2565b60405180910390f35b3480156101a6575f5ffd5b506101af610360565b6040516101bc9190610561565b60405180910390f35b5f5f82036101da5760028054905090506102e9565b5f60015f8581526020019081526020015f20540361023757600283908060018154018082558091505060019003905f5260205f20015f909190919091505560036001015f81548092919061022d9061057a565b9190505550610252565b60036002015f81548092919061024c9061057a565b91905055505b8160015f8581526020019081526020015f20819055507f8b39ff47dca36ab5b8b80845238af53aa579625ac7fb173dc09376adada4176983836002805490506040516102a0939291906104b2565b60405180910390a1827f40bed843c6c5f72002f9b469cf4c1ee9f7fb1eb48f091c1267970f98522ac02d836040516102d89190610499565b60405180910390a260028054905090505b92915050565b5f5f5f60035f0154600360010154600360020154925092509250909192565b5f60035f015f8154809291906103239061057a565b919050555060015f8381526020019081526020015f20549050919050565b5f5f5f60035f0154600360010154600360020154925092509250909192565b610368610397565b60036040518060600160405290815f820154815260200160018201548152602001600282015481525050905090565b60405180606001604052805f81526020015f81526020015f81525090565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6103f5826103b5565b9150610400836103b5565b9250828201905080821115610418576104176103be565b5b92915050565b5f5ffd5b61042b816103b5565b8114610435575f5ffd5b50565b5f8135905061044681610422565b92915050565b5f5f604083850312156104625761046161041e565b5b5f61046f85828601610438565b925050602061048085828601610438565b9150509250929050565b610493816103b5565b82525050565b5f6020820190506104ac5f83018461048a565b92915050565b5f6060820190506104c55f83018661048a565b6104d2602083018561048a565b6104df604083018461048a565b949350505050565b5f602082840312156104fc576104fb61041e565b5b5f61050984828501610438565b91505092915050565b61051b816103b5565b82525050565b606082015f8201516105355f850182610512565b5060208201516105486020850182610512565b50604082015161055b6040850182610512565b50505050565b5f6060820190506105745f830184610521565b92915050565b5f610584826103b5565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036105b6576105b56103be565b5b60018201905091905056fea264697066735822122063e58431f2afdc667f8e687d3e6a99085a93c1fd3ce40b218463b8ddd3cc093664736f6c634300081c0033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// DB is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type DB struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDB creates a new instance of DB.
|
||||||
|
func NewDB() *DB {
|
||||||
|
parsed, err := DBMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &DB{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *DB) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackGet is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x9507d39a.
|
||||||
|
//
|
||||||
|
// Solidity: function get(uint256 k) returns(uint256)
|
||||||
|
func (dB *DB) PackGet(k *big.Int) []byte {
|
||||||
|
enc, err := dB.abi.Pack("get", k)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackGet is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x9507d39a.
|
||||||
|
//
|
||||||
|
// Solidity: function get(uint256 k) returns(uint256)
|
||||||
|
func (dB *DB) UnpackGet(data []byte) (*big.Int, error) {
|
||||||
|
out, err := dB.abi.Unpack("get", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackGetNamedStatParams is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xe369ba3b.
|
||||||
|
//
|
||||||
|
// Solidity: function getNamedStatParams() view returns(uint256 gets, uint256 inserts, uint256 mods)
|
||||||
|
func (dB *DB) PackGetNamedStatParams() []byte {
|
||||||
|
enc, err := dB.abi.Pack("getNamedStatParams")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNamedStatParamsOutput serves as a container for the return parameters of contract
|
||||||
|
// method GetNamedStatParams.
|
||||||
|
type GetNamedStatParamsOutput struct {
|
||||||
|
Gets *big.Int
|
||||||
|
Inserts *big.Int
|
||||||
|
Mods *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackGetNamedStatParams is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xe369ba3b.
|
||||||
|
//
|
||||||
|
// Solidity: function getNamedStatParams() view returns(uint256 gets, uint256 inserts, uint256 mods)
|
||||||
|
func (dB *DB) UnpackGetNamedStatParams(data []byte) (GetNamedStatParamsOutput, error) {
|
||||||
|
out, err := dB.abi.Unpack("getNamedStatParams", data)
|
||||||
|
outstruct := new(GetNamedStatParamsOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Gets = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Inserts = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Mods = abi.ConvertType(out[2], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackGetStatParams is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x6fcb9c70.
|
||||||
|
//
|
||||||
|
// Solidity: function getStatParams() view returns(uint256, uint256, uint256)
|
||||||
|
func (dB *DB) PackGetStatParams() []byte {
|
||||||
|
enc, err := dB.abi.Pack("getStatParams")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStatParamsOutput serves as a container for the return parameters of contract
|
||||||
|
// method GetStatParams.
|
||||||
|
type GetStatParamsOutput struct {
|
||||||
|
Arg0 *big.Int
|
||||||
|
Arg1 *big.Int
|
||||||
|
Arg2 *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackGetStatParams is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x6fcb9c70.
|
||||||
|
//
|
||||||
|
// Solidity: function getStatParams() view returns(uint256, uint256, uint256)
|
||||||
|
func (dB *DB) UnpackGetStatParams(data []byte) (GetStatParamsOutput, error) {
|
||||||
|
out, err := dB.abi.Unpack("getStatParams", data)
|
||||||
|
outstruct := new(GetStatParamsOutput)
|
||||||
|
if err != nil {
|
||||||
|
return *outstruct, err
|
||||||
|
}
|
||||||
|
outstruct.Arg0 = abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Arg1 = abi.ConvertType(out[1], new(big.Int)).(*big.Int)
|
||||||
|
outstruct.Arg2 = abi.ConvertType(out[2], new(big.Int)).(*big.Int)
|
||||||
|
return *outstruct, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackGetStatsStruct is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xee8161e0.
|
||||||
|
//
|
||||||
|
// Solidity: function getStatsStruct() view returns((uint256,uint256,uint256))
|
||||||
|
func (dB *DB) PackGetStatsStruct() []byte {
|
||||||
|
enc, err := dB.abi.Pack("getStatsStruct")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackGetStatsStruct is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xee8161e0.
|
||||||
|
//
|
||||||
|
// Solidity: function getStatsStruct() view returns((uint256,uint256,uint256))
|
||||||
|
func (dB *DB) UnpackGetStatsStruct(data []byte) (DBStats, error) {
|
||||||
|
out, err := dB.abi.Unpack("getStatsStruct", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new(DBStats), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new(DBStats)).(*DBStats)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackInsert is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x1d834a1b.
|
||||||
|
//
|
||||||
|
// Solidity: function insert(uint256 k, uint256 v) returns(uint256)
|
||||||
|
func (dB *DB) PackInsert(k *big.Int, v *big.Int) []byte {
|
||||||
|
enc, err := dB.abi.Pack("insert", k, v)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackInsert is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x1d834a1b.
|
||||||
|
//
|
||||||
|
// Solidity: function insert(uint256 k, uint256 v) returns(uint256)
|
||||||
|
func (dB *DB) UnpackInsert(data []byte) (*big.Int, error) {
|
||||||
|
out, err := dB.abi.Unpack("insert", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBInsert represents a Insert event raised by the DB contract.
|
||||||
|
type DBInsert struct {
|
||||||
|
Key *big.Int
|
||||||
|
Value *big.Int
|
||||||
|
Length *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const DBInsertEventName = "Insert"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (DBInsert) ContractEventName() string {
|
||||||
|
return DBInsertEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackInsertEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event Insert(uint256 key, uint256 value, uint256 length)
|
||||||
|
func (dB *DB) UnpackInsertEvent(log *types.Log) (*DBInsert, error) {
|
||||||
|
event := "Insert"
|
||||||
|
if log.Topics[0] != dB.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(DBInsert)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := dB.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range dB.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBKeyedInsert represents a KeyedInsert event raised by the DB contract.
|
||||||
|
type DBKeyedInsert struct {
|
||||||
|
Key *big.Int
|
||||||
|
Value *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const DBKeyedInsertEventName = "KeyedInsert"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (DBKeyedInsert) ContractEventName() string {
|
||||||
|
return DBKeyedInsertEventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackKeyedInsertEvent is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event KeyedInsert(uint256 indexed key, uint256 value)
|
||||||
|
func (dB *DB) UnpackKeyedInsertEvent(log *types.Log) (*DBKeyedInsert, error) {
|
||||||
|
event := "KeyedInsert"
|
||||||
|
if log.Topics[0] != dB.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(DBKeyedInsert)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := dB.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range dB.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
66
accounts/abi/bind/v2/internal/contracts/db/contract.sol
Normal file
66
accounts/abi/bind/v2/internal/contracts/db/contract.sol
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.7.0 <0.9.0;
|
||||||
|
|
||||||
|
contract DB {
|
||||||
|
uint balance = 0;
|
||||||
|
mapping(uint => uint) private _store;
|
||||||
|
uint[] private _keys;
|
||||||
|
struct Stats {
|
||||||
|
uint gets;
|
||||||
|
uint inserts;
|
||||||
|
uint mods; // modifications
|
||||||
|
}
|
||||||
|
Stats _stats;
|
||||||
|
|
||||||
|
event KeyedInsert(uint indexed key, uint value);
|
||||||
|
event Insert(uint key, uint value, uint length);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
_stats = Stats(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert adds a key value to the store, returning the new length of the store.
|
||||||
|
function insert(uint k, uint v) external returns (uint) {
|
||||||
|
// No need to store 0 values
|
||||||
|
if (v == 0) {
|
||||||
|
return _keys.length;
|
||||||
|
}
|
||||||
|
// Check if a key is being overriden
|
||||||
|
if (_store[k] == 0) {
|
||||||
|
_keys.push(k);
|
||||||
|
_stats.inserts++;
|
||||||
|
} else {
|
||||||
|
_stats.mods++;
|
||||||
|
}
|
||||||
|
_store[k] = v;
|
||||||
|
emit Insert(k, v, _keys.length);
|
||||||
|
emit KeyedInsert(k, v);
|
||||||
|
|
||||||
|
return _keys.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get(uint k) public returns (uint) {
|
||||||
|
_stats.gets++;
|
||||||
|
return _store[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatParams() public view returns (uint, uint, uint) {
|
||||||
|
return (_stats.gets, _stats.inserts, _stats.mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNamedStatParams() public view returns (uint gets, uint inserts, uint mods) {
|
||||||
|
return (_stats.gets, _stats.inserts, _stats.mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatsStruct() public view returns (Stats memory) {
|
||||||
|
return _stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
receive() external payable {
|
||||||
|
balance += msg.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback(bytes calldata _input) external returns (bytes memory _output) {
|
||||||
|
_output = _input;
|
||||||
|
}
|
||||||
|
}
|
||||||
160
accounts/abi/bind/v2/internal/contracts/events/bindings.go
Normal file
160
accounts/abi/bind/v2/internal/contracts/events/bindings.go
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package events
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// CMetaData contains all meta data concerning the C contract.
|
||||||
|
var CMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"basic1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"basic2\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"EmitMulti\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EmitOne\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
|
||||||
|
ID: "55ef3c19a0ab1c1845f9e347540c1e51f5",
|
||||||
|
Bin: "0x6080604052348015600e575f5ffd5b506101a08061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063cb49374914610038578063e8e49a7114610042575b5f5ffd5b61004061004c565b005b61004a6100fd565b005b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161007e9190610151565b60405180910390a260037f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd20760046040516100b89190610151565b60405180910390a25f15157f3b29b9f6d15ba80d866afb3d70b7548ab1ffda3ef6e65f35f1cb05b0e2b29f4e60016040516100f39190610151565b60405180910390a2565b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161012f9190610151565b60405180910390a2565b5f819050919050565b61014b81610139565b82525050565b5f6020820190506101645f830184610142565b9291505056fea26469706673582212207331c79de16a73a1639c4c4b3489ea78a3ed35fe62a178824f586df12672ac0564736f6c634300081c0033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// C is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type C struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewC creates a new instance of C.
|
||||||
|
func NewC() *C {
|
||||||
|
parsed, err := CMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &C{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *C) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackEmitMulti is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xcb493749.
|
||||||
|
//
|
||||||
|
// Solidity: function EmitMulti() returns()
|
||||||
|
func (c *C) PackEmitMulti() []byte {
|
||||||
|
enc, err := c.abi.Pack("EmitMulti")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackEmitOne is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xe8e49a71.
|
||||||
|
//
|
||||||
|
// Solidity: function EmitOne() returns()
|
||||||
|
func (c *C) PackEmitOne() []byte {
|
||||||
|
enc, err := c.abi.Pack("EmitOne")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// CBasic1 represents a basic1 event raised by the C contract.
|
||||||
|
type CBasic1 struct {
|
||||||
|
Id *big.Int
|
||||||
|
Data *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const CBasic1EventName = "basic1"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (CBasic1) ContractEventName() string {
|
||||||
|
return CBasic1EventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBasic1Event is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event basic1(uint256 indexed id, uint256 data)
|
||||||
|
func (c *C) UnpackBasic1Event(log *types.Log) (*CBasic1, error) {
|
||||||
|
event := "basic1"
|
||||||
|
if log.Topics[0] != c.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(CBasic1)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range c.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CBasic2 represents a basic2 event raised by the C contract.
|
||||||
|
type CBasic2 struct {
|
||||||
|
Flag bool
|
||||||
|
Data *big.Int
|
||||||
|
Raw *types.Log // Blockchain specific contextual infos
|
||||||
|
}
|
||||||
|
|
||||||
|
const CBasic2EventName = "basic2"
|
||||||
|
|
||||||
|
// ContractEventName returns the user-defined event name.
|
||||||
|
func (CBasic2) ContractEventName() string {
|
||||||
|
return CBasic2EventName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBasic2Event is the Go binding that unpacks the event data emitted
|
||||||
|
// by contract.
|
||||||
|
//
|
||||||
|
// Solidity: event basic2(bool indexed flag, uint256 data)
|
||||||
|
func (c *C) UnpackBasic2Event(log *types.Log) (*CBasic2, error) {
|
||||||
|
event := "basic2"
|
||||||
|
if log.Topics[0] != c.abi.Events[event].ID {
|
||||||
|
return nil, errors.New("event signature mismatch")
|
||||||
|
}
|
||||||
|
out := new(CBasic2)
|
||||||
|
if len(log.Data) > 0 {
|
||||||
|
if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var indexed abi.Arguments
|
||||||
|
for _, arg := range c.abi.Events[event].Inputs {
|
||||||
|
if arg.Indexed {
|
||||||
|
indexed = append(indexed, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := abi.ParseTopics(out, indexed, log.Topics[1:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out.Raw = log
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"contracts":{"contract.sol:C":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"basic1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"flag","type":"bool"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"basic2","type":"event"},{"inputs":[],"name":"EmitMulti","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"EmitOne","outputs":[],"stateMutability":"nonpayable","type":"function"}],"bin":"6080604052348015600e575f5ffd5b506101a08061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063cb49374914610038578063e8e49a7114610042575b5f5ffd5b61004061004c565b005b61004a6100fd565b005b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161007e9190610151565b60405180910390a260037f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd20760046040516100b89190610151565b60405180910390a25f15157f3b29b9f6d15ba80d866afb3d70b7548ab1ffda3ef6e65f35f1cb05b0e2b29f4e60016040516100f39190610151565b60405180910390a2565b60017f8f17dc823e2f9fcdf730b8182c935574691e811e7d46399fe0ff0087795cd207600260405161012f9190610151565b60405180910390a2565b5f819050919050565b61014b81610139565b82525050565b5f6020820190506101645f830184610142565b9291505056fea26469706673582212207331c79de16a73a1639c4c4b3489ea78a3ed35fe62a178824f586df12672ac0564736f6c634300081c0033"}},"version":"0.8.28+commit.7893614a.Darwin.appleclang"}
|
||||||
36
accounts/abi/bind/v2/internal/contracts/events/contract.sol
Normal file
36
accounts/abi/bind/v2/internal/contracts/events/contract.sol
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.26;
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
event basic1(
|
||||||
|
uint256 indexed id,
|
||||||
|
uint256 data
|
||||||
|
);
|
||||||
|
event basic2(
|
||||||
|
bool indexed flag,
|
||||||
|
uint256 data
|
||||||
|
);
|
||||||
|
|
||||||
|
function EmitOne() public {
|
||||||
|
emit basic1(
|
||||||
|
uint256(1),
|
||||||
|
uint256(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit multiple events, different types
|
||||||
|
function EmitMulti() public {
|
||||||
|
emit basic1(
|
||||||
|
uint256(1),
|
||||||
|
uint256(2));
|
||||||
|
emit basic1(
|
||||||
|
uint256(3),
|
||||||
|
uint256(4));
|
||||||
|
emit basic2(
|
||||||
|
false,
|
||||||
|
uint256(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// do something with these
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,486 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package nested_libraries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// C1MetaData contains all meta data concerning the C1 contract.
|
||||||
|
var C1MetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"v1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"v2\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"res\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "ae26158f1824f3918bd66724ee8b6eb7c9",
|
||||||
|
Bin: "0x6080604052348015600e575f5ffd5b506040516103983803806103988339818101604052810190602e91906066565b5050609d565b5f5ffd5b5f819050919050565b6048816038565b81146051575f5ffd5b50565b5f815190506060816041565b92915050565b5f5f6040838503121560795760786034565b5b5f6084858286016054565b92505060206093858286016054565b9150509250929050565b6102ee806100aa5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80632ad112721461002d575b5f5ffd5b6100476004803603810190610042919061019e565b61005d565b60405161005491906101d8565b60405180910390f35b5f600173__$ffc1393672b8ed81d0c8093ffcb0e7fbe8$__632ad112725f6040518263ffffffff1660e01b81526004016100979190610200565b602060405180830381865af41580156100b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100d6919061022d565b73__$5f33a1fab8ea7d932b4bc8c5e7dcd90bc2$__632ad11272856040518263ffffffff1660e01b815260040161010d9190610200565b602060405180830381865af4158015610128573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061014c919061022d565b6101569190610285565b6101609190610285565b9050919050565b5f5ffd5b5f819050919050565b61017d8161016b565b8114610187575f5ffd5b50565b5f8135905061019881610174565b92915050565b5f602082840312156101b3576101b2610167565b5b5f6101c08482850161018a565b91505092915050565b6101d28161016b565b82525050565b5f6020820190506101eb5f8301846101c9565b92915050565b6101fa8161016b565b82525050565b5f6020820190506102135f8301846101f1565b92915050565b5f8151905061022781610174565b92915050565b5f6020828403121561024257610241610167565b5b5f61024f84828501610219565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61028f8261016b565b915061029a8361016b565b92508282019050808211156102b2576102b1610258565b5b9291505056fea26469706673582212205d4715a8d20a3a0a43113e268ec8868b3c3ce24f7cbdb8735b4eeeebf0b5565164736f6c634300081c0033",
|
||||||
|
Deps: []*bind.MetaData{
|
||||||
|
&L1MetaData,
|
||||||
|
&L4MetaData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// C1 is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type C1 struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewC1 creates a new instance of C1.
|
||||||
|
func NewC1() *C1 {
|
||||||
|
parsed, err := C1MetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &C1{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *C1) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackConstructor is the Go binding used to pack the parameters required for
|
||||||
|
// contract deployment.
|
||||||
|
//
|
||||||
|
// Solidity: constructor(uint256 v1, uint256 v2) returns()
|
||||||
|
func (c1 *C1) PackConstructor(v1 *big.Int, v2 *big.Int) []byte {
|
||||||
|
enc, err := c1.abi.Pack("", v1, v2)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256 res)
|
||||||
|
func (c1 *C1) PackDo(val *big.Int) []byte {
|
||||||
|
enc, err := c1.abi.Pack("Do", val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDo is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256 res)
|
||||||
|
func (c1 *C1) UnpackDo(data []byte) (*big.Int, error) {
|
||||||
|
out, err := c1.abi.Unpack("Do", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// C2MetaData contains all meta data concerning the C2 contract.
|
||||||
|
var C2MetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"v1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"v2\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"res\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "78ef2840de5b706112ca2dbfa765501a89",
|
||||||
|
Bin: "0x6080604052348015600e575f5ffd5b506040516103983803806103988339818101604052810190602e91906066565b5050609d565b5f5ffd5b5f819050919050565b6048816038565b81146051575f5ffd5b50565b5f815190506060816041565b92915050565b5f5f6040838503121560795760786034565b5b5f6084858286016054565b92505060206093858286016054565b9150509250929050565b6102ee806100aa5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80632ad112721461002d575b5f5ffd5b6100476004803603810190610042919061019e565b61005d565b60405161005491906101d8565b60405180910390f35b5f600173__$ffc1393672b8ed81d0c8093ffcb0e7fbe8$__632ad112725f6040518263ffffffff1660e01b81526004016100979190610200565b602060405180830381865af41580156100b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100d6919061022d565b73__$6070639404c39b5667691bb1f9177e1eac$__632ad11272856040518263ffffffff1660e01b815260040161010d9190610200565b602060405180830381865af4158015610128573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061014c919061022d565b6101569190610285565b6101609190610285565b9050919050565b5f5ffd5b5f819050919050565b61017d8161016b565b8114610187575f5ffd5b50565b5f8135905061019881610174565b92915050565b5f602082840312156101b3576101b2610167565b5b5f6101c08482850161018a565b91505092915050565b6101d28161016b565b82525050565b5f6020820190506101eb5f8301846101c9565b92915050565b6101fa8161016b565b82525050565b5f6020820190506102135f8301846101f1565b92915050565b5f8151905061022781610174565b92915050565b5f6020828403121561024257610241610167565b5b5f61024f84828501610219565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61028f8261016b565b915061029a8361016b565b92508282019050808211156102b2576102b1610258565b5b9291505056fea2646970667358221220dd394981f1e9fefa4d88bac1c4f1da4131779c7d3bd4189958d278e57e96d96f64736f6c634300081c0033",
|
||||||
|
Deps: []*bind.MetaData{
|
||||||
|
&L1MetaData,
|
||||||
|
&L4bMetaData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// C2 is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type C2 struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewC2 creates a new instance of C2.
|
||||||
|
func NewC2() *C2 {
|
||||||
|
parsed, err := C2MetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &C2{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *C2) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackConstructor is the Go binding used to pack the parameters required for
|
||||||
|
// contract deployment.
|
||||||
|
//
|
||||||
|
// Solidity: constructor(uint256 v1, uint256 v2) returns()
|
||||||
|
func (c2 *C2) PackConstructor(v1 *big.Int, v2 *big.Int) []byte {
|
||||||
|
enc, err := c2.abi.Pack("", v1, v2)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256 res)
|
||||||
|
func (c2 *C2) PackDo(val *big.Int) []byte {
|
||||||
|
enc, err := c2.abi.Pack("Do", val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDo is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256 res)
|
||||||
|
func (c2 *C2) UnpackDo(data []byte) (*big.Int, error) {
|
||||||
|
out, err := c2.abi.Unpack("Do", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// L1MetaData contains all meta data concerning the L1 contract.
|
||||||
|
var L1MetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "ffc1393672b8ed81d0c8093ffcb0e7fbe8",
|
||||||
|
Bin: "0x61011c61004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106032575f3560e01c80632ad11272146036575b5f5ffd5b604c600480360381019060489190609c565b6060565b6040516057919060cf565b60405180910390f35b5f60019050919050565b5f5ffd5b5f819050919050565b607e81606e565b81146087575f5ffd5b50565b5f813590506096816077565b92915050565b5f6020828403121560ae5760ad606a565b5b5f60b984828501608a565b91505092915050565b60c981606e565b82525050565b5f60208201905060e05f83018460c2565b9291505056fea26469706673582212200161c5f22d130a2b7ec6cf22e0910e42e32c2881fa4a8a01455f524f63cf218d64736f6c634300081c0033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// L1 is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type L1 struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewL1 creates a new instance of L1.
|
||||||
|
func NewL1() *L1 {
|
||||||
|
parsed, err := L1MetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &L1{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *L1) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l1 *L1) PackDo(val *big.Int) []byte {
|
||||||
|
enc, err := l1.abi.Pack("Do", val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDo is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l1 *L1) UnpackDo(data []byte) (*big.Int, error) {
|
||||||
|
out, err := l1.abi.Unpack("Do", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// L2MetaData contains all meta data concerning the L2 contract.
|
||||||
|
var L2MetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "2ce896a6dd38932d354f317286f90bc675",
|
||||||
|
Bin: "0x61025161004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c80632ad1127214610038575b5f5ffd5b610052600480360381019061004d9190610129565b610068565b60405161005f9190610163565b60405180910390f35b5f600173__$ffc1393672b8ed81d0c8093ffcb0e7fbe8$__632ad11272846040518263ffffffff1660e01b81526004016100a29190610163565b602060405180830381865af41580156100bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e19190610190565b6100eb91906101e8565b9050919050565b5f5ffd5b5f819050919050565b610108816100f6565b8114610112575f5ffd5b50565b5f81359050610123816100ff565b92915050565b5f6020828403121561013e5761013d6100f2565b5b5f61014b84828501610115565b91505092915050565b61015d816100f6565b82525050565b5f6020820190506101765f830184610154565b92915050565b5f8151905061018a816100ff565b92915050565b5f602082840312156101a5576101a46100f2565b5b5f6101b28482850161017c565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6101f2826100f6565b91506101fd836100f6565b9250828201905080821115610215576102146101bb565b5b9291505056fea264697066735822122026999f96e14b0e279909ca5972343113c358e93a904569409a86866e2064f0fa64736f6c634300081c0033",
|
||||||
|
Deps: []*bind.MetaData{
|
||||||
|
&L1MetaData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// L2 is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type L2 struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewL2 creates a new instance of L2.
|
||||||
|
func NewL2() *L2 {
|
||||||
|
parsed, err := L2MetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &L2{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *L2) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l2 *L2) PackDo(val *big.Int) []byte {
|
||||||
|
enc, err := l2.abi.Pack("Do", val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDo is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l2 *L2) UnpackDo(data []byte) (*big.Int, error) {
|
||||||
|
out, err := l2.abi.Unpack("Do", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// L2bMetaData contains all meta data concerning the L2b contract.
|
||||||
|
var L2bMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "fd1474cf57f7ed48491e8bfdfd0d172adf",
|
||||||
|
Bin: "0x61025161004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c80632ad1127214610038575b5f5ffd5b610052600480360381019061004d9190610129565b610068565b60405161005f9190610163565b60405180910390f35b5f600173__$ffc1393672b8ed81d0c8093ffcb0e7fbe8$__632ad11272846040518263ffffffff1660e01b81526004016100a29190610163565b602060405180830381865af41580156100bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e19190610190565b6100eb91906101e8565b9050919050565b5f5ffd5b5f819050919050565b610108816100f6565b8114610112575f5ffd5b50565b5f81359050610123816100ff565b92915050565b5f6020828403121561013e5761013d6100f2565b5b5f61014b84828501610115565b91505092915050565b61015d816100f6565b82525050565b5f6020820190506101765f830184610154565b92915050565b5f8151905061018a816100ff565b92915050565b5f602082840312156101a5576101a46100f2565b5b5f6101b28482850161017c565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6101f2826100f6565b91506101fd836100f6565b9250828201905080821115610215576102146101bb565b5b9291505056fea2646970667358221220d6e7078682642d273736fd63baaa28538fe72495816c810fa0e77034de385dc564736f6c634300081c0033",
|
||||||
|
Deps: []*bind.MetaData{
|
||||||
|
&L1MetaData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// L2b is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type L2b struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewL2b creates a new instance of L2b.
|
||||||
|
func NewL2b() *L2b {
|
||||||
|
parsed, err := L2bMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &L2b{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *L2b) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l2b *L2b) PackDo(val *big.Int) []byte {
|
||||||
|
enc, err := l2b.abi.Pack("Do", val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDo is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l2b *L2b) UnpackDo(data []byte) (*big.Int, error) {
|
||||||
|
out, err := l2b.abi.Unpack("Do", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// L3MetaData contains all meta data concerning the L3 contract.
|
||||||
|
var L3MetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "d03b97f5e1a564374023a72ac7d1806773",
|
||||||
|
Bin: "0x61011c61004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106032575f3560e01c80632ad11272146036575b5f5ffd5b604c600480360381019060489190609c565b6060565b6040516057919060cf565b60405180910390f35b5f60019050919050565b5f5ffd5b5f819050919050565b607e81606e565b81146087575f5ffd5b50565b5f813590506096816077565b92915050565b5f6020828403121560ae5760ad606a565b5b5f60b984828501608a565b91505092915050565b60c981606e565b82525050565b5f60208201905060e05f83018460c2565b9291505056fea264697066735822122094cfcb0ce039318885cc58f6d8e609e6e4bec575e1a046d3d15ea2e01e97241e64736f6c634300081c0033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// L3 is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type L3 struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewL3 creates a new instance of L3.
|
||||||
|
func NewL3() *L3 {
|
||||||
|
parsed, err := L3MetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &L3{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *L3) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l3 *L3) PackDo(val *big.Int) []byte {
|
||||||
|
enc, err := l3.abi.Pack("Do", val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDo is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l3 *L3) UnpackDo(data []byte) (*big.Int, error) {
|
||||||
|
out, err := l3.abi.Unpack("Do", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// L4MetaData contains all meta data concerning the L4 contract.
|
||||||
|
var L4MetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "5f33a1fab8ea7d932b4bc8c5e7dcd90bc2",
|
||||||
|
Bin: "0x6102d161004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c80632ad1127214610038575b5f5ffd5b610052600480360381019061004d91906101a9565b610068565b60405161005f91906101e3565b60405180910390f35b5f600173__$d03b97f5e1a564374023a72ac7d1806773$__632ad11272846040518263ffffffff1660e01b81526004016100a291906101e3565b602060405180830381865af41580156100bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e19190610210565b73__$2ce896a6dd38932d354f317286f90bc675$__632ad11272856040518263ffffffff1660e01b815260040161011891906101e3565b602060405180830381865af4158015610133573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101579190610210565b6101619190610268565b61016b9190610268565b9050919050565b5f5ffd5b5f819050919050565b61018881610176565b8114610192575f5ffd5b50565b5f813590506101a38161017f565b92915050565b5f602082840312156101be576101bd610172565b5b5f6101cb84828501610195565b91505092915050565b6101dd81610176565b82525050565b5f6020820190506101f65f8301846101d4565b92915050565b5f8151905061020a8161017f565b92915050565b5f6020828403121561022557610224610172565b5b5f610232848285016101fc565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61027282610176565b915061027d83610176565b92508282019050808211156102955761029461023b565b5b9291505056fea2646970667358221220531485f0b9ff78ba5ef06ef345aaddccec3ad15d1460014ccd7c2a58d36d0d4464736f6c634300081c0033",
|
||||||
|
Deps: []*bind.MetaData{
|
||||||
|
&L2MetaData,
|
||||||
|
&L3MetaData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// L4 is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type L4 struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewL4 creates a new instance of L4.
|
||||||
|
func NewL4() *L4 {
|
||||||
|
parsed, err := L4MetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &L4{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *L4) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l4 *L4) PackDo(val *big.Int) []byte {
|
||||||
|
enc, err := l4.abi.Pack("Do", val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDo is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l4 *L4) UnpackDo(data []byte) (*big.Int, error) {
|
||||||
|
out, err := l4.abi.Unpack("Do", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// L4bMetaData contains all meta data concerning the L4b contract.
|
||||||
|
var L4bMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"Do\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "6070639404c39b5667691bb1f9177e1eac",
|
||||||
|
Bin: "0x61025161004d600b8282823980515f1a6073146041577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c80632ad1127214610038575b5f5ffd5b610052600480360381019061004d9190610129565b610068565b60405161005f9190610163565b60405180910390f35b5f600173__$fd1474cf57f7ed48491e8bfdfd0d172adf$__632ad11272846040518263ffffffff1660e01b81526004016100a29190610163565b602060405180830381865af41580156100bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100e19190610190565b6100eb91906101e8565b9050919050565b5f5ffd5b5f819050919050565b610108816100f6565b8114610112575f5ffd5b50565b5f81359050610123816100ff565b92915050565b5f6020828403121561013e5761013d6100f2565b5b5f61014b84828501610115565b91505092915050565b61015d816100f6565b82525050565b5f6020820190506101765f830184610154565b92915050565b5f8151905061018a816100ff565b92915050565b5f602082840312156101a5576101a46100f2565b5b5f6101b28482850161017c565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6101f2826100f6565b91506101fd836100f6565b9250828201905080821115610215576102146101bb565b5b9291505056fea264697066735822122008a2478fd2427f180ace529e137b69337cb655dc21d6426de37054c32e821c6a64736f6c634300081c0033",
|
||||||
|
Deps: []*bind.MetaData{
|
||||||
|
&L2bMetaData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// L4b is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type L4b struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewL4b creates a new instance of L4b.
|
||||||
|
func NewL4b() *L4b {
|
||||||
|
parsed, err := L4bMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &L4b{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *L4b) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackDo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l4b *L4b) PackDo(val *big.Int) []byte {
|
||||||
|
enc, err := l4b.abi.Pack("Do", val)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackDo is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0x2ad11272.
|
||||||
|
//
|
||||||
|
// Solidity: function Do(uint256 val) pure returns(uint256)
|
||||||
|
func (l4b *L4b) UnpackDo(data []byte) (*big.Int, error) {
|
||||||
|
out, err := l4b.abi.Unpack("Do", data)
|
||||||
|
if err != nil {
|
||||||
|
return new(big.Int), err
|
||||||
|
}
|
||||||
|
out0 := abi.ConvertType(out[0], new(big.Int)).(*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,76 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.26;
|
||||||
|
|
||||||
|
|
||||||
|
// L1
|
||||||
|
// \
|
||||||
|
// L2 L3 L1
|
||||||
|
// \ / /
|
||||||
|
// L4 /
|
||||||
|
// \ /
|
||||||
|
// C1
|
||||||
|
//
|
||||||
|
library L1 {
|
||||||
|
function Do(uint256 val) public pure returns (uint256) {
|
||||||
|
return uint256(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L2 {
|
||||||
|
function Do(uint256 val) public pure returns (uint256) {
|
||||||
|
return L1.Do(val) + uint256(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L3 {
|
||||||
|
function Do(uint256 val) public pure returns (uint256) {
|
||||||
|
return uint256(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L4 {
|
||||||
|
function Do(uint256 val) public pure returns (uint256) {
|
||||||
|
return L2.Do(uint256(val)) + L3.Do(uint256(val)) + uint256(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C1 {
|
||||||
|
function Do(uint256 val) public pure returns (uint256 res) {
|
||||||
|
return L4.Do(uint256(val)) + L1.Do(uint256(0)) + uint256(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(uint256 v1, uint256 v2) {
|
||||||
|
// do something with these
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// second contract+libraries: slightly different library deps than V1, but sharing several
|
||||||
|
// L1
|
||||||
|
// \
|
||||||
|
// L2b L3 L1
|
||||||
|
// \ / /
|
||||||
|
// L4b /
|
||||||
|
// \ /
|
||||||
|
// C2
|
||||||
|
//
|
||||||
|
library L4b {
|
||||||
|
function Do(uint256 val) public pure returns (uint256) {
|
||||||
|
return L2b.Do(uint256(val)) + uint256(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
library L2b {
|
||||||
|
function Do(uint256 val) public pure returns (uint256) {
|
||||||
|
return L1.Do(uint256(val)) + uint256(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C2 {
|
||||||
|
function Do(uint256 val) public pure returns (uint256 res) {
|
||||||
|
return L4b.Do(uint256(val)) + L1.Do(uint256(0)) + uint256(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(uint256 v1, uint256 v2) {
|
||||||
|
// do something with these
|
||||||
|
}
|
||||||
|
}
|
||||||
217
accounts/abi/bind/v2/internal/contracts/solc_errors/bindings.go
Normal file
217
accounts/abi/bind/v2/internal/contracts/solc_errors/bindings.go
Normal file
|
|
@ -0,0 +1,217 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package solc_errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// CMetaData contains all meta data concerning the C contract.
|
||||||
|
var CMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"arg1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg2\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg3\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"arg4\",\"type\":\"bool\"}],\"name\":\"BadThing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"arg1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg2\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg3\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg4\",\"type\":\"uint256\"}],\"name\":\"BadThing2\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Bar\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Foo\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "55ef3c19a0ab1c1845f9e347540c1e51f5",
|
||||||
|
Bin: "0x6080604052348015600e575f5ffd5b506101c58061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063b0a378b014610038578063bfb4ebcf14610042575b5f5ffd5b61004061004c565b005b61004a610092565b005b5f6001600260036040517fd233a24f00000000000000000000000000000000000000000000000000000000815260040161008994939291906100ef565b60405180910390fd5b5f600160025f6040517fbb6a82f10000000000000000000000000000000000000000000000000000000081526004016100ce949392919061014c565b60405180910390fd5b5f819050919050565b6100e9816100d7565b82525050565b5f6080820190506101025f8301876100e0565b61010f60208301866100e0565b61011c60408301856100e0565b61012960608301846100e0565b95945050505050565b5f8115159050919050565b61014681610132565b82525050565b5f60808201905061015f5f8301876100e0565b61016c60208301866100e0565b61017960408301856100e0565b610186606083018461013d565b9594505050505056fea26469706673582212206a82b4c28576e4483a81102558271cfefc891cd63b95440dea521185c1ff6a2a64736f6c634300081c0033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// C is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type C struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewC creates a new instance of C.
|
||||||
|
func NewC() *C {
|
||||||
|
parsed, err := CMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &C{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *C) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackBar is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xb0a378b0.
|
||||||
|
//
|
||||||
|
// Solidity: function Bar() pure returns()
|
||||||
|
func (c *C) PackBar() []byte {
|
||||||
|
enc, err := c.abi.Pack("Bar")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackFoo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xbfb4ebcf.
|
||||||
|
//
|
||||||
|
// Solidity: function Foo() pure returns()
|
||||||
|
func (c *C) PackFoo() []byte {
|
||||||
|
enc, err := c.abi.Pack("Foo")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackError attempts to decode the provided error data using user-defined
|
||||||
|
// error definitions.
|
||||||
|
func (c *C) UnpackError(raw []byte) (any, error) {
|
||||||
|
if bytes.Equal(raw[:4], c.abi.Errors["BadThing"].ID.Bytes()[:4]) {
|
||||||
|
return c.UnpackBadThingError(raw[4:])
|
||||||
|
}
|
||||||
|
if bytes.Equal(raw[:4], c.abi.Errors["BadThing2"].ID.Bytes()[:4]) {
|
||||||
|
return c.UnpackBadThing2Error(raw[4:])
|
||||||
|
}
|
||||||
|
return nil, errors.New("Unknown error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CBadThing represents a BadThing error raised by the C contract.
|
||||||
|
type CBadThing struct {
|
||||||
|
Arg1 *big.Int
|
||||||
|
Arg2 *big.Int
|
||||||
|
Arg3 *big.Int
|
||||||
|
Arg4 bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorID returns the hash of canonical representation of the error's signature.
|
||||||
|
//
|
||||||
|
// Solidity: error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4)
|
||||||
|
func CBadThingErrorID() common.Hash {
|
||||||
|
return common.HexToHash("0xbb6a82f123854747ef4381e30e497f934a3854753fec99a69c35c30d4b46714d")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBadThingError is the Go binding used to decode the provided
|
||||||
|
// error data into the corresponding Go error struct.
|
||||||
|
//
|
||||||
|
// Solidity: error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4)
|
||||||
|
func (c *C) UnpackBadThingError(raw []byte) (*CBadThing, error) {
|
||||||
|
out := new(CBadThing)
|
||||||
|
if err := c.abi.UnpackIntoInterface(out, "BadThing", raw); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CBadThing2 represents a BadThing2 error raised by the C contract.
|
||||||
|
type CBadThing2 struct {
|
||||||
|
Arg1 *big.Int
|
||||||
|
Arg2 *big.Int
|
||||||
|
Arg3 *big.Int
|
||||||
|
Arg4 *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorID returns the hash of canonical representation of the error's signature.
|
||||||
|
//
|
||||||
|
// Solidity: error BadThing2(uint256 arg1, uint256 arg2, uint256 arg3, uint256 arg4)
|
||||||
|
func CBadThing2ErrorID() common.Hash {
|
||||||
|
return common.HexToHash("0xd233a24f02271fe7c9470e060d0fda6447a142bf12ab31fed7ab65affd546175")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBadThing2Error is the Go binding used to decode the provided
|
||||||
|
// error data into the corresponding Go error struct.
|
||||||
|
//
|
||||||
|
// Solidity: error BadThing2(uint256 arg1, uint256 arg2, uint256 arg3, uint256 arg4)
|
||||||
|
func (c *C) UnpackBadThing2Error(raw []byte) (*CBadThing2, error) {
|
||||||
|
out := new(CBadThing2)
|
||||||
|
if err := c.abi.UnpackIntoInterface(out, "BadThing2", raw); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// C2MetaData contains all meta data concerning the C2 contract.
|
||||||
|
var C2MetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"arg1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg2\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"arg3\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"arg4\",\"type\":\"bool\"}],\"name\":\"BadThing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Foo\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "78ef2840de5b706112ca2dbfa765501a89",
|
||||||
|
Bin: "0x6080604052348015600e575f5ffd5b506101148061001c5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c8063bfb4ebcf14602a575b5f5ffd5b60306032565b005b5f600160025f6040517fbb6a82f1000000000000000000000000000000000000000000000000000000008152600401606c949392919060a3565b60405180910390fd5b5f819050919050565b6085816075565b82525050565b5f8115159050919050565b609d81608b565b82525050565b5f60808201905060b45f830187607e565b60bf6020830186607e565b60ca6040830185607e565b60d560608301846096565b9594505050505056fea2646970667358221220e90bf647ffc897060e44b88d54995ed0c03c988fbccaf034375c2ff4e594690764736f6c634300081c0033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// C2 is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type C2 struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewC2 creates a new instance of C2.
|
||||||
|
func NewC2() *C2 {
|
||||||
|
parsed, err := C2MetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &C2{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *C2) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackFoo is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xbfb4ebcf.
|
||||||
|
//
|
||||||
|
// Solidity: function Foo() pure returns()
|
||||||
|
func (c2 *C2) PackFoo() []byte {
|
||||||
|
enc, err := c2.abi.Pack("Foo")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackError attempts to decode the provided error data using user-defined
|
||||||
|
// error definitions.
|
||||||
|
func (c2 *C2) UnpackError(raw []byte) (any, error) {
|
||||||
|
if bytes.Equal(raw[:4], c2.abi.Errors["BadThing"].ID.Bytes()[:4]) {
|
||||||
|
return c2.UnpackBadThingError(raw[4:])
|
||||||
|
}
|
||||||
|
return nil, errors.New("Unknown error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// C2BadThing represents a BadThing error raised by the C2 contract.
|
||||||
|
type C2BadThing struct {
|
||||||
|
Arg1 *big.Int
|
||||||
|
Arg2 *big.Int
|
||||||
|
Arg3 *big.Int
|
||||||
|
Arg4 bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorID returns the hash of canonical representation of the error's signature.
|
||||||
|
//
|
||||||
|
// Solidity: error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4)
|
||||||
|
func C2BadThingErrorID() common.Hash {
|
||||||
|
return common.HexToHash("0xbb6a82f123854747ef4381e30e497f934a3854753fec99a69c35c30d4b46714d")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackBadThingError is the Go binding used to decode the provided
|
||||||
|
// error data into the corresponding Go error struct.
|
||||||
|
//
|
||||||
|
// Solidity: error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4)
|
||||||
|
func (c2 *C2) UnpackBadThingError(raw []byte) (*C2BadThing, error) {
|
||||||
|
out := new(C2BadThing)
|
||||||
|
if err := c2.abi.UnpackIntoInterface(out, "BadThing", raw); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"contracts":{"contract.sol:C":{"abi":[{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"bool","name":"arg4","type":"bool"}],"name":"BadThing","type":"error"},{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"uint256","name":"arg4","type":"uint256"}],"name":"BadThing2","type":"error"},{"inputs":[],"name":"Bar","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"Foo","outputs":[],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f5ffd5b506101c58061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063b0a378b014610038578063bfb4ebcf14610042575b5f5ffd5b61004061004c565b005b61004a610092565b005b5f6001600260036040517fd233a24f00000000000000000000000000000000000000000000000000000000815260040161008994939291906100ef565b60405180910390fd5b5f600160025f6040517fbb6a82f10000000000000000000000000000000000000000000000000000000081526004016100ce949392919061014c565b60405180910390fd5b5f819050919050565b6100e9816100d7565b82525050565b5f6080820190506101025f8301876100e0565b61010f60208301866100e0565b61011c60408301856100e0565b61012960608301846100e0565b95945050505050565b5f8115159050919050565b61014681610132565b82525050565b5f60808201905061015f5f8301876100e0565b61016c60208301866100e0565b61017960408301856100e0565b610186606083018461013d565b9594505050505056fea26469706673582212206a82b4c28576e4483a81102558271cfefc891cd63b95440dea521185c1ff6a2a64736f6c634300081c0033"},"contract.sol:C2":{"abi":[{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"bool","name":"arg4","type":"bool"}],"name":"BadThing","type":"error"},{"inputs":[],"name":"Foo","outputs":[],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f5ffd5b506101148061001c5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c8063bfb4ebcf14602a575b5f5ffd5b60306032565b005b5f600160025f6040517fbb6a82f1000000000000000000000000000000000000000000000000000000008152600401606c949392919060a3565b60405180910390fd5b5f819050919050565b6085816075565b82525050565b5f8115159050919050565b609d81608b565b82525050565b5f60808201905060b45f830187607e565b60bf6020830186607e565b60ca6040830185607e565b60d560608301846096565b9594505050505056fea2646970667358221220e90bf647ffc897060e44b88d54995ed0c03c988fbccaf034375c2ff4e594690764736f6c634300081c0033"}},"version":"0.8.28+commit.7893614a.Darwin.appleclang"}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.26;
|
||||||
|
|
||||||
|
error BadThing(uint256 arg1, uint256 arg2, uint256 arg3, bool arg4);
|
||||||
|
error BadThing2(uint256 arg1, uint256 arg2, uint256 arg3, uint256 arg4);
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function Foo() public pure {
|
||||||
|
revert BadThing({
|
||||||
|
arg1: uint256(0),
|
||||||
|
arg2: uint256(1),
|
||||||
|
arg3: uint256(2),
|
||||||
|
arg4: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function Bar() public pure {
|
||||||
|
revert BadThing2({
|
||||||
|
arg1: uint256(0),
|
||||||
|
arg2: uint256(1),
|
||||||
|
arg3: uint256(2),
|
||||||
|
arg4: uint256(3)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// purpose of this is to test that generation of metadata for contract that emits one error produces valid Go code
|
||||||
|
contract C2 {
|
||||||
|
function Foo() public pure {
|
||||||
|
revert BadThing({
|
||||||
|
arg1: uint256(0),
|
||||||
|
arg2: uint256(1),
|
||||||
|
arg3: uint256(2),
|
||||||
|
arg4: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Code generated via abigen V2 - DO NOT EDIT.
|
||||||
|
// This file is a generated binding and any manual changes will be lost.
|
||||||
|
|
||||||
|
package uint256arrayreturn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var (
|
||||||
|
_ = bytes.Equal
|
||||||
|
_ = errors.New
|
||||||
|
_ = big.NewInt
|
||||||
|
_ = common.Big1
|
||||||
|
_ = types.BloomLookup
|
||||||
|
_ = abi.ConvertType
|
||||||
|
)
|
||||||
|
|
||||||
|
// MyContractMetaData contains all meta data concerning the MyContract contract.
|
||||||
|
var MyContractMetaData = bind.MetaData{
|
||||||
|
ABI: "[{\"inputs\":[],\"name\":\"GetNums\",\"outputs\":[{\"internalType\":\"uint256[5]\",\"name\":\"\",\"type\":\"uint256[5]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]",
|
||||||
|
ID: "e48e83c9c45b19a47bd451eedc725a6bff",
|
||||||
|
Bin: "0x6080604052348015600e575f5ffd5b506101a78061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063bd6d10071461002d575b5f5ffd5b61003561004b565b6040516100429190610158565b60405180910390f35b610053610088565b5f6040518060a001604052805f8152602001600181526020016002815260200160038152602001600481525090508091505090565b6040518060a00160405280600590602082028036833780820191505090505090565b5f60059050919050565b5f81905092915050565b5f819050919050565b5f819050919050565b6100d9816100c7565b82525050565b5f6100ea83836100d0565b60208301905092915050565b5f602082019050919050565b61010b816100aa565b61011581846100b4565b9250610120826100be565b805f5b8381101561015057815161013787826100df565b9650610142836100f6565b925050600181019050610123565b505050505050565b5f60a08201905061016b5f830184610102565b9291505056fea2646970667358221220ef76cc678ca215c3e9e5261e3f33ac1cb9901c3186c2af167bfcd8f03b3b864c64736f6c634300081c0033",
|
||||||
|
}
|
||||||
|
|
||||||
|
// MyContract is an auto generated Go binding around an Ethereum contract.
|
||||||
|
type MyContract struct {
|
||||||
|
abi abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMyContract creates a new instance of MyContract.
|
||||||
|
func NewMyContract() *MyContract {
|
||||||
|
parsed, err := MyContractMetaData.ParseABI()
|
||||||
|
if err != nil {
|
||||||
|
panic(errors.New("invalid ABI: " + err.Error()))
|
||||||
|
}
|
||||||
|
return &MyContract{abi: *parsed}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance creates a wrapper for a deployed contract instance at the given address.
|
||||||
|
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
|
||||||
|
func (c *MyContract) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
|
||||||
|
return bind.NewBoundContract(addr, c.abi, backend, backend, backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackGetNums is the Go binding used to pack the parameters required for calling
|
||||||
|
// the contract method with ID 0xbd6d1007.
|
||||||
|
//
|
||||||
|
// Solidity: function GetNums() pure returns(uint256[5])
|
||||||
|
func (myContract *MyContract) PackGetNums() []byte {
|
||||||
|
enc, err := myContract.abi.Pack("GetNums")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackGetNums is the Go binding that unpacks the parameters returned
|
||||||
|
// from invoking the contract method with ID 0xbd6d1007.
|
||||||
|
//
|
||||||
|
// Solidity: function GetNums() pure returns(uint256[5])
|
||||||
|
func (myContract *MyContract) UnpackGetNums(data []byte) ([5]*big.Int, error) {
|
||||||
|
out, err := myContract.abi.Unpack("GetNums", data)
|
||||||
|
if err != nil {
|
||||||
|
return *new([5]*big.Int), err
|
||||||
|
}
|
||||||
|
out0 := *abi.ConvertType(out[0], new([5]*big.Int)).(*[5]*big.Int)
|
||||||
|
return out0, err
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"contracts":{"contract.sol:MyContract":{"abi":[{"inputs":[],"name":"GetNums","outputs":[{"internalType":"uint256[5]","name":"","type":"uint256[5]"}],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f5ffd5b506101a78061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063bd6d10071461002d575b5f5ffd5b61003561004b565b6040516100429190610158565b60405180910390f35b610053610088565b5f6040518060a001604052805f8152602001600181526020016002815260200160038152602001600481525090508091505090565b6040518060a00160405280600590602082028036833780820191505090505090565b5f60059050919050565b5f81905092915050565b5f819050919050565b5f819050919050565b6100d9816100c7565b82525050565b5f6100ea83836100d0565b60208301905092915050565b5f602082019050919050565b61010b816100aa565b61011581846100b4565b9250610120826100be565b805f5b8381101561015057815161013787826100df565b9650610142836100f6565b925050600181019050610123565b505050505050565b5f60a08201905061016b5f830184610102565b9291505056fea2646970667358221220ef76cc678ca215c3e9e5261e3f33ac1cb9901c3186c2af167bfcd8f03b3b864c64736f6c634300081c0033"}},"version":"0.8.28+commit.7893614a.Darwin.appleclang"}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.26;
|
||||||
|
|
||||||
|
contract MyContract {
|
||||||
|
// emit multiple events, different types
|
||||||
|
function GetNums() public pure returns (uint256[5] memory) {
|
||||||
|
uint256[5] memory myNums = [uint256(0), uint256(1), uint256(2), uint256(3), uint256(4)];
|
||||||
|
return myNums;
|
||||||
|
}
|
||||||
|
}
|
||||||
243
accounts/abi/bind/v2/lib.go
Normal file
243
accounts/abi/bind/v2/lib.go
Normal file
|
|
@ -0,0 +1,243 @@
|
||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Package bind implements utilities for interacting with Solidity contracts.
|
||||||
|
// This is the 'runtime' for contract bindings generated with the abigen command.
|
||||||
|
// It includes methods for calling/transacting, filtering chain history for
|
||||||
|
// specific custom Solidity event types, and creating event subscriptions to monitor the
|
||||||
|
// chain for event occurrences.
|
||||||
|
//
|
||||||
|
// Two methods for contract deployment are provided:
|
||||||
|
// - [DeployContract] is intended to be used for deployment of a single contract.
|
||||||
|
// - [LinkAndDeploy] is intended for the deployment of multiple
|
||||||
|
// contracts, potentially with library dependencies.
|
||||||
|
package bind
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContractEvent is a type constraint for ABI event types.
|
||||||
|
type ContractEvent interface {
|
||||||
|
ContractEventName() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterEvents filters a historical block range for instances of emission of a
|
||||||
|
// specific event type from a specified contract. It returns an error if the
|
||||||
|
// provided filter opts are invalid or the backend is closed.
|
||||||
|
//
|
||||||
|
// FilterEvents is intended to be used with contract event unpack methods in
|
||||||
|
// bindings generated with the abigen --v2 flag. It should be
|
||||||
|
// preferred over BoundContract.FilterLogs.
|
||||||
|
func FilterEvents[Ev ContractEvent](c *BoundContract, opts *FilterOpts, unpack func(*types.Log) (*Ev, error), topics ...[]any) (*EventIterator[Ev], error) {
|
||||||
|
var e Ev
|
||||||
|
logs, sub, err := c.FilterLogs(opts, e.ContractEventName(), topics...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &EventIterator[Ev]{unpack: unpack, logs: logs, sub: sub}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchEvents creates an event subscription to notify when logs of the
|
||||||
|
// specified event type are emitted from the given contract. Received logs are
|
||||||
|
// unpacked and forwarded to sink. If topics are specified, only events are
|
||||||
|
// forwarded which match the topics.
|
||||||
|
//
|
||||||
|
// WatchEvents returns a subscription or an error if the provided WatchOpts are
|
||||||
|
// invalid or the backend is closed.
|
||||||
|
//
|
||||||
|
// WatchEvents is intended to be used with contract event unpack methods in
|
||||||
|
// bindings generated with the abigen --v2 flag. It should be
|
||||||
|
// preferred over BoundContract.WatchLogs.
|
||||||
|
func WatchEvents[Ev ContractEvent](c *BoundContract, opts *WatchOpts, unpack func(*types.Log) (*Ev, error), sink chan<- *Ev, topics ...[]any) (event.Subscription, error) {
|
||||||
|
var e Ev
|
||||||
|
logs, sub, err := c.WatchLogs(opts, e.ContractEventName(), topics...)
|
||||||
|
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
|
||||||
|
ev, err := unpack(&log)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case sink <- ev:
|
||||||
|
case err := <-sub.Err():
|
||||||
|
return err
|
||||||
|
case <-quit:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case err := <-sub.Err():
|
||||||
|
return err
|
||||||
|
case <-quit:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventIterator is an object for iterating over the results of a event log
|
||||||
|
// filter call.
|
||||||
|
type EventIterator[T any] struct {
|
||||||
|
current *T
|
||||||
|
unpack func(*types.Log) (*T, error)
|
||||||
|
logs <-chan types.Log
|
||||||
|
sub ethereum.Subscription
|
||||||
|
fail error // error to hold reason for iteration failure
|
||||||
|
closed bool // true if Close has been called
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current value of the iterator, or nil if there isn't one.
|
||||||
|
func (it *EventIterator[T]) Value() *T {
|
||||||
|
return it.current
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next advances the iterator to the subsequent event (if there is one),
|
||||||
|
// returning true if the iterator advanced.
|
||||||
|
//
|
||||||
|
// If the attempt to convert the raw log object to an instance of T using the
|
||||||
|
// unpack function provided via FilterEvents returns an error: that error is
|
||||||
|
// returned and subsequent calls to Next will not advance the iterator.
|
||||||
|
func (it *EventIterator[T]) Next() (advanced bool) {
|
||||||
|
// If the iterator failed with an error, don't proceed
|
||||||
|
if it.fail != nil || it.closed {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// if the iterator is still active, block until a log is received or the
|
||||||
|
// underlying subscription terminates.
|
||||||
|
select {
|
||||||
|
case log := <-it.logs:
|
||||||
|
res, err := it.unpack(&log)
|
||||||
|
if err != nil {
|
||||||
|
it.fail = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
it.current = res
|
||||||
|
return true
|
||||||
|
case <-it.sub.Err():
|
||||||
|
// regardless of how the subscription ends, still be able to iterate
|
||||||
|
// over any unread logs.
|
||||||
|
select {
|
||||||
|
case log := <-it.logs:
|
||||||
|
res, err := it.unpack(&log)
|
||||||
|
if err != nil {
|
||||||
|
it.fail = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
it.current = res
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns an error if iteration has failed.
|
||||||
|
func (it *EventIterator[T]) Error() error {
|
||||||
|
return it.fail
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close releases any pending underlying resources. Any subsequent calls to
|
||||||
|
// Next will not advance the iterator, but the current value remains accessible.
|
||||||
|
func (it *EventIterator[T]) Close() error {
|
||||||
|
it.closed = true
|
||||||
|
it.sub.Unsubscribe()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call performs an eth_call to a contract with optional call data.
|
||||||
|
//
|
||||||
|
// To call a function that doesn't return any output, pass nil as the unpack
|
||||||
|
// function. This can be useful if you just want to check that the function
|
||||||
|
// doesn't revert.
|
||||||
|
//
|
||||||
|
// Call is intended to be used with contract method unpack methods in
|
||||||
|
// bindings generated with the abigen --v2 flag. It should be
|
||||||
|
// preferred over BoundContract.Call
|
||||||
|
func Call[T any](c *BoundContract, opts *CallOpts, calldata []byte, unpack func([]byte) (T, error)) (T, error) {
|
||||||
|
var defaultResult T
|
||||||
|
packedOutput, err := c.CallRaw(opts, calldata)
|
||||||
|
if err != nil {
|
||||||
|
return defaultResult, err
|
||||||
|
}
|
||||||
|
if unpack == nil {
|
||||||
|
if len(packedOutput) > 0 {
|
||||||
|
return defaultResult, errors.New("contract returned data, but no unpack function was given")
|
||||||
|
}
|
||||||
|
return defaultResult, nil
|
||||||
|
}
|
||||||
|
res, err := unpack(packedOutput)
|
||||||
|
if err != nil {
|
||||||
|
return defaultResult, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transact creates and submits a transaction to a contract with optional input
|
||||||
|
// data.
|
||||||
|
//
|
||||||
|
// Transact is identical to BoundContract.RawTransact, and is provided as a
|
||||||
|
// package-level method so that interactions with contracts whose bindings were
|
||||||
|
// generated with the abigen --v2 flag are consistent (they do not require
|
||||||
|
// calling methods on the BoundContract instance).
|
||||||
|
func Transact(c *BoundContract, opt *TransactOpts, data []byte) (*types.Transaction, error) {
|
||||||
|
return c.RawTransact(opt, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeployContract creates and submits a deployment transaction based on the
|
||||||
|
// deployer bytecode and optional ABI-encoded constructor input. It returns
|
||||||
|
// the address and creation transaction of the pending contract, or an error
|
||||||
|
// if the creation failed.
|
||||||
|
//
|
||||||
|
// To initiate the deployment of multiple contracts with one method call, see the
|
||||||
|
// [LinkAndDeploy] method.
|
||||||
|
func DeployContract(opts *TransactOpts, bytecode []byte, backend ContractBackend, constructorInput []byte) (common.Address, *types.Transaction, error) {
|
||||||
|
c := NewBoundContract(common.Address{}, abi.ABI{}, backend, backend, backend)
|
||||||
|
|
||||||
|
tx, err := c.RawCreationTransact(opts, append(bytecode, constructorInput...))
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, err
|
||||||
|
}
|
||||||
|
return crypto.CreateAddress(opts.From, tx.Nonce()), tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultDeployer returns a DeployFn that signs and submits creation transactions
|
||||||
|
// using the given signer.
|
||||||
|
//
|
||||||
|
// The DeployFn returned by DefaultDeployer should be used by LinkAndDeploy in
|
||||||
|
// almost all cases, unless a custom DeployFn implementation is needed.
|
||||||
|
func DefaultDeployer(opts *TransactOpts, backend ContractBackend) DeployFn {
|
||||||
|
return func(input []byte, deployer []byte) (common.Address, *types.Transaction, error) {
|
||||||
|
addr, tx, err := DeployContract(opts, deployer, backend, input)
|
||||||
|
if err != nil {
|
||||||
|
return common.Address{}, nil, err
|
||||||
|
}
|
||||||
|
return addr, tx, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
361
accounts/abi/bind/v2/lib_test.go
Normal file
361
accounts/abi/bind/v2/lib_test.go
Normal file
|
|
@ -0,0 +1,361 @@
|
||||||
|
// 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 bind_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2/internal/contracts/events"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2/internal/contracts/nested_libraries"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2/internal/contracts/solc_errors"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
"github.com/ethereum/go-ethereum/ethclient/simulated"
|
||||||
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
var testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
|
||||||
|
|
||||||
|
func testSetup() (*backends.SimulatedBackend, error) {
|
||||||
|
backend := simulated.NewBackend(
|
||||||
|
types.GenesisAlloc{
|
||||||
|
testAddr: {Balance: big.NewInt(10000000000000000)},
|
||||||
|
},
|
||||||
|
func(nodeConf *node.Config, ethConf *ethconfig.Config) {
|
||||||
|
ethConf.Genesis.Difficulty = big.NewInt(0)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// we should just be able to use the backend directly, instead of using
|
||||||
|
// this deprecated interface. However, the simulated backend no longer
|
||||||
|
// implements backends.SimulatedBackend...
|
||||||
|
bindBackend := backends.SimulatedBackend{
|
||||||
|
Backend: backend,
|
||||||
|
Client: backend.Client(),
|
||||||
|
}
|
||||||
|
return &bindBackend, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTestDeployer(backend simulated.Client) func(input, deployer []byte) (common.Address, *types.Transaction, error) {
|
||||||
|
chainId, _ := backend.ChainID(context.Background())
|
||||||
|
return bind.DefaultDeployer(bind.NewKeyedTransactor(testKey, chainId), backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test that deploying a contract with library dependencies works,
|
||||||
|
// verifying by calling method on the deployed contract.
|
||||||
|
func TestDeploymentLibraries(t *testing.T) {
|
||||||
|
bindBackend, err := testSetup()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err setting up test: %v", err)
|
||||||
|
}
|
||||||
|
defer bindBackend.Backend.Close()
|
||||||
|
|
||||||
|
c := nested_libraries.NewC1()
|
||||||
|
constructorInput := c.PackConstructor(big.NewInt(42), big.NewInt(1))
|
||||||
|
deploymentParams := &bind.DeploymentParams{
|
||||||
|
Contracts: []*bind.MetaData{&nested_libraries.C1MetaData},
|
||||||
|
Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput},
|
||||||
|
}
|
||||||
|
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(bindBackend.Client))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %+v\n", err)
|
||||||
|
}
|
||||||
|
bindBackend.Commit()
|
||||||
|
|
||||||
|
if len(res.Addresses) != 5 {
|
||||||
|
t.Fatalf("deployment should have generated 5 addresses. got %d", len(res.Addresses))
|
||||||
|
}
|
||||||
|
for _, tx := range res.Txs {
|
||||||
|
_, err = bind.WaitDeployed(context.Background(), bindBackend, tx.Hash())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error deploying library: %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doInput := c.PackDo(big.NewInt(1))
|
||||||
|
contractAddr := res.Addresses[nested_libraries.C1MetaData.ID]
|
||||||
|
callOpts := &bind.CallOpts{From: common.Address{}, Context: context.Background()}
|
||||||
|
instance := c.Instance(bindBackend, contractAddr)
|
||||||
|
internalCallCount, err := bind.Call(instance, callOpts, doInput, c.UnpackDo)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err unpacking result: %v", err)
|
||||||
|
}
|
||||||
|
if internalCallCount.Uint64() != 6 {
|
||||||
|
t.Fatalf("expected internal call count of 6. got %d.", internalCallCount.Uint64())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as TestDeployment. However, stagger the deployments with overrides:
|
||||||
|
// first deploy the library deps and then the contract.
|
||||||
|
func TestDeploymentWithOverrides(t *testing.T) {
|
||||||
|
bindBackend, err := testSetup()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err setting up test: %v", err)
|
||||||
|
}
|
||||||
|
defer bindBackend.Backend.Close()
|
||||||
|
|
||||||
|
// deploy all the library dependencies of our target contract, but not the target contract itself.
|
||||||
|
deploymentParams := &bind.DeploymentParams{
|
||||||
|
Contracts: nested_libraries.C1MetaData.Deps,
|
||||||
|
}
|
||||||
|
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(bindBackend))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %+v\n", err)
|
||||||
|
}
|
||||||
|
bindBackend.Commit()
|
||||||
|
|
||||||
|
if len(res.Addresses) != 4 {
|
||||||
|
t.Fatalf("deployment should have generated 4 addresses. got %d", len(res.Addresses))
|
||||||
|
}
|
||||||
|
for _, tx := range res.Txs {
|
||||||
|
_, err = bind.WaitDeployed(context.Background(), bindBackend, tx.Hash())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error deploying library: %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c := nested_libraries.NewC1()
|
||||||
|
constructorInput := c.PackConstructor(big.NewInt(42), big.NewInt(1))
|
||||||
|
overrides := res.Addresses
|
||||||
|
|
||||||
|
// deploy the contract
|
||||||
|
deploymentParams = &bind.DeploymentParams{
|
||||||
|
Contracts: []*bind.MetaData{&nested_libraries.C1MetaData},
|
||||||
|
Inputs: map[string][]byte{nested_libraries.C1MetaData.ID: constructorInput},
|
||||||
|
Overrides: overrides,
|
||||||
|
}
|
||||||
|
res, err = bind.LinkAndDeploy(deploymentParams, makeTestDeployer(bindBackend))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %+v\n", err)
|
||||||
|
}
|
||||||
|
bindBackend.Commit()
|
||||||
|
|
||||||
|
if len(res.Addresses) != 1 {
|
||||||
|
t.Fatalf("deployment should have generated 1 address. got %d", len(res.Addresses))
|
||||||
|
}
|
||||||
|
for _, tx := range res.Txs {
|
||||||
|
_, err = bind.WaitDeployed(context.Background(), bindBackend, tx.Hash())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error deploying library: %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the deployed contract and make sure it returns the correct result
|
||||||
|
doInput := c.PackDo(big.NewInt(1))
|
||||||
|
instance := c.Instance(bindBackend, res.Addresses[nested_libraries.C1MetaData.ID])
|
||||||
|
callOpts := new(bind.CallOpts)
|
||||||
|
internalCallCount, err := bind.Call(instance, callOpts, doInput, c.UnpackDo)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error calling contract: %v", err)
|
||||||
|
}
|
||||||
|
if internalCallCount.Uint64() != 6 {
|
||||||
|
t.Fatalf("expected internal call count of 6. got %d.", internalCallCount.Uint64())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns transaction auth to send a basic transaction from testAddr
|
||||||
|
func defaultTxAuth() *bind.TransactOpts {
|
||||||
|
signer := types.LatestSigner(params.AllDevChainProtocolChanges)
|
||||||
|
opts := &bind.TransactOpts{
|
||||||
|
From: testAddr,
|
||||||
|
Nonce: nil,
|
||||||
|
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
||||||
|
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
signedTx, err := tx.WithSignature(signer, signature)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return signedTx, nil
|
||||||
|
},
|
||||||
|
Context: context.Background(),
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvents(t *testing.T) {
|
||||||
|
// test watch/filter logs method on a contract that emits various kinds of events (struct-containing, etc.)
|
||||||
|
backend, err := testSetup()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error setting up testing env: %v", err)
|
||||||
|
}
|
||||||
|
deploymentParams := &bind.DeploymentParams{
|
||||||
|
Contracts: []*bind.MetaData{&events.CMetaData},
|
||||||
|
}
|
||||||
|
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(backend))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error deploying contract for testing: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
backend.Commit()
|
||||||
|
if _, err := bind.WaitDeployed(context.Background(), backend, res.Txs[events.CMetaData.ID].Hash()); err != nil {
|
||||||
|
t.Fatalf("WaitDeployed failed %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := events.NewC()
|
||||||
|
instance := c.Instance(backend, res.Addresses[events.CMetaData.ID])
|
||||||
|
|
||||||
|
newCBasic1Ch := make(chan *events.CBasic1)
|
||||||
|
newCBasic2Ch := make(chan *events.CBasic2)
|
||||||
|
watchOpts := &bind.WatchOpts{}
|
||||||
|
sub1, err := bind.WatchEvents(instance, watchOpts, c.UnpackBasic1Event, newCBasic1Ch)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("WatchEvents returned error: %v", err)
|
||||||
|
}
|
||||||
|
sub2, err := bind.WatchEvents(instance, watchOpts, c.UnpackBasic2Event, newCBasic2Ch)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("WatchEvents returned error: %v", err)
|
||||||
|
}
|
||||||
|
defer sub1.Unsubscribe()
|
||||||
|
defer sub2.Unsubscribe()
|
||||||
|
|
||||||
|
packedInput := c.PackEmitMulti()
|
||||||
|
tx, err := bind.Transact(instance, defaultTxAuth(), packedInput)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to send transaction: %v", err)
|
||||||
|
}
|
||||||
|
backend.Commit()
|
||||||
|
if _, err := bind.WaitMined(context.Background(), backend, tx.Hash()); err != nil {
|
||||||
|
t.Fatalf("error waiting for tx to be mined: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout := time.NewTimer(2 * time.Second)
|
||||||
|
e1Count := 0
|
||||||
|
e2Count := 0
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-newCBasic1Ch:
|
||||||
|
e1Count++
|
||||||
|
case <-newCBasic2Ch:
|
||||||
|
e2Count++
|
||||||
|
case <-timeout.C:
|
||||||
|
goto done
|
||||||
|
}
|
||||||
|
if e1Count == 2 && e2Count == 1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
if e1Count != 2 {
|
||||||
|
t.Fatalf("expected event type 1 count to be 2. got %d", e1Count)
|
||||||
|
}
|
||||||
|
if e2Count != 1 {
|
||||||
|
t.Fatalf("expected event type 2 count to be 1. got %d", e2Count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// now, test that we can filter those same logs after they were included in the chain
|
||||||
|
|
||||||
|
filterOpts := &bind.FilterOpts{
|
||||||
|
Start: 0,
|
||||||
|
Context: context.Background(),
|
||||||
|
}
|
||||||
|
it, err := bind.FilterEvents(instance, filterOpts, c.UnpackBasic1Event)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error filtering logs %v\n", err)
|
||||||
|
}
|
||||||
|
it2, err := bind.FilterEvents(instance, filterOpts, c.UnpackBasic2Event)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error filtering logs %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
e1Count = 0
|
||||||
|
e2Count = 0
|
||||||
|
for it.Next() {
|
||||||
|
if err := it.Error(); err != nil {
|
||||||
|
t.Fatalf("got error while iterating events for e1: %v", err)
|
||||||
|
}
|
||||||
|
e1Count++
|
||||||
|
}
|
||||||
|
for it2.Next() {
|
||||||
|
if err := it2.Error(); err != nil {
|
||||||
|
t.Fatalf("got error while iterating events for e2: %v", err)
|
||||||
|
}
|
||||||
|
e2Count++
|
||||||
|
}
|
||||||
|
if e1Count != 2 {
|
||||||
|
t.Fatalf("expected e1Count of 2 from filter call. got %d", e1Count)
|
||||||
|
}
|
||||||
|
if e2Count != 1 {
|
||||||
|
t.Fatalf("expected e2Count of 1 from filter call. got %d", e1Count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrors(t *testing.T) {
|
||||||
|
// test watch/filter logs method on a contract that emits various kinds of events (struct-containing, etc.)
|
||||||
|
backend, err := testSetup()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error setting up testing env: %v", err)
|
||||||
|
}
|
||||||
|
deploymentParams := &bind.DeploymentParams{
|
||||||
|
Contracts: []*bind.MetaData{&solc_errors.CMetaData},
|
||||||
|
}
|
||||||
|
res, err := bind.LinkAndDeploy(deploymentParams, makeTestDeployer(backend))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error deploying contract for testing: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
backend.Commit()
|
||||||
|
if _, err := bind.WaitDeployed(context.Background(), backend, res.Txs[solc_errors.CMetaData.ID].Hash()); err != nil {
|
||||||
|
t.Fatalf("WaitDeployed failed %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := solc_errors.NewC()
|
||||||
|
instance := c.Instance(backend, res.Addresses[solc_errors.CMetaData.ID])
|
||||||
|
packedInput := c.PackFoo()
|
||||||
|
opts := &bind.CallOpts{From: res.Addresses[solc_errors.CMetaData.ID]}
|
||||||
|
_, err = bind.Call[struct{}](instance, opts, packedInput, nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected call to fail")
|
||||||
|
}
|
||||||
|
raw, hasRevertErrorData := ethclient.RevertErrorData(err)
|
||||||
|
if !hasRevertErrorData {
|
||||||
|
t.Fatalf("expected call error to contain revert error data.")
|
||||||
|
}
|
||||||
|
rawUnpackedErr, err := c.UnpackError(raw)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected to unpack error")
|
||||||
|
}
|
||||||
|
|
||||||
|
unpackedErr, ok := rawUnpackedErr.(*solc_errors.CBadThing)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("unexpected type for error")
|
||||||
|
}
|
||||||
|
if unpackedErr.Arg1.Cmp(big.NewInt(0)) != 0 {
|
||||||
|
t.Fatalf("bad unpacked error result: expected Arg1 field to be 0. got %s", unpackedErr.Arg1.String())
|
||||||
|
}
|
||||||
|
if unpackedErr.Arg2.Cmp(big.NewInt(1)) != 0 {
|
||||||
|
t.Fatalf("bad unpacked error result: expected Arg2 field to be 1. got %s", unpackedErr.Arg2.String())
|
||||||
|
}
|
||||||
|
if unpackedErr.Arg3.Cmp(big.NewInt(2)) != 0 {
|
||||||
|
t.Fatalf("bad unpacked error result: expected Arg3 to be 2. got %s", unpackedErr.Arg3.String())
|
||||||
|
}
|
||||||
|
if unpackedErr.Arg4 != false {
|
||||||
|
t.Fatalf("bad unpacked error result: expected Arg4 to be false. got true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,19 +29,13 @@ import (
|
||||||
|
|
||||||
// WaitMined waits for tx to be mined on the blockchain.
|
// WaitMined waits for tx to be mined on the blockchain.
|
||||||
// It stops waiting when the context is canceled.
|
// It stops waiting when the context is canceled.
|
||||||
func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) {
|
func WaitMined(ctx context.Context, b DeployBackend, txHash common.Hash) (*types.Receipt, error) {
|
||||||
return WaitMinedHash(ctx, b, tx.Hash())
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitMinedHash waits for a transaction with the provided hash to be mined on the blockchain.
|
|
||||||
// It stops waiting when the context is canceled.
|
|
||||||
func WaitMinedHash(ctx context.Context, b DeployBackend, hash common.Hash) (*types.Receipt, error) {
|
|
||||||
queryTicker := time.NewTicker(time.Second)
|
queryTicker := time.NewTicker(time.Second)
|
||||||
defer queryTicker.Stop()
|
defer queryTicker.Stop()
|
||||||
|
|
||||||
logger := log.New("hash", hash)
|
logger := log.New("hash", txHash)
|
||||||
for {
|
for {
|
||||||
receipt, err := b.TransactionReceipt(ctx, hash)
|
receipt, err := b.TransactionReceipt(ctx, txHash)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return receipt, nil
|
return receipt, nil
|
||||||
}
|
}
|
||||||
|
|
@ -61,24 +55,16 @@ func WaitMinedHash(ctx context.Context, b DeployBackend, hash common.Hash) (*typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitDeployed waits for a contract deployment transaction and returns the on-chain
|
// WaitDeployed waits for a contract deployment transaction with the provided hash and
|
||||||
// contract address when it is mined. It stops waiting when ctx is canceled.
|
// returns the on-chain contract address when it is mined. It stops waiting when ctx is
|
||||||
func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) {
|
// canceled.
|
||||||
if tx.To() != nil {
|
func WaitDeployed(ctx context.Context, b DeployBackend, hash common.Hash) (common.Address, error) {
|
||||||
return common.Address{}, errors.New("tx is not contract creation")
|
receipt, err := WaitMined(ctx, b, hash)
|
||||||
}
|
|
||||||
return WaitDeployedHash(ctx, b, tx.Hash())
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitDeployedHash waits for a contract deployment transaction with the provided hash and returns the on-chain
|
|
||||||
// contract address when it is mined. It stops waiting when ctx is canceled.
|
|
||||||
func WaitDeployedHash(ctx context.Context, b DeployBackend, hash common.Hash) (common.Address, error) {
|
|
||||||
receipt, err := WaitMinedHash(ctx, b, hash)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
}
|
}
|
||||||
if receipt.ContractAddress == (common.Address{}) {
|
if receipt.ContractAddress == (common.Address{}) {
|
||||||
return common.Address{}, errors.New("zero address")
|
return common.Address{}, ErrNoAddressInReceipt
|
||||||
}
|
}
|
||||||
// Check that code has indeed been deployed at the address.
|
// Check that code has indeed been deployed at the address.
|
||||||
// This matters on pre-Homestead chains: OOG in the constructor
|
// This matters on pre-Homestead chains: OOG in the constructor
|
||||||
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"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"
|
||||||
|
|
@ -31,8 +31,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
|
||||||
|
|
||||||
var waitDeployedTests = map[string]struct {
|
var waitDeployedTests = map[string]struct {
|
||||||
code string
|
code string
|
||||||
gas uint64
|
gas uint64
|
||||||
|
|
@ -77,7 +75,7 @@ func TestWaitDeployed(t *testing.T) {
|
||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
)
|
)
|
||||||
go func() {
|
go func() {
|
||||||
address, err = bind.WaitDeployed(ctx, backend.Client(), tx)
|
address, err = bind.WaitDeployed(ctx, backend.Client(), tx.Hash())
|
||||||
close(mined)
|
close(mined)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -122,9 +120,8 @@ func TestWaitDeployedCornerCases(t *testing.T) {
|
||||||
t.Errorf("failed to send transaction: %q", err)
|
t.Errorf("failed to send transaction: %q", err)
|
||||||
}
|
}
|
||||||
backend.Commit()
|
backend.Commit()
|
||||||
notContractCreation := errors.New("tx is not contract creation")
|
if _, err := bind.WaitDeployed(ctx, backend.Client(), tx.Hash()); err != bind.ErrNoAddressInReceipt {
|
||||||
if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != notContractCreation.Error() {
|
t.Errorf("error mismatch: want %q, got %q, ", bind.ErrNoAddressInReceipt, err)
|
||||||
t.Errorf("error mismatch: want %q, got %q, ", notContractCreation, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a transaction that is not mined.
|
// Create a transaction that is not mined.
|
||||||
|
|
@ -133,7 +130,7 @@ func TestWaitDeployedCornerCases(t *testing.T) {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
contextCanceled := errors.New("context canceled")
|
contextCanceled := errors.New("context canceled")
|
||||||
if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != contextCanceled.Error() {
|
if _, err := bind.WaitDeployed(ctx, backend.Client(), tx.Hash()); err.Error() != contextCanceled.Error() {
|
||||||
t.Errorf("error mismatch: want %q, got %q, ", contextCanceled, err)
|
t.Errorf("error mismatch: want %q, got %q, ", contextCanceled, err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
@ -31,6 +31,46 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func BenchmarkUnpack(b *testing.B) {
|
||||||
|
testCases := []struct {
|
||||||
|
def string
|
||||||
|
packed string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
def: `[{"type": "uint32"}]`,
|
||||||
|
packed: "0000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
def: `[{"type": "uint32[]"}]`,
|
||||||
|
packed: "0000000000000000000000000000000000000000000000000000000000000020" +
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000002" +
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000001" +
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000002",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, test := range testCases {
|
||||||
|
b.Run(strconv.Itoa(i), func(b *testing.B) {
|
||||||
|
def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def)
|
||||||
|
abi, err := JSON(strings.NewReader(def))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("invalid ABI definition %s: %v", def, err)
|
||||||
|
}
|
||||||
|
encb, err := hex.DecodeString(test.packed)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("invalid hex %s: %v", test.packed, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
var result any
|
||||||
|
for range b.N {
|
||||||
|
result, _ = abi.Unpack("method", encb)
|
||||||
|
}
|
||||||
|
_ = result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestUnpack tests the general pack/unpack tests in packing_test.go
|
// TestUnpack tests the general pack/unpack tests in packing_test.go
|
||||||
func TestUnpack(t *testing.T) {
|
func TestUnpack(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
|
||||||
1
beacon/params/checkpoint_holesky.hex
Normal file
1
beacon/params/checkpoint_holesky.hex
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0xf5606a019f0f1006e9ec2070695045f4334450362a48da4c5965314510e0b4c3
|
||||||
1
beacon/params/checkpoint_mainnet.hex
Normal file
1
beacon/params/checkpoint_mainnet.hex
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0x3c0cb4aa83beded1803d262664ba4392b1023f334d9cca02dc3a6925987ebe91
|
||||||
1
beacon/params/checkpoint_sepolia.hex
Normal file
1
beacon/params/checkpoint_sepolia.hex
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0xa8d56457aa414523d93659aef1f7409bbfb72ad75e94d917c8c0b1baa38153ef
|
||||||
|
|
@ -17,14 +17,25 @@
|
||||||
package params
|
package params
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed checkpoint_mainnet.hex
|
||||||
|
var checkpointMainnet string
|
||||||
|
|
||||||
|
//go:embed checkpoint_sepolia.hex
|
||||||
|
var checkpointSepolia string
|
||||||
|
|
||||||
|
//go:embed checkpoint_holesky.hex
|
||||||
|
var checkpointHolesky string
|
||||||
|
|
||||||
var (
|
var (
|
||||||
MainnetLightConfig = (&ChainConfig{
|
MainnetLightConfig = (&ChainConfig{
|
||||||
GenesisValidatorsRoot: common.HexToHash("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"),
|
GenesisValidatorsRoot: common.HexToHash("0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"),
|
||||||
GenesisTime: 1606824023,
|
GenesisTime: 1606824023,
|
||||||
Checkpoint: common.HexToHash("0x6509b691f4de4f7b083f2784938fd52f0e131675432b3fd85ea549af9aebd3d0"),
|
Checkpoint: common.HexToHash(checkpointMainnet),
|
||||||
}).
|
}).
|
||||||
AddFork("GENESIS", 0, []byte{0, 0, 0, 0}).
|
AddFork("GENESIS", 0, []byte{0, 0, 0, 0}).
|
||||||
AddFork("ALTAIR", 74240, []byte{1, 0, 0, 0}).
|
AddFork("ALTAIR", 74240, []byte{1, 0, 0, 0}).
|
||||||
|
|
@ -35,7 +46,7 @@ var (
|
||||||
SepoliaLightConfig = (&ChainConfig{
|
SepoliaLightConfig = (&ChainConfig{
|
||||||
GenesisValidatorsRoot: common.HexToHash("0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078"),
|
GenesisValidatorsRoot: common.HexToHash("0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078"),
|
||||||
GenesisTime: 1655733600,
|
GenesisTime: 1655733600,
|
||||||
Checkpoint: common.HexToHash("0x456e85f5608afab3465a0580bff8572255f6d97af0c5f939e3f7536b5edb2d3f"),
|
Checkpoint: common.HexToHash(checkpointSepolia),
|
||||||
}).
|
}).
|
||||||
AddFork("GENESIS", 0, []byte{144, 0, 0, 105}).
|
AddFork("GENESIS", 0, []byte{144, 0, 0, 105}).
|
||||||
AddFork("ALTAIR", 50, []byte{144, 0, 0, 112}).
|
AddFork("ALTAIR", 50, []byte{144, 0, 0, 112}).
|
||||||
|
|
@ -47,7 +58,7 @@ var (
|
||||||
HoleskyLightConfig = (&ChainConfig{
|
HoleskyLightConfig = (&ChainConfig{
|
||||||
GenesisValidatorsRoot: common.HexToHash("0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1"),
|
GenesisValidatorsRoot: common.HexToHash("0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1"),
|
||||||
GenesisTime: 1695902400,
|
GenesisTime: 1695902400,
|
||||||
Checkpoint: common.HexToHash("0x6456a1317f54d4b4f2cb5bc9d153b5af0988fe767ef0609f0236cf29030bcff7"),
|
Checkpoint: common.HexToHash(checkpointHolesky),
|
||||||
}).
|
}).
|
||||||
AddFork("GENESIS", 0, []byte{1, 1, 112, 0}).
|
AddFork("GENESIS", 0, []byte{1, 1, 112, 0}).
|
||||||
AddFork("ALTAIR", 0, []byte{2, 1, 112, 0}).
|
AddFork("ALTAIR", 0, []byte{2, 1, 112, 0}).
|
||||||
|
|
@ -55,4 +66,17 @@ var (
|
||||||
AddFork("CAPELLA", 256, []byte{4, 1, 112, 0}).
|
AddFork("CAPELLA", 256, []byte{4, 1, 112, 0}).
|
||||||
AddFork("DENEB", 29696, []byte{5, 1, 112, 0}).
|
AddFork("DENEB", 29696, []byte{5, 1, 112, 0}).
|
||||||
AddFork("ELECTRA", 115968, []byte{6, 1, 112, 0})
|
AddFork("ELECTRA", 115968, []byte{6, 1, 112, 0})
|
||||||
|
|
||||||
|
HoodiLightConfig = (&ChainConfig{
|
||||||
|
GenesisValidatorsRoot: common.HexToHash("0x212f13fc4df078b6cb7db228f1c8307566dcecf900867401a92023d7ba99cb5f"),
|
||||||
|
GenesisTime: 1742212800,
|
||||||
|
Checkpoint: common.HexToHash(""),
|
||||||
|
}).
|
||||||
|
AddFork("GENESIS", 0, common.FromHex("0x10000910")).
|
||||||
|
AddFork("ALTAIR", 0, common.FromHex("0x20000910")).
|
||||||
|
AddFork("BELLATRIX", 0, common.FromHex("0x30000910")).
|
||||||
|
AddFork("CAPELLA", 0, common.FromHex("0x40000910")).
|
||||||
|
AddFork("DENEB", 0, common.FromHex("0x50000910")).
|
||||||
|
AddFork("ELECTRA", 2048, common.FromHex("0x60000910")).
|
||||||
|
AddFork("FULU", 18446744073709551615, common.FromHex("0x70000910"))
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/abigen"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common/compiler"
|
"github.com/ethereum/go-ethereum/common/compiler"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
@ -63,14 +63,13 @@ var (
|
||||||
Name: "out",
|
Name: "out",
|
||||||
Usage: "Output file for the generated binding (default = stdout)",
|
Usage: "Output file for the generated binding (default = stdout)",
|
||||||
}
|
}
|
||||||
langFlag = &cli.StringFlag{
|
|
||||||
Name: "lang",
|
|
||||||
Usage: "Destination language for the bindings (go)",
|
|
||||||
Value: "go",
|
|
||||||
}
|
|
||||||
aliasFlag = &cli.StringFlag{
|
aliasFlag = &cli.StringFlag{
|
||||||
Name: "alias",
|
Name: "alias",
|
||||||
Usage: "Comma separated aliases for function and event renaming, e.g. original1=alias1, original2=alias2",
|
Usage: "Comma separated aliases for function and event renaming. If --v2 is set, errors are aliased as well. e.g. original1=alias1, original2=alias2",
|
||||||
|
}
|
||||||
|
v2Flag = &cli.BoolFlag{
|
||||||
|
Name: "v2",
|
||||||
|
Usage: "Generates v2 bindings",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -86,13 +85,13 @@ func init() {
|
||||||
excFlag,
|
excFlag,
|
||||||
pkgFlag,
|
pkgFlag,
|
||||||
outFlag,
|
outFlag,
|
||||||
langFlag,
|
|
||||||
aliasFlag,
|
aliasFlag,
|
||||||
|
v2Flag,
|
||||||
}
|
}
|
||||||
app.Action = abigen
|
app.Action = generate
|
||||||
}
|
}
|
||||||
|
|
||||||
func abigen(c *cli.Context) error {
|
func generate(c *cli.Context) error {
|
||||||
flags.CheckExclusive(c, abiFlag, jsonFlag) // Only one source can be selected.
|
flags.CheckExclusive(c, abiFlag, jsonFlag) // Only one source can be selected.
|
||||||
|
|
||||||
if c.String(pkgFlag.Name) == "" {
|
if c.String(pkgFlag.Name) == "" {
|
||||||
|
|
@ -101,13 +100,6 @@ func abigen(c *cli.Context) error {
|
||||||
if c.String(abiFlag.Name) == "" && c.String(jsonFlag.Name) == "" {
|
if c.String(abiFlag.Name) == "" && c.String(jsonFlag.Name) == "" {
|
||||||
utils.Fatalf("Either contract ABI source (--abi) or combined-json (--combined-json) are required")
|
utils.Fatalf("Either contract ABI source (--abi) or combined-json (--combined-json) are required")
|
||||||
}
|
}
|
||||||
var lang bind.Lang
|
|
||||||
switch c.String(langFlag.Name) {
|
|
||||||
case "go":
|
|
||||||
lang = bind.LangGo
|
|
||||||
default:
|
|
||||||
utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.String(langFlag.Name))
|
|
||||||
}
|
|
||||||
// If the entire solidity code was specified, build and bind based on that
|
// If the entire solidity code was specified, build and bind based on that
|
||||||
var (
|
var (
|
||||||
abis []string
|
abis []string
|
||||||
|
|
@ -219,7 +211,15 @@ func abigen(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Generate the contract binding
|
// Generate the contract binding
|
||||||
code, err := bind.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), lang, libs, aliases)
|
var (
|
||||||
|
code string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if c.IsSet(v2Flag.Name) {
|
||||||
|
code, err = abigen.BindV2(types, abis, bins, c.String(pkgFlag.Name), libs, aliases)
|
||||||
|
} else {
|
||||||
|
code, err = abigen.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), libs, aliases)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to generate ABI binding: %v", err)
|
utils.Fatalf("Failed to generate ABI binding: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ func main() {
|
||||||
utils.MainnetFlag,
|
utils.MainnetFlag,
|
||||||
utils.SepoliaFlag,
|
utils.SepoliaFlag,
|
||||||
utils.HoleskyFlag,
|
utils.HoleskyFlag,
|
||||||
|
utils.HoodiFlag,
|
||||||
utils.BlsyncApiFlag,
|
utils.BlsyncApiFlag,
|
||||||
utils.BlsyncJWTSecretFlag,
|
utils.BlsyncJWTSecretFlag,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,8 @@ func ethFilter(args []string) (nodeFilter, error) {
|
||||||
filter = forkid.NewStaticFilter(params.SepoliaChainConfig, core.DefaultSepoliaGenesisBlock().ToBlock())
|
filter = forkid.NewStaticFilter(params.SepoliaChainConfig, core.DefaultSepoliaGenesisBlock().ToBlock())
|
||||||
case "holesky":
|
case "holesky":
|
||||||
filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock())
|
filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock())
|
||||||
|
case "hoodi":
|
||||||
|
filter = forkid.NewStaticFilter(params.HoodiChainConfig, core.DefaultHoodiGenesisBlock().ToBlock())
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown network %q", args[0])
|
return nil, fmt.Errorf("unknown network %q", args[0])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Tran
|
||||||
if tx.protected {
|
if tx.protected {
|
||||||
signed, err = types.SignTx(tx.tx, signer, tx.key)
|
signed, err = types.SignTx(tx.tx, signer, tx.key)
|
||||||
} else {
|
} else {
|
||||||
signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key)
|
signed, err = types.SignTx(tx.tx, types.HomesteadSigner{}, tx.key)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,9 @@ var stateTestCommand = &cli.Command{
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
BenchFlag,
|
BenchFlag,
|
||||||
DumpFlag,
|
DumpFlag,
|
||||||
|
forkFlag,
|
||||||
HumanReadableFlag,
|
HumanReadableFlag,
|
||||||
|
idxFlag,
|
||||||
RunFlag,
|
RunFlag,
|
||||||
}, traceFlags),
|
}, traceFlags),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,11 @@ import (
|
||||||
"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/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/debug"
|
||||||
"github.com/ethereum/go-ethereum/internal/era"
|
"github.com/ethereum/go-ethereum/internal/era"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
@ -65,7 +68,7 @@ It expects the genesis file as argument.`,
|
||||||
Name: "dumpgenesis",
|
Name: "dumpgenesis",
|
||||||
Usage: "Dumps genesis block JSON configuration to stdout",
|
Usage: "Dumps genesis block JSON configuration to stdout",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Flags: append([]cli.Flag{utils.DataDirFlag}, utils.NetworkFlags...),
|
Flags: slices.Concat([]cli.Flag{utils.DataDirFlag}, utils.NetworkFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The dumpgenesis command prints the genesis configuration of the network preset
|
The dumpgenesis command prints the genesis configuration of the network preset
|
||||||
if one is set. Otherwise it prints the genesis from the datadir.`,
|
if one is set. Otherwise it prints the genesis from the datadir.`,
|
||||||
|
|
@ -77,11 +80,11 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
|
||||||
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
|
||||||
utils.GCModeFlag,
|
utils.GCModeFlag,
|
||||||
utils.SnapshotFlag,
|
utils.SnapshotFlag,
|
||||||
utils.CacheDatabaseFlag,
|
utils.CacheDatabaseFlag,
|
||||||
utils.CacheGCFlag,
|
utils.CacheGCFlag,
|
||||||
|
utils.NoCompactionFlag,
|
||||||
utils.MetricsEnabledFlag,
|
utils.MetricsEnabledFlag,
|
||||||
utils.MetricsEnabledExpensiveFlag,
|
utils.MetricsEnabledExpensiveFlag,
|
||||||
utils.MetricsHTTPFlag,
|
utils.MetricsHTTPFlag,
|
||||||
|
|
@ -100,8 +103,15 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
|
||||||
utils.VMTraceFlag,
|
utils.VMTraceFlag,
|
||||||
utils.VMTraceJsonConfigFlag,
|
utils.VMTraceJsonConfigFlag,
|
||||||
utils.TransactionHistoryFlag,
|
utils.TransactionHistoryFlag,
|
||||||
|
utils.LogHistoryFlag,
|
||||||
|
utils.LogNoHistoryFlag,
|
||||||
|
utils.LogExportCheckpointsFlag,
|
||||||
utils.StateHistoryFlag,
|
utils.StateHistoryFlag,
|
||||||
}, utils.DatabaseFlags),
|
}, utils.DatabaseFlags, debug.Flags),
|
||||||
|
Before: func(ctx *cli.Context) error {
|
||||||
|
flags.MigrateGlobalFlags(ctx)
|
||||||
|
return debug.Setup(ctx)
|
||||||
|
},
|
||||||
Description: `
|
Description: `
|
||||||
The import command allows the import of blocks from an RLP-encoded format. This format can be a single file
|
The import command allows the import of blocks from an RLP-encoded format. This format can be a single file
|
||||||
containing multiple RLP-encoded blocks, or multiple files can be given.
|
containing multiple RLP-encoded blocks, or multiple files can be given.
|
||||||
|
|
@ -115,10 +125,7 @@ to import successfully.`,
|
||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "Export blockchain into file",
|
Usage: "Export blockchain into file",
|
||||||
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{utils.CacheFlag}, utils.DatabaseFlags),
|
||||||
utils.CacheFlag,
|
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.DatabaseFlags),
|
|
||||||
Description: `
|
Description: `
|
||||||
Requires a first argument of the file to write to.
|
Requires a first argument of the file to write to.
|
||||||
Optional second and third arguments control the first and
|
Optional second and third arguments control the first and
|
||||||
|
|
@ -131,12 +138,7 @@ be gzipped.`,
|
||||||
Name: "import-history",
|
Name: "import-history",
|
||||||
Usage: "Import an Era archive",
|
Usage: "Import an Era archive",
|
||||||
ArgsUsage: "<dir>",
|
ArgsUsage: "<dir>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{utils.TxLookupLimitFlag, utils.TransactionHistoryFlag}, utils.DatabaseFlags, utils.NetworkFlags),
|
||||||
utils.TxLookupLimitFlag,
|
|
||||||
},
|
|
||||||
utils.DatabaseFlags,
|
|
||||||
utils.NetworkFlags,
|
|
||||||
),
|
|
||||||
Description: `
|
Description: `
|
||||||
The import-history command will import blocks and their corresponding receipts
|
The import-history command will import blocks and their corresponding receipts
|
||||||
from Era archives.
|
from Era archives.
|
||||||
|
|
@ -147,7 +149,7 @@ from Era archives.
|
||||||
Name: "export-history",
|
Name: "export-history",
|
||||||
Usage: "Export blockchain history to Era archives",
|
Usage: "Export blockchain history to Era archives",
|
||||||
ArgsUsage: "<dir> <first> <last>",
|
ArgsUsage: "<dir> <first> <last>",
|
||||||
Flags: slices.Concat(utils.DatabaseFlags),
|
Flags: utils.DatabaseFlags,
|
||||||
Description: `
|
Description: `
|
||||||
The export-history command will export blocks and their corresponding receipts
|
The export-history command will export blocks and their corresponding receipts
|
||||||
into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
||||||
|
|
@ -158,10 +160,7 @@ into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
||||||
Name: "import-preimages",
|
Name: "import-preimages",
|
||||||
Usage: "Import the preimage database from an RLP stream",
|
Usage: "Import the preimage database from an RLP stream",
|
||||||
ArgsUsage: "<datafile>",
|
ArgsUsage: "<datafile>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{utils.CacheFlag}, utils.DatabaseFlags),
|
||||||
utils.CacheFlag,
|
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.DatabaseFlags),
|
|
||||||
Description: `
|
Description: `
|
||||||
The import-preimages command imports hash preimages from an RLP encoded stream.
|
The import-preimages command imports hash preimages from an RLP encoded stream.
|
||||||
It's deprecated, please use "geth db import" instead.
|
It's deprecated, please use "geth db import" instead.
|
||||||
|
|
@ -186,6 +185,18 @@ It's deprecated, please use "geth db import" instead.
|
||||||
This command dumps out the state for a given block (or latest, if none provided).
|
This command dumps out the state for a given block (or latest, if none provided).
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pruneCommand = &cli.Command{
|
||||||
|
Action: pruneHistory,
|
||||||
|
Name: "prune-history",
|
||||||
|
Usage: "Prune blockchain history (block bodies and receipts) up to the merge block",
|
||||||
|
ArgsUsage: "",
|
||||||
|
Flags: utils.DatabaseFlags,
|
||||||
|
Description: `
|
||||||
|
The prune-history command removes historical block bodies and receipts from the
|
||||||
|
blockchain database up to the merge block, while preserving block headers. This
|
||||||
|
helps reduce storage requirements for nodes that don't need full historical data.`,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// initGenesis will initialise the given JSON format genesis file and writes it as
|
// initGenesis will initialise the given JSON format genesis file and writes it as
|
||||||
|
|
@ -419,6 +430,10 @@ func importHistory(ctx *cli.Context) error {
|
||||||
network = "mainnet"
|
network = "mainnet"
|
||||||
case ctx.Bool(utils.SepoliaFlag.Name):
|
case ctx.Bool(utils.SepoliaFlag.Name):
|
||||||
network = "sepolia"
|
network = "sepolia"
|
||||||
|
case ctx.Bool(utils.HoleskyFlag.Name):
|
||||||
|
network = "holesky"
|
||||||
|
case ctx.Bool(utils.HoodiFlag.Name):
|
||||||
|
network = "hoodi"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No network flag set, try to determine network based on files
|
// No network flag set, try to determine network based on files
|
||||||
|
|
@ -595,3 +610,51 @@ func hashish(x string) bool {
|
||||||
_, err := strconv.Atoi(x)
|
_, err := strconv.Atoi(x)
|
||||||
return err != nil
|
return err != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pruneHistory(ctx *cli.Context) error {
|
||||||
|
stack, _ := makeConfigNode(ctx)
|
||||||
|
defer stack.Close()
|
||||||
|
|
||||||
|
// Open the chain database
|
||||||
|
chain, chaindb := utils.MakeChain(ctx, stack, false)
|
||||||
|
defer chaindb.Close()
|
||||||
|
defer chain.Stop()
|
||||||
|
|
||||||
|
// Determine the prune point. This will be the first PoS block.
|
||||||
|
prunePoint, ok := ethconfig.HistoryPrunePoints[chain.Genesis().Hash()]
|
||||||
|
if !ok || prunePoint == nil {
|
||||||
|
return errors.New("prune point not found")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
mergeBlock = prunePoint.BlockNumber
|
||||||
|
mergeBlockHash = prunePoint.BlockHash.Hex()
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check we're far enough past merge to ensure all data is in freezer
|
||||||
|
currentHeader := chain.CurrentHeader()
|
||||||
|
if currentHeader == nil {
|
||||||
|
return errors.New("current header not found")
|
||||||
|
}
|
||||||
|
if currentHeader.Number.Uint64() < mergeBlock+params.FullImmutabilityThreshold {
|
||||||
|
return fmt.Errorf("chain not far enough past merge block, need %d more blocks",
|
||||||
|
mergeBlock+params.FullImmutabilityThreshold-currentHeader.Number.Uint64())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double-check the prune block in db has the expected hash.
|
||||||
|
hash := rawdb.ReadCanonicalHash(chaindb, mergeBlock)
|
||||||
|
if hash != common.HexToHash(mergeBlockHash) {
|
||||||
|
return fmt.Errorf("merge block hash mismatch: got %s, want %s", hash.Hex(), mergeBlockHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Starting history pruning", "head", currentHeader.Number, "tail", mergeBlock, "tailHash", mergeBlockHash)
|
||||||
|
start := time.Now()
|
||||||
|
rawdb.PruneTransactionIndex(chaindb, mergeBlock)
|
||||||
|
if _, err := chaindb.TruncateTail(mergeBlock); err != nil {
|
||||||
|
return fmt.Errorf("failed to truncate ancient data: %v", err)
|
||||||
|
}
|
||||||
|
log.Info("History pruning completed", "tail", mergeBlock, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
|
|
||||||
|
// TODO(s1na): what if there is a crash between the two prune operations?
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ func makeFullNode(ctx *cli.Context) *node.Node {
|
||||||
|
|
||||||
if ctx.IsSet(utils.DeveloperFlag.Name) {
|
if ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||||
// Start dev mode.
|
// Start dev mode.
|
||||||
simBeacon, err := catalyst.NewSimulatedBeacon(ctx.Uint64(utils.DeveloperPeriodFlag.Name), eth)
|
simBeacon, err := catalyst.NewSimulatedBeacon(ctx.Uint64(utils.DeveloperPeriodFlag.Name), cfg.Eth.Miner.PendingFeeRecipient, eth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("failed to register dev mode catalyst service: %v", err)
|
utils.Fatalf("failed to register dev mode catalyst service: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,12 +86,10 @@ Remove blockchain and state databases`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dbInspectCmd = &cli.Command{
|
dbInspectCmd = &cli.Command{
|
||||||
Action: inspect,
|
Action: inspect,
|
||||||
Name: "inspect",
|
Name: "inspect",
|
||||||
ArgsUsage: "<prefix> <start>",
|
ArgsUsage: "<prefix> <start>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Usage: "Inspect the storage size for each type of data in the database",
|
Usage: "Inspect the storage size for each type of data in the database",
|
||||||
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
||||||
}
|
}
|
||||||
|
|
@ -109,16 +107,13 @@ a data corruption.`,
|
||||||
Action: dbStats,
|
Action: dbStats,
|
||||||
Name: "stats",
|
Name: "stats",
|
||||||
Usage: "Print leveldb statistics",
|
Usage: "Print leveldb statistics",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
}
|
}
|
||||||
dbCompactCmd = &cli.Command{
|
dbCompactCmd = &cli.Command{
|
||||||
Action: dbCompact,
|
Action: dbCompact,
|
||||||
Name: "compact",
|
Name: "compact",
|
||||||
Usage: "Compact leveldb database. WARNING: May take a very long time",
|
Usage: "Compact leveldb database. WARNING: May take a very long time",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.CacheDatabaseFlag,
|
utils.CacheDatabaseFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
|
|
@ -127,13 +122,11 @@ WARNING: This operation may take a very long time to finish, and may cause datab
|
||||||
corruption if it is aborted during execution'!`,
|
corruption if it is aborted during execution'!`,
|
||||||
}
|
}
|
||||||
dbGetCmd = &cli.Command{
|
dbGetCmd = &cli.Command{
|
||||||
Action: dbGet,
|
Action: dbGet,
|
||||||
Name: "get",
|
Name: "get",
|
||||||
Usage: "Show the value of a database key",
|
Usage: "Show the value of a database key",
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
}
|
}
|
||||||
dbDeleteCmd = &cli.Command{
|
dbDeleteCmd = &cli.Command{
|
||||||
|
|
@ -141,9 +134,7 @@ corruption if it is aborted during execution'!`,
|
||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "Delete a database key (WARNING: may corrupt your database)",
|
Usage: "Delete a database key (WARNING: may corrupt your database)",
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Description: `This command deletes the specified database key from the database.
|
Description: `This command deletes the specified database key from the database.
|
||||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}
|
}
|
||||||
|
|
@ -152,59 +143,47 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Name: "put",
|
Name: "put",
|
||||||
Usage: "Set the value of a database key (WARNING: may corrupt your database)",
|
Usage: "Set the value of a database key (WARNING: may corrupt your database)",
|
||||||
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Description: `This command sets a given database key to the given value.
|
Description: `This command sets a given database key to the given value.
|
||||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
}
|
}
|
||||||
dbGetSlotsCmd = &cli.Command{
|
dbGetSlotsCmd = &cli.Command{
|
||||||
Action: dbDumpTrie,
|
Action: dbDumpTrie,
|
||||||
Name: "dumptrie",
|
Name: "dumptrie",
|
||||||
Usage: "Show the storage key/values of a given storage trie",
|
Usage: "Show the storage key/values of a given storage trie",
|
||||||
ArgsUsage: "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
|
ArgsUsage: "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
}
|
}
|
||||||
dbDumpFreezerIndex = &cli.Command{
|
dbDumpFreezerIndex = &cli.Command{
|
||||||
Action: freezerInspect,
|
Action: freezerInspect,
|
||||||
Name: "freezer-index",
|
Name: "freezer-index",
|
||||||
Usage: "Dump out the index of a specific freezer table",
|
Usage: "Dump out the index of a specific freezer table",
|
||||||
ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
|
ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Description: "This command displays information about the freezer index.",
|
Description: "This command displays information about the freezer index.",
|
||||||
}
|
}
|
||||||
dbImportCmd = &cli.Command{
|
dbImportCmd = &cli.Command{
|
||||||
Action: importLDBdata,
|
Action: importLDBdata,
|
||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Imports leveldb-data from an exported RLP dump.",
|
Usage: "Imports leveldb-data from an exported RLP dump.",
|
||||||
ArgsUsage: "<dumpfile> <start (optional)",
|
ArgsUsage: "<dumpfile> <start (optional)",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Description: "The import command imports the specific chain data from an RLP encoded stream.",
|
Description: "The import command imports the specific chain data from an RLP encoded stream.",
|
||||||
}
|
}
|
||||||
dbExportCmd = &cli.Command{
|
dbExportCmd = &cli.Command{
|
||||||
Action: exportChaindata,
|
Action: exportChaindata,
|
||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
|
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
|
||||||
ArgsUsage: "<type> <dumpfile>",
|
ArgsUsage: "<type> <dumpfile>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
|
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
|
||||||
}
|
}
|
||||||
dbMetadataCmd = &cli.Command{
|
dbMetadataCmd = &cli.Command{
|
||||||
Action: showMetaData,
|
Action: showMetaData,
|
||||||
Name: "metadata",
|
Name: "metadata",
|
||||||
Usage: "Shows metadata about the chain status.",
|
Usage: "Shows metadata about the chain status.",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
utils.SyncModeFlag,
|
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
|
||||||
Description: "Shows metadata about the chain status.",
|
Description: "Shows metadata about the chain status.",
|
||||||
}
|
}
|
||||||
dbInspectHistoryCmd = &cli.Command{
|
dbInspectHistoryCmd = &cli.Command{
|
||||||
|
|
@ -213,7 +192,6 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
Usage: "Inspect the state history within block range",
|
Usage: "Inspect the state history within block range",
|
||||||
ArgsUsage: "<address> [OPTIONAL <storage-slot>]",
|
ArgsUsage: "<address> [OPTIONAL <storage-slot>]",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: slices.Concat([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
|
||||||
&cli.Uint64Flag{
|
&cli.Uint64Flag{
|
||||||
Name: "start",
|
Name: "start",
|
||||||
Usage: "block number of the range start, zero means earliest history",
|
Usage: "block number of the range start, zero means earliest history",
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,9 @@ var (
|
||||||
utils.TxLookupLimitFlag, // deprecated
|
utils.TxLookupLimitFlag, // deprecated
|
||||||
utils.TransactionHistoryFlag,
|
utils.TransactionHistoryFlag,
|
||||||
utils.ChainHistoryFlag,
|
utils.ChainHistoryFlag,
|
||||||
|
utils.LogHistoryFlag,
|
||||||
|
utils.LogNoHistoryFlag,
|
||||||
|
utils.LogExportCheckpointsFlag,
|
||||||
utils.StateHistoryFlag,
|
utils.StateHistoryFlag,
|
||||||
utils.LightServeFlag, // deprecated
|
utils.LightServeFlag, // deprecated
|
||||||
utils.LightIngressFlag, // deprecated
|
utils.LightIngressFlag, // deprecated
|
||||||
|
|
@ -139,7 +142,6 @@ var (
|
||||||
utils.VMTraceJsonConfigFlag,
|
utils.VMTraceJsonConfigFlag,
|
||||||
utils.NetworkIdFlag,
|
utils.NetworkIdFlag,
|
||||||
utils.EthStatsURLFlag,
|
utils.EthStatsURLFlag,
|
||||||
utils.NoCompactionFlag,
|
|
||||||
utils.GpoBlocksFlag,
|
utils.GpoBlocksFlag,
|
||||||
utils.GpoPercentileFlag,
|
utils.GpoPercentileFlag,
|
||||||
utils.GpoMaxGasPriceFlag,
|
utils.GpoMaxGasPriceFlag,
|
||||||
|
|
@ -223,6 +225,7 @@ func init() {
|
||||||
removedbCommand,
|
removedbCommand,
|
||||||
dumpCommand,
|
dumpCommand,
|
||||||
dumpGenesisCommand,
|
dumpGenesisCommand,
|
||||||
|
pruneCommand,
|
||||||
// See accountcmd.go:
|
// See accountcmd.go:
|
||||||
accountCommand,
|
accountCommand,
|
||||||
walletCommand,
|
walletCommand,
|
||||||
|
|
@ -293,6 +296,9 @@ func prepare(ctx *cli.Context) {
|
||||||
case ctx.IsSet(utils.HoleskyFlag.Name):
|
case ctx.IsSet(utils.HoleskyFlag.Name):
|
||||||
log.Info("Starting Geth on Holesky testnet...")
|
log.Info("Starting Geth on Holesky testnet...")
|
||||||
|
|
||||||
|
case ctx.IsSet(utils.HoodiFlag.Name):
|
||||||
|
log.Info("Starting Geth on Hoodi testnet...")
|
||||||
|
|
||||||
case ctx.IsSet(utils.DeveloperFlag.Name):
|
case ctx.IsSet(utils.DeveloperFlag.Name):
|
||||||
log.Info("Starting Geth in ephemeral dev mode...")
|
log.Info("Starting Geth in ephemeral dev mode...")
|
||||||
log.Warn(`You are running Geth in --dev mode. Please note the following:
|
log.Warn(`You are running Geth in --dev mode. Please note the following:
|
||||||
|
|
@ -319,6 +325,7 @@ func prepare(ctx *cli.Context) {
|
||||||
// Make sure we're not on any supported preconfigured testnet either
|
// Make sure we're not on any supported preconfigured testnet either
|
||||||
if !ctx.IsSet(utils.HoleskyFlag.Name) &&
|
if !ctx.IsSet(utils.HoleskyFlag.Name) &&
|
||||||
!ctx.IsSet(utils.SepoliaFlag.Name) &&
|
!ctx.IsSet(utils.SepoliaFlag.Name) &&
|
||||||
|
!ctx.IsSet(utils.HoodiFlag.Name) &&
|
||||||
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||||
// Nope, we're really on mainnet. Bump that cache up!
|
// Nope, we're really on mainnet. Bump that cache up!
|
||||||
log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)
|
log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ var ErrImportInterrupted = errors.New("interrupted")
|
||||||
// is redirected to a different file.
|
// is redirected to a different file.
|
||||||
func Fatalf(format string, args ...interface{}) {
|
func Fatalf(format string, args ...interface{}) {
|
||||||
w := io.MultiWriter(os.Stdout, os.Stderr)
|
w := io.MultiWriter(os.Stdout, os.Stderr)
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" || runtime.GOOS == "openbsd" {
|
||||||
// The SameFile check below doesn't work on Windows.
|
// The SameFile check below doesn't work on Windows neither OpenBSD.
|
||||||
// stdout is unlikely to get redirected though, so just print there.
|
// stdout is unlikely to get redirected though, so just print there.
|
||||||
w = os.Stdout
|
w = os.Stdout
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@ func (iter *testIterator) Next() (byte, []byte, []byte, bool) {
|
||||||
if iter.index == 42 {
|
if iter.index == 42 {
|
||||||
iter.index += 1
|
iter.index += 1
|
||||||
}
|
}
|
||||||
return OpBatchAdd, []byte(fmt.Sprintf("key-%04d", iter.index)),
|
return OpBatchAdd, fmt.Appendf(nil, "key-%04d", iter.index),
|
||||||
[]byte(fmt.Sprintf("value %d", iter.index)), true
|
fmt.Appendf(nil, "value %d", iter.index), true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *testIterator) Release() {}
|
func (iter *testIterator) Release() {}
|
||||||
|
|
@ -72,7 +72,7 @@ func testExport(t *testing.T, f string) {
|
||||||
}
|
}
|
||||||
// verify
|
// verify
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
v, err := db.Get([]byte(fmt.Sprintf("key-%04d", i)))
|
v, err := db.Get(fmt.Appendf(nil, "key-%04d", i))
|
||||||
if (i < 5 || i == 42) && err == nil {
|
if (i < 5 || i == 42) && err == nil {
|
||||||
t.Fatalf("expected no element at idx %d, got '%v'", i, string(v))
|
t.Fatalf("expected no element at idx %d, got '%v'", i, string(v))
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,7 @@ func testExport(t *testing.T, f string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v, err := db.Get([]byte(fmt.Sprintf("key-%04d", 1000)))
|
v, err := db.Get(fmt.Appendf(nil, "key-%04d", 1000))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected no element at idx %d, got '%v'", 1000, string(v))
|
t.Fatalf("expected no element at idx %d, got '%v'", 1000, string(v))
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +120,7 @@ func (iter *deletionIterator) Next() (byte, []byte, []byte, bool) {
|
||||||
if iter.index == 42 {
|
if iter.index == 42 {
|
||||||
iter.index += 1
|
iter.index += 1
|
||||||
}
|
}
|
||||||
return OpBatchDel, []byte(fmt.Sprintf("key-%04d", iter.index)), nil, true
|
return OpBatchDel, fmt.Appendf(nil, "key-%04d", iter.index), nil, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *deletionIterator) Release() {}
|
func (iter *deletionIterator) Release() {}
|
||||||
|
|
@ -132,14 +132,14 @@ func testDeletion(t *testing.T, f string) {
|
||||||
}
|
}
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
db.Put([]byte(fmt.Sprintf("key-%04d", i)), []byte(fmt.Sprintf("value %d", i)))
|
db.Put(fmt.Appendf(nil, "key-%04d", i), fmt.Appendf(nil, "value %d", i))
|
||||||
}
|
}
|
||||||
err = ImportLDBData(db, f, 5, make(chan struct{}))
|
err = ImportLDBData(db, f, 5, make(chan struct{}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
v, err := db.Get([]byte(fmt.Sprintf("key-%04d", i)))
|
v, err := db.Get(fmt.Appendf(nil, "key-%04d", i))
|
||||||
if i < 5 || i == 42 {
|
if i < 5 || i == 42 {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("expected element at idx %d, got '%v'", i, err)
|
t.Fatalf("expected element at idx %d, got '%v'", i, err)
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ var (
|
||||||
}
|
}
|
||||||
NetworkIdFlag = &cli.Uint64Flag{
|
NetworkIdFlag = &cli.Uint64Flag{
|
||||||
Name: "networkid",
|
Name: "networkid",
|
||||||
Usage: "Explicitly set network id (integer)(For testnets: use --sepolia, --holesky instead)",
|
Usage: "Explicitly set network id (integer)(For testnets: use --sepolia, --holesky, --hoodi instead)",
|
||||||
Value: ethconfig.Defaults.NetworkId,
|
Value: ethconfig.Defaults.NetworkId,
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
|
|
@ -153,6 +153,11 @@ var (
|
||||||
Usage: "Holesky network: pre-configured proof-of-stake test network",
|
Usage: "Holesky network: pre-configured proof-of-stake test network",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
|
HoodiFlag = &cli.BoolFlag{
|
||||||
|
Name: "hoodi",
|
||||||
|
Usage: "Hoodi network: pre-configured proof-of-stake test network",
|
||||||
|
Category: flags.EthCategory,
|
||||||
|
}
|
||||||
// Dev mode
|
// Dev mode
|
||||||
DeveloperFlag = &cli.BoolFlag{
|
DeveloperFlag = &cli.BoolFlag{
|
||||||
Name: "dev",
|
Name: "dev",
|
||||||
|
|
@ -278,6 +283,23 @@ var (
|
||||||
Value: ethconfig.Defaults.HistoryMode.String(),
|
Value: ethconfig.Defaults.HistoryMode.String(),
|
||||||
Category: flags.StateCategory,
|
Category: flags.StateCategory,
|
||||||
}
|
}
|
||||||
|
LogHistoryFlag = &cli.Uint64Flag{
|
||||||
|
Name: "history.logs",
|
||||||
|
Usage: "Number of recent blocks to maintain log search index for (default = about one year, 0 = entire chain)",
|
||||||
|
Value: ethconfig.Defaults.LogHistory,
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
}
|
||||||
|
LogNoHistoryFlag = &cli.BoolFlag{
|
||||||
|
Name: "history.logs.disable",
|
||||||
|
Usage: "Do not maintain log search index",
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
}
|
||||||
|
LogExportCheckpointsFlag = &cli.StringFlag{
|
||||||
|
Name: "history.logs.export",
|
||||||
|
Usage: "Export checkpoints to file in go source file format",
|
||||||
|
Category: flags.StateCategory,
|
||||||
|
Value: "",
|
||||||
|
}
|
||||||
// Beacon client light sync settings
|
// Beacon client light sync settings
|
||||||
BeaconApiFlag = &cli.StringSliceFlag{
|
BeaconApiFlag = &cli.StringSliceFlag{
|
||||||
Name: "beacon.api",
|
Name: "beacon.api",
|
||||||
|
|
@ -941,6 +963,7 @@ var (
|
||||||
TestnetFlags = []cli.Flag{
|
TestnetFlags = []cli.Flag{
|
||||||
SepoliaFlag,
|
SepoliaFlag,
|
||||||
HoleskyFlag,
|
HoleskyFlag,
|
||||||
|
HoodiFlag,
|
||||||
}
|
}
|
||||||
// NetworkFlags is the flag group of all built-in supported networks.
|
// NetworkFlags is the flag group of all built-in supported networks.
|
||||||
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
|
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
|
||||||
|
|
@ -967,6 +990,9 @@ func MakeDataDir(ctx *cli.Context) string {
|
||||||
if ctx.Bool(HoleskyFlag.Name) {
|
if ctx.Bool(HoleskyFlag.Name) {
|
||||||
return filepath.Join(path, "holesky")
|
return filepath.Join(path, "holesky")
|
||||||
}
|
}
|
||||||
|
if ctx.Bool(HoodiFlag.Name) {
|
||||||
|
return filepath.Join(path, "hoodi")
|
||||||
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
Fatalf("Cannot determine default data directory, please set manually (--datadir)")
|
Fatalf("Cannot determine default data directory, please set manually (--datadir)")
|
||||||
|
|
@ -1027,6 +1053,8 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
urls = params.HoleskyBootnodes
|
urls = params.HoleskyBootnodes
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
urls = params.SepoliaBootnodes
|
urls = params.SepoliaBootnodes
|
||||||
|
case ctx.Bool(HoodiFlag.Name):
|
||||||
|
urls = params.HoodiBootnodes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg.BootstrapNodes = mustParseBootnodes(urls)
|
cfg.BootstrapNodes = mustParseBootnodes(urls)
|
||||||
|
|
@ -1411,6 +1439,8 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) {
|
||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
|
||||||
case ctx.Bool(HoleskyFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
case ctx.Bool(HoleskyFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "holesky")
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "holesky")
|
||||||
|
case ctx.Bool(HoodiFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
||||||
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "hoodi")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1537,7 +1567,7 @@ func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
// SetEthConfig applies eth-related command line flags to the config.
|
// SetEthConfig applies eth-related command line flags to the config.
|
||||||
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// Avoid conflicting network flags
|
// Avoid conflicting network flags
|
||||||
flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag)
|
flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag, HoodiFlag)
|
||||||
flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
||||||
|
|
||||||
// Set configurations from CLI flags
|
// Set configurations from CLI flags
|
||||||
|
|
@ -1629,12 +1659,25 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
log.Warn("The flag --txlookuplimit is deprecated and will be removed, please use --history.transactions")
|
log.Warn("The flag --txlookuplimit is deprecated and will be removed, please use --history.transactions")
|
||||||
cfg.TransactionHistory = ctx.Uint64(TxLookupLimitFlag.Name)
|
cfg.TransactionHistory = ctx.Uint64(TxLookupLimitFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 {
|
if ctx.String(GCModeFlag.Name) == "archive" {
|
||||||
cfg.TransactionHistory = 0
|
if cfg.TransactionHistory != 0 {
|
||||||
log.Warn("Disabled transaction unindexing for archive node")
|
cfg.TransactionHistory = 0
|
||||||
|
log.Warn("Disabled transaction unindexing for archive node")
|
||||||
|
}
|
||||||
|
|
||||||
cfg.StateScheme = rawdb.HashScheme
|
if cfg.StateScheme != rawdb.HashScheme {
|
||||||
log.Warn("Forcing hash state-scheme for archive mode")
|
cfg.StateScheme = rawdb.HashScheme
|
||||||
|
log.Warn("Forcing hash state-scheme for archive mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ctx.IsSet(LogHistoryFlag.Name) {
|
||||||
|
cfg.LogHistory = ctx.Uint64(LogHistoryFlag.Name)
|
||||||
|
}
|
||||||
|
if ctx.IsSet(LogNoHistoryFlag.Name) {
|
||||||
|
cfg.LogNoHistory = true
|
||||||
|
}
|
||||||
|
if ctx.IsSet(LogExportCheckpointsFlag.Name) {
|
||||||
|
cfg.LogExportCheckpoints = ctx.String(LogExportCheckpointsFlag.Name)
|
||||||
}
|
}
|
||||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
||||||
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
||||||
|
|
@ -1712,6 +1755,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
}
|
}
|
||||||
cfg.Genesis = core.DefaultSepoliaGenesisBlock()
|
cfg.Genesis = core.DefaultSepoliaGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
|
||||||
|
case ctx.Bool(HoodiFlag.Name):
|
||||||
|
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||||
|
cfg.NetworkId = 560048
|
||||||
|
}
|
||||||
|
cfg.Genesis = core.DefaultHoodiGenesisBlock()
|
||||||
|
SetDNSDiscoveryDefaults(cfg, params.HoodiGenesisHash)
|
||||||
case ctx.Bool(DeveloperFlag.Name):
|
case ctx.Bool(DeveloperFlag.Name):
|
||||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||||
cfg.NetworkId = 1337
|
cfg.NetworkId = 1337
|
||||||
|
|
@ -1757,8 +1806,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// the miner will fail to start.
|
// the miner will fail to start.
|
||||||
cfg.Miner.PendingFeeRecipient = developer.Address
|
cfg.Miner.PendingFeeRecipient = developer.Address
|
||||||
|
|
||||||
if err := ks.Unlock(developer, passphrase); err != nil {
|
// try to unlock the first keystore account
|
||||||
Fatalf("Failed to unlock developer account: %v", err)
|
if len(ks.Accounts()) > 0 {
|
||||||
|
if err := ks.Unlock(developer, passphrase); err != nil {
|
||||||
|
Fatalf("Failed to unlock developer account: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Info("Using developer account", "address", developer.Address)
|
log.Info("Using developer account", "address", developer.Address)
|
||||||
|
|
||||||
|
|
@ -1823,6 +1875,8 @@ func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig {
|
||||||
config.ChainConfig = *bparams.SepoliaLightConfig
|
config.ChainConfig = *bparams.SepoliaLightConfig
|
||||||
case ctx.Bool(HoleskyFlag.Name):
|
case ctx.Bool(HoleskyFlag.Name):
|
||||||
config.ChainConfig = *bparams.HoleskyLightConfig
|
config.ChainConfig = *bparams.HoleskyLightConfig
|
||||||
|
case ctx.Bool(HoodiFlag.Name):
|
||||||
|
config.ChainConfig = *bparams.HoodiLightConfig
|
||||||
default:
|
default:
|
||||||
if !customConfig {
|
if !customConfig {
|
||||||
config.ChainConfig = *bparams.MainnetLightConfig
|
config.ChainConfig = *bparams.MainnetLightConfig
|
||||||
|
|
@ -2026,7 +2080,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
|
||||||
}
|
}
|
||||||
chainDb = remotedb.New(client)
|
chainDb = remotedb.New(client)
|
||||||
default:
|
default:
|
||||||
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly)
|
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "eth/db/chaindata/", readonly)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Could not open database: %v", err)
|
Fatalf("Could not open database: %v", err)
|
||||||
|
|
@ -2089,6 +2143,8 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
|
||||||
genesis = core.DefaultHoleskyGenesisBlock()
|
genesis = core.DefaultHoleskyGenesisBlock()
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
genesis = core.DefaultSepoliaGenesisBlock()
|
genesis = core.DefaultSepoliaGenesisBlock()
|
||||||
|
case ctx.Bool(HoodiFlag.Name):
|
||||||
|
genesis = core.DefaultHoodiGenesisBlock()
|
||||||
case ctx.Bool(DeveloperFlag.Name):
|
case ctx.Bool(DeveloperFlag.Name):
|
||||||
Fatalf("Developer chains are ephemeral")
|
Fatalf("Developer chains are ephemeral")
|
||||||
}
|
}
|
||||||
|
|
@ -2133,6 +2189,8 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
}
|
}
|
||||||
if !ctx.Bool(SnapshotFlag.Name) {
|
if !ctx.Bool(SnapshotFlag.Name) {
|
||||||
cache.SnapshotLimit = 0 // Disabled
|
cache.SnapshotLimit = 0 // Disabled
|
||||||
|
} else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
|
||||||
|
cache.SnapshotLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100
|
||||||
}
|
}
|
||||||
// If we're in readonly, do not bother generating snapshot data.
|
// If we're in readonly, do not bother generating snapshot data.
|
||||||
if readonly {
|
if readonly {
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,9 @@ func (s *filterTestSuite) filterFullRange(t *utesting.T) {
|
||||||
|
|
||||||
func (s *filterTestSuite) queryAndCheck(t *utesting.T, query *filterQuery) {
|
func (s *filterTestSuite) queryAndCheck(t *utesting.T, query *filterQuery) {
|
||||||
query.run(s.cfg.client, s.cfg.historyPruneBlock)
|
query.run(s.cfg.client, s.cfg.historyPruneBlock)
|
||||||
|
if query.Err == errPrunedHistory {
|
||||||
|
return
|
||||||
|
}
|
||||||
if query.Err != nil {
|
if query.Err != nil {
|
||||||
t.Errorf("Filter query failed (fromBlock: %d toBlock: %d addresses: %v topics: %v error: %v)", query.FromBlock, query.ToBlock, query.Address, query.Topics, query.Err)
|
t.Errorf("Filter query failed (fromBlock: %d toBlock: %d addresses: %v topics: %v error: %v)", query.FromBlock, query.ToBlock, query.Address, query.Topics, query.Err)
|
||||||
return
|
return
|
||||||
|
|
@ -126,6 +129,9 @@ func (s *filterTestSuite) fullRangeQueryAndCheck(t *utesting.T, query *filterQue
|
||||||
Topics: query.Topics,
|
Topics: query.Topics,
|
||||||
}
|
}
|
||||||
frQuery.run(s.cfg.client, s.cfg.historyPruneBlock)
|
frQuery.run(s.cfg.client, s.cfg.historyPruneBlock)
|
||||||
|
if frQuery.Err == errPrunedHistory {
|
||||||
|
return
|
||||||
|
}
|
||||||
if frQuery.Err != nil {
|
if frQuery.Err != nil {
|
||||||
t.Errorf("Full range filter query failed (addresses: %v topics: %v error: %v)", frQuery.Address, frQuery.Topics, frQuery.Err)
|
t.Errorf("Full range filter query failed (addresses: %v topics: %v error: %v)", frQuery.Address, frQuery.Topics, frQuery.Err)
|
||||||
return
|
return
|
||||||
|
|
@ -206,14 +212,11 @@ func (fq *filterQuery) run(client *client, historyPruneBlock *uint64) {
|
||||||
Addresses: fq.Address,
|
Addresses: fq.Address,
|
||||||
Topics: fq.Topics,
|
Topics: fq.Topics,
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
if err = validateHistoryPruneErr(fq.Err, uint64(fq.FromBlock), historyPruneBlock); err == errPrunedHistory {
|
|
||||||
return
|
|
||||||
} else if err != nil {
|
|
||||||
fmt.Printf("Filter query failed: fromBlock: %d toBlock: %d addresses: %v topics: %v error: %v\n",
|
|
||||||
fq.FromBlock, fq.ToBlock, fq.Address, fq.Topics, err)
|
|
||||||
}
|
|
||||||
fq.Err = err
|
|
||||||
}
|
|
||||||
fq.results = logs
|
fq.results = logs
|
||||||
|
fq.Err = validateHistoryPruneErr(err, uint64(fq.FromBlock), historyPruneBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fq *filterQuery) printError() {
|
||||||
|
fmt.Printf("Filter query failed: fromBlock: %d toBlock: %d addresses: %v topics: %v error: %v\n",
|
||||||
|
fq.FromBlock, fq.ToBlock, fq.Address, fq.Topics, fq.Err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ var (
|
||||||
Action: filterGenCmd,
|
Action: filterGenCmd,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
filterQueryFileFlag,
|
filterQueryFileFlag,
|
||||||
filterErrorFileFlag,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
filterQueryFileFlag = &cli.StringFlag{
|
filterQueryFileFlag = &cli.StringFlag{
|
||||||
|
|
@ -72,8 +71,8 @@ func filterGenCmd(ctx *cli.Context) error {
|
||||||
query := f.newQuery()
|
query := f.newQuery()
|
||||||
query.run(f.client, nil)
|
query.run(f.client, nil)
|
||||||
if query.Err != nil {
|
if query.Err != nil {
|
||||||
f.errors = append(f.errors, query)
|
query.printError()
|
||||||
continue
|
exit("filter query failed")
|
||||||
}
|
}
|
||||||
if len(query.results) > 0 && len(query.results) <= maxFilterResultSize {
|
if len(query.results) > 0 && len(query.results) <= maxFilterResultSize {
|
||||||
for {
|
for {
|
||||||
|
|
@ -90,8 +89,8 @@ func filterGenCmd(ctx *cli.Context) error {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if extQuery.Err != nil {
|
if extQuery.Err != nil {
|
||||||
f.errors = append(f.errors, extQuery)
|
extQuery.printError()
|
||||||
break
|
exit("filter query failed")
|
||||||
}
|
}
|
||||||
if len(extQuery.results) > maxFilterResultSize {
|
if len(extQuery.results) > maxFilterResultSize {
|
||||||
break
|
break
|
||||||
|
|
@ -101,7 +100,6 @@ func filterGenCmd(ctx *cli.Context) error {
|
||||||
f.storeQuery(query)
|
f.storeQuery(query)
|
||||||
if time.Since(lastWrite) > time.Second*10 {
|
if time.Since(lastWrite) > time.Second*10 {
|
||||||
f.writeQueries()
|
f.writeQueries()
|
||||||
f.writeErrors()
|
|
||||||
lastWrite = time.Now()
|
lastWrite = time.Now()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -112,18 +110,15 @@ func filterGenCmd(ctx *cli.Context) error {
|
||||||
type filterTestGen struct {
|
type filterTestGen struct {
|
||||||
client *client
|
client *client
|
||||||
queryFile string
|
queryFile string
|
||||||
errorFile string
|
|
||||||
|
|
||||||
finalizedBlock int64
|
finalizedBlock int64
|
||||||
queries [filterBuckets][]*filterQuery
|
queries [filterBuckets][]*filterQuery
|
||||||
errors []*filterQuery
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFilterTestGen(ctx *cli.Context) *filterTestGen {
|
func newFilterTestGen(ctx *cli.Context) *filterTestGen {
|
||||||
return &filterTestGen{
|
return &filterTestGen{
|
||||||
client: makeClient(ctx),
|
client: makeClient(ctx),
|
||||||
queryFile: ctx.String(filterQueryFileFlag.Name),
|
queryFile: ctx.String(filterQueryFileFlag.Name),
|
||||||
errorFile: ctx.String(filterErrorFileFlag.Name),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,17 +355,6 @@ func (s *filterTestGen) writeQueries() {
|
||||||
file.Close()
|
file.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeQueries serializes the generated errors to the error file.
|
|
||||||
func (s *filterTestGen) writeErrors() {
|
|
||||||
file, err := os.Create(s.errorFile)
|
|
||||||
if err != nil {
|
|
||||||
exit(fmt.Errorf("Error creating filter error file %s: %v", s.errorFile, err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
json.NewEncoder(file).Encode(s.errors)
|
|
||||||
}
|
|
||||||
|
|
||||||
func mustGetFinalizedBlock(client *client) int64 {
|
func mustGetFinalizedBlock(client *client) int64 {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,10 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -41,7 +43,7 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const passCount = 1
|
const passCount = 3
|
||||||
|
|
||||||
func filterPerfCmd(ctx *cli.Context) error {
|
func filterPerfCmd(ctx *cli.Context) error {
|
||||||
cfg := testConfigFromCLI(ctx)
|
cfg := testConfigFromCLI(ctx)
|
||||||
|
|
@ -61,7 +63,10 @@ func filterPerfCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run test queries.
|
// Run test queries.
|
||||||
var failed, mismatch int
|
var (
|
||||||
|
failed, pruned, mismatch int
|
||||||
|
errors []*filterQuery
|
||||||
|
)
|
||||||
for i := 1; i <= passCount; i++ {
|
for i := 1; i <= passCount; i++ {
|
||||||
fmt.Println("Performance test pass", i, "/", passCount)
|
fmt.Println("Performance test pass", i, "/", passCount)
|
||||||
for len(queries) > 0 {
|
for len(queries) > 0 {
|
||||||
|
|
@ -71,27 +76,35 @@ func filterPerfCmd(ctx *cli.Context) error {
|
||||||
queries = queries[:len(queries)-1]
|
queries = queries[:len(queries)-1]
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
qt.query.run(cfg.client, cfg.historyPruneBlock)
|
qt.query.run(cfg.client, cfg.historyPruneBlock)
|
||||||
|
if qt.query.Err == errPrunedHistory {
|
||||||
|
pruned++
|
||||||
|
continue
|
||||||
|
}
|
||||||
qt.runtime = append(qt.runtime, time.Since(start))
|
qt.runtime = append(qt.runtime, time.Since(start))
|
||||||
slices.Sort(qt.runtime)
|
slices.Sort(qt.runtime)
|
||||||
qt.medianTime = qt.runtime[len(qt.runtime)/2]
|
qt.medianTime = qt.runtime[len(qt.runtime)/2]
|
||||||
if qt.query.Err != nil {
|
if qt.query.Err != nil {
|
||||||
|
qt.query.printError()
|
||||||
|
errors = append(errors, qt.query)
|
||||||
failed++
|
failed++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if rhash := qt.query.calculateHash(); *qt.query.ResultHash != rhash {
|
if rhash := qt.query.calculateHash(); *qt.query.ResultHash != rhash {
|
||||||
fmt.Printf("Filter query result mismatch: fromBlock: %d toBlock: %d addresses: %v topics: %v expected hash: %064x calculated hash: %064x\n", qt.query.FromBlock, qt.query.ToBlock, qt.query.Address, qt.query.Topics, *qt.query.ResultHash, rhash)
|
fmt.Printf("Filter query result mismatch: fromBlock: %d toBlock: %d addresses: %v topics: %v expected hash: %064x calculated hash: %064x\n", qt.query.FromBlock, qt.query.ToBlock, qt.query.Address, qt.query.Topics, *qt.query.ResultHash, rhash)
|
||||||
|
errors = append(errors, qt.query)
|
||||||
|
mismatch++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
processed = append(processed, qt)
|
processed = append(processed, qt)
|
||||||
if len(processed)%50 == 0 {
|
if len(processed)%50 == 0 {
|
||||||
fmt.Println(" processed:", len(processed), "remaining", len(queries), "failed:", failed, "result mismatch:", mismatch)
|
fmt.Println(" processed:", len(processed), "remaining", len(queries), "failed:", failed, "pruned:", pruned, "result mismatch:", mismatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
queries, processed = processed, nil
|
queries, processed = processed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show results and stats.
|
// Show results and stats.
|
||||||
fmt.Println("Performance test finished; processed:", len(queries), "failed:", failed, "result mismatch:", mismatch)
|
fmt.Println("Performance test finished; processed:", len(queries), "failed:", failed, "pruned:", pruned, "result mismatch:", mismatch)
|
||||||
stats := make([]bucketStats, len(f.queries))
|
stats := make([]bucketStats, len(f.queries))
|
||||||
var wildcardStats bucketStats
|
var wildcardStats bucketStats
|
||||||
for _, qt := range queries {
|
for _, qt := range queries {
|
||||||
|
|
@ -114,11 +127,14 @@ func filterPerfCmd(ctx *cli.Context) error {
|
||||||
sort.Slice(queries, func(i, j int) bool {
|
sort.Slice(queries, func(i, j int) bool {
|
||||||
return queries[i].medianTime > queries[j].medianTime
|
return queries[i].medianTime > queries[j].medianTime
|
||||||
})
|
})
|
||||||
for i := 0; i < 10; i++ {
|
for i, q := range queries {
|
||||||
q := queries[i]
|
if i >= 10 {
|
||||||
|
break
|
||||||
|
}
|
||||||
fmt.Printf("Most expensive query #%-2d median runtime: %13v max runtime: %13v result count: %4d fromBlock: %9d toBlock: %9d addresses: %v topics: %v\n",
|
fmt.Printf("Most expensive query #%-2d median runtime: %13v max runtime: %13v result count: %4d fromBlock: %9d toBlock: %9d addresses: %v topics: %v\n",
|
||||||
i+1, q.medianTime, q.runtime[len(q.runtime)-1], len(q.query.results), q.query.FromBlock, q.query.ToBlock, q.query.Address, q.query.Topics)
|
i+1, q.medianTime, q.runtime[len(q.runtime)-1], len(q.query.results), q.query.FromBlock, q.query.ToBlock, q.query.Address, q.query.Topics)
|
||||||
}
|
}
|
||||||
|
writeErrors(ctx.String(filterErrorFileFlag.Name), errors)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,3 +151,14 @@ func (st *bucketStats) print(name string) {
|
||||||
fmt.Printf("%-20s queries: %4d average block length: %12.2f average log count: %7.2f average runtime: %13v\n",
|
fmt.Printf("%-20s queries: %4d average block length: %12.2f average log count: %7.2f average runtime: %13v\n",
|
||||||
name, st.count, float64(st.blocks)/float64(st.count), float64(st.logs)/float64(st.count), st.runtime/time.Duration(st.count))
|
name, st.count, float64(st.blocks)/float64(st.count), float64(st.logs)/float64(st.count), st.runtime/time.Duration(st.count))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeQueries serializes the generated errors to the error file.
|
||||||
|
func writeErrors(errorFile string, errors []*filterQuery) {
|
||||||
|
file, err := os.Create(errorFile)
|
||||||
|
if err != nil {
|
||||||
|
exit(fmt.Errorf("Error creating filter error file %s: %v", errorFile, err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
json.NewEncoder(file).Encode(errors)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ func (i *HexOrDecimal256) MarshalText() ([]byte, error) {
|
||||||
if i == nil {
|
if i == nil {
|
||||||
return []byte("0x0"), nil
|
return []byte("0x0"), nil
|
||||||
}
|
}
|
||||||
return []byte(fmt.Sprintf("%#x", (*big.Int)(i))), nil
|
return fmt.Appendf(nil, "%#x", (*big.Int)(i)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decimal256 unmarshals big.Int as a decimal string. When unmarshalling,
|
// Decimal256 unmarshals big.Int as a decimal string. When unmarshalling,
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ func (i *HexOrDecimal64) UnmarshalText(input []byte) error {
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (i HexOrDecimal64) MarshalText() ([]byte, error) {
|
func (i HexOrDecimal64) MarshalText() ([]byte, error) {
|
||||||
return []byte(fmt.Sprintf("%#x", uint64(i))), nil
|
return fmt.Appendf(nil, "%#x", uint64(i)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseUint64 parses s as an integer in decimal or hexadecimal syntax.
|
// ParseUint64 parses s as an integer in decimal or hexadecimal syntax.
|
||||||
|
|
|
||||||
115
common/range.go
Normal file
115
common/range.go
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
// Copyright 2025 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"iter"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Range represents a range of integers.
|
||||||
|
type Range[T uint32 | uint64] struct {
|
||||||
|
first, afterLast T
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRange creates a new range based of first element and number of elements.
|
||||||
|
func NewRange[T uint32 | uint64](first, count T) Range[T] {
|
||||||
|
return Range[T]{first, first + count}
|
||||||
|
}
|
||||||
|
|
||||||
|
// First returns the first element of the range.
|
||||||
|
func (r Range[T]) First() T {
|
||||||
|
return r.first
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last returns the last element of the range. This panics for empty ranges.
|
||||||
|
func (r Range[T]) Last() T {
|
||||||
|
if r.first == r.afterLast {
|
||||||
|
panic("last item of zero length range is not allowed")
|
||||||
|
}
|
||||||
|
return r.afterLast - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterLast returns the first element after the range. This allows obtaining
|
||||||
|
// information about the end part of zero length ranges.
|
||||||
|
func (r Range[T]) AfterLast() T {
|
||||||
|
return r.afterLast
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of elements in the range.
|
||||||
|
func (r Range[T]) Count() T {
|
||||||
|
return r.afterLast - r.first
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns true if the range is empty.
|
||||||
|
func (r Range[T]) IsEmpty() bool {
|
||||||
|
return r.first == r.afterLast
|
||||||
|
}
|
||||||
|
|
||||||
|
// Includes returns true if the given element is inside the range.
|
||||||
|
func (r Range[T]) Includes(v T) bool {
|
||||||
|
return v >= r.first && v < r.afterLast
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFirst updates the first element of the list.
|
||||||
|
func (r *Range[T]) SetFirst(v T) {
|
||||||
|
r.first = v
|
||||||
|
if r.afterLast < r.first {
|
||||||
|
r.afterLast = r.first
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAfterLast updates the end of the range by specifying the first element
|
||||||
|
// after the range. This allows setting zero length ranges.
|
||||||
|
func (r *Range[T]) SetAfterLast(v T) {
|
||||||
|
r.afterLast = v
|
||||||
|
if r.afterLast < r.first {
|
||||||
|
r.first = r.afterLast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLast updates last element of the range.
|
||||||
|
func (r *Range[T]) SetLast(v T) {
|
||||||
|
r.SetAfterLast(v + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection returns the intersection of two ranges.
|
||||||
|
func (r Range[T]) Intersection(q Range[T]) Range[T] {
|
||||||
|
i := Range[T]{first: max(r.first, q.first), afterLast: min(r.afterLast, q.afterLast)}
|
||||||
|
if i.first > i.afterLast {
|
||||||
|
return Range[T]{}
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union returns the union of two ranges. Panics for gapped ranges.
|
||||||
|
func (r Range[T]) Union(q Range[T]) Range[T] {
|
||||||
|
if max(r.first, q.first) > min(r.afterLast, q.afterLast) {
|
||||||
|
panic("cannot create union; gap between ranges")
|
||||||
|
}
|
||||||
|
return Range[T]{first: min(r.first, q.first), afterLast: max(r.afterLast, q.afterLast)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iter iterates all integers in the range.
|
||||||
|
func (r Range[T]) Iter() iter.Seq[T] {
|
||||||
|
return func(yield func(T) bool) {
|
||||||
|
for i := r.first; i < r.afterLast; i++ {
|
||||||
|
if !yield(i) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
// Copyright 2025 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -14,5 +14,23 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Package bloombits implements bloom filtering on batches of data.
|
package common
|
||||||
package bloombits
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRangeIter(t *testing.T) {
|
||||||
|
r := NewRange[uint32](1, 7)
|
||||||
|
values := slices.Collect(r.Iter())
|
||||||
|
if !slices.Equal(values, []uint32{1, 2, 3, 4, 5, 6, 7}) {
|
||||||
|
t.Fatalf("wrong iter values: %v", values)
|
||||||
|
}
|
||||||
|
|
||||||
|
empty := NewRange[uint32](1, 0)
|
||||||
|
values = slices.Collect(empty.Iter())
|
||||||
|
if !slices.Equal(values, []uint32{}) {
|
||||||
|
t.Fatalf("wrong iter values: %v", values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -332,7 +332,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
||||||
bc.processor = NewStateProcessor(chainConfig, bc.hc)
|
bc.processor = NewStateProcessor(chainConfig, bc.hc)
|
||||||
|
|
||||||
bc.genesisBlock = bc.GetBlockByNumber(0)
|
genesisHeader := bc.GetHeaderByNumber(0)
|
||||||
|
bc.genesisBlock = types.NewBlockWithHeader(genesisHeader)
|
||||||
if bc.genesisBlock == nil {
|
if bc.genesisBlock == nil {
|
||||||
return nil, ErrNoGenesis
|
return nil, ErrNoGenesis
|
||||||
}
|
}
|
||||||
|
|
@ -906,7 +907,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||||
rawdb.DeleteBody(db, hash, num)
|
rawdb.DeleteBody(db, hash, num)
|
||||||
rawdb.DeleteReceipts(db, hash, num)
|
rawdb.DeleteReceipts(db, hash, num)
|
||||||
}
|
}
|
||||||
// Todo(rjl493456442) txlookup, bloombits, etc
|
// Todo(rjl493456442) txlookup, log index, etc
|
||||||
}
|
}
|
||||||
// If SetHead was only called as a chain reparation method, try to skip
|
// If SetHead was only called as a chain reparation method, try to skip
|
||||||
// touching the header chain altogether, unless the freezer is broken
|
// touching the header chain altogether, unless the freezer is broken
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,11 @@ func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
|
||||||
return bc.hc.GetHeaderByNumber(number)
|
return bc.hc.GetHeaderByNumber(number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBlockNumber retrieves the block number associated with a block hash.
|
||||||
|
func (bc *BlockChain) GetBlockNumber(hash common.Hash) *uint64 {
|
||||||
|
return bc.hc.GetBlockNumber(hash)
|
||||||
|
}
|
||||||
|
|
||||||
// GetHeadersFrom returns a contiguous segment of headers, in rlp-form, going
|
// GetHeadersFrom returns a contiguous segment of headers, in rlp-form, going
|
||||||
// backwards from the given number.
|
// backwards from the given number.
|
||||||
func (bc *BlockChain) GetHeadersFrom(number, count uint64) []rlp.RawValue {
|
func (bc *BlockChain) GetHeadersFrom(number, count uint64) []rlp.RawValue {
|
||||||
|
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
// Copyright 2021 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/bitutil"
|
|
||||||
"github.com/ethereum/go-ethereum/core/bloombits"
|
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// bloomThrottling is the time to wait between processing two consecutive index
|
|
||||||
// sections. It's useful during chain upgrades to prevent disk overload.
|
|
||||||
bloomThrottling = 100 * time.Millisecond
|
|
||||||
)
|
|
||||||
|
|
||||||
// BloomIndexer implements a core.ChainIndexer, building up a rotated bloom bits index
|
|
||||||
// for the Ethereum header bloom filters, permitting blazing fast filtering.
|
|
||||||
type BloomIndexer struct {
|
|
||||||
size uint64 // section size to generate bloombits for
|
|
||||||
db ethdb.Database // database instance to write index data and metadata into
|
|
||||||
gen *bloombits.Generator // generator to rotate the bloom bits crating the bloom index
|
|
||||||
section uint64 // Section is the section number being processed currently
|
|
||||||
head common.Hash // Head is the hash of the last header processed
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBloomIndexer returns a chain indexer that generates bloom bits data for the
|
|
||||||
// canonical chain for fast logs filtering.
|
|
||||||
func NewBloomIndexer(db ethdb.Database, size, confirms uint64) *ChainIndexer {
|
|
||||||
backend := &BloomIndexer{
|
|
||||||
db: db,
|
|
||||||
size: size,
|
|
||||||
}
|
|
||||||
table := rawdb.NewTable(db, string(rawdb.BloomBitsIndexPrefix))
|
|
||||||
|
|
||||||
return NewChainIndexer(db, table, backend, size, confirms, bloomThrottling, "bloombits")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset implements core.ChainIndexerBackend, starting a new bloombits index
|
|
||||||
// section.
|
|
||||||
func (b *BloomIndexer) Reset(ctx context.Context, section uint64, lastSectionHead common.Hash) error {
|
|
||||||
gen, err := bloombits.NewGenerator(uint(b.size))
|
|
||||||
b.gen, b.section, b.head = gen, section, common.Hash{}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process implements core.ChainIndexerBackend, adding a new header's bloom into
|
|
||||||
// the index.
|
|
||||||
func (b *BloomIndexer) Process(ctx context.Context, header *types.Header) error {
|
|
||||||
b.gen.AddBloom(uint(header.Number.Uint64()-b.section*b.size), header.Bloom)
|
|
||||||
b.head = header.Hash()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit implements core.ChainIndexerBackend, finalizing the bloom section and
|
|
||||||
// writing it out into the database.
|
|
||||||
func (b *BloomIndexer) Commit() error {
|
|
||||||
batch := b.db.NewBatchWithSize((int(b.size) / 8) * types.BloomBitLength)
|
|
||||||
for i := 0; i < types.BloomBitLength; i++ {
|
|
||||||
bits, err := b.gen.Bitset(uint(i))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rawdb.WriteBloomBits(batch, uint(i), b.section, b.head, bitutil.CompressBytes(bits))
|
|
||||||
}
|
|
||||||
return batch.Write()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prune returns an empty error since we don't support pruning here.
|
|
||||||
func (b *BloomIndexer) Prune(threshold uint64) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package bloombits
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// errSectionOutOfBounds is returned if the user tried to add more bloom filters
|
|
||||||
// to the batch than available space, or if tries to retrieve above the capacity.
|
|
||||||
errSectionOutOfBounds = errors.New("section out of bounds")
|
|
||||||
|
|
||||||
// errBloomBitOutOfBounds is returned if the user tried to retrieve specified
|
|
||||||
// bit bloom above the capacity.
|
|
||||||
errBloomBitOutOfBounds = errors.New("bloom bit out of bounds")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Generator takes a number of bloom filters and generates the rotated bloom bits
|
|
||||||
// to be used for batched filtering.
|
|
||||||
type Generator struct {
|
|
||||||
blooms [types.BloomBitLength][]byte // Rotated blooms for per-bit matching
|
|
||||||
sections uint // Number of sections to batch together
|
|
||||||
nextSec uint // Next section to set when adding a bloom
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGenerator creates a rotated bloom generator that can iteratively fill a
|
|
||||||
// batched bloom filter's bits.
|
|
||||||
func NewGenerator(sections uint) (*Generator, error) {
|
|
||||||
if sections%8 != 0 {
|
|
||||||
return nil, errors.New("section count not multiple of 8")
|
|
||||||
}
|
|
||||||
b := &Generator{sections: sections}
|
|
||||||
for i := 0; i < types.BloomBitLength; i++ {
|
|
||||||
b.blooms[i] = make([]byte, sections/8)
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddBloom takes a single bloom filter and sets the corresponding bit column
|
|
||||||
// in memory accordingly.
|
|
||||||
func (b *Generator) AddBloom(index uint, bloom types.Bloom) error {
|
|
||||||
// Make sure we're not adding more bloom filters than our capacity
|
|
||||||
if b.nextSec >= b.sections {
|
|
||||||
return errSectionOutOfBounds
|
|
||||||
}
|
|
||||||
if b.nextSec != index {
|
|
||||||
return errors.New("bloom filter with unexpected index")
|
|
||||||
}
|
|
||||||
// Rotate the bloom and insert into our collection
|
|
||||||
byteIndex := b.nextSec / 8
|
|
||||||
bitIndex := byte(7 - b.nextSec%8)
|
|
||||||
for byt := 0; byt < types.BloomByteLength; byt++ {
|
|
||||||
bloomByte := bloom[types.BloomByteLength-1-byt]
|
|
||||||
if bloomByte == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
base := 8 * byt
|
|
||||||
b.blooms[base+7][byteIndex] |= ((bloomByte >> 7) & 1) << bitIndex
|
|
||||||
b.blooms[base+6][byteIndex] |= ((bloomByte >> 6) & 1) << bitIndex
|
|
||||||
b.blooms[base+5][byteIndex] |= ((bloomByte >> 5) & 1) << bitIndex
|
|
||||||
b.blooms[base+4][byteIndex] |= ((bloomByte >> 4) & 1) << bitIndex
|
|
||||||
b.blooms[base+3][byteIndex] |= ((bloomByte >> 3) & 1) << bitIndex
|
|
||||||
b.blooms[base+2][byteIndex] |= ((bloomByte >> 2) & 1) << bitIndex
|
|
||||||
b.blooms[base+1][byteIndex] |= ((bloomByte >> 1) & 1) << bitIndex
|
|
||||||
b.blooms[base][byteIndex] |= (bloomByte & 1) << bitIndex
|
|
||||||
}
|
|
||||||
b.nextSec++
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bitset returns the bit vector belonging to the given bit index after all
|
|
||||||
// blooms have been added.
|
|
||||||
func (b *Generator) Bitset(idx uint) ([]byte, error) {
|
|
||||||
if b.nextSec != b.sections {
|
|
||||||
return nil, errors.New("bloom not fully generated yet")
|
|
||||||
}
|
|
||||||
if idx >= types.BloomBitLength {
|
|
||||||
return nil, errBloomBitOutOfBounds
|
|
||||||
}
|
|
||||||
return b.blooms[idx], nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package bloombits
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
crand "crypto/rand"
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Tests that batched bloom bits are correctly rotated from the input bloom
|
|
||||||
// filters.
|
|
||||||
func TestGenerator(t *testing.T) {
|
|
||||||
// Generate the input and the rotated output
|
|
||||||
var input, output [types.BloomBitLength][types.BloomByteLength]byte
|
|
||||||
|
|
||||||
for i := 0; i < types.BloomBitLength; i++ {
|
|
||||||
for j := 0; j < types.BloomBitLength; j++ {
|
|
||||||
bit := byte(rand.Int() % 2)
|
|
||||||
|
|
||||||
input[i][j/8] |= bit << byte(7-j%8)
|
|
||||||
output[types.BloomBitLength-1-j][i/8] |= bit << byte(7-i%8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Crunch the input through the generator and verify the result
|
|
||||||
gen, err := NewGenerator(types.BloomBitLength)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to create bloombit generator: %v", err)
|
|
||||||
}
|
|
||||||
for i, bloom := range input {
|
|
||||||
if err := gen.AddBloom(uint(i), bloom); err != nil {
|
|
||||||
t.Fatalf("bloom %d: failed to add: %v", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i, want := range output {
|
|
||||||
have, err := gen.Bitset(uint(i))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("output %d: failed to retrieve bits: %v", i, err)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(have, want[:]) {
|
|
||||||
t.Errorf("output %d: bit vector mismatch have %x, want %x", i, have, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkGenerator(b *testing.B) {
|
|
||||||
var input [types.BloomBitLength][types.BloomByteLength]byte
|
|
||||||
b.Run("empty", func(b *testing.B) {
|
|
||||||
b.ReportAllocs()
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
// Crunch the input through the generator and verify the result
|
|
||||||
gen, err := NewGenerator(types.BloomBitLength)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatalf("failed to create bloombit generator: %v", err)
|
|
||||||
}
|
|
||||||
for j, bloom := range &input {
|
|
||||||
if err := gen.AddBloom(uint(j), bloom); err != nil {
|
|
||||||
b.Fatalf("bloom %d: failed to add: %v", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
for i := 0; i < types.BloomBitLength; i++ {
|
|
||||||
crand.Read(input[i][:])
|
|
||||||
}
|
|
||||||
b.Run("random", func(b *testing.B) {
|
|
||||||
b.ReportAllocs()
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
// Crunch the input through the generator and verify the result
|
|
||||||
gen, err := NewGenerator(types.BloomBitLength)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatalf("failed to create bloombit generator: %v", err)
|
|
||||||
}
|
|
||||||
for j, bloom := range &input {
|
|
||||||
if err := gen.AddBloom(uint(j), bloom); err != nil {
|
|
||||||
b.Fatalf("bloom %d: failed to add: %v", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,649 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package bloombits
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"math"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/bitutil"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
)
|
|
||||||
|
|
||||||
// bloomIndexes represents the bit indexes inside the bloom filter that belong
|
|
||||||
// to some key.
|
|
||||||
type bloomIndexes [3]uint
|
|
||||||
|
|
||||||
// calcBloomIndexes returns the bloom filter bit indexes belonging to the given key.
|
|
||||||
func calcBloomIndexes(b []byte) bloomIndexes {
|
|
||||||
b = crypto.Keccak256(b)
|
|
||||||
|
|
||||||
var idxs bloomIndexes
|
|
||||||
for i := 0; i < len(idxs); i++ {
|
|
||||||
idxs[i] = (uint(b[2*i])<<8)&2047 + uint(b[2*i+1])
|
|
||||||
}
|
|
||||||
return idxs
|
|
||||||
}
|
|
||||||
|
|
||||||
// partialMatches with a non-nil vector represents a section in which some sub-
|
|
||||||
// matchers have already found potential matches. Subsequent sub-matchers will
|
|
||||||
// binary AND their matches with this vector. If vector is nil, it represents a
|
|
||||||
// section to be processed by the first sub-matcher.
|
|
||||||
type partialMatches struct {
|
|
||||||
section uint64
|
|
||||||
bitset []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieval represents a request for retrieval task assignments for a given
|
|
||||||
// bit with the given number of fetch elements, or a response for such a request.
|
|
||||||
// It can also have the actual results set to be used as a delivery data struct.
|
|
||||||
//
|
|
||||||
// The context and error fields are used by the light client to terminate matching
|
|
||||||
// early if an error is encountered on some path of the pipeline.
|
|
||||||
type Retrieval struct {
|
|
||||||
Bit uint
|
|
||||||
Sections []uint64
|
|
||||||
Bitsets [][]byte
|
|
||||||
|
|
||||||
Context context.Context
|
|
||||||
Error error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matcher is a pipelined system of schedulers and logic matchers which perform
|
|
||||||
// binary AND/OR operations on the bit-streams, creating a stream of potential
|
|
||||||
// blocks to inspect for data content.
|
|
||||||
type Matcher struct {
|
|
||||||
sectionSize uint64 // Size of the data batches to filter on
|
|
||||||
|
|
||||||
filters [][]bloomIndexes // Filter the system is matching for
|
|
||||||
schedulers map[uint]*scheduler // Retrieval schedulers for loading bloom bits
|
|
||||||
|
|
||||||
retrievers chan chan uint // Retriever processes waiting for bit allocations
|
|
||||||
counters chan chan uint // Retriever processes waiting for task count reports
|
|
||||||
retrievals chan chan *Retrieval // Retriever processes waiting for task allocations
|
|
||||||
deliveries chan *Retrieval // Retriever processes waiting for task response deliveries
|
|
||||||
|
|
||||||
running atomic.Bool // Atomic flag whether a session is live or not
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMatcher creates a new pipeline for retrieving bloom bit streams and doing
|
|
||||||
// address and topic filtering on them. Setting a filter component to `nil` is
|
|
||||||
// allowed and will result in that filter rule being skipped (OR 0x11...1).
|
|
||||||
func NewMatcher(sectionSize uint64, filters [][][]byte) *Matcher {
|
|
||||||
// Create the matcher instance
|
|
||||||
m := &Matcher{
|
|
||||||
sectionSize: sectionSize,
|
|
||||||
schedulers: make(map[uint]*scheduler),
|
|
||||||
retrievers: make(chan chan uint),
|
|
||||||
counters: make(chan chan uint),
|
|
||||||
retrievals: make(chan chan *Retrieval),
|
|
||||||
deliveries: make(chan *Retrieval),
|
|
||||||
}
|
|
||||||
// Calculate the bloom bit indexes for the groups we're interested in
|
|
||||||
m.filters = nil
|
|
||||||
|
|
||||||
for _, filter := range filters {
|
|
||||||
// Gather the bit indexes of the filter rule, special casing the nil filter
|
|
||||||
if len(filter) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
bloomBits := make([]bloomIndexes, len(filter))
|
|
||||||
for i, clause := range filter {
|
|
||||||
if clause == nil {
|
|
||||||
bloomBits = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
bloomBits[i] = calcBloomIndexes(clause)
|
|
||||||
}
|
|
||||||
// Accumulate the filter rules if no nil rule was within
|
|
||||||
if bloomBits != nil {
|
|
||||||
m.filters = append(m.filters, bloomBits)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// For every bit, create a scheduler to load/download the bit vectors
|
|
||||||
for _, bloomIndexLists := range m.filters {
|
|
||||||
for _, bloomIndexList := range bloomIndexLists {
|
|
||||||
for _, bloomIndex := range bloomIndexList {
|
|
||||||
m.addScheduler(bloomIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// addScheduler adds a bit stream retrieval scheduler for the given bit index if
|
|
||||||
// it has not existed before. If the bit is already selected for filtering, the
|
|
||||||
// existing scheduler can be used.
|
|
||||||
func (m *Matcher) addScheduler(idx uint) {
|
|
||||||
if _, ok := m.schedulers[idx]; ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.schedulers[idx] = newScheduler(idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start starts the matching process and returns a stream of bloom matches in
|
|
||||||
// a given range of blocks. If there are no more matches in the range, the result
|
|
||||||
// channel is closed.
|
|
||||||
func (m *Matcher) Start(ctx context.Context, begin, end uint64, results chan uint64) (*MatcherSession, error) {
|
|
||||||
// Make sure we're not creating concurrent sessions
|
|
||||||
if m.running.Swap(true) {
|
|
||||||
return nil, errors.New("matcher already running")
|
|
||||||
}
|
|
||||||
defer m.running.Store(false)
|
|
||||||
|
|
||||||
// Initiate a new matching round
|
|
||||||
session := &MatcherSession{
|
|
||||||
matcher: m,
|
|
||||||
quit: make(chan struct{}),
|
|
||||||
ctx: ctx,
|
|
||||||
}
|
|
||||||
for _, scheduler := range m.schedulers {
|
|
||||||
scheduler.reset()
|
|
||||||
}
|
|
||||||
sink := m.run(begin, end, cap(results), session)
|
|
||||||
|
|
||||||
// Read the output from the result sink and deliver to the user
|
|
||||||
session.pend.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer session.pend.Done()
|
|
||||||
defer close(results)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
|
|
||||||
case res, ok := <-sink:
|
|
||||||
// New match result found
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Calculate the first and last blocks of the section
|
|
||||||
sectionStart := res.section * m.sectionSize
|
|
||||||
|
|
||||||
first := sectionStart
|
|
||||||
if begin > first {
|
|
||||||
first = begin
|
|
||||||
}
|
|
||||||
last := sectionStart + m.sectionSize - 1
|
|
||||||
if end < last {
|
|
||||||
last = end
|
|
||||||
}
|
|
||||||
// Iterate over all the blocks in the section and return the matching ones
|
|
||||||
for i := first; i <= last; i++ {
|
|
||||||
// Skip the entire byte if no matches are found inside (and we're processing an entire byte!)
|
|
||||||
next := res.bitset[(i-sectionStart)/8]
|
|
||||||
if next == 0 {
|
|
||||||
if i%8 == 0 {
|
|
||||||
i += 7
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Some bit it set, do the actual submatching
|
|
||||||
if bit := 7 - i%8; next&(1<<bit) != 0 {
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
case results <- i:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return session, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// run creates a daisy-chain of sub-matchers, one for the address set and one
|
|
||||||
// for each topic set, each sub-matcher receiving a section only if the previous
|
|
||||||
// ones have all found a potential match in one of the blocks of the section,
|
|
||||||
// then binary AND-ing its own matches and forwarding the result to the next one.
|
|
||||||
//
|
|
||||||
// The method starts feeding the section indexes into the first sub-matcher on a
|
|
||||||
// new goroutine and returns a sink channel receiving the results.
|
|
||||||
func (m *Matcher) run(begin, end uint64, buffer int, session *MatcherSession) chan *partialMatches {
|
|
||||||
// Create the source channel and feed section indexes into
|
|
||||||
source := make(chan *partialMatches, buffer)
|
|
||||||
|
|
||||||
session.pend.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer session.pend.Done()
|
|
||||||
defer close(source)
|
|
||||||
|
|
||||||
for i := begin / m.sectionSize; i <= end/m.sectionSize; i++ {
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
case source <- &partialMatches{i, bytes.Repeat([]byte{0xff}, int(m.sectionSize/8))}:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// Assemble the daisy-chained filtering pipeline
|
|
||||||
next := source
|
|
||||||
dist := make(chan *request, buffer)
|
|
||||||
|
|
||||||
for _, bloom := range m.filters {
|
|
||||||
next = m.subMatch(next, dist, bloom, session)
|
|
||||||
}
|
|
||||||
// Start the request distribution
|
|
||||||
session.pend.Add(1)
|
|
||||||
go m.distributor(dist, session)
|
|
||||||
|
|
||||||
return next
|
|
||||||
}
|
|
||||||
|
|
||||||
// subMatch creates a sub-matcher that filters for a set of addresses or topics, binary OR-s those matches, then
|
|
||||||
// binary AND-s the result to the daisy-chain input (source) and forwards it to the daisy-chain output.
|
|
||||||
// The matches of each address/topic are calculated by fetching the given sections of the three bloom bit indexes belonging to
|
|
||||||
// that address/topic, and binary AND-ing those vectors together.
|
|
||||||
func (m *Matcher) subMatch(source chan *partialMatches, dist chan *request, bloom []bloomIndexes, session *MatcherSession) chan *partialMatches {
|
|
||||||
// Start the concurrent schedulers for each bit required by the bloom filter
|
|
||||||
sectionSources := make([][3]chan uint64, len(bloom))
|
|
||||||
sectionSinks := make([][3]chan []byte, len(bloom))
|
|
||||||
for i, bits := range bloom {
|
|
||||||
for j, bit := range bits {
|
|
||||||
sectionSources[i][j] = make(chan uint64, cap(source))
|
|
||||||
sectionSinks[i][j] = make(chan []byte, cap(source))
|
|
||||||
|
|
||||||
m.schedulers[bit].run(sectionSources[i][j], dist, sectionSinks[i][j], session.quit, &session.pend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
process := make(chan *partialMatches, cap(source)) // entries from source are forwarded here after fetches have been initiated
|
|
||||||
results := make(chan *partialMatches, cap(source))
|
|
||||||
|
|
||||||
session.pend.Add(2)
|
|
||||||
go func() {
|
|
||||||
// Tear down the goroutine and terminate all source channels
|
|
||||||
defer session.pend.Done()
|
|
||||||
defer close(process)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
for _, bloomSources := range sectionSources {
|
|
||||||
for _, bitSource := range bloomSources {
|
|
||||||
close(bitSource)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// Read sections from the source channel and multiplex into all bit-schedulers
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
|
|
||||||
case subres, ok := <-source:
|
|
||||||
// New subresult from previous link
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Multiplex the section index to all bit-schedulers
|
|
||||||
for _, bloomSources := range sectionSources {
|
|
||||||
for _, bitSource := range bloomSources {
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
case bitSource <- subres.section:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Notify the processor that this section will become available
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
case process <- subres:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
// Tear down the goroutine and terminate the final sink channel
|
|
||||||
defer session.pend.Done()
|
|
||||||
defer close(results)
|
|
||||||
|
|
||||||
// Read the source notifications and collect the delivered results
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
|
|
||||||
case subres, ok := <-process:
|
|
||||||
// Notified of a section being retrieved
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Gather all the sub-results and merge them together
|
|
||||||
var orVector []byte
|
|
||||||
for _, bloomSinks := range sectionSinks {
|
|
||||||
var andVector []byte
|
|
||||||
for _, bitSink := range bloomSinks {
|
|
||||||
var data []byte
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
case data = <-bitSink:
|
|
||||||
}
|
|
||||||
if andVector == nil {
|
|
||||||
andVector = make([]byte, int(m.sectionSize/8))
|
|
||||||
copy(andVector, data)
|
|
||||||
} else {
|
|
||||||
bitutil.ANDBytes(andVector, andVector, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if orVector == nil {
|
|
||||||
orVector = andVector
|
|
||||||
} else {
|
|
||||||
bitutil.ORBytes(orVector, orVector, andVector)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if orVector == nil {
|
|
||||||
orVector = make([]byte, int(m.sectionSize/8))
|
|
||||||
}
|
|
||||||
if subres.bitset != nil {
|
|
||||||
bitutil.ANDBytes(orVector, orVector, subres.bitset)
|
|
||||||
}
|
|
||||||
if bitutil.TestBytes(orVector) {
|
|
||||||
select {
|
|
||||||
case <-session.quit:
|
|
||||||
return
|
|
||||||
case results <- &partialMatches{subres.section, orVector}:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
// distributor receives requests from the schedulers and queues them into a set
|
|
||||||
// of pending requests, which are assigned to retrievers wanting to fulfil them.
|
|
||||||
func (m *Matcher) distributor(dist chan *request, session *MatcherSession) {
|
|
||||||
defer session.pend.Done()
|
|
||||||
|
|
||||||
var (
|
|
||||||
requests = make(map[uint][]uint64) // Per-bit list of section requests, ordered by section number
|
|
||||||
unallocs = make(map[uint]struct{}) // Bits with pending requests but not allocated to any retriever
|
|
||||||
retrievers chan chan uint // Waiting retrievers (toggled to nil if unallocs is empty)
|
|
||||||
allocs int // Number of active allocations to handle graceful shutdown requests
|
|
||||||
shutdown = session.quit // Shutdown request channel, will gracefully wait for pending requests
|
|
||||||
)
|
|
||||||
|
|
||||||
// assign is a helper method to try to assign a pending bit an actively
|
|
||||||
// listening servicer, or schedule it up for later when one arrives.
|
|
||||||
assign := func(bit uint) {
|
|
||||||
select {
|
|
||||||
case fetcher := <-m.retrievers:
|
|
||||||
allocs++
|
|
||||||
fetcher <- bit
|
|
||||||
default:
|
|
||||||
// No retrievers active, start listening for new ones
|
|
||||||
retrievers = m.retrievers
|
|
||||||
unallocs[bit] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-shutdown:
|
|
||||||
// Shutdown requested. No more retrievers can be allocated,
|
|
||||||
// but we still need to wait until all pending requests have returned.
|
|
||||||
shutdown = nil
|
|
||||||
if allocs == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case req := <-dist:
|
|
||||||
// New retrieval request arrived to be distributed to some fetcher process
|
|
||||||
queue := requests[req.bit]
|
|
||||||
index := sort.Search(len(queue), func(i int) bool { return queue[i] >= req.section })
|
|
||||||
requests[req.bit] = append(queue[:index], append([]uint64{req.section}, queue[index:]...)...)
|
|
||||||
|
|
||||||
// If it's a new bit and we have waiting fetchers, allocate to them
|
|
||||||
if len(queue) == 0 {
|
|
||||||
assign(req.bit)
|
|
||||||
}
|
|
||||||
|
|
||||||
case fetcher := <-retrievers:
|
|
||||||
// New retriever arrived, find the lowest section-ed bit to assign
|
|
||||||
bit, best := uint(0), uint64(math.MaxUint64)
|
|
||||||
for idx := range unallocs {
|
|
||||||
if requests[idx][0] < best {
|
|
||||||
bit, best = idx, requests[idx][0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Stop tracking this bit (and alloc notifications if no more work is available)
|
|
||||||
delete(unallocs, bit)
|
|
||||||
if len(unallocs) == 0 {
|
|
||||||
retrievers = nil
|
|
||||||
}
|
|
||||||
allocs++
|
|
||||||
fetcher <- bit
|
|
||||||
|
|
||||||
case fetcher := <-m.counters:
|
|
||||||
// New task count request arrives, return number of items
|
|
||||||
fetcher <- uint(len(requests[<-fetcher]))
|
|
||||||
|
|
||||||
case fetcher := <-m.retrievals:
|
|
||||||
// New fetcher waiting for tasks to retrieve, assign
|
|
||||||
task := <-fetcher
|
|
||||||
if want := len(task.Sections); want >= len(requests[task.Bit]) {
|
|
||||||
task.Sections = requests[task.Bit]
|
|
||||||
delete(requests, task.Bit)
|
|
||||||
} else {
|
|
||||||
task.Sections = append(task.Sections[:0], requests[task.Bit][:want]...)
|
|
||||||
requests[task.Bit] = append(requests[task.Bit][:0], requests[task.Bit][want:]...)
|
|
||||||
}
|
|
||||||
fetcher <- task
|
|
||||||
|
|
||||||
// If anything was left unallocated, try to assign to someone else
|
|
||||||
if len(requests[task.Bit]) > 0 {
|
|
||||||
assign(task.Bit)
|
|
||||||
}
|
|
||||||
|
|
||||||
case result := <-m.deliveries:
|
|
||||||
// New retrieval task response from fetcher, split out missing sections and
|
|
||||||
// deliver complete ones
|
|
||||||
var (
|
|
||||||
sections = make([]uint64, 0, len(result.Sections))
|
|
||||||
bitsets = make([][]byte, 0, len(result.Bitsets))
|
|
||||||
missing = make([]uint64, 0, len(result.Sections))
|
|
||||||
)
|
|
||||||
for i, bitset := range result.Bitsets {
|
|
||||||
if len(bitset) == 0 {
|
|
||||||
missing = append(missing, result.Sections[i])
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sections = append(sections, result.Sections[i])
|
|
||||||
bitsets = append(bitsets, bitset)
|
|
||||||
}
|
|
||||||
m.schedulers[result.Bit].deliver(sections, bitsets)
|
|
||||||
allocs--
|
|
||||||
|
|
||||||
// Reschedule missing sections and allocate bit if newly available
|
|
||||||
if len(missing) > 0 {
|
|
||||||
queue := requests[result.Bit]
|
|
||||||
for _, section := range missing {
|
|
||||||
index := sort.Search(len(queue), func(i int) bool { return queue[i] >= section })
|
|
||||||
queue = append(queue[:index], append([]uint64{section}, queue[index:]...)...)
|
|
||||||
}
|
|
||||||
requests[result.Bit] = queue
|
|
||||||
|
|
||||||
if len(queue) == len(missing) {
|
|
||||||
assign(result.Bit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// End the session when all pending deliveries have arrived.
|
|
||||||
if shutdown == nil && allocs == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatcherSession is returned by a started matcher to be used as a terminator
|
|
||||||
// for the actively running matching operation.
|
|
||||||
type MatcherSession struct {
|
|
||||||
matcher *Matcher
|
|
||||||
|
|
||||||
closer sync.Once // Sync object to ensure we only ever close once
|
|
||||||
quit chan struct{} // Quit channel to request pipeline termination
|
|
||||||
|
|
||||||
ctx context.Context // Context used by the light client to abort filtering
|
|
||||||
err error // Global error to track retrieval failures deep in the chain
|
|
||||||
errLock sync.Mutex
|
|
||||||
|
|
||||||
pend sync.WaitGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close stops the matching process and waits for all subprocesses to terminate
|
|
||||||
// before returning. The timeout may be used for graceful shutdown, allowing the
|
|
||||||
// currently running retrievals to complete before this time.
|
|
||||||
func (s *MatcherSession) Close() {
|
|
||||||
s.closer.Do(func() {
|
|
||||||
// Signal termination and wait for all goroutines to tear down
|
|
||||||
close(s.quit)
|
|
||||||
s.pend.Wait()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns any failure encountered during the matching session.
|
|
||||||
func (s *MatcherSession) Error() error {
|
|
||||||
s.errLock.Lock()
|
|
||||||
defer s.errLock.Unlock()
|
|
||||||
|
|
||||||
return s.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocateRetrieval assigns a bloom bit index to a client process that can either
|
|
||||||
// immediately request and fetch the section contents assigned to this bit or wait
|
|
||||||
// a little while for more sections to be requested.
|
|
||||||
func (s *MatcherSession) allocateRetrieval() (uint, bool) {
|
|
||||||
fetcher := make(chan uint)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-s.quit:
|
|
||||||
return 0, false
|
|
||||||
case s.matcher.retrievers <- fetcher:
|
|
||||||
bit, ok := <-fetcher
|
|
||||||
return bit, ok
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pendingSections returns the number of pending section retrievals belonging to
|
|
||||||
// the given bloom bit index.
|
|
||||||
func (s *MatcherSession) pendingSections(bit uint) int {
|
|
||||||
fetcher := make(chan uint)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-s.quit:
|
|
||||||
return 0
|
|
||||||
case s.matcher.counters <- fetcher:
|
|
||||||
fetcher <- bit
|
|
||||||
return int(<-fetcher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocateSections assigns all or part of an already allocated bit-task queue
|
|
||||||
// to the requesting process.
|
|
||||||
func (s *MatcherSession) allocateSections(bit uint, count int) []uint64 {
|
|
||||||
fetcher := make(chan *Retrieval)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-s.quit:
|
|
||||||
return nil
|
|
||||||
case s.matcher.retrievals <- fetcher:
|
|
||||||
task := &Retrieval{
|
|
||||||
Bit: bit,
|
|
||||||
Sections: make([]uint64, count),
|
|
||||||
}
|
|
||||||
fetcher <- task
|
|
||||||
return (<-fetcher).Sections
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// deliverSections delivers a batch of section bit-vectors for a specific bloom
|
|
||||||
// bit index to be injected into the processing pipeline.
|
|
||||||
func (s *MatcherSession) deliverSections(bit uint, sections []uint64, bitsets [][]byte) {
|
|
||||||
s.matcher.deliveries <- &Retrieval{Bit: bit, Sections: sections, Bitsets: bitsets}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiplex polls the matcher session for retrieval tasks and multiplexes it into
|
|
||||||
// the requested retrieval queue to be serviced together with other sessions.
|
|
||||||
//
|
|
||||||
// This method will block for the lifetime of the session. Even after termination
|
|
||||||
// of the session, any request in-flight need to be responded to! Empty responses
|
|
||||||
// are fine though in that case.
|
|
||||||
func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan *Retrieval) {
|
|
||||||
waitTimer := time.NewTimer(wait)
|
|
||||||
defer waitTimer.Stop()
|
|
||||||
|
|
||||||
for {
|
|
||||||
// Allocate a new bloom bit index to retrieve data for, stopping when done
|
|
||||||
bit, ok := s.allocateRetrieval()
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Bit allocated, throttle a bit if we're below our batch limit
|
|
||||||
if s.pendingSections(bit) < batch {
|
|
||||||
waitTimer.Reset(wait)
|
|
||||||
select {
|
|
||||||
case <-s.quit:
|
|
||||||
// Session terminating, we can't meaningfully service, abort
|
|
||||||
s.allocateSections(bit, 0)
|
|
||||||
s.deliverSections(bit, []uint64{}, [][]byte{})
|
|
||||||
return
|
|
||||||
|
|
||||||
case <-waitTimer.C:
|
|
||||||
// Throttling up, fetch whatever is available
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Allocate as much as we can handle and request servicing
|
|
||||||
sections := s.allocateSections(bit, batch)
|
|
||||||
request := make(chan *Retrieval)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-s.quit:
|
|
||||||
// Session terminating, we can't meaningfully service, abort
|
|
||||||
s.deliverSections(bit, sections, make([][]byte, len(sections)))
|
|
||||||
return
|
|
||||||
|
|
||||||
case mux <- request:
|
|
||||||
// Retrieval accepted, something must arrive before we're aborting
|
|
||||||
request <- &Retrieval{Bit: bit, Sections: sections, Context: s.ctx}
|
|
||||||
|
|
||||||
result := <-request
|
|
||||||
|
|
||||||
// Deliver a result before s.Close() to avoid a deadlock
|
|
||||||
s.deliverSections(result.Bit, result.Sections, result.Bitsets)
|
|
||||||
|
|
||||||
if result.Error != nil {
|
|
||||||
s.errLock.Lock()
|
|
||||||
s.err = result.Error
|
|
||||||
s.errLock.Unlock()
|
|
||||||
s.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,292 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package bloombits
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"math/rand"
|
|
||||||
"sync/atomic"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
const testSectionSize = 4096
|
|
||||||
|
|
||||||
// Tests that wildcard filter rules (nil) can be specified and are handled well.
|
|
||||||
func TestMatcherWildcards(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
matcher := NewMatcher(testSectionSize, [][][]byte{
|
|
||||||
{common.Address{}.Bytes(), common.Address{0x01}.Bytes()}, // Default address is not a wildcard
|
|
||||||
{common.Hash{}.Bytes(), common.Hash{0x01}.Bytes()}, // Default hash is not a wildcard
|
|
||||||
{common.Hash{0x01}.Bytes()}, // Plain rule, sanity check
|
|
||||||
{common.Hash{0x01}.Bytes(), nil}, // Wildcard suffix, drop rule
|
|
||||||
{nil, common.Hash{0x01}.Bytes()}, // Wildcard prefix, drop rule
|
|
||||||
{nil, nil}, // Wildcard combo, drop rule
|
|
||||||
{}, // Inited wildcard rule, drop rule
|
|
||||||
nil, // Proper wildcard rule, drop rule
|
|
||||||
})
|
|
||||||
if len(matcher.filters) != 3 {
|
|
||||||
t.Fatalf("filter system size mismatch: have %d, want %d", len(matcher.filters), 3)
|
|
||||||
}
|
|
||||||
if len(matcher.filters[0]) != 2 {
|
|
||||||
t.Fatalf("address clause size mismatch: have %d, want %d", len(matcher.filters[0]), 2)
|
|
||||||
}
|
|
||||||
if len(matcher.filters[1]) != 2 {
|
|
||||||
t.Fatalf("combo topic clause size mismatch: have %d, want %d", len(matcher.filters[1]), 2)
|
|
||||||
}
|
|
||||||
if len(matcher.filters[2]) != 1 {
|
|
||||||
t.Fatalf("singletone topic clause size mismatch: have %d, want %d", len(matcher.filters[2]), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests the matcher pipeline on a single continuous workflow without interrupts.
|
|
||||||
func TestMatcherContinuous(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
testMatcherDiffBatches(t, [][]bloomIndexes{{{10, 20, 30}}}, 0, 100000, false, 75)
|
|
||||||
testMatcherDiffBatches(t, [][]bloomIndexes{{{32, 3125, 100}}, {{40, 50, 10}}}, 0, 100000, false, 81)
|
|
||||||
testMatcherDiffBatches(t, [][]bloomIndexes{{{4, 8, 11}, {7, 8, 17}}, {{9, 9, 12}, {15, 20, 13}}, {{18, 15, 15}, {12, 10, 4}}}, 0, 10000, false, 36)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests the matcher pipeline on a constantly interrupted and resumed work pattern
|
|
||||||
// with the aim of ensuring data items are requested only once.
|
|
||||||
func TestMatcherIntermittent(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
testMatcherDiffBatches(t, [][]bloomIndexes{{{10, 20, 30}}}, 0, 100000, true, 75)
|
|
||||||
testMatcherDiffBatches(t, [][]bloomIndexes{{{32, 3125, 100}}, {{40, 50, 10}}}, 0, 100000, true, 81)
|
|
||||||
testMatcherDiffBatches(t, [][]bloomIndexes{{{4, 8, 11}, {7, 8, 17}}, {{9, 9, 12}, {15, 20, 13}}, {{18, 15, 15}, {12, 10, 4}}}, 0, 10000, true, 36)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests the matcher pipeline on random input to hopefully catch anomalies.
|
|
||||||
func TestMatcherRandom(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
testMatcherBothModes(t, makeRandomIndexes([]int{1}, 50), 0, 10000, 0)
|
|
||||||
testMatcherBothModes(t, makeRandomIndexes([]int{3}, 50), 0, 10000, 0)
|
|
||||||
testMatcherBothModes(t, makeRandomIndexes([]int{2, 2, 2}, 20), 0, 10000, 0)
|
|
||||||
testMatcherBothModes(t, makeRandomIndexes([]int{5, 5, 5}, 50), 0, 10000, 0)
|
|
||||||
testMatcherBothModes(t, makeRandomIndexes([]int{4, 4, 4}, 20), 0, 10000, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that the matcher can properly find matches if the starting block is
|
|
||||||
// shifted from a multiple of 8. This is needed to cover an optimisation with
|
|
||||||
// bitset matching https://github.com/ethereum/go-ethereum/issues/15309.
|
|
||||||
func TestMatcherShifted(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
// Block 0 always matches in the tests, skip ahead of first 8 blocks with the
|
|
||||||
// start to get a potential zero byte in the matcher bitset.
|
|
||||||
|
|
||||||
// To keep the second bitset byte zero, the filter must only match for the first
|
|
||||||
// time in block 16, so doing an all-16 bit filter should suffice.
|
|
||||||
|
|
||||||
// To keep the starting block non divisible by 8, block number 9 is the first
|
|
||||||
// that would introduce a shift and not match block 0.
|
|
||||||
testMatcherBothModes(t, [][]bloomIndexes{{{16, 16, 16}}}, 9, 64, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that matching on everything doesn't crash (special case internally).
|
|
||||||
func TestWildcardMatcher(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
testMatcherBothModes(t, nil, 0, 10000, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// makeRandomIndexes generates a random filter system, composed of multiple filter
|
|
||||||
// criteria, each having one bloom list component for the address and arbitrarily
|
|
||||||
// many topic bloom list components.
|
|
||||||
func makeRandomIndexes(lengths []int, max int) [][]bloomIndexes {
|
|
||||||
res := make([][]bloomIndexes, len(lengths))
|
|
||||||
for i, topics := range lengths {
|
|
||||||
res[i] = make([]bloomIndexes, topics)
|
|
||||||
for j := 0; j < topics; j++ {
|
|
||||||
for k := 0; k < len(res[i][j]); k++ {
|
|
||||||
res[i][j][k] = uint(rand.Intn(max-1) + 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// testMatcherDiffBatches runs the given matches test in single-delivery and also
|
|
||||||
// in batches delivery mode, verifying that all kinds of deliveries are handled
|
|
||||||
// correctly within.
|
|
||||||
func testMatcherDiffBatches(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, intermittent bool, retrievals uint32) {
|
|
||||||
singleton := testMatcher(t, filter, start, blocks, intermittent, retrievals, 1)
|
|
||||||
batched := testMatcher(t, filter, start, blocks, intermittent, retrievals, 16)
|
|
||||||
|
|
||||||
if singleton != batched {
|
|
||||||
t.Errorf("filter = %v blocks = %v intermittent = %v: request count mismatch, %v in singleton vs. %v in batched mode", filter, blocks, intermittent, singleton, batched)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// testMatcherBothModes runs the given matcher test in both continuous as well as
|
|
||||||
// in intermittent mode, verifying that the request counts match each other.
|
|
||||||
func testMatcherBothModes(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, retrievals uint32) {
|
|
||||||
continuous := testMatcher(t, filter, start, blocks, false, retrievals, 16)
|
|
||||||
intermittent := testMatcher(t, filter, start, blocks, true, retrievals, 16)
|
|
||||||
|
|
||||||
if continuous != intermittent {
|
|
||||||
t.Errorf("filter = %v blocks = %v: request count mismatch, %v in continuous vs. %v in intermittent mode", filter, blocks, continuous, intermittent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// testMatcher is a generic tester to run the given matcher test and return the
|
|
||||||
// number of requests made for cross validation between different modes.
|
|
||||||
func testMatcher(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, intermittent bool, retrievals uint32, maxReqCount int) uint32 {
|
|
||||||
// Create a new matcher an simulate our explicit random bitsets
|
|
||||||
matcher := NewMatcher(testSectionSize, nil)
|
|
||||||
matcher.filters = filter
|
|
||||||
|
|
||||||
for _, rule := range filter {
|
|
||||||
for _, topic := range rule {
|
|
||||||
for _, bit := range topic {
|
|
||||||
matcher.addScheduler(bit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Track the number of retrieval requests made
|
|
||||||
var requested atomic.Uint32
|
|
||||||
|
|
||||||
// Start the matching session for the filter and the retriever goroutines
|
|
||||||
quit := make(chan struct{})
|
|
||||||
matches := make(chan uint64, 16)
|
|
||||||
|
|
||||||
session, err := matcher.Start(context.Background(), start, blocks-1, matches)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to stat matcher session: %v", err)
|
|
||||||
}
|
|
||||||
startRetrievers(session, quit, &requested, maxReqCount)
|
|
||||||
|
|
||||||
// Iterate over all the blocks and verify that the pipeline produces the correct matches
|
|
||||||
for i := start; i < blocks; i++ {
|
|
||||||
if expMatch3(filter, i) {
|
|
||||||
match, ok := <-matches
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("filter = %v blocks = %v intermittent = %v: expected #%v, results channel closed", filter, blocks, intermittent, i)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if match != i {
|
|
||||||
t.Errorf("filter = %v blocks = %v intermittent = %v: expected #%v, got #%v", filter, blocks, intermittent, i, match)
|
|
||||||
}
|
|
||||||
// If we're testing intermittent mode, abort and restart the pipeline
|
|
||||||
if intermittent {
|
|
||||||
session.Close()
|
|
||||||
close(quit)
|
|
||||||
|
|
||||||
quit = make(chan struct{})
|
|
||||||
matches = make(chan uint64, 16)
|
|
||||||
|
|
||||||
session, err = matcher.Start(context.Background(), i+1, blocks-1, matches)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to stat matcher session: %v", err)
|
|
||||||
}
|
|
||||||
startRetrievers(session, quit, &requested, maxReqCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Ensure the result channel is torn down after the last block
|
|
||||||
match, ok := <-matches
|
|
||||||
if ok {
|
|
||||||
t.Errorf("filter = %v blocks = %v intermittent = %v: expected closed channel, got #%v", filter, blocks, intermittent, match)
|
|
||||||
}
|
|
||||||
// Clean up the session and ensure we match the expected retrieval count
|
|
||||||
session.Close()
|
|
||||||
close(quit)
|
|
||||||
|
|
||||||
if retrievals != 0 && requested.Load() != retrievals {
|
|
||||||
t.Errorf("filter = %v blocks = %v intermittent = %v: request count mismatch, have #%v, want #%v", filter, blocks, intermittent, requested.Load(), retrievals)
|
|
||||||
}
|
|
||||||
return requested.Load()
|
|
||||||
}
|
|
||||||
|
|
||||||
// startRetrievers starts a batch of goroutines listening for section requests
|
|
||||||
// and serving them.
|
|
||||||
func startRetrievers(session *MatcherSession, quit chan struct{}, retrievals *atomic.Uint32, batch int) {
|
|
||||||
requests := make(chan chan *Retrieval)
|
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
// Start a multiplexer to test multiple threaded execution
|
|
||||||
go session.Multiplex(batch, 100*time.Microsecond, requests)
|
|
||||||
|
|
||||||
// Start a services to match the above multiplexer
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
// Wait for a service request or a shutdown
|
|
||||||
select {
|
|
||||||
case <-quit:
|
|
||||||
return
|
|
||||||
|
|
||||||
case request := <-requests:
|
|
||||||
task := <-request
|
|
||||||
|
|
||||||
task.Bitsets = make([][]byte, len(task.Sections))
|
|
||||||
for i, section := range task.Sections {
|
|
||||||
if rand.Int()%4 != 0 { // Handle occasional missing deliveries
|
|
||||||
task.Bitsets[i] = generateBitset(task.Bit, section)
|
|
||||||
retrievals.Add(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request <- task
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateBitset generates the rotated bitset for the given bloom bit and section
|
|
||||||
// numbers.
|
|
||||||
func generateBitset(bit uint, section uint64) []byte {
|
|
||||||
bitset := make([]byte, testSectionSize/8)
|
|
||||||
for i := 0; i < len(bitset); i++ {
|
|
||||||
for b := 0; b < 8; b++ {
|
|
||||||
blockIdx := section*testSectionSize + uint64(i*8+b)
|
|
||||||
bitset[i] += bitset[i]
|
|
||||||
if (blockIdx % uint64(bit)) == 0 {
|
|
||||||
bitset[i]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bitset
|
|
||||||
}
|
|
||||||
|
|
||||||
func expMatch1(filter bloomIndexes, i uint64) bool {
|
|
||||||
for _, ii := range filter {
|
|
||||||
if (i % uint64(ii)) != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func expMatch2(filter []bloomIndexes, i uint64) bool {
|
|
||||||
for _, ii := range filter {
|
|
||||||
if expMatch1(ii, i) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func expMatch3(filter [][]bloomIndexes, i uint64) bool {
|
|
||||||
for _, ii := range filter {
|
|
||||||
if !expMatch2(ii, i) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
@ -1,181 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package bloombits
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// request represents a bloom retrieval task to prioritize and pull from the local
|
|
||||||
// database or remotely from the network.
|
|
||||||
type request struct {
|
|
||||||
section uint64 // Section index to retrieve the bit-vector from
|
|
||||||
bit uint // Bit index within the section to retrieve the vector of
|
|
||||||
}
|
|
||||||
|
|
||||||
// response represents the state of a requested bit-vector through a scheduler.
|
|
||||||
type response struct {
|
|
||||||
cached []byte // Cached bits to dedup multiple requests
|
|
||||||
done chan struct{} // Channel to allow waiting for completion
|
|
||||||
}
|
|
||||||
|
|
||||||
// scheduler handles the scheduling of bloom-filter retrieval operations for
|
|
||||||
// entire section-batches belonging to a single bloom bit. Beside scheduling the
|
|
||||||
// retrieval operations, this struct also deduplicates the requests and caches
|
|
||||||
// the results to minimize network/database overhead even in complex filtering
|
|
||||||
// scenarios.
|
|
||||||
type scheduler struct {
|
|
||||||
bit uint // Index of the bit in the bloom filter this scheduler is responsible for
|
|
||||||
responses map[uint64]*response // Currently pending retrieval requests or already cached responses
|
|
||||||
lock sync.Mutex // Lock protecting the responses from concurrent access
|
|
||||||
}
|
|
||||||
|
|
||||||
// newScheduler creates a new bloom-filter retrieval scheduler for a specific
|
|
||||||
// bit index.
|
|
||||||
func newScheduler(idx uint) *scheduler {
|
|
||||||
return &scheduler{
|
|
||||||
bit: idx,
|
|
||||||
responses: make(map[uint64]*response),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// run creates a retrieval pipeline, receiving section indexes from sections and
|
|
||||||
// returning the results in the same order through the done channel. Concurrent
|
|
||||||
// runs of the same scheduler are allowed, leading to retrieval task deduplication.
|
|
||||||
func (s *scheduler) run(sections chan uint64, dist chan *request, done chan []byte, quit chan struct{}, wg *sync.WaitGroup) {
|
|
||||||
// Create a forwarder channel between requests and responses of the same size as
|
|
||||||
// the distribution channel (since that will block the pipeline anyway).
|
|
||||||
pend := make(chan uint64, cap(dist))
|
|
||||||
|
|
||||||
// Start the pipeline schedulers to forward between user -> distributor -> user
|
|
||||||
wg.Add(2)
|
|
||||||
go s.scheduleRequests(sections, dist, pend, quit, wg)
|
|
||||||
go s.scheduleDeliveries(pend, done, quit, wg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset cleans up any leftovers from previous runs. This is required before a
|
|
||||||
// restart to ensure the no previously requested but never delivered state will
|
|
||||||
// cause a lockup.
|
|
||||||
func (s *scheduler) reset() {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
for section, res := range s.responses {
|
|
||||||
if res.cached == nil {
|
|
||||||
delete(s.responses, section)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// scheduleRequests reads section retrieval requests from the input channel,
|
|
||||||
// deduplicates the stream and pushes unique retrieval tasks into the distribution
|
|
||||||
// channel for a database or network layer to honour.
|
|
||||||
func (s *scheduler) scheduleRequests(reqs chan uint64, dist chan *request, pend chan uint64, quit chan struct{}, wg *sync.WaitGroup) {
|
|
||||||
// Clean up the goroutine and pipeline when done
|
|
||||||
defer wg.Done()
|
|
||||||
defer close(pend)
|
|
||||||
|
|
||||||
// Keep reading and scheduling section requests
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-quit:
|
|
||||||
return
|
|
||||||
|
|
||||||
case section, ok := <-reqs:
|
|
||||||
// New section retrieval requested
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Deduplicate retrieval requests
|
|
||||||
unique := false
|
|
||||||
|
|
||||||
s.lock.Lock()
|
|
||||||
if s.responses[section] == nil {
|
|
||||||
s.responses[section] = &response{
|
|
||||||
done: make(chan struct{}),
|
|
||||||
}
|
|
||||||
unique = true
|
|
||||||
}
|
|
||||||
s.lock.Unlock()
|
|
||||||
|
|
||||||
// Schedule the section for retrieval and notify the deliverer to expect this section
|
|
||||||
if unique {
|
|
||||||
select {
|
|
||||||
case <-quit:
|
|
||||||
return
|
|
||||||
case dist <- &request{bit: s.bit, section: section}:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-quit:
|
|
||||||
return
|
|
||||||
case pend <- section:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// scheduleDeliveries reads section acceptance notifications and waits for them
|
|
||||||
// to be delivered, pushing them into the output data buffer.
|
|
||||||
func (s *scheduler) scheduleDeliveries(pend chan uint64, done chan []byte, quit chan struct{}, wg *sync.WaitGroup) {
|
|
||||||
// Clean up the goroutine and pipeline when done
|
|
||||||
defer wg.Done()
|
|
||||||
defer close(done)
|
|
||||||
|
|
||||||
// Keep reading notifications and scheduling deliveries
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-quit:
|
|
||||||
return
|
|
||||||
|
|
||||||
case idx, ok := <-pend:
|
|
||||||
// New section retrieval pending
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Wait until the request is honoured
|
|
||||||
s.lock.Lock()
|
|
||||||
res := s.responses[idx]
|
|
||||||
s.lock.Unlock()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-quit:
|
|
||||||
return
|
|
||||||
case <-res.done:
|
|
||||||
}
|
|
||||||
// Deliver the result
|
|
||||||
select {
|
|
||||||
case <-quit:
|
|
||||||
return
|
|
||||||
case done <- res.cached:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// deliver is called by the request distributor when a reply to a request arrives.
|
|
||||||
func (s *scheduler) deliver(sections []uint64, data [][]byte) {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
for i, section := range sections {
|
|
||||||
if res := s.responses[section]; res != nil && res.cached == nil { // Avoid non-requests and double deliveries
|
|
||||||
res.cached = data[i]
|
|
||||||
close(res.done)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package bloombits
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"math/big"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Tests that the scheduler can deduplicate and forward retrieval requests to
|
|
||||||
// underlying fetchers and serve responses back, irrelevant of the concurrency
|
|
||||||
// of the requesting clients or serving data fetchers.
|
|
||||||
func TestSchedulerSingleClientSingleFetcher(t *testing.T) { testScheduler(t, 1, 1, 5000) }
|
|
||||||
func TestSchedulerSingleClientMultiFetcher(t *testing.T) { testScheduler(t, 1, 10, 5000) }
|
|
||||||
func TestSchedulerMultiClientSingleFetcher(t *testing.T) { testScheduler(t, 10, 1, 5000) }
|
|
||||||
func TestSchedulerMultiClientMultiFetcher(t *testing.T) { testScheduler(t, 10, 10, 5000) }
|
|
||||||
|
|
||||||
func testScheduler(t *testing.T, clients int, fetchers int, requests int) {
|
|
||||||
t.Parallel()
|
|
||||||
f := newScheduler(0)
|
|
||||||
|
|
||||||
// Create a batch of handler goroutines that respond to bloom bit requests and
|
|
||||||
// deliver them to the scheduler.
|
|
||||||
var fetchPend sync.WaitGroup
|
|
||||||
fetchPend.Add(fetchers)
|
|
||||||
defer fetchPend.Wait()
|
|
||||||
|
|
||||||
fetch := make(chan *request, 16)
|
|
||||||
defer close(fetch)
|
|
||||||
|
|
||||||
var delivered atomic.Uint32
|
|
||||||
for i := 0; i < fetchers; i++ {
|
|
||||||
go func() {
|
|
||||||
defer fetchPend.Done()
|
|
||||||
|
|
||||||
for req := range fetch {
|
|
||||||
delivered.Add(1)
|
|
||||||
|
|
||||||
f.deliver([]uint64{
|
|
||||||
req.section + uint64(requests), // Non-requested data (ensure it doesn't go out of bounds)
|
|
||||||
req.section, // Requested data
|
|
||||||
req.section, // Duplicated data (ensure it doesn't double close anything)
|
|
||||||
}, [][]byte{
|
|
||||||
{},
|
|
||||||
new(big.Int).SetUint64(req.section).Bytes(),
|
|
||||||
new(big.Int).SetUint64(req.section).Bytes(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
// Start a batch of goroutines to concurrently run scheduling tasks
|
|
||||||
quit := make(chan struct{})
|
|
||||||
|
|
||||||
var pend sync.WaitGroup
|
|
||||||
pend.Add(clients)
|
|
||||||
|
|
||||||
for i := 0; i < clients; i++ {
|
|
||||||
go func() {
|
|
||||||
defer pend.Done()
|
|
||||||
|
|
||||||
in := make(chan uint64, 16)
|
|
||||||
out := make(chan []byte, 16)
|
|
||||||
|
|
||||||
f.run(in, fetch, out, quit, &pend)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for j := 0; j < requests; j++ {
|
|
||||||
in <- uint64(j)
|
|
||||||
}
|
|
||||||
close(in)
|
|
||||||
}()
|
|
||||||
b := new(big.Int)
|
|
||||||
for j := 0; j < requests; j++ {
|
|
||||||
bits := <-out
|
|
||||||
if want := b.SetUint64(uint64(j)).Bytes(); !bytes.Equal(bits, want) {
|
|
||||||
t.Errorf("vector %d: delivered content mismatch: have %x, want %x", j, bits, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
pend.Wait()
|
|
||||||
|
|
||||||
if have := delivered.Load(); int(have) != requests {
|
|
||||||
t.Errorf("request count mismatch: have %v, want %v", have, requests)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,522 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChainIndexerBackend defines the methods needed to process chain segments in
|
|
||||||
// the background and write the segment results into the database. These can be
|
|
||||||
// used to create filter blooms or CHTs.
|
|
||||||
type ChainIndexerBackend interface {
|
|
||||||
// Reset initiates the processing of a new chain segment, potentially terminating
|
|
||||||
// any partially completed operations (in case of a reorg).
|
|
||||||
Reset(ctx context.Context, section uint64, prevHead common.Hash) error
|
|
||||||
|
|
||||||
// Process crunches through the next header in the chain segment. The caller
|
|
||||||
// will ensure a sequential order of headers.
|
|
||||||
Process(ctx context.Context, header *types.Header) error
|
|
||||||
|
|
||||||
// Commit finalizes the section metadata and stores it into the database.
|
|
||||||
Commit() error
|
|
||||||
|
|
||||||
// Prune deletes the chain index older than the given threshold.
|
|
||||||
Prune(threshold uint64) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChainIndexerChain interface is used for connecting the indexer to a blockchain
|
|
||||||
type ChainIndexerChain interface {
|
|
||||||
// CurrentHeader retrieves the latest locally known header.
|
|
||||||
CurrentHeader() *types.Header
|
|
||||||
|
|
||||||
// SubscribeChainHeadEvent subscribes to new head header notifications.
|
|
||||||
SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChainIndexer does a post-processing job for equally sized sections of the
|
|
||||||
// canonical chain (like BlooomBits and CHT structures). A ChainIndexer is
|
|
||||||
// connected to the blockchain through the event system by starting a
|
|
||||||
// ChainHeadEventLoop in a goroutine.
|
|
||||||
//
|
|
||||||
// Further child ChainIndexers can be added which use the output of the parent
|
|
||||||
// section indexer. These child indexers receive new head notifications only
|
|
||||||
// after an entire section has been finished or in case of rollbacks that might
|
|
||||||
// affect already finished sections.
|
|
||||||
type ChainIndexer struct {
|
|
||||||
chainDb ethdb.Database // Chain database to index the data from
|
|
||||||
indexDb ethdb.Database // Prefixed table-view of the db to write index metadata into
|
|
||||||
backend ChainIndexerBackend // Background processor generating the index data content
|
|
||||||
children []*ChainIndexer // Child indexers to cascade chain updates to
|
|
||||||
|
|
||||||
active atomic.Bool // Flag whether the event loop was started
|
|
||||||
update chan struct{} // Notification channel that headers should be processed
|
|
||||||
quit chan chan error // Quit channel to tear down running goroutines
|
|
||||||
ctx context.Context
|
|
||||||
ctxCancel func()
|
|
||||||
|
|
||||||
sectionSize uint64 // Number of blocks in a single chain segment to process
|
|
||||||
confirmsReq uint64 // Number of confirmations before processing a completed segment
|
|
||||||
|
|
||||||
storedSections uint64 // Number of sections successfully indexed into the database
|
|
||||||
knownSections uint64 // Number of sections known to be complete (block wise)
|
|
||||||
cascadedHead uint64 // Block number of the last completed section cascaded to subindexers
|
|
||||||
|
|
||||||
checkpointSections uint64 // Number of sections covered by the checkpoint
|
|
||||||
checkpointHead common.Hash // Section head belonging to the checkpoint
|
|
||||||
|
|
||||||
throttling time.Duration // Disk throttling to prevent a heavy upgrade from hogging resources
|
|
||||||
|
|
||||||
log log.Logger
|
|
||||||
lock sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewChainIndexer creates a new chain indexer to do background processing on
|
|
||||||
// chain segments of a given size after certain number of confirmations passed.
|
|
||||||
// The throttling parameter might be used to prevent database thrashing.
|
|
||||||
func NewChainIndexer(chainDb ethdb.Database, indexDb ethdb.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer {
|
|
||||||
c := &ChainIndexer{
|
|
||||||
chainDb: chainDb,
|
|
||||||
indexDb: indexDb,
|
|
||||||
backend: backend,
|
|
||||||
update: make(chan struct{}, 1),
|
|
||||||
quit: make(chan chan error),
|
|
||||||
sectionSize: section,
|
|
||||||
confirmsReq: confirm,
|
|
||||||
throttling: throttling,
|
|
||||||
log: log.New("type", kind),
|
|
||||||
}
|
|
||||||
// Initialize database dependent fields and start the updater
|
|
||||||
c.loadValidSections()
|
|
||||||
c.ctx, c.ctxCancel = context.WithCancel(context.Background())
|
|
||||||
|
|
||||||
go c.updateLoop()
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddCheckpoint adds a checkpoint. Sections are never processed and the chain
|
|
||||||
// is not expected to be available before this point. The indexer assumes that
|
|
||||||
// the backend has sufficient information available to process subsequent sections.
|
|
||||||
//
|
|
||||||
// Note: knownSections == 0 and storedSections == checkpointSections until
|
|
||||||
// syncing reaches the checkpoint
|
|
||||||
func (c *ChainIndexer) AddCheckpoint(section uint64, shead common.Hash) {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
// Short circuit if the given checkpoint is below than local's.
|
|
||||||
if c.checkpointSections >= section+1 || section < c.storedSections {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.checkpointSections = section + 1
|
|
||||||
c.checkpointHead = shead
|
|
||||||
|
|
||||||
c.setSectionHead(section, shead)
|
|
||||||
c.setValidSections(section + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start creates a goroutine to feed chain head events into the indexer for
|
|
||||||
// cascading background processing. Children do not need to be started, they
|
|
||||||
// are notified about new events by their parents.
|
|
||||||
func (c *ChainIndexer) Start(chain ChainIndexerChain) {
|
|
||||||
events := make(chan ChainHeadEvent, 10)
|
|
||||||
sub := chain.SubscribeChainHeadEvent(events)
|
|
||||||
|
|
||||||
go c.eventLoop(chain.CurrentHeader(), events, sub)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close tears down all goroutines belonging to the indexer and returns any error
|
|
||||||
// that might have occurred internally.
|
|
||||||
func (c *ChainIndexer) Close() error {
|
|
||||||
var errs []error
|
|
||||||
|
|
||||||
c.ctxCancel()
|
|
||||||
|
|
||||||
// Tear down the primary update loop
|
|
||||||
errc := make(chan error)
|
|
||||||
c.quit <- errc
|
|
||||||
if err := <-errc; err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
// If needed, tear down the secondary event loop
|
|
||||||
if c.active.Load() {
|
|
||||||
c.quit <- errc
|
|
||||||
if err := <-errc; err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Close all children
|
|
||||||
for _, child := range c.children {
|
|
||||||
if err := child.Close(); err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Return any failures
|
|
||||||
switch {
|
|
||||||
case len(errs) == 0:
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case len(errs) == 1:
|
|
||||||
return errs[0]
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("%v", errs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// eventLoop is a secondary - optional - event loop of the indexer which is only
|
|
||||||
// started for the outermost indexer to push chain head events into a processing
|
|
||||||
// queue.
|
|
||||||
func (c *ChainIndexer) eventLoop(currentHeader *types.Header, events chan ChainHeadEvent, sub event.Subscription) {
|
|
||||||
// Mark the chain indexer as active, requiring an additional teardown
|
|
||||||
c.active.Store(true)
|
|
||||||
|
|
||||||
defer sub.Unsubscribe()
|
|
||||||
|
|
||||||
// Fire the initial new head event to start any outstanding processing
|
|
||||||
c.newHead(currentHeader.Number.Uint64(), false)
|
|
||||||
|
|
||||||
var (
|
|
||||||
prevHeader = currentHeader
|
|
||||||
prevHash = currentHeader.Hash()
|
|
||||||
)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case errc := <-c.quit:
|
|
||||||
// Chain indexer terminating, report no failure and abort
|
|
||||||
errc <- nil
|
|
||||||
return
|
|
||||||
|
|
||||||
case ev, ok := <-events:
|
|
||||||
// Received a new event, ensure it's not nil (closing) and update
|
|
||||||
if !ok {
|
|
||||||
errc := <-c.quit
|
|
||||||
errc <- nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ev.Header.ParentHash != prevHash {
|
|
||||||
// Reorg to the common ancestor if needed (might not exist in light sync mode, skip reorg then)
|
|
||||||
// TODO(karalabe, zsfelfoldi): This seems a bit brittle, can we detect this case explicitly?
|
|
||||||
|
|
||||||
if rawdb.ReadCanonicalHash(c.chainDb, prevHeader.Number.Uint64()) != prevHash {
|
|
||||||
if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, ev.Header); h != nil {
|
|
||||||
c.newHead(h.Number.Uint64(), true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.newHead(ev.Header.Number.Uint64(), false)
|
|
||||||
|
|
||||||
prevHeader, prevHash = ev.Header, ev.Header.Hash()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// newHead notifies the indexer about new chain heads and/or reorgs.
|
|
||||||
func (c *ChainIndexer) newHead(head uint64, reorg bool) {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
// If a reorg happened, invalidate all sections until that point
|
|
||||||
if reorg {
|
|
||||||
// Revert the known section number to the reorg point
|
|
||||||
known := (head + 1) / c.sectionSize
|
|
||||||
stored := known
|
|
||||||
if known < c.checkpointSections {
|
|
||||||
known = 0
|
|
||||||
}
|
|
||||||
if stored < c.checkpointSections {
|
|
||||||
stored = c.checkpointSections
|
|
||||||
}
|
|
||||||
if known < c.knownSections {
|
|
||||||
c.knownSections = known
|
|
||||||
}
|
|
||||||
// Revert the stored sections from the database to the reorg point
|
|
||||||
if stored < c.storedSections {
|
|
||||||
c.setValidSections(stored)
|
|
||||||
}
|
|
||||||
// Update the new head number to the finalized section end and notify children
|
|
||||||
head = known * c.sectionSize
|
|
||||||
|
|
||||||
if head < c.cascadedHead {
|
|
||||||
c.cascadedHead = head
|
|
||||||
for _, child := range c.children {
|
|
||||||
child.newHead(c.cascadedHead, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// No reorg, calculate the number of newly known sections and update if high enough
|
|
||||||
var sections uint64
|
|
||||||
if head >= c.confirmsReq {
|
|
||||||
sections = (head + 1 - c.confirmsReq) / c.sectionSize
|
|
||||||
if sections < c.checkpointSections {
|
|
||||||
sections = 0
|
|
||||||
}
|
|
||||||
if sections > c.knownSections {
|
|
||||||
if c.knownSections < c.checkpointSections {
|
|
||||||
// syncing reached the checkpoint, verify section head
|
|
||||||
syncedHead := rawdb.ReadCanonicalHash(c.chainDb, c.checkpointSections*c.sectionSize-1)
|
|
||||||
if syncedHead != c.checkpointHead {
|
|
||||||
c.log.Error("Synced chain does not match checkpoint", "number", c.checkpointSections*c.sectionSize-1, "expected", c.checkpointHead, "synced", syncedHead)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.knownSections = sections
|
|
||||||
|
|
||||||
select {
|
|
||||||
case c.update <- struct{}{}:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateLoop is the main event loop of the indexer which pushes chain segments
|
|
||||||
// down into the processing backend.
|
|
||||||
func (c *ChainIndexer) updateLoop() {
|
|
||||||
var (
|
|
||||||
updating bool
|
|
||||||
updated time.Time
|
|
||||||
)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case errc := <-c.quit:
|
|
||||||
// Chain indexer terminating, report no failure and abort
|
|
||||||
errc <- nil
|
|
||||||
return
|
|
||||||
|
|
||||||
case <-c.update:
|
|
||||||
// Section headers completed (or rolled back), update the index
|
|
||||||
c.lock.Lock()
|
|
||||||
if c.knownSections > c.storedSections {
|
|
||||||
// Periodically print an upgrade log message to the user
|
|
||||||
if time.Since(updated) > 8*time.Second {
|
|
||||||
if c.knownSections > c.storedSections+1 {
|
|
||||||
updating = true
|
|
||||||
c.log.Info("Upgrading chain index", "percentage", c.storedSections*100/c.knownSections)
|
|
||||||
}
|
|
||||||
updated = time.Now()
|
|
||||||
}
|
|
||||||
// Cache the current section count and head to allow unlocking the mutex
|
|
||||||
c.verifyLastHead()
|
|
||||||
section := c.storedSections
|
|
||||||
var oldHead common.Hash
|
|
||||||
if section > 0 {
|
|
||||||
oldHead = c.SectionHead(section - 1)
|
|
||||||
}
|
|
||||||
// Process the newly defined section in the background
|
|
||||||
c.lock.Unlock()
|
|
||||||
newHead, err := c.processSection(section, oldHead)
|
|
||||||
if err != nil {
|
|
||||||
select {
|
|
||||||
case <-c.ctx.Done():
|
|
||||||
<-c.quit <- nil
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
c.log.Error("Section processing failed", "error", err)
|
|
||||||
}
|
|
||||||
c.lock.Lock()
|
|
||||||
|
|
||||||
// If processing succeeded and no reorgs occurred, mark the section completed
|
|
||||||
if err == nil && (section == 0 || oldHead == c.SectionHead(section-1)) {
|
|
||||||
c.setSectionHead(section, newHead)
|
|
||||||
c.setValidSections(section + 1)
|
|
||||||
if c.storedSections == c.knownSections && updating {
|
|
||||||
updating = false
|
|
||||||
c.log.Info("Finished upgrading chain index")
|
|
||||||
}
|
|
||||||
c.cascadedHead = c.storedSections*c.sectionSize - 1
|
|
||||||
for _, child := range c.children {
|
|
||||||
c.log.Trace("Cascading chain index update", "head", c.cascadedHead)
|
|
||||||
child.newHead(c.cascadedHead, false)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If processing failed, don't retry until further notification
|
|
||||||
c.log.Debug("Chain index processing failed", "section", section, "err", err)
|
|
||||||
c.verifyLastHead()
|
|
||||||
c.knownSections = c.storedSections
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If there are still further sections to process, reschedule
|
|
||||||
if c.knownSections > c.storedSections {
|
|
||||||
time.AfterFunc(c.throttling, func() {
|
|
||||||
select {
|
|
||||||
case c.update <- struct{}{}:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
c.lock.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// processSection processes an entire section by calling backend functions while
|
|
||||||
// ensuring the continuity of the passed headers. Since the chain mutex is not
|
|
||||||
// held while processing, the continuity can be broken by a long reorg, in which
|
|
||||||
// case the function returns with an error.
|
|
||||||
func (c *ChainIndexer) processSection(section uint64, lastHead common.Hash) (common.Hash, error) {
|
|
||||||
c.log.Trace("Processing new chain section", "section", section)
|
|
||||||
|
|
||||||
// Reset and partial processing
|
|
||||||
if err := c.backend.Reset(c.ctx, section, lastHead); err != nil {
|
|
||||||
c.setValidSections(0)
|
|
||||||
return common.Hash{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for number := section * c.sectionSize; number < (section+1)*c.sectionSize; number++ {
|
|
||||||
hash := rawdb.ReadCanonicalHash(c.chainDb, number)
|
|
||||||
if hash == (common.Hash{}) {
|
|
||||||
return common.Hash{}, fmt.Errorf("canonical block #%d unknown", number)
|
|
||||||
}
|
|
||||||
header := rawdb.ReadHeader(c.chainDb, hash, number)
|
|
||||||
if header == nil {
|
|
||||||
return common.Hash{}, fmt.Errorf("block #%d [%x..] not found", number, hash[:4])
|
|
||||||
} else if header.ParentHash != lastHead {
|
|
||||||
return common.Hash{}, errors.New("chain reorged during section processing")
|
|
||||||
}
|
|
||||||
if err := c.backend.Process(c.ctx, header); err != nil {
|
|
||||||
return common.Hash{}, err
|
|
||||||
}
|
|
||||||
lastHead = header.Hash()
|
|
||||||
}
|
|
||||||
if err := c.backend.Commit(); err != nil {
|
|
||||||
return common.Hash{}, err
|
|
||||||
}
|
|
||||||
return lastHead, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// verifyLastHead compares last stored section head with the corresponding block hash in the
|
|
||||||
// actual canonical chain and rolls back reorged sections if necessary to ensure that stored
|
|
||||||
// sections are all valid
|
|
||||||
func (c *ChainIndexer) verifyLastHead() {
|
|
||||||
for c.storedSections > 0 && c.storedSections > c.checkpointSections {
|
|
||||||
if c.SectionHead(c.storedSections-1) == rawdb.ReadCanonicalHash(c.chainDb, c.storedSections*c.sectionSize-1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.setValidSections(c.storedSections - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sections returns the number of processed sections maintained by the indexer
|
|
||||||
// and also the information about the last header indexed for potential canonical
|
|
||||||
// verifications.
|
|
||||||
func (c *ChainIndexer) Sections() (uint64, uint64, common.Hash) {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
c.verifyLastHead()
|
|
||||||
return c.storedSections, c.storedSections*c.sectionSize - 1, c.SectionHead(c.storedSections - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddChildIndexer adds a child ChainIndexer that can use the output of this one
|
|
||||||
func (c *ChainIndexer) AddChildIndexer(indexer *ChainIndexer) {
|
|
||||||
if indexer == c {
|
|
||||||
panic("can't add indexer as a child of itself")
|
|
||||||
}
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
c.children = append(c.children, indexer)
|
|
||||||
|
|
||||||
// Cascade any pending updates to new children too
|
|
||||||
sections := c.storedSections
|
|
||||||
if c.knownSections < sections {
|
|
||||||
// if a section is "stored" but not "known" then it is a checkpoint without
|
|
||||||
// available chain data so we should not cascade it yet
|
|
||||||
sections = c.knownSections
|
|
||||||
}
|
|
||||||
if sections > 0 {
|
|
||||||
indexer.newHead(sections*c.sectionSize-1, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prune deletes all chain data older than given threshold.
|
|
||||||
func (c *ChainIndexer) Prune(threshold uint64) error {
|
|
||||||
return c.backend.Prune(threshold)
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadValidSections reads the number of valid sections from the index database
|
|
||||||
// and caches is into the local state.
|
|
||||||
func (c *ChainIndexer) loadValidSections() {
|
|
||||||
data, _ := c.indexDb.Get([]byte("count"))
|
|
||||||
if len(data) == 8 {
|
|
||||||
c.storedSections = binary.BigEndian.Uint64(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setValidSections writes the number of valid sections to the index database
|
|
||||||
func (c *ChainIndexer) setValidSections(sections uint64) {
|
|
||||||
// Set the current number of valid sections in the database
|
|
||||||
var data [8]byte
|
|
||||||
binary.BigEndian.PutUint64(data[:], sections)
|
|
||||||
c.indexDb.Put([]byte("count"), data[:])
|
|
||||||
|
|
||||||
// Remove any reorged sections, caching the valids in the mean time
|
|
||||||
for c.storedSections > sections {
|
|
||||||
c.storedSections--
|
|
||||||
c.removeSectionHead(c.storedSections)
|
|
||||||
}
|
|
||||||
c.storedSections = sections // needed if new > old
|
|
||||||
}
|
|
||||||
|
|
||||||
// SectionHead retrieves the last block hash of a processed section from the
|
|
||||||
// index database.
|
|
||||||
func (c *ChainIndexer) SectionHead(section uint64) common.Hash {
|
|
||||||
var data [8]byte
|
|
||||||
binary.BigEndian.PutUint64(data[:], section)
|
|
||||||
|
|
||||||
hash, _ := c.indexDb.Get(append([]byte("shead"), data[:]...))
|
|
||||||
if len(hash) == len(common.Hash{}) {
|
|
||||||
return common.BytesToHash(hash)
|
|
||||||
}
|
|
||||||
return common.Hash{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setSectionHead writes the last block hash of a processed section to the index
|
|
||||||
// database.
|
|
||||||
func (c *ChainIndexer) setSectionHead(section uint64, hash common.Hash) {
|
|
||||||
var data [8]byte
|
|
||||||
binary.BigEndian.PutUint64(data[:], section)
|
|
||||||
|
|
||||||
c.indexDb.Put(append([]byte("shead"), data[:]...), hash.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeSectionHead removes the reference to a processed section from the index
|
|
||||||
// database.
|
|
||||||
func (c *ChainIndexer) removeSectionHead(section uint64) {
|
|
||||||
var data [8]byte
|
|
||||||
binary.BigEndian.PutUint64(data[:], section)
|
|
||||||
|
|
||||||
c.indexDb.Delete(append([]byte("shead"), data[:]...))
|
|
||||||
}
|
|
||||||
|
|
@ -1,246 +0,0 @@
|
||||||
// Copyright 2017 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Runs multiple tests with randomized parameters.
|
|
||||||
func TestChainIndexerSingle(t *testing.T) {
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
testChainIndexer(t, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs multiple tests with randomized parameters and different number of
|
|
||||||
// chain backends.
|
|
||||||
func TestChainIndexerWithChildren(t *testing.T) {
|
|
||||||
for i := 2; i < 8; i++ {
|
|
||||||
testChainIndexer(t, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// testChainIndexer runs a test with either a single chain indexer or a chain of
|
|
||||||
// multiple backends. The section size and required confirmation count parameters
|
|
||||||
// are randomized.
|
|
||||||
func testChainIndexer(t *testing.T, count int) {
|
|
||||||
db := rawdb.NewMemoryDatabase()
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
// Create a chain of indexers and ensure they all report empty
|
|
||||||
backends := make([]*testChainIndexBackend, count)
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
var (
|
|
||||||
sectionSize = uint64(rand.Intn(100) + 1)
|
|
||||||
confirmsReq = uint64(rand.Intn(10))
|
|
||||||
)
|
|
||||||
backends[i] = &testChainIndexBackend{t: t, processCh: make(chan uint64)}
|
|
||||||
backends[i].indexer = NewChainIndexer(db, rawdb.NewTable(db, string([]byte{byte(i)})), backends[i], sectionSize, confirmsReq, 0, fmt.Sprintf("indexer-%d", i))
|
|
||||||
|
|
||||||
if sections, _, _ := backends[i].indexer.Sections(); sections != 0 {
|
|
||||||
t.Fatalf("Canonical section count mismatch: have %v, want %v", sections, 0)
|
|
||||||
}
|
|
||||||
if i > 0 {
|
|
||||||
backends[i-1].indexer.AddChildIndexer(backends[i].indexer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer backends[0].indexer.Close() // parent indexer shuts down children
|
|
||||||
// notify pings the root indexer about a new head or reorg, then expect
|
|
||||||
// processed blocks if a section is processable
|
|
||||||
notify := func(headNum, failNum uint64, reorg bool) {
|
|
||||||
backends[0].indexer.newHead(headNum, reorg)
|
|
||||||
if reorg {
|
|
||||||
for _, backend := range backends {
|
|
||||||
headNum = backend.reorg(headNum)
|
|
||||||
backend.assertSections()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var cascade bool
|
|
||||||
for _, backend := range backends {
|
|
||||||
headNum, cascade = backend.assertBlocks(headNum, failNum)
|
|
||||||
if !cascade {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
backend.assertSections()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// inject inserts a new random canonical header into the database directly
|
|
||||||
inject := func(number uint64) {
|
|
||||||
header := &types.Header{Number: big.NewInt(int64(number)), Extra: big.NewInt(rand.Int63()).Bytes()}
|
|
||||||
if number > 0 {
|
|
||||||
header.ParentHash = rawdb.ReadCanonicalHash(db, number-1)
|
|
||||||
}
|
|
||||||
rawdb.WriteHeader(db, header)
|
|
||||||
rawdb.WriteCanonicalHash(db, header.Hash(), number)
|
|
||||||
}
|
|
||||||
// Start indexer with an already existing chain
|
|
||||||
for i := uint64(0); i <= 100; i++ {
|
|
||||||
inject(i)
|
|
||||||
}
|
|
||||||
notify(100, 100, false)
|
|
||||||
|
|
||||||
// Add new blocks one by one
|
|
||||||
for i := uint64(101); i <= 1000; i++ {
|
|
||||||
inject(i)
|
|
||||||
notify(i, i, false)
|
|
||||||
}
|
|
||||||
// Do a reorg
|
|
||||||
notify(500, 500, true)
|
|
||||||
|
|
||||||
// Create new fork
|
|
||||||
for i := uint64(501); i <= 1000; i++ {
|
|
||||||
inject(i)
|
|
||||||
notify(i, i, false)
|
|
||||||
}
|
|
||||||
for i := uint64(1001); i <= 1500; i++ {
|
|
||||||
inject(i)
|
|
||||||
}
|
|
||||||
// Failed processing scenario where less blocks are available than notified
|
|
||||||
notify(2000, 1500, false)
|
|
||||||
|
|
||||||
// Notify about a reorg (which could have caused the missing blocks if happened during processing)
|
|
||||||
notify(1500, 1500, true)
|
|
||||||
|
|
||||||
// Create new fork
|
|
||||||
for i := uint64(1501); i <= 2000; i++ {
|
|
||||||
inject(i)
|
|
||||||
notify(i, i, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// testChainIndexBackend implements ChainIndexerBackend
|
|
||||||
type testChainIndexBackend struct {
|
|
||||||
t *testing.T
|
|
||||||
indexer *ChainIndexer
|
|
||||||
section, headerCnt, stored uint64
|
|
||||||
processCh chan uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// assertSections verifies if a chain indexer has the correct number of section.
|
|
||||||
func (b *testChainIndexBackend) assertSections() {
|
|
||||||
// Keep trying for 3 seconds if it does not match
|
|
||||||
var sections uint64
|
|
||||||
for i := 0; i < 300; i++ {
|
|
||||||
sections, _, _ = b.indexer.Sections()
|
|
||||||
if sections == b.stored {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
}
|
|
||||||
b.t.Fatalf("Canonical section count mismatch: have %v, want %v", sections, b.stored)
|
|
||||||
}
|
|
||||||
|
|
||||||
// assertBlocks expects processing calls after new blocks have arrived. If the
|
|
||||||
// failNum < headNum then we are simulating a scenario where a reorg has happened
|
|
||||||
// after the processing has started and the processing of a section fails.
|
|
||||||
func (b *testChainIndexBackend) assertBlocks(headNum, failNum uint64) (uint64, bool) {
|
|
||||||
var sections uint64
|
|
||||||
if headNum >= b.indexer.confirmsReq {
|
|
||||||
sections = (headNum + 1 - b.indexer.confirmsReq) / b.indexer.sectionSize
|
|
||||||
if sections > b.stored {
|
|
||||||
// expect processed blocks
|
|
||||||
for expectd := b.stored * b.indexer.sectionSize; expectd < sections*b.indexer.sectionSize; expectd++ {
|
|
||||||
if expectd > failNum {
|
|
||||||
// rolled back after processing started, no more process calls expected
|
|
||||||
// wait until updating is done to make sure that processing actually fails
|
|
||||||
var updating bool
|
|
||||||
for i := 0; i < 300; i++ {
|
|
||||||
b.indexer.lock.Lock()
|
|
||||||
updating = b.indexer.knownSections > b.indexer.storedSections
|
|
||||||
b.indexer.lock.Unlock()
|
|
||||||
if !updating {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
}
|
|
||||||
if updating {
|
|
||||||
b.t.Fatalf("update did not finish")
|
|
||||||
}
|
|
||||||
sections = expectd / b.indexer.sectionSize
|
|
||||||
break
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-time.After(10 * time.Second):
|
|
||||||
b.t.Fatalf("Expected processed block #%d, got nothing", expectd)
|
|
||||||
case processed := <-b.processCh:
|
|
||||||
if processed != expectd {
|
|
||||||
b.t.Errorf("Expected processed block #%d, got #%d", expectd, processed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.stored = sections
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if b.stored == 0 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return b.stored*b.indexer.sectionSize - 1, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *testChainIndexBackend) reorg(headNum uint64) uint64 {
|
|
||||||
firstChanged := (headNum + 1) / b.indexer.sectionSize
|
|
||||||
if firstChanged < b.stored {
|
|
||||||
b.stored = firstChanged
|
|
||||||
}
|
|
||||||
return b.stored * b.indexer.sectionSize
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *testChainIndexBackend) Reset(ctx context.Context, section uint64, prevHead common.Hash) error {
|
|
||||||
b.section = section
|
|
||||||
b.headerCnt = 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *testChainIndexBackend) Process(ctx context.Context, header *types.Header) error {
|
|
||||||
b.headerCnt++
|
|
||||||
if b.headerCnt > b.indexer.sectionSize {
|
|
||||||
b.t.Error("Processing too many headers")
|
|
||||||
}
|
|
||||||
//t.processCh <- header.Number.Uint64()
|
|
||||||
select {
|
|
||||||
case <-time.After(10 * time.Second):
|
|
||||||
b.t.Error("Unexpected call to Process")
|
|
||||||
// Can't use Fatal since this is not the test's goroutine.
|
|
||||||
// Returning error stops the chainIndexer's updateLoop
|
|
||||||
return errors.New("unexpected call to Process")
|
|
||||||
case b.processCh <- header.Number.Uint64():
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *testChainIndexBackend) Commit() error {
|
|
||||||
if b.headerCnt != b.indexer.sectionSize {
|
|
||||||
b.t.Error("Not enough headers processed")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *testChainIndexBackend) Prune(threshold uint64) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -504,6 +504,13 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
if gen != nil {
|
if gen != nil {
|
||||||
gen(i, b)
|
gen(i, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requests := b.collectRequests(false)
|
||||||
|
if requests != nil {
|
||||||
|
reqHash := types.CalcRequestsHash(requests)
|
||||||
|
b.header.RequestsHash = &reqHash
|
||||||
|
}
|
||||||
|
|
||||||
body := &types.Body{
|
body := &types.Body{
|
||||||
Transactions: b.txs,
|
Transactions: b.txs,
|
||||||
Uncles: b.uncles,
|
Uncles: b.uncles,
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,11 @@ func (cv *ChainView) getReceipts(number uint64) types.Receipts {
|
||||||
if number > cv.headNumber {
|
if number > cv.headNumber {
|
||||||
panic("invalid block number")
|
panic("invalid block number")
|
||||||
}
|
}
|
||||||
return cv.chain.GetReceiptsByHash(cv.blockHash(number))
|
blockHash := cv.blockHash(number)
|
||||||
|
if blockHash == (common.Hash{}) {
|
||||||
|
log.Error("Chain view: block hash unavailable", "number", number, "head", cv.headNumber)
|
||||||
|
}
|
||||||
|
return cv.chain.GetReceiptsByHash(blockHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// limitedView returns a new chain view that is a truncated version of the parent view.
|
// limitedView returns a new chain view that is a truncated version of the parent view.
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ var checkpointsSepoliaJSON []byte
|
||||||
//go:embed checkpoints_holesky.json
|
//go:embed checkpoints_holesky.json
|
||||||
var checkpointsHoleskyJSON []byte
|
var checkpointsHoleskyJSON []byte
|
||||||
|
|
||||||
|
//go:embed checkpoints_hoodi.json
|
||||||
|
var checkpointsHoodiJSON []byte
|
||||||
|
|
||||||
// checkpoints lists sets of checkpoints for multiple chains. The matching
|
// checkpoints lists sets of checkpoints for multiple chains. The matching
|
||||||
// checkpoint set is autodetected by the indexer once the canonical chain is
|
// checkpoint set is autodetected by the indexer once the canonical chain is
|
||||||
// known.
|
// known.
|
||||||
|
|
@ -53,6 +56,7 @@ var checkpoints = []checkpointList{
|
||||||
decodeCheckpoints(checkpointsMainnetJSON),
|
decodeCheckpoints(checkpointsMainnetJSON),
|
||||||
decodeCheckpoints(checkpointsSepoliaJSON),
|
decodeCheckpoints(checkpointsSepoliaJSON),
|
||||||
decodeCheckpoints(checkpointsHoleskyJSON),
|
decodeCheckpoints(checkpointsHoleskyJSON),
|
||||||
|
decodeCheckpoints(checkpointsHoodiJSON),
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeCheckpoints(encoded []byte) (result checkpointList) {
|
func decodeCheckpoints(encoded []byte) (result checkpointList) {
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,21 @@
|
||||||
[
|
[
|
||||||
{"blockNumber": 814411, "blockId": "0xf763e96fc3920359c5f706803024b78e83796a3a8563bb5a83c3ddd7cbfde287", "firstIndex": 67107637},
|
{"blockNumber": 814410, "blockId": "0x6c38f0d4ff2c23ae187f581cebb0963c0ec2dbf051b289de1582c369c98a3244", "firstIndex": 67107349},
|
||||||
{"blockNumber": 914278, "blockId": "0x0678cf8d53c0d6d27896df657d98cc73bc63ca468b6295068003938ef9b0f927", "firstIndex": 134217671},
|
{"blockNumber": 914268, "blockId": "0xeff161573a11eb6e2ab930674a5245b2c5ffc5e9e63093503344ec6fa60578a3", "firstIndex": 134216064},
|
||||||
{"blockNumber": 1048874, "blockId": "0x3620c3d52a40ff4d9fc58c3104cfa2f327f55592caf6a2394c207a5e00b4f740", "firstIndex": 201326382},
|
{"blockNumber": 1048866, "blockId": "0xebd3b95415dad9ab7f2b1d25e48c791e299063c09427bbde54217029c3e215ad", "firstIndex": 201325914},
|
||||||
{"blockNumber": 1144441, "blockId": "0x438fb42850f5a0d8e1666de598a4d0106b62da0f7448c62fe029b8cbad35d08d", "firstIndex": 268435440},
|
{"blockNumber": 1144433, "blockId": "0x0c895438ef12a2c835b4372c209e40a499ba2b18ed0e658846813784de391392", "firstIndex": 268434935},
|
||||||
{"blockNumber": 1230411, "blockId": "0xf0ee07e60a93910723b259473a253dd9cf674e8b78c4f153b32ad7032efffeeb", "firstIndex": 335543079},
|
{"blockNumber": 1230406, "blockId": "0xd3512e7241efc9853e46b1ad565403d302f62457b6dd84917c31ff375fabf487", "firstIndex": 335544096},
|
||||||
{"blockNumber": 1309112, "blockId": "0xc1646e5ef4b4343880a85b1a4111e3321d609a1225e9cebbe10d1c7abf99e58d", "firstIndex": 402653100},
|
{"blockNumber": 1309104, "blockId": "0xcf108c6e002e7a5657bf7587adde03edf5f20d03e95b66a194eb8080daaf4f97", "firstIndex": 402653143},
|
||||||
{"blockNumber": 1380522, "blockId": "0x1617cae91989d97ac6335c4217aa6cc7f7f4c2837e20b3b5211d98d6f9e97e44", "firstIndex": 469761917},
|
{"blockNumber": 1380499, "blockId": "0x984b0f8b6bf06f1240bbca8c1df9bef3880bedafd5b5c2a55cbc2f64c9efb974", "firstIndex": 469759822},
|
||||||
{"blockNumber": 1476962, "blockId": "0xd978455d2618d093dfc685d7f43f61be6dae0fa8a9cb915ae459aa6e0a5525f0", "firstIndex": 536870773},
|
{"blockNumber": 1476950, "blockId": "0x8323b528bb8d80a96b172de92452be0f45078a9ca311cb4be6675f089e25a426", "firstIndex": 536870335},
|
||||||
{"blockNumber": 1533518, "blockId": "0xe7d39d71bd9d5f1f3157c35e0329531a7950a19e3042407e38948b89b5384f78", "firstIndex": 603979664},
|
{"blockNumber": 1533506, "blockId": "0x737dc416070aa3b522a0c2ab813a70c1820f062c718f27597394f309f0004106", "firstIndex": 603979618},
|
||||||
{"blockNumber": 1613787, "blockId": "0xa793168d135c075732a618ec367faaed5f359ffa81898c73cb4ec54ec2caa696", "firstIndex": 671088003},
|
{"blockNumber": 1613764, "blockId": "0x9d6a5a505afdda86b1ebcc2b10cb687a1f89c2e2b74315945a3ddc6a0b3c9cd6", "firstIndex": 671088253},
|
||||||
{"blockNumber": 1719099, "blockId": "0xc4394c71a8a24efe64c5ff2afcdd1594f3708524e6084aa7dadd862bd704ab03", "firstIndex": 738196914},
|
{"blockNumber": 1719073, "blockId": "0x17bf6a51d9c55a908c3e9e652f80b2aa464b049c697abf3bd5a537e461aff0b9", "firstIndex": 738197366},
|
||||||
{"blockNumber": 1973165, "blockId": "0xee3a9e959a437c707a3036736ec8d42a9261ac6100972c26f65eedcde315a81d", "firstIndex": 805306333},
|
{"blockNumber": 1973133, "blockId": "0x14b288d70e688de3334d09283670301aacfed21c193da8a56fd63767f8177705", "firstIndex": 805305624},
|
||||||
{"blockNumber": 2274844, "blockId": "0x76e2d33653ed9282c63ad09d721e1f2e29064aa9c26202e20fc4cc73e8dfe5f6", "firstIndex": 872415141},
|
{"blockNumber": 2274761, "blockId": "0xf02790b273b04219e001d2fcc93e8e47708cb228364e96ad754bc8050d08a9aa", "firstIndex": 872414871},
|
||||||
{"blockNumber": 2530503, "blockId": "0x59f4e45345f8b8f848be5004fe75c4a28f651864256c3aa9b2da63369432b718", "firstIndex": 939523693},
|
{"blockNumber": 2530470, "blockId": "0x157ea98b1a7e66dd3f045da8e25219800671f9a000211d3d94006efd33d89a80", "firstIndex": 939523234},
|
||||||
{"blockNumber": 2781903, "blockId": "0xc981e91c6fb69c5e8146ead738fcfc561831f11d7786d39c7fa533966fc37675", "firstIndex": 1006632906},
|
{"blockNumber": 2781706, "blockId": "0xa723663a584e280700d2302eba03d1b3b6549333db70c6152576d33e2911f594", "firstIndex": 1006632936},
|
||||||
{"blockNumber": 3101713, "blockId": "0xc7baa577c91d8439e3fc79002d2113d07ca54a4724bf2f1f5af937b7ba8e1f32", "firstIndex": 1073741382},
|
{"blockNumber": 3101669, "blockId": "0xa6e66a18fed64d33178c7088f273c404be597662c34f6e6884cf2e24f3ea4ace", "firstIndex": 1073741353},
|
||||||
{"blockNumber": 3221770, "blockId": "0xa6b8240b7883fcc71aa5001b5ba66c889975c5217e14c16edebdd6f6e23a9424", "firstIndex": 1140850360}
|
{"blockNumber": 3221725, "blockId": "0xe771f897dece48b1583cc1d1d10de8015da57407eb1fdf239fdbe46eaab85143", "firstIndex": 1140850137},
|
||||||
|
{"blockNumber": 3357164, "blockId": "0x6252d0aa54c79623b0680069c88d7b5c47983f0d5c4845b6c811b8d9b5e8ff3c", "firstIndex": 1207959453},
|
||||||
|
{"blockNumber": 3447019, "blockId": "0xeb7d585e1e063f3cc05ed399fbf6c2df63c271f62f030acb804e9fb1e74b6dc1", "firstIndex": 1275067542}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue