mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
Merge branch 'gethmaster' into gethintegration
This commit is contained in:
commit
8261fd8160
147 changed files with 11020 additions and 2050 deletions
|
|
@ -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"
|
||||||
|
|
@ -2072,20 +2072,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 +2098,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
|
||||||
|
}
|
||||||
|
|
@ -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) {
|
||||||
|
|
@ -433,14 +450,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 +495,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 +525,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 +548,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)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
@ -55,4 +55,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))
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,9 @@ 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),
|
||||||
Description: `
|
Description: `
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
||||||
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
common/range_test.go
Normal file
36
common/range_test.go
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
// 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 (
|
||||||
|
"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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
1
core/filtermaps/checkpoints_hoodi.json
Normal file
1
core/filtermaps/checkpoints_hoodi.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
[]
|
||||||
|
|
@ -1,256 +1,264 @@
|
||||||
[
|
[
|
||||||
{"blockNumber": 4166218, "blockId": "0xdd767e0426256179125551e8e40f33565a96d1c94076c7746fa79d767ed4ad65", "firstIndex": 67108680},
|
{"blockNumber": 4166212, "blockId": "0xd94b724fc1c7dceb3251b51b81f7a0f3220ae5b9add1e62917004f14f2a3532c", "firstIndex": 67108840},
|
||||||
{"blockNumber": 4514014, "blockId": "0x33a0879bdabea4a7a3f2b424388cbcbf2fbd519bddadf13752a259049c78e95d", "firstIndex": 134217343},
|
{"blockNumber": 4513996, "blockId": "0xc0fd25fef5888609d05fa8c5620d8e18c31cdd675dd4ee926ff966668f0e5d76", "firstIndex": 134217480},
|
||||||
{"blockNumber": 4817415, "blockId": "0x4f0e8c7dd04fbe0985b9394575b19f13ea66a2a628fa5b08178ce4b138c6db80", "firstIndex": 201326352},
|
{"blockNumber": 4817399, "blockId": "0x8573c3166fb7f716e97cf6109d382f86441238e0b85828944a072ae8583a6cfa", "firstIndex": 201326547},
|
||||||
{"blockNumber": 5087733, "blockId": "0xc84cd5e9cda999c919803c7a53a23bb77a18827fbde401d3463f1e9e52536424", "firstIndex": 268435343},
|
{"blockNumber": 5087706, "blockId": "0xcd2dfae45901e299b25faa04c10df60983d5c0a3d0e478e789c7aeec980cf691", "firstIndex": 268435422},
|
||||||
{"blockNumber": 5306107, "blockId": "0x13f028b5fc055d23f55a92a2eeecfbcfbda8a08e4cd519ce451ba2e70428f5f9", "firstIndex": 335544094},
|
{"blockNumber": 5306085, "blockId": "0xe8026984c85873f2b24018a7e0bdf8c2df136b2fc49666b4addf0d2e067890da", "firstIndex": 335544018},
|
||||||
{"blockNumber": 5509918, "blockId": "0x1ed770a58a7b4d4a828b7bb44c8820a674d562b23a6a0139981abe4c489d4dad", "firstIndex": 402652853},
|
{"blockNumber": 5509898, "blockId": "0x41bc63dc8184f9a7d4b9a5a554e00eee32fee60ccfa2339264be11270ac28de1", "firstIndex": 402652789},
|
||||||
{"blockNumber": 5670390, "blockId": "0x3923ee6a62e6cc5132afdadf1851ae4e73148e6fbe0a8319cafd2a120c98efa3", "firstIndex": 469761897},
|
{"blockNumber": 5670367, "blockId": "0xe61c2ba463f2f458817ed1bf0ff9fb9d07e9d7354f46b48175b2d784b817bf3b", "firstIndex": 469761896},
|
||||||
{"blockNumber": 5826139, "blockId": "0xe61bc6ef03c333805f26319e1688f82553f98aa5e902b200e0621a3371b69050", "firstIndex": 536870853},
|
{"blockNumber": 5826113, "blockId": "0xfbbb1fc5e03a5562bf6b7f1799d7a572d9ef66c7fd0e0b9f4fed7262767b5c86", "firstIndex": 536870852},
|
||||||
{"blockNumber": 5953029, "blockId": "0x43d710b1b7243b848400975048ccefdfaba091c692c7f01c619d988886cc160f", "firstIndex": 603979580},
|
{"blockNumber": 5953008, "blockId": "0x6bbdccd094928e846de3c615a33f2952e3259afaa1929f4ee241a56907d0593b", "firstIndex": 603979150},
|
||||||
{"blockNumber": 6102846, "blockId": "0xa100b2018f6545cc689656b4b846677b138955b7efd30e850cd14c246430ba18", "firstIndex": 671088291},
|
{"blockNumber": 6102812, "blockId": "0x2403f2502088a1fa26c1294f5245032fe3b7f3a8bb14c12d0ba8d577156bbc1b", "firstIndex": 671087962},
|
||||||
{"blockNumber": 6276718, "blockId": "0xb832ac448b06c104ba50faefd58b0b94d53c0fba5cb268086adad4db99c2f35f", "firstIndex": 738197399},
|
{"blockNumber": 6276672, "blockId": "0xeaa05a0e0574fbb164244628a7d14d9d47f1692941098aa737059d44104401df", "firstIndex": 738197399},
|
||||||
{"blockNumber": 6448696, "blockId": "0x48e8ae6f729ad6c76b6cf632bd52a6df7886ed55be09d43c5004fcc1463e533b", "firstIndex": 805305988},
|
{"blockNumber": 6448662, "blockId": "0xe6f097fa18a2cef425514e863659e42e1aa8d74df49cb0bed5877e82a08d1f84", "firstIndex": 805306056},
|
||||||
{"blockNumber": 6655974, "blockId": "0xac395971a6ffc30f807848f68b97b2834f8ea13478a7615860b6a69e3d0823ca", "firstIndex": 872415033},
|
{"blockNumber": 6655925, "blockId": "0xee5c9d87b06dc0c2e850fead07bcd13f85d45ad6b5a6e7ebee53cc8618772786", "firstIndex": 872415229},
|
||||||
{"blockNumber": 6873949, "blockId": "0xc522ddb1113b1e9a87b2bdcb11ce78756beba6454a890122f121a032b5769354", "firstIndex": 939523784},
|
{"blockNumber": 6873878, "blockId": "0x9a0ea103146da21fa1d9cab7ff609ec2c5e7f1856288a1f744239588e33904c2", "firstIndex": 939524080},
|
||||||
{"blockNumber": 7080953, "blockId": "0x3606de577d80120d1edbb64bad7fa6795e788bae342866a98cc58ce2f7575045", "firstIndex": 1006632796},
|
{"blockNumber": 7080893, "blockId": "0x35ad45055d7a1a3ef94efeb05e4122757bcc126ff1bc2b4ac72dc78ab3c0fd75", "firstIndex": 1006632327},
|
||||||
{"blockNumber": 7267002, "blockId": "0xad770882a69d216e955e34fef84851e56c0de82deacd6187a7a41f6170cd6c6d", "firstIndex": 1073741045},
|
{"blockNumber": 7266955, "blockId": "0x7b80f70520f2c16eb5890f4963af8f60446f50af82b589ceaf009d09e704b302", "firstIndex": 1073741608},
|
||||||
{"blockNumber": 7466708, "blockId": "0x17a48817b3a65aba333a5b56f3ff2e86fbcc19e184b046a5305a5182fdd8eb8a", "firstIndex": 1140850680},
|
{"blockNumber": 7466649, "blockId": "0xea8980b5c692c729013f9cc4c9f66e94d5ef2c5caad23f370be0953b6d85f32c", "firstIndex": 1140850335},
|
||||||
{"blockNumber": 7661807, "blockId": "0xa74731ee775fbd3f4d9313c68562737dd7c8d2c9eb968791d8abe167e16ddc96", "firstIndex": 1207959112},
|
{"blockNumber": 7661736, "blockId": "0x615cdb03dbf29a22d59bbc769c03f3647c2c9abb7d1767f3f6529708209e7073", "firstIndex": 1207959232},
|
||||||
{"blockNumber": 7834556, "blockId": "0xe4b4812448075508cb05a0e3257f91b49509dc78cd963676a633864db6e78956", "firstIndex": 1275068095},
|
{"blockNumber": 7834494, "blockId": "0x05b7dd13e2eb8a833e4b278f9151ca01b294ae5fc5617769422ec85ffb446215", "firstIndex": 1275068098},
|
||||||
{"blockNumber": 7990068, "blockId": "0x07bd4ca38abb4584a6209e04035646aa545ebbb6c948d438d4c25bfd9cb205fa", "firstIndex": 1342176620},
|
{"blockNumber": 7989998, "blockId": "0x4b5026add7f2fc2c02993b82c61bceba1b75cfcb8a78c5112cc2832bc0413be6", "firstIndex": 1342177025},
|
||||||
{"blockNumber": 8143032, "blockId": "0x0e3149e9637290b044ee693b8fcb66e23d22db3ad0bdda32962138ba18e59f3f", "firstIndex": 1409285949},
|
{"blockNumber": 8142950, "blockId": "0x9f56b7753a0e9964973f3e096e1385215e3aef232b448359e5bec05046b016a3", "firstIndex": 1409285545},
|
||||||
{"blockNumber": 8297660, "blockId": "0x34cd24f80247f7dfaf316b2e637f4b62f72ecc90703014fb25cb98ad044fc2c0", "firstIndex": 1476394911},
|
{"blockNumber": 8297598, "blockId": "0x2ddfeb161fe34ff73c4a995bb94256c3b522b39348169edb97bb3d876ccdf77d", "firstIndex": 1476394898},
|
||||||
{"blockNumber": 8465137, "blockId": "0x4452fa296498248d7f10c9dc6ec1e4ae7503aa07f491e6d38b21aea5d2c658a8", "firstIndex": 1543503744},
|
{"blockNumber": 8465061, "blockId": "0xfdbe5435da5ae9fb34a9154e5ebe515afac9a128e383f798f1e69952be404fcd", "firstIndex": 1543503805},
|
||||||
{"blockNumber": 8655820, "blockId": "0x7bdb9008b30be420f7152cc294ac6e5328eed5b4abd954a34105de3da24f3cc6", "firstIndex": 1610612619},
|
{"blockNumber": 8655740, "blockId": "0x305137325a39a44aba997e214c05f32d965658f7e3fe20322f2e57e72f239977", "firstIndex": 1610612406},
|
||||||
{"blockNumber": 8807187, "blockId": "0xde03e3bfddc722c019f0b59bc55efabcd5ab68c6711f4c08d0390a56f396590d", "firstIndex": 1677721589},
|
{"blockNumber": 8807102, "blockId": "0xc32f9fd9a43d2b502dbcc4a683ffe324fca9a871753478bcb1f4fb9573da96a5", "firstIndex": 1677721343},
|
||||||
{"blockNumber": 8911171, "blockId": "0xe44f342de74ab05a2a994f8841bdf88f720b9dc260177ba4030d0f7077901324", "firstIndex": 1744830310},
|
{"blockNumber": 8911110, "blockId": "0x806eabee7dc429b57afcb6c0b72b61728b4f13c62ee9942f1813790463f9ab5b", "firstIndex": 1744830172},
|
||||||
{"blockNumber": 8960320, "blockId": "0x79764f9ff6e0fe4848eda1805687872021076e4e603112861af84181395ac559", "firstIndex": 1811938893},
|
{"blockNumber": 8960262, "blockId": "0xa69f24032e9d5761565e726d484926a0932c6ca7fdb4c04a55bfc5e8f5879c4d", "firstIndex": 1811938729},
|
||||||
{"blockNumber": 9085994, "blockId": "0x24a101d1c8a63367a0953d10dc79c3b587a93bd7fd382084708adefce0b8363f", "firstIndex": 1879047965},
|
{"blockNumber": 9085906, "blockId": "0x922b4d6aeca64517f5048fa1ffa98d3e813bc415716a1763d07cf2bdea236896", "firstIndex": 1879048062},
|
||||||
{"blockNumber": 9230924, "blockId": "0xb176a98d3acd855cbb75265fb6be955a8d51abc771e021e13275d5b3ecb07eeb", "firstIndex": 1946156668},
|
{"blockNumber": 9230838, "blockId": "0xd892f513c48c95a859ae59c4e00ec4be0d684c549456c90e9c36669c11092f50", "firstIndex": 1946156580},
|
||||||
{"blockNumber": 9390535, "blockId": "0x640f5e2d511a5141878d57ae7a619f19b72a2bd3ef019cf0a22d74d93d9acf07", "firstIndex": 2013265733},
|
{"blockNumber": 9390449, "blockId": "0xcc0ced78fa66b570f338d129794d574560a23958e28d0d5288003d4542cec734", "firstIndex": 2013264376},
|
||||||
{"blockNumber": 9515674, "blockId": "0xff4a7b6b21aeaeb6e1a75ecd22b1f34c058a0ce1477ce90a8ce78165fd1d0941", "firstIndex": 2080374553},
|
{"blockNumber": 9515554, "blockId": "0xc06d04737813c3e2c8e910b2d4543c5c684c7bfe235bb501445f68fd0663f3d9", "firstIndex": 2080374749},
|
||||||
{"blockNumber": 9659426, "blockId": "0xc351455249343b41e9171e183612b68c3c895271c62bd2c53d9e3ab1aa865aa1", "firstIndex": 2147483567},
|
{"blockNumber": 9659367, "blockId": "0x765fa33d9418b1ed648e88b497b4bf4aa66990e6413dfc155525cda61e3cc813", "firstIndex": 2147483344},
|
||||||
{"blockNumber": 9794018, "blockId": "0xde98035b4b7f9449c256239b65c7ff2c0330de44dee190106d0a96fb6f683238", "firstIndex": 2214592213},
|
{"blockNumber": 9793940, "blockId": "0x9527dcbd85a100c51aee4ba90828fee23312f5f041859f3416a54fd87a437ce2", "firstIndex": 2214591669},
|
||||||
{"blockNumber": 9923840, "blockId": "0x881da313a1e2b6fab58a1d6fa65b5dacfdc9d68a3112a647104955b5233f84e3", "firstIndex": 2281701302},
|
{"blockNumber": 9923756, "blockId": "0xc4da5fdd2de077459fe84f721d7fc01ef69683e03e634b0c5443186486792246", "firstIndex": 2281700949},
|
||||||
{"blockNumber": 10042435, "blockId": "0x451f6459640a6f54e2a535cc3a49cfc469861da3ddc101840ab3aef9e17fa424", "firstIndex": 2348810174},
|
{"blockNumber": 10042325, "blockId": "0x6f554f195d20e4ba1262f73cf2c1cd44b14a71befe5ef0a5318fc309f8cde9fa", "firstIndex": 2348810131},
|
||||||
{"blockNumber": 10168883, "blockId": "0x5d16ff5adf0df1e4dc810da60af37399ef733be7870f21112b8c2cfff4995dd9", "firstIndex": 2415918783},
|
{"blockNumber": 10168768, "blockId": "0xdcdf88ec2c197d552343c80d01375a35d6462aff39c5bd976160f7176d2add64", "firstIndex": 2415918723},
|
||||||
{"blockNumber": 10289554, "blockId": "0x85d5690f15a787c43b9a49e8dd6e324f0b3e0c9796d07c0cfb128e5c168f5488", "firstIndex": 2483027930},
|
{"blockNumber": 10289467, "blockId": "0x5ece23babcf6b8838695b891b044c3dcf8120cdc15acd83018e96ffc590f6cd0", "firstIndex": 2483027720},
|
||||||
{"blockNumber": 10386676, "blockId": "0x20f675ea72db448024a8a0b8e3ec180cac37a5910575bc32f8d9f5cdfe3c2649", "firstIndex": 2550136212},
|
{"blockNumber": 10386601, "blockId": "0xd398ee129aea1247019fa39dc2f5083819687d8f5ad17ec39ba1803d178fbcda", "firstIndex": 2550136043},
|
||||||
{"blockNumber": 10479675, "blockId": "0x014abb07acf2330cc78800ca1f564928f2daccca4b389bf5c59f4b840d843ec0", "firstIndex": 2617245218},
|
{"blockNumber": 10479586, "blockId": "0x61c1cccd60a546eacc29f2ae2a6facab402b4f35e2986c6629b302e6b1ebca3e", "firstIndex": 2617245577},
|
||||||
{"blockNumber": 10562661, "blockId": "0xd437607a3f81ce8b7c605e167ce5e52bf8a3e02cdc646997bd0ccc57a50ad7d1", "firstIndex": 2684354520},
|
{"blockNumber": 10562579, "blockId": "0x14fd6a079050e3e110140372605c050945d6db03746fa5b84a8718cb2a0e9b86", "firstIndex": 2684353802},
|
||||||
{"blockNumber": 10641508, "blockId": "0x2e8ab6470c29f90ac23dcfc58310f0208f5d0e752a0c7982a77a223eca104082", "firstIndex": 2751462730},
|
{"blockNumber": 10641438, "blockId": "0x1998dcae09111b2c1bf6d0592e2f0b4a0143fe7db7115ff94b2b73b74542cee4", "firstIndex": 2751463334},
|
||||||
{"blockNumber": 10717156, "blockId": "0x8820447b6429dd12be603c1c130be532e9db065bb4bc6b2a9d4551794d63789a", "firstIndex": 2818571831},
|
{"blockNumber": 10717094, "blockId": "0x9ce45a150bb6bd13687d0692c86716911ffc6aff5831a03f4015bdffb85f5093", "firstIndex": 2818571144},
|
||||||
{"blockNumber": 10784549, "blockId": "0xc557daab80a7cdc963d62aa881faf3ab1baceff8e027046bcd203e432e0983b3", "firstIndex": 2885680800},
|
{"blockNumber": 10784494, "blockId": "0xf65c936cf578e673696477f7db7189b47222fdf7ed13096564b9d47b15c86eb9", "firstIndex": 2885680709},
|
||||||
{"blockNumber": 10848651, "blockId": "0xede1b0de5db6685a6f589096ceb8fccb08d3ff60e8b00a93caa4a775b48e07fc", "firstIndex": 2952789740},
|
{"blockNumber": 10848591, "blockId": "0x84ea8e9d5789302ebe88888115488f91cfb75fd89e282dfbd29ba9d6225ab0ca", "firstIndex": 2952789491},
|
||||||
{"blockNumber": 10909166, "blockId": "0x989db675899d13323006a4d6174557e3c5501c672afd60d8bd902fc98d37e92e", "firstIndex": 3019897599},
|
{"blockNumber": 10909102, "blockId": "0x22275047f643f4a3b82c349274a53d56a00da25beac89655877fb8cbfa3182c8", "firstIndex": 3019898024},
|
||||||
{"blockNumber": 10972902, "blockId": "0x5484050cc2c7d774bc5cd6af1c2ef8c19d1de12dabe25867c9b365924ea10434", "firstIndex": 3087007422},
|
{"blockNumber": 10972828, "blockId": "0x38e8acfec19bb53ab9fe70dd3577ccd8bd7c41b4d468b8f099a19bf06ce56518", "firstIndex": 3087006561},
|
||||||
{"blockNumber": 11036597, "blockId": "0x1e3686e19056587c385262d5b0a07b3ec04e804c2d59e9aaca1e5876e78f69ae", "firstIndex": 3154116231},
|
{"blockNumber": 11036532, "blockId": "0x478dac03f520e987a6e845cac1b3a756d69e4f5257f20758b8fc38456e7b6884", "firstIndex": 3154116463},
|
||||||
{"blockNumber": 11102520, "blockId": "0x339cf302fe813cce3bb9318b860dfa8be7f688413f38a6ea1987a1b84d742b4b", "firstIndex": 3221224863},
|
{"blockNumber": 11102457, "blockId": "0x1a36616b03351ebe481330fc86578f57d9da5c0dda59f4406d49b53a2fa9b6f6", "firstIndex": 3221224961},
|
||||||
{"blockNumber": 11168162, "blockId": "0xc0fa21ea090627610bcac4732dff702633f310cabafc42bc500d3d4805198fe0", "firstIndex": 3288334273},
|
{"blockNumber": 11168092, "blockId": "0xb23af483ca6dbc2fb8d2fada1f8189de2e155758ed9ecbbb20c234a30c7e093c", "firstIndex": 3288333510},
|
||||||
{"blockNumber": 11233707, "blockId": "0x491c37a479b8cf22eaa3654ae34c5ddc4627df8c58ca8a6979159e1710428576", "firstIndex": 3355442691},
|
{"blockNumber": 11233640, "blockId": "0xdc4c80d8370823773425b31e70b3af59582b556514857d1e9a9b4c53b880a424", "firstIndex": 3355442901},
|
||||||
{"blockNumber": 11300526, "blockId": "0xb7366d2a24df99002cffe0c9a00959c93ef0dcfc3fd17389e2020bf5caa788eb", "firstIndex": 3422551480},
|
{"blockNumber": 11300454, "blockId": "0xdbd4d8e9c1756093037f431330db4604e5a3e67bb74f425f667633d5298fe34c", "firstIndex": 3422551962},
|
||||||
{"blockNumber": 11367621, "blockId": "0xce53df5080c5b5238bb7717dfbfd88c2f574cfbb3d91f92b57171a00e9776cd2", "firstIndex": 3489660710},
|
{"blockNumber": 11367550, "blockId": "0x9e00816bd5b39353657a99421d278091599a39f246bbf8c0898f83e6d70b7c7c", "firstIndex": 3489660743},
|
||||||
{"blockNumber": 11431881, "blockId": "0x2a08ff9c4f6fd152166213d902f0870822429f01d5f90e384ac54a3eac0ceb3a", "firstIndex": 3556768626},
|
{"blockNumber": 11431820, "blockId": "0xd32d5e5871ce71acc9dcc7cf9d8cb9d964646182529c327a0ddf617814e27d74", "firstIndex": 3556769150},
|
||||||
{"blockNumber": 11497107, "blockId": "0x1f99c6b65f2b1cb06ed1786c6a0274ff1b9eacab6cb729fcd386f10ebbd88123", "firstIndex": 3623878389},
|
{"blockNumber": 11497031, "blockId": "0xed823054d4b293294e3301d3131e2ae9f0ce63c9f07d2d80fc144e42d535d61d", "firstIndex": 3623878513},
|
||||||
{"blockNumber": 11560104, "blockId": "0xebe6924817bbdfe52af49667da1376bae5a2994b375d4b996e8ff2683744e37a", "firstIndex": 3690986640},
|
{"blockNumber": 11560027, "blockId": "0x7098177efe77cfb5912dc63069fe366033111041ca5c539907a89e439c861d8f", "firstIndex": 3690987092},
|
||||||
{"blockNumber": 11625129, "blockId": "0xbe6eee325329ee2fe632d8576864c29dd1c79bab891dc0a22d5b2ac87618d26e", "firstIndex": 3758095773},
|
{"blockNumber": 11625049, "blockId": "0x61fccb47104a076b905d390498a1b38c317348bb1567e69aa1b670bed7a6a13f", "firstIndex": 3758096043},
|
||||||
{"blockNumber": 11690397, "blockId": "0xc28bf55f858ddf5b82d1ceb3b5258b90a9ca34df8863a1c652c4d359f5748fdf", "firstIndex": 3825204492},
|
{"blockNumber": 11690298, "blockId": "0xaf6f9e9c92db9e155f1ffb35eb68765c09de1206c353c9a56a5d5fa53e2d88d2", "firstIndex": 3825204430},
|
||||||
{"blockNumber": 11755087, "blockId": "0x0c10cde6ce1bbe24dc57347fe4aaebc17b7d8e8d7d97e3db573133477f494740", "firstIndex": 3892314051},
|
{"blockNumber": 11755003, "blockId": "0xf9efb54f08a2b59086a607541005928f1bda54fa2c46fcc48352fa6aa461c03a", "firstIndex": 3892313541},
|
||||||
{"blockNumber": 11819674, "blockId": "0x36b694a1776c94e4c6ae4a410931b2086de47a83e437517040e3290ce9afff67", "firstIndex": 3959422445},
|
{"blockNumber": 11819591, "blockId": "0xa551deb3bd2ec0ca2683cb76adb8fb295d171a3787aa5ff071bd1fa94d3af82e", "firstIndex": 3959422322},
|
||||||
{"blockNumber": 11883358, "blockId": "0x21f447aca9ddf94ed71df9fa3648a12acc2ba603f89f24c4784936864c41945f", "firstIndex": 4026531743},
|
{"blockNumber": 11883278, "blockId": "0x60c7a359d4aeb09b63b64487fa7794aee87c41b11446f69ba83e24d5bce6947f", "firstIndex": 4026531239},
|
||||||
{"blockNumber": 11948524, "blockId": "0x71a52b6cce80d3a552b0daa18beb952facf81a89bc7ca769d08ac297f317507a", "firstIndex": 4093640009},
|
{"blockNumber": 11948436, "blockId": "0x1c46fb22653e5f9eb9503fe532151519845d05b121291766715973e027eb9c0c", "firstIndex": 4093639741},
|
||||||
{"blockNumber": 12013168, "blockId": "0x9a7fb369b8d8cd0edd0d890d636096f20c63abb7eb5798ad1e578cac599e3db8", "firstIndex": 4160748475},
|
{"blockNumber": 12013084, "blockId": "0x0b8d1da9e70c4494ba61190390c891230846e69d9b0be605df8b04c4199ffd1b", "firstIndex": 4160749561},
|
||||||
{"blockNumber": 12078711, "blockId": "0x5de09329413b0c2f58d926f225197552a335ba3d5544d7bdb45e7574f78c9b8d", "firstIndex": 4227858275},
|
{"blockNumber": 12078612, "blockId": "0xb049af260be25c6153b67c227689b0556d8fb7d6033c3f61b8218f5c4ac5917a", "firstIndex": 4227857310},
|
||||||
{"blockNumber": 12143640, "blockId": "0xbeafc0e1e0586f5a95f00f2a796d7df122c79c187aa2d917129297f24b8306bd", "firstIndex": 4294967145},
|
{"blockNumber": 12143549, "blockId": "0x685dce41efbe2bab0ac9a4b9026d9e5faa3e01ae4637c8181cd2f1eac326fe6a", "firstIndex": 4294966232},
|
||||||
{"blockNumber": 12208005, "blockId": "0x052487095cdd4a604808e6c14e30fb68b3fa546d35585b315f287219d38ef77c", "firstIndex": 4362075289},
|
{"blockNumber": 12207918, "blockId": "0x53644ea8f781c6270f1136ed4bbcb956c98f12a4793c2f56f49b3105282b13ea", "firstIndex": 4362075410},
|
||||||
{"blockNumber": 12272465, "blockId": "0x82c8a50413bd67a0d6f53b085adcd9ae8c25ecc07ed766fa80297a8dcae63b29", "firstIndex": 4429184610},
|
{"blockNumber": 12272370, "blockId": "0x503523e1a01cb7d68be0eb22f36280c0ee7a1fc802061a704e326fbb8efcfe27", "firstIndex": 4429184831},
|
||||||
{"blockNumber": 12329418, "blockId": "0x294c147e48d32c217ff3f27a3c8c989f15eee57a911408ec4c28d4f13a36bb3b", "firstIndex": 4496292968},
|
{"blockNumber": 12329342, "blockId": "0xe6a1bf78dd827def078e23c768cf6e96666ee06b5fdc113380a4769d85f4bd33", "firstIndex": 4496293151},
|
||||||
{"blockNumber": 12382388, "blockId": "0x8c2555965ff735690d2d94ececc48df4700e079c7b21b8e601a30d4e99bc4b5b", "firstIndex": 4563401809},
|
{"blockNumber": 12382311, "blockId": "0x352fe793c16b1d8aea195af86ee9aec3dbaa83e7a32872a0d222a77e96fc0e57", "firstIndex": 4563402486},
|
||||||
{"blockNumber": 12437052, "blockId": "0x2e38362031f36a0f3394da619dcc03be03c19700594cbd1df84c2c476a87de63", "firstIndex": 4630511012},
|
{"blockNumber": 12436970, "blockId": "0x90276349edf0941bb3327dc1d749d0371fe550eaddafb5141fcacdd281de0976", "firstIndex": 4630510187},
|
||||||
{"blockNumber": 12490026, "blockId": "0x122749c02a55c9c2a1e69068f54b6c1d25419eb743e3553aba91acf1daeadc35", "firstIndex": 4697619920},
|
{"blockNumber": 12489954, "blockId": "0x71894b1e1608aeba777662a6055e601ce6f17950dbe3844c3601e0f88cbd5848", "firstIndex": 4697619586},
|
||||||
{"blockNumber": 12541747, "blockId": "0xfb9f12aa2902da798ac05fab425434f8c7ce98050d67d416dbb32f98c21f66f7", "firstIndex": 4764728267},
|
{"blockNumber": 12541655, "blockId": "0xc34c7299041df72a81c4b86e81639d2dfcebfae603e287fc143881a636ce1188", "firstIndex": 4764728948},
|
||||||
{"blockNumber": 12597413, "blockId": "0x9a7a399c2904ac8d0fec580550525e7e1a73d8f65f739bf7c05d86e389d0d3f7", "firstIndex": 4831837757},
|
{"blockNumber": 12597319, "blockId": "0x4c4dc71d8d2f1223ad0469ddfe09fa8934f64e3712ed83708d6e1b9c64eceebb", "firstIndex": 4831837390},
|
||||||
{"blockNumber": 12651950, "blockId": "0xb78dcb572cdafb9c4e2f3863ef518a3b2df0cd4f76faa26a423b2ca0c1cde734", "firstIndex": 4898946491},
|
{"blockNumber": 12651863, "blockId": "0x406a642c8364fb61cbd896512a2d19ecdba3932ab09ac67cf48d91aa1a03f24e", "firstIndex": 4898946362},
|
||||||
{"blockNumber": 12706472, "blockId": "0xfd21f41ec6b0c39287d7d48c134d1212a261c53d65db99739994b003150bbad1", "firstIndex": 4966054796},
|
{"blockNumber": 12706391, "blockId": "0xa7fc3739898f7ff5733896313b248fb0b306a132681609b8b9e2671b42dac3a1", "firstIndex": 4966054748},
|
||||||
{"blockNumber": 12762929, "blockId": "0xc94d994bc40b2ae7dc23cf2b92cc01e84915f090bb57c0d9a67584bd564d3916", "firstIndex": 5033164307},
|
{"blockNumber": 12762840, "blockId": "0x5a1048966dfa55a48248517c45683ce342671bf544117d2bac13d8e343563136", "firstIndex": 5033164303},
|
||||||
{"blockNumber": 12816689, "blockId": "0x7770c72f22cbf6ccf7ab85d203088f7ede89632cf0042c690102f926a90bd09d", "firstIndex": 5100273412},
|
{"blockNumber": 12816597, "blockId": "0x97f5b87f422870a8ffeff70c12f4377dde96d248aa912cb64ebfaea51dc086b6", "firstIndex": 5100272541},
|
||||||
{"blockNumber": 12872408, "blockId": "0x2e008b8c952d828875d777f7912f472af96ffc977f2ceae884006682cab6b8ed", "firstIndex": 5167381625},
|
{"blockNumber": 12872315, "blockId": "0x432f7df7973fdea4e5abe2c09b634ca3b724e37a19d5ec23ca5810e4854c6b33", "firstIndex": 5167382243},
|
||||||
{"blockNumber": 12929718, "blockId": "0x85eb0ed3c5910c6a01b65ef0a5b76c59c2cdb5094e6e27eb87c751d77bcc2c88", "firstIndex": 5234491305},
|
{"blockNumber": 12929620, "blockId": "0xa4524e3b4c5dadac91df2f29696532cfed377f47469fe7cfabf10baac945eea2", "firstIndex": 5234490748},
|
||||||
{"blockNumber": 12988757, "blockId": "0xdf12045bea73af18d4e71f8be8e334160f78b85f96a3535a4056409d8b61355a", "firstIndex": 5301600237},
|
{"blockNumber": 12988653, "blockId": "0x9be70e31aeea164c370d8d183a1af45120693b13d360edc78214535c40ef1d63", "firstIndex": 5301600248},
|
||||||
{"blockNumber": 13049172, "blockId": "0xf07608d97a101cd9a95fee9d9062a15bcb333263e555f8cfa31da037e0468f30", "firstIndex": 5368709080},
|
{"blockNumber": 13049074, "blockId": "0x3076857bd17959c2a3df18357eab3ecbb7ca25457785b07074d2e885eb566fc2", "firstIndex": 5368707746},
|
||||||
{"blockNumber": 13108936, "blockId": "0x42739341db582d2f39b91ec9e8cc758777ca3f6ff9f25cd98883619fd5f026a7", "firstIndex": 5435817013},
|
{"blockNumber": 13108823, "blockId": "0x67b2764f6b53779e3d683def2c7659c6d92814152574073d24f10cd67200a22b", "firstIndex": 5435817680},
|
||||||
{"blockNumber": 13175495, "blockId": "0x564f25eacb229350b7c648b5828169e7a0344ae62e866206828e2cfad8947f10", "firstIndex": 5502926476},
|
{"blockNumber": 13175389, "blockId": "0x0d41e34dbca58dec45e0509b6cbf027b2377220845a85caebbf3a14b8505e8ce", "firstIndex": 5502925085},
|
||||||
{"blockNumber": 13237721, "blockId": "0x0973425abec0fa6319701b46e07c2373b0580e3adbed6900aad27d5bf26dcb95", "firstIndex": 5570035419},
|
{"blockNumber": 13237624, "blockId": "0x723e0818d54ab1b1c53efc2f2f448c16c1f943af2033575c612c3c71228d4ddf", "firstIndex": 5570034948},
|
||||||
{"blockNumber": 13298771, "blockId": "0xf3a16fec5be808c9f7782fb578dc8cef7f8e2110f7289bd03c0cc13977dd1518", "firstIndex": 5637143840},
|
{"blockNumber": 13298658, "blockId": "0xd7f9f477b20bcf1379ccaaae701c9658a02b177861e0af9e873c63fe8b854f4b", "firstIndex": 5637144562},
|
||||||
{"blockNumber": 13361281, "blockId": "0x3c0b6364201ca9221b61af3de27a3a87e111870b8c7efc43a6d8496e98c68690", "firstIndex": 5704253046},
|
{"blockNumber": 13361166, "blockId": "0x9f9e4130093269d59045f91344a13eb2786023e02099f53dd44854d50a7f5ffb", "firstIndex": 5704253260},
|
||||||
{"blockNumber": 13421819, "blockId": "0x2f472e57997b95558b99e3e5e7e0e8d4dbf8b71c081aac6536c9ff5925dac2ce", "firstIndex": 5771361231},
|
{"blockNumber": 13421716, "blockId": "0x28752f35ad2adeba342ef6aa51bca1c0abc757c4f712cf620c8a5e6a8576636e", "firstIndex": 5771361775},
|
||||||
{"blockNumber": 13480620, "blockId": "0xc4d689e87464a0c83c661c8e3a0614c370631de857f7e385b161dfe8bacd3e71", "firstIndex": 5838469468},
|
{"blockNumber": 13480516, "blockId": "0x43f4ecf24c17b7a77621e2ca09c88c53b3407fb018f4bb3a032c212015b4e18d", "firstIndex": 5838469616},
|
||||||
{"blockNumber": 13535793, "blockId": "0xe7674bacc8edce9fb3efd59b92c97da48fe7ace1de314b4a67d7d032fc3bb680", "firstIndex": 5905578026},
|
{"blockNumber": 13535688, "blockId": "0x99ffcd9982219a4be45fa5f15622b288afe4f85da536956d39dccac1ec416444", "firstIndex": 5905579739},
|
||||||
{"blockNumber": 13590588, "blockId": "0x6a3e86bdce7dd7d8792e1af9156edd8c3ffee7c20fed97001f58a9a2699f6594", "firstIndex": 5972687757},
|
{"blockNumber": 13590487, "blockId": "0xff7b74464a318037e0670c0be7a5b1b79418d1a42c7a3587c46adc1ef720c819", "firstIndex": 5972688013},
|
||||||
{"blockNumber": 13646707, "blockId": "0xab404a5d3709cf571b04e9493f37116eeb5dd2bc9dc10c48387c1e0199013d69", "firstIndex": 6039797165},
|
{"blockNumber": 13646596, "blockId": "0xd555ce5f2b65ffeec9b9e3e75a56f5f23d7353a1014bcc861efd7df6e5dc2c92", "firstIndex": 6039797525},
|
||||||
{"blockNumber": 13703025, "blockId": "0x20e2fde15b8fe56f5dd7ab0f324c552038167ed44864bf3978e531ae68d6d138", "firstIndex": 6106905803},
|
{"blockNumber": 13702902, "blockId": "0x3e8feab590c6631c63931fee83bf7e10234890bdf377b1b374fb70221b9ac9c0", "firstIndex": 6106905641},
|
||||||
{"blockNumber": 13761024, "blockId": "0x2ae49275e13e780f1d29aea8507b2a708ff7bfe977efac93e050273b8b3a8164", "firstIndex": 6174015107},
|
{"blockNumber": 13760908, "blockId": "0x18e96fa585c57aad1f2a8dc9639d9f4fe53c3f38894862471b7cec17f97f3cb1", "firstIndex": 6174014330},
|
||||||
{"blockNumber": 13819468, "blockId": "0xb9d19cb31dedb1128b11cad9ffd6e58c70fe7ba65ba68f1ac63668ac5160ad85", "firstIndex": 6241124350},
|
{"blockNumber": 13819340, "blockId": "0x25384bf2cef178e30c4d9e0abae59357055241fc715133b2bb078e8278e5296a", "firstIndex": 6241123906},
|
||||||
{"blockNumber": 13877932, "blockId": "0x80b1ff0bb069a8479360a15eaa84ba30da02cfacadc564837f4b1c90478addb8", "firstIndex": 6308232256},
|
{"blockNumber": 13877817, "blockId": "0x4a84a0a7035dbfed0e1281fb1df162a195f2c516686a2e2a6ad605e6f2b3cf57", "firstIndex": 6308232690},
|
||||||
{"blockNumber": 13935384, "blockId": "0xe1f5469a559a6114dd469af61b118b9d9551a69bbd49a4e88f2a2d724830c871", "firstIndex": 6375341632},
|
{"blockNumber": 13935260, "blockId": "0x6c14a8e563614edbad66698ebe911e997e27844f9d33c7069795379540e71a44", "firstIndex": 6375341148},
|
||||||
{"blockNumber": 13994042, "blockId": "0x25188fb75f2328c870ade7c38ef42ff5fddef9c4e364eebe4c5d8d9cc3ecabab", "firstIndex": 6442449799},
|
{"blockNumber": 13993914, "blockId": "0xc0991d1bc431c5215fb0218b0b541f2b4fae0994775e5eddb016965fe5b4a0c7", "firstIndex": 6442448947},
|
||||||
{"blockNumber": 14051123, "blockId": "0xf4ef2bce9ee9222bdcf6b3a0c204676d9345e211e10c983e523930274e041ef1", "firstIndex": 6509559107},
|
{"blockNumber": 14051007, "blockId": "0x854803ce364b6fe4446800e74448a5ee883e7d472e8a0347f1ad13bd347fa69f", "firstIndex": 6509558964},
|
||||||
{"blockNumber": 14109189, "blockId": "0x80b730c28f75d8cb5ec2fb736341cd87cb4ecb2c9c614e0a4ecc0f9812675d50", "firstIndex": 6576667347},
|
{"blockNumber": 14109063, "blockId": "0xa3fadce7ab18a5fedcfed9e3b1f0cf2fb32151172c362327c602343bc26dde8f", "firstIndex": 6576668017},
|
||||||
{"blockNumber": 14166822, "blockId": "0xf662a24b91684fa8ac462b31071f406de8d6183dba46d30d690f4407bc6af36f", "firstIndex": 6643777079},
|
{"blockNumber": 14166701, "blockId": "0xaa2443a38e2b0d6b01cf4b73de54d2b7e92c99475bd0802beebd86845c126d1b", "firstIndex": 6643774648},
|
||||||
{"blockNumber": 14222488, "blockId": "0x7333e324c96b12f11a38d1fc2ddb4860e018b90f5dc10f3dbe19f7679bb95535", "firstIndex": 6710885890},
|
{"blockNumber": 14222367, "blockId": "0xa27c78134c1fbf432c8caee7c9d2ef323fdde519a065804c9c8da6ca1615e04f", "firstIndex": 6710886238},
|
||||||
{"blockNumber": 14277180, "blockId": "0x4373c1000e8e10179657689e2f0e42f88bd1601ecb4a5d83970d10287f6654cc", "firstIndex": 6777994595},
|
{"blockNumber": 14277029, "blockId": "0x5d0ed08b65db01e382c339dcb2715b2927fb472b0c1f4256841c386d785c3f3a", "firstIndex": 6777995247},
|
||||||
{"blockNumber": 14331080, "blockId": "0x9c708a750a3f284ec0ee950110b36fd488cb1ec24cd0c2ea72c19551ec5c42a5", "firstIndex": 6845103719},
|
{"blockNumber": 14330955, "blockId": "0x3e5014d82c416549acfe2e26b13ff5ddf29ad74943ef5b94a65eca0a4d72d82e", "firstIndex": 6845102969},
|
||||||
{"blockNumber": 14384243, "blockId": "0x34ce7503b76335aa18dec880b0cefd388a29e0fcff6f2e1ddda8fb8c0ac1daf0", "firstIndex": 6912212376},
|
{"blockNumber": 14384139, "blockId": "0x720e1fd687292019c3fa1812c39c73d20fde783c0196f43378a51cb4e0b46d65", "firstIndex": 6912212078},
|
||||||
{"blockNumber": 14437670, "blockId": "0x79842efd3e406b41f51935fe2e6ad20a7dd5a9db2280ebd7f602ed93da1e3c24", "firstIndex": 6979320543},
|
{"blockNumber": 14437534, "blockId": "0xe4342ab6f363066d9c2514a870241ceb63df232d33659fdb3928faf433360bb4", "firstIndex": 6979321493},
|
||||||
{"blockNumber": 14489204, "blockId": "0xcd12addf0afdc229e9fe3bd0a34677a3826c5e78d4baf715f8ed36b736d6627a", "firstIndex": 7046430591},
|
{"blockNumber": 14489073, "blockId": "0xeb2f9923d816e773460eccfa42eb4ff2bbfc353b756ba274e98dc85c64ab1536", "firstIndex": 7046428879},
|
||||||
{"blockNumber": 14541688, "blockId": "0x55f617abf208a73fc467e8cb5feead586b671dbb0f6281570b3c44b8eabb2b9e", "firstIndex": 7113538755},
|
{"blockNumber": 14541559, "blockId": "0x55cc33721fa9022964f47c30f4146fee7cc80f5b4158d7ecea0ff661cbba3487", "firstIndex": 7113538857},
|
||||||
{"blockNumber": 14594551, "blockId": "0xc7211bf772e93c8c2f945fcb6098b47c3455604cb8b94a505cb5cb720914c369", "firstIndex": 7180646025},
|
{"blockNumber": 14594432, "blockId": "0x676441bdc1ec430a9fbc05e56a0437a475606a253f9fdffc86f5f6286c159b5d", "firstIndex": 7180647956},
|
||||||
{"blockNumber": 14645065, "blockId": "0x6d5b0326f4b22e2b0196986a514f23ec6e9a62f70f53300a22b21ff661a6ef7e", "firstIndex": 7247756883},
|
{"blockNumber": 14644942, "blockId": "0x03232a1d3c9b2f1f0c2a4b780c83bce66238d9abdeed71c2a8af9e97a53011b0", "firstIndex": 7247754981},
|
||||||
{"blockNumber": 14695926, "blockId": "0x0a77272250e43b4bb46c02eb76944881a3c6b00a21bb9086a8229199bd62d97a", "firstIndex": 7314865843},
|
{"blockNumber": 14695793, "blockId": "0x6017f6d1d79188692e1a1a18de5f93b83b97905c8ff5bed5cef4b2e9f4d4d41b", "firstIndex": 7314863646},
|
||||||
{"blockNumber": 14746330, "blockId": "0xd677fdbaf8efb1bfdc138ac6b2bd5d0e890a29acb1f52f40169181ad517b0d31", "firstIndex": 7381974956},
|
{"blockNumber": 14746186, "blockId": "0x332c8ac0b2960fb1627407d45443201a0f6de7421b52af077b32fa6e018e5401", "firstIndex": 7381974499},
|
||||||
{"blockNumber": 14798546, "blockId": "0xbb277e8623acd2ce2340cf32f6c0ddab70fd95d862287f68a3c37250a70619cd", "firstIndex": 7449082890},
|
{"blockNumber": 14798403, "blockId": "0x4507ae1d9f27a3eada874dcf04112a5d4ee7155701afd3fb857fe58201a2dede", "firstIndex": 7449082752},
|
||||||
{"blockNumber": 14848230, "blockId": "0x587b39f11bdaa2091291c7c3947e88df2e91e7997f2375dfd43b6e310a538582", "firstIndex": 7516192636},
|
{"blockNumber": 14848093, "blockId": "0xff98c820c66c3beaaa3b195158c94f099148573a7f032295ba7156c13f78eaa8", "firstIndex": 7516191978},
|
||||||
{"blockNumber": 14897646, "blockId": "0xf5b5c9d0c024ca0c0f0c6171871f609687f4ccb064ededbd61176cf23a9011e8", "firstIndex": 7583299602},
|
{"blockNumber": 14897508, "blockId": "0x49c31d3433b197585f733d7c382ae16d9d78bf59c333a9b76362cc6c5fed270c", "firstIndex": 7583300663},
|
||||||
{"blockNumber": 14950782, "blockId": "0x50549486afaf92a4c3520012b325e914ef77a82e4d6530a71f9b1cca31bfae18", "firstIndex": 7650409868},
|
{"blockNumber": 14950638, "blockId": "0xf1a1609206788977841927271808fe1c42d059026385d025bf4cea0c0a05966b", "firstIndex": 7650408992},
|
||||||
{"blockNumber": 15004101, "blockId": "0x7edac55dea3ee4308db60b9bc0524836226fe301e085b3ce39105bd145ba7fc3", "firstIndex": 7717517503},
|
{"blockNumber": 15003958, "blockId": "0xf9e6b41108d907672f29ba1df97ed83aca2ba933335e6b5ccfb5d4001807b33f", "firstIndex": 7717519105},
|
||||||
{"blockNumber": 15056903, "blockId": "0xb4cfd02d435718598179cdba3f5c11eb8653fe97ec8d89c60673e3e07b8dfc94", "firstIndex": 7784627997},
|
{"blockNumber": 15056783, "blockId": "0x126a5a5c22e878a4c42bea890d48cfe00edf7fbc27d805c88a5269540bc94a42", "firstIndex": 7784628173},
|
||||||
{"blockNumber": 15108302, "blockId": "0x53c77a7de4515e9e93467a76f04cc401834bcdd64e9dfa03cf6d2844a6930293", "firstIndex": 7851736988},
|
{"blockNumber": 15108163, "blockId": "0x5f8494ccacefce9fef8a95a52247f2670ed30bb5a3b3deb85c645e72c115d506", "firstIndex": 7851735261},
|
||||||
{"blockNumber": 15159526, "blockId": "0x1a31ad84b423254d7ff24e7eca54048ed8cc13cec5eb7289bf3f98ed4de9f724", "firstIndex": 7918844431},
|
{"blockNumber": 15159385, "blockId": "0x0fed6c5aafb53e9cdb0d8620c3eef9b619fb3ae9559296618f634eddae33f0c6", "firstIndex": 7918844299},
|
||||||
{"blockNumber": 15211013, "blockId": "0xe5d491e1d6cc5322454143b915c106be1bf28114a41b054ba5e5cfe0abecafba", "firstIndex": 7985953942},
|
{"blockNumber": 15210872, "blockId": "0x37bdb94b57044b67fbd9b9a7cdc728fcfd2066cf1904cab478fd42d41ec6e1f0", "firstIndex": 7985954119},
|
||||||
{"blockNumber": 15264389, "blockId": "0xd9939bb9e58e95d2672c1148b4ec5730204527d3f3fc98ca03a67dc85cf3d710", "firstIndex": 8053063187},
|
{"blockNumber": 15264226, "blockId": "0xc173ad8a791e2293efd8e0b2c9f088fac49233aabb1e72db6a045aa9904f4728", "firstIndex": 8053061840},
|
||||||
{"blockNumber": 15315862, "blockId": "0x7254f99c4bb05235d5b437984c9132164e33182d4ce11a3847999da5c28b4092", "firstIndex": 8120172147},
|
{"blockNumber": 15315693, "blockId": "0x985cf97bf28f0becb2b16abfe629a5f520596e45fc23f4936bc2f6298b8145f9", "firstIndex": 8120172048},
|
||||||
{"blockNumber": 15364726, "blockId": "0x11b57547579d9009679e327f57e308fe86856391805bc3c86e7b39daae890f52", "firstIndex": 8187281042},
|
{"blockNumber": 15364606, "blockId": "0x593362ef8a82140f3dd3ff13d0ce50287dcb0b8b3d31ffcc7813c6be16f7438d", "firstIndex": 8187281275},
|
||||||
{"blockNumber": 15412886, "blockId": "0xbe3602b1dbef9015a3ec7968ac7652edf4424934b6bf7b713b99d8556f1d9444", "firstIndex": 8254390023},
|
{"blockNumber": 15412727, "blockId": "0x5a6ff10acc48e9e8bcf963b042012ea094628b9488b8bf569783b3297c67eedd", "firstIndex": 8254388575},
|
||||||
{"blockNumber": 15462792, "blockId": "0x3348ca4e14ac8d3c6ac6df676deaf3e3b5e0a11b599f73bd9739b74ebd693efe", "firstIndex": 8321499024},
|
{"blockNumber": 15462642, "blockId": "0x137f15c5d112b0fdc6e4c84393032030646122c3b0d86286143a1ab8bfacbac4", "firstIndex": 8321497214},
|
||||||
{"blockNumber": 15509914, "blockId": "0xbc98fd6b71438d5a169f9373172fea799fa3d22a8e6fe648d35e1070f2261113", "firstIndex": 8388606521},
|
{"blockNumber": 15509781, "blockId": "0xe58a8ca223b7c03755d046a6212bc33fa9814f73efe52804d8eea7ae4b4bd7f9", "firstIndex": 8388606496},
|
||||||
{"blockNumber": 15558748, "blockId": "0x5fa2cf499276ae74a5b8618990e71ed11a063619afe25c01b46e6252eba14c19", "firstIndex": 8455716577},
|
{"blockNumber": 15558625, "blockId": "0x4127d527b58c7685a1237d228508ea77d40f33dbeffb5cc30e47e83a4b6152a5", "firstIndex": 8455714910},
|
||||||
{"blockNumber": 15604217, "blockId": "0x78a608e13d2eb3c5fed81a19b829ede88071cf01ea9ff58112a7472435f97c30", "firstIndex": 8522825668},
|
{"blockNumber": 15604075, "blockId": "0x7d1c1bccfe5c23a1edd81246e6e55277f271cffef30bde22c9d1202f764dd96f", "firstIndex": 8522823324},
|
||||||
{"blockNumber": 15651869, "blockId": "0xd465d861d925d1475440782ff16c2b3361ba3c8e169d7cc90eb8dfc0f31b0aac", "firstIndex": 8589934080},
|
{"blockNumber": 15651742, "blockId": "0x732e5203a504fd97510325c1fb876476ca132831e78182367cd4b4efae1232c3", "firstIndex": 8589934155},
|
||||||
{"blockNumber": 15700968, "blockId": "0x71e3def131271e02c06ca945d14a995703a48faac1334a9e2e2321edd0b504d0", "firstIndex": 8657043390},
|
{"blockNumber": 15700810, "blockId": "0xe031decb5e42a69dafcc814441227085508cf51c9c77f35d06487db19bd05a6a", "firstIndex": 8657041374},
|
||||||
{"blockNumber": 15762986, "blockId": "0x9b1b51dca2eae29162ca66968a77b45175f134b44aea3defadcb924f83e0b944", "firstIndex": 8724151376},
|
{"blockNumber": 15762855, "blockId": "0xbdff9b1e193c44f35bf38945d2523c74ef59c4f352efc93fad02ef34eef1c5f0", "firstIndex": 8724150924},
|
||||||
{"blockNumber": 15814455, "blockId": "0x3c04a509cb6304d3df4bef57e0119d9e615ab737ec0b4a7deada6e5f57d9f873", "firstIndex": 8791260562},
|
{"blockNumber": 15814304, "blockId": "0x524a226d9f48e37db00e252c7f6a1350d1829d38fe83c756021cc11c56d3b2dd", "firstIndex": 8791259373},
|
||||||
{"blockNumber": 15865639, "blockId": "0x9e9e26148c774518ecf362c0e7c65a5c1b054a8a3e4e36036c70e273fac6147c", "firstIndex": 8858368894},
|
{"blockNumber": 15865514, "blockId": "0x4e4ad46f3ae7fb2a2e7cb94aa804929cb7353c79c78cc2cbcee710da5f0ec4b5", "firstIndex": 8858369571},
|
||||||
{"blockNumber": 15920564, "blockId": "0x9efe1d4dbfd9aa891ac0cffd3e1422a27ba2ea4add211b6900a2242cdb0f0ca0", "firstIndex": 8925477950},
|
{"blockNumber": 15920411, "blockId": "0xa39e4cbd8e84b427e44b8d06b5b1149652f3af5fa88633b802665b8677772bc5", "firstIndex": 8925477782},
|
||||||
{"blockNumber": 15974371, "blockId": "0xc63ccef7bc35a0b431a411f99fe581b322d00cfc6422d078696808a5658a32ac", "firstIndex": 8992587107},
|
{"blockNumber": 15974193, "blockId": "0x4a3f82935e6fcda6ce7636001989b65b79422d362e60833e01185a7960b2fa55", "firstIndex": 8992587369},
|
||||||
{"blockNumber": 16032913, "blockId": "0x3e60957224964669a8646914e3166553b9f4256d5be160b17995d838af3ef137", "firstIndex": 9059696632},
|
{"blockNumber": 16032739, "blockId": "0x7f50bb76dfd01125e0a4a7595106e43329eb8bd02e819be2ade4248a403c714a", "firstIndex": 9059696611},
|
||||||
{"blockNumber": 16091057, "blockId": "0x12b346047bb49063ab6d9e737775924cf05c52114202ddb1a2bdaf9caabbfe0c", "firstIndex": 9126804912},
|
{"blockNumber": 16090896, "blockId": "0xdc4db130973ef793d2223844e35122a2477e642d86c69616fb3604d2a79805c4", "firstIndex": 9126804425},
|
||||||
{"blockNumber": 16150977, "blockId": "0x49318a32ff0ce979c4061c1c34db2a94fb06e7669c93742b75aff14a134fa598", "firstIndex": 9193913896},
|
{"blockNumber": 16150783, "blockId": "0xb46294fe1cbcbbdff7309ebf0bf481e78e2589d386b95fa4c781c437e02e0aec", "firstIndex": 9193912139},
|
||||||
{"blockNumber": 16207432, "blockId": "0xf7870865edf81be4389a0be01468da959de703df0d431610814d16ed480176e4", "firstIndex": 9261019778},
|
{"blockNumber": 16207278, "blockId": "0x8a3af0387572b56989bb6c98d8860e07b5cdefb2ebe7b1dc58be07c24a53e056", "firstIndex": 9261022215},
|
||||||
{"blockNumber": 16262582, "blockId": "0x25818e0f4d54af6c44ef7b23add34409a47de3ab1c905889478f3ec8ad173ec3", "firstIndex": 9328131320},
|
{"blockNumber": 16262389, "blockId": "0xec5a03d88cfc1bf8c278ddce7ace5032c3f7ed5032b4575df54779ec1abca131", "firstIndex": 9328130680},
|
||||||
{"blockNumber": 16319695, "blockId": "0x25de4b1c18cc503f5d12b4fa9072d33a11fa503a3dbeb9ab3d016b57c1e5cd4d", "firstIndex": 9395240790},
|
{"blockNumber": 16319525, "blockId": "0x74ae702375e242205fe4986448b0ee494d4a38ccc813981489c4b0488e58a949", "firstIndex": 9395240779},
|
||||||
{"blockNumber": 16373605, "blockId": "0x3794a5e0d2aa10baf1e6a5ec623d6089fdd39799eff633017d8df5144526939f", "firstIndex": 9462349509},
|
{"blockNumber": 16373441, "blockId": "0x5f404555cf45c547ef0fc044f2701bc7a28ce1e432de06e0264dbfd1c17447d0", "firstIndex": 9462347671},
|
||||||
{"blockNumber": 16423494, "blockId": "0xe0217d947ba3865dfc9288e0c890b0996457bb9d18467bd125e86bbb0052b57f", "firstIndex": 9529458033},
|
{"blockNumber": 16423343, "blockId": "0xe4af890b6c4dd3b10af2e6c08f14563bd2a3121b22a3cc6a0db29d438c1dcc59", "firstIndex": 9529457704},
|
||||||
{"blockNumber": 16474853, "blockId": "0xd454f033d190f22f9e56f0209ea1eeb3b6257805d5d88650d2759eb4d24821b7", "firstIndex": 9596567055},
|
{"blockNumber": 16474687, "blockId": "0x019a8b374cf150fcda1c8af2a3e7ba63603ae81744d6343897c4b17ee58411d5", "firstIndex": 9596566169},
|
||||||
{"blockNumber": 16525689, "blockId": "0x8a23cbbf3e258e13f5a1ada434366796cb4a3e5b1062455582fb2bc3ab991541", "firstIndex": 9663674943},
|
{"blockNumber": 16525504, "blockId": "0xad394ce7e84e1c904cc5dd6dabd51b1a575c0b2fb006f10f272875b7f921904e", "firstIndex": 9663675287},
|
||||||
{"blockNumber": 16574203, "blockId": "0xc1a5b7d26e8222bd2d56ef4108f75d69f7c116707d348950834e00962241a4f8", "firstIndex": 9730785112},
|
{"blockNumber": 16574051, "blockId": "0x098e2dca2eda0d700aa3127bdfb679ce16e3ca297a305978c6ecfff044269511", "firstIndex": 9730784563},
|
||||||
{"blockNumber": 16622622, "blockId": "0x3ddb3ef7a4309bd788258fb0d62613c89a0b4de715f4e12f6017a194d19d6481", "firstIndex": 9797893665},
|
{"blockNumber": 16622457, "blockId": "0x8627f1237731c1127116898724f1b6420b8e7bcd8e18a0ea568f192bbd2cd55d", "firstIndex": 9797893241},
|
||||||
{"blockNumber": 16672585, "blockId": "0x8aa5e9f72b261f9e2a9eb768483d1bbd84d3a88fdb1346f6a9a7f262fd28ba41", "firstIndex": 9865002893},
|
{"blockNumber": 16672410, "blockId": "0x3e32b46faa670b191b89bea84a68022d5ea8b90008b388a948ff27f871d17292", "firstIndex": 9865002964},
|
||||||
{"blockNumber": 16720124, "blockId": "0x2128f8baf264166e37554d5c31a06de58d9ccfb663117358251da548a23a060f", "firstIndex": 9932111275},
|
{"blockNumber": 16719964, "blockId": "0x1668c3ea6cb256f306e93851cc2c00612f85df5cf7b5527ffce14c89088d7fdf", "firstIndex": 9932111708},
|
||||||
{"blockNumber": 16769162, "blockId": "0x6b3e849482d3222032740ad6b8f98e24636c82682a6a3572b1ef76dfebc66821", "firstIndex": 9999217824},
|
{"blockNumber": 16769014, "blockId": "0xed9a6f88e47b5bfe4d5bc92e1c1bfeb252f716f0990ffa1f907655c0f5e3a365", "firstIndex": 9999220312},
|
||||||
{"blockNumber": 16818311, "blockId": "0xe45f57381978a2bfc85bd20af1c41e2b630412642ac4f606b477f05f030ef5d9", "firstIndex": 10066328668},
|
{"blockNumber": 16818134, "blockId": "0x93504ba617500698a1b46f3110cd26827b8efe468190b2a91d3595784e34a1b6", "firstIndex": 10066329167},
|
||||||
{"blockNumber": 16869531, "blockId": "0xa154555266d24dc1f4885af5fafcf8cab3de788998cf69e1d28f56aa13a40c43", "firstIndex": 10133437302},
|
{"blockNumber": 16869369, "blockId": "0x94ca4b395a5c36c4e9d07cbb08271f0680455af4e4659906b647e16abebd7d4e", "firstIndex": 10133438415},
|
||||||
{"blockNumber": 16921611, "blockId": "0xf1f829b4ab5eec6e243916dd530993fa11eef5510fd730e8d09ead6b380355a1", "firstIndex": 10200547185},
|
{"blockNumber": 16921428, "blockId": "0x66650775bff4cb95de56099c10b06f3dfe302a731b391f406d1aa551121308ba", "firstIndex": 10200547148},
|
||||||
{"blockNumber": 16974870, "blockId": "0x1a33202b95926ae4cb8e6e99d8d150f3c50d817b3a316452bdf428c971dabde5", "firstIndex": 10267655914},
|
{"blockNumber": 16974677, "blockId": "0x58d5fc4cd45047dac10d55a036e0a4448faacc1041b29c4c7fb41a6e9394c3ff", "firstIndex": 10267655623},
|
||||||
{"blockNumber": 17031277, "blockId": "0x706c9dd0dc81e7ac29d2ea0f826e6b8a1dcb5adb1b904ff6e43260729c9fd0a7", "firstIndex": 10334764934},
|
{"blockNumber": 17031050, "blockId": "0x9d15b831979e95fc4149ecae46478cac1e54470b277d57d7102d19a72f28eeba", "firstIndex": 10334764441},
|
||||||
{"blockNumber": 17086330, "blockId": "0x085a80cafe96b520105b9a1f8e7a2bbc9474da24da7e6344ca7c4d32db822f92", "firstIndex": 10401871892},
|
{"blockNumber": 17086163, "blockId": "0x978ff48863fcdb50b274ea4220e7635c13c41bae91912db9e24205fb917fde85", "firstIndex": 10401873176},
|
||||||
{"blockNumber": 17141311, "blockId": "0x33ec6513dfa515bc5f6356476b4eb075a8064181d6aaf6aa1a1e18887e342f74", "firstIndex": 10468982364},
|
{"blockNumber": 17141086, "blockId": "0x4084d442499893361731f17534944d260cccd8e07d41c52d7160910555770b90", "firstIndex": 10468982462},
|
||||||
{"blockNumber": 17190907, "blockId": "0x6f41273d3bf30d3347e7eb68872a49b3ac947f314543478be7a28a55e5c41a3c", "firstIndex": 10536090817},
|
{"blockNumber": 17190735, "blockId": "0x42ed86fb42def23870df6ec23204f557669ec7cd8de59c9f3ef9ab90704e4b11", "firstIndex": 10536090726},
|
||||||
{"blockNumber": 17237199, "blockId": "0x9a87a14a128c0345a366940f821a14f16719de628658ac0628e410a72d723e90", "firstIndex": 10603200178},
|
{"blockNumber": 17237026, "blockId": "0x9a49d943f82a7335f8049df4d953080f25920e3b098f6a2d872520166b225961", "firstIndex": 10603199938},
|
||||||
{"blockNumber": 17287181, "blockId": "0x9c6e78adcf562ac63c103e3e5a02f025023079aca79bdd6ef18f7bd2a6271c29", "firstIndex": 10670309183},
|
{"blockNumber": 17287007, "blockId": "0xac3d189676d24eadc62adcf97d8730a001a7766fe3ac27b18e745ca9727f6c46", "firstIndex": 10670308186},
|
||||||
{"blockNumber": 17338652, "blockId": "0x1b747da97b2397a293602af57514dab4ca1010bb6c601ff05cb2012dd1124ebb", "firstIndex": 10737418023},
|
{"blockNumber": 17338498, "blockId": "0xe50e251aa0a3209fa8a0030b237cf8357b08eeb80492a432c8aa5969a820ee42", "firstIndex": 10737417623},
|
||||||
{"blockNumber": 17389337, "blockId": "0xbc3c0ca1e5989605b9b59c94b418562eb17ccbce30e45ac8531cf0b3867a6b2c", "firstIndex": 10804522857},
|
{"blockNumber": 17389178, "blockId": "0x1e18cedcfa6c81bc845c9136fc92f9f27ca8fff8847289bb139f374f0f6ba733", "firstIndex": 10804526769},
|
||||||
{"blockNumber": 17442261, "blockId": "0x1ec341be1cbd09f559bfa3d3e39a341d8e21052eeb7880931d43d086651733b7", "firstIndex": 10871635535},
|
{"blockNumber": 17442038, "blockId": "0x07f47ebbee99938fb96beb1ffadf8266f71d0d73f393172f0e24facd40d45c97", "firstIndex": 10871635940},
|
||||||
{"blockNumber": 17497787, "blockId": "0x6069880d486f2548599df1e14e12752d3eb9bc99843a98cd6631c22be1b58554", "firstIndex": 10938744657},
|
{"blockNumber": 17497589, "blockId": "0x247a5e852e36e46f7897ad1875e93d810ff4434bb835b469afae3a3d3d4a9c9a", "firstIndex": 10938744251},
|
||||||
{"blockNumber": 17554322, "blockId": "0x69b2564bc00b1f310f6b416912869d7530d7864bf7d70d55c7ace554f129b989", "firstIndex": 11005852829},
|
{"blockNumber": 17554111, "blockId": "0x420e420a1b599e4dc3bd115652b4d6f5eedc391086ef064f97a9cbffc02b62f9", "firstIndex": 11005853686},
|
||||||
{"blockNumber": 17608492, "blockId": "0x7d590653d5fa52c0d3ee453a77d2088504f57adcef35cd57c567afb554608457", "firstIndex": 11072961972},
|
{"blockNumber": 17608282, "blockId": "0xb2ba644d3593d3c832f932f14ffec532e26e9e1cdcd8fbe7477f46e238c6bffd", "firstIndex": 11072962303},
|
||||||
{"blockNumber": 17664272, "blockId": "0xdc16159d3500cdc7410873102f41fc55de2a8a41e3779c4b70e6224a541e2b9e", "firstIndex": 11140070967},
|
{"blockNumber": 17664091, "blockId": "0x6d0bfff8145652a617bfe03ab87e3af09219cdb822c9c214b42b16f20742c1eb", "firstIndex": 11140070260},
|
||||||
{"blockNumber": 17715101, "blockId": "0x655e33c4e81182464ea0b0e1fdbc53ce53902431db5107326b816091a4564652", "firstIndex": 11207179487},
|
{"blockNumber": 17714917, "blockId": "0x61509544b5174d3ff5d48816ff54f2929c8a400ef21454116056baa136b607b6", "firstIndex": 11207179013},
|
||||||
{"blockNumber": 17764042, "blockId": "0x54439184f31cd83ba06b48b6dbfdd744ae7246355be1327b44744058711d05c0", "firstIndex": 11274287303},
|
{"blockNumber": 17763850, "blockId": "0x8da83012621f42670601406c902ce6e48e77c6285dcc6983e108e69b3a8d5d2d", "firstIndex": 11274288732},
|
||||||
{"blockNumber": 17814383, "blockId": "0xfb453bc951360c76fb09bb1b9a3e39d23ececa0adb93368cc3f41f0457845089", "firstIndex": 11341397984},
|
{"blockNumber": 17814186, "blockId": "0xc37bda200856589c220dc206e31186d6c12761fd193f5bc7123cf331fbbed7f5", "firstIndex": 11341397343},
|
||||||
{"blockNumber": 17864648, "blockId": "0x32a68823ef4ec0cbab2fe50c97e3f462b575e8b117da40d00c710b4c66ee1d6d", "firstIndex": 11408505657},
|
{"blockNumber": 17864461, "blockId": "0x99af43893dc9f54c55abbdbd7b000e27248145371e9b00db116dfb961b36749c", "firstIndex": 11408506122},
|
||||||
{"blockNumber": 17913366, "blockId": "0x04b944aab8a4ff91b77c2191817cf051766100c227616a3746af53407e740124", "firstIndex": 11475614351},
|
{"blockNumber": 17913212, "blockId": "0x9b642236d63d756fcd3404713bc6abe97804b46a9e665ae5f1d9aa48e693fe78", "firstIndex": 11475614347},
|
||||||
{"blockNumber": 17961690, "blockId": "0x08bee7cc0b764106ca01dd5370b617879487ffb423688c96e948dce125990f45", "firstIndex": 11542723488},
|
{"blockNumber": 17961497, "blockId": "0xaec9b1e851cf51646673ec7698e1d5964d44eb04729ad11385f6ae84d497070a", "firstIndex": 11542723713},
|
||||||
{"blockNumber": 18011048, "blockId": "0x94c39d3a64f3e9a91b1d98554cd29e1390e30fa61cfa4e909c503eee2fd9f165", "firstIndex": 11609833142},
|
{"blockNumber": 18010859, "blockId": "0xb15fb7fc308516cad5f1dadfb7dd92fd3fe612308f67154cf2a241990aa15bc4", "firstIndex": 11609833204},
|
||||||
{"blockNumber": 18061209, "blockId": "0x2ee9ade68955c030488c8a30537bdf948355f7dd5ae64942b5bfce1be6650e19", "firstIndex": 11676941316},
|
{"blockNumber": 18061052, "blockId": "0xd8ea94b8b8a7380d21dc433abb69973f3de2eeb339f4aaffdb79f85a5d86929d", "firstIndex": 11676938565},
|
||||||
{"blockNumber": 18111692, "blockId": "0xd6c4fd0c1cc20ed5e7960bb5043e9e5e9c66a4d2ec5709ac9797fff678435640", "firstIndex": 11744050346},
|
{"blockNumber": 18111466, "blockId": "0x5b5cc6d182bffaf06692a7efda8cad5d4742fdbce5c1146b3be3c5be10ea046a", "firstIndex": 11744048539},
|
||||||
{"blockNumber": 18166212, "blockId": "0x3262588c2ef79a3b3f6a3db6435202d22f5667cd48c136b0797404901525c9ff", "firstIndex": 11811159686},
|
{"blockNumber": 18166001, "blockId": "0x901d8401c795542c75069cd917781fa587ad416da0a5298f144fae2f14305705", "firstIndex": 11811159949},
|
||||||
{"blockNumber": 18218743, "blockId": "0x935bd9a4164ff7ecd09a37b916ce5bf78487bd19377b5b17be153e39318aee74", "firstIndex": 11878268593},
|
{"blockNumber": 18218505, "blockId": "0x5894285023f34ec6fd501cd90b605e118b9688ca7c01082289bf69a6987142bc", "firstIndex": 11878268395},
|
||||||
{"blockNumber": 18271236, "blockId": "0xe58ebb821f27e3665898f390802a3d129d217b3a3ee36d890a85cf22a0a8aa33", "firstIndex": 11945376750},
|
{"blockNumber": 18271037, "blockId": "0x3f0fce315fd993d966b6c599ebd360462466e67046d512dc430ac07f75243bae", "firstIndex": 11945377050},
|
||||||
{"blockNumber": 18323007, "blockId": "0x3997a841468efa1bc614bfc3de4502274901b04b428f87a1f3086dfd78cda1eb", "firstIndex": 12012485748},
|
{"blockNumber": 18322778, "blockId": "0xfa6536b3b06e7b579e53a8d01368182808c950586e39e12485be3145c3acbf43", "firstIndex": 12012486036},
|
||||||
{"blockNumber": 18372443, "blockId": "0xc44a13a5d02e8dc39f355de5e21ce7bb311ce7f4d9114ff480dce235a169e416", "firstIndex": 12079595370},
|
{"blockNumber": 18372240, "blockId": "0x5531859d5b8a4093020e2fb971808d0eeaddd7d61dc58d70f34923081f97336f", "firstIndex": 12079595358},
|
||||||
{"blockNumber": 18421829, "blockId": "0x7da63a0b613d8745597b2ac64fd5cc8b2fb14b24d163b12a0a39d7d3d4ff7b5c", "firstIndex": 12146703582},
|
{"blockNumber": 18421630, "blockId": "0xfeadff676fe8f04d0362b77ea2d7c3ea59b05d68cc6b2cc95cfe751558b1bfa7", "firstIndex": 12146703872},
|
||||||
{"blockNumber": 18471706, "blockId": "0xd632a1893f415ff618f4b612a7687e6af1f12feeed81f46f0022090829c1eb4c", "firstIndex": 12213812677},
|
{"blockNumber": 18471472, "blockId": "0x352b0a17e4160d334b876eb180d686fd67c7ddc40a78219b0bc4b59f5ae5912d", "firstIndex": 12213813174},
|
||||||
{"blockNumber": 18522301, "blockId": "0x44fa2cf08145ae40e8e42f4e6b4ab7df360a17c5a065ce45fcc41b51bee011f4", "firstIndex": 12280921639},
|
{"blockNumber": 18522088, "blockId": "0xf7d408309246089531b47c787049c7ffd2820c1b87b4804033a458bc193a3432", "firstIndex": 12280921181},
|
||||||
{"blockNumber": 18572935, "blockId": "0x72b8ab4c78c90425ee054b4806a8be703da0febdf1d51866358ec2bd21ba9529", "firstIndex": 12348029751},
|
{"blockNumber": 18572725, "blockId": "0x44126d4a5b43594b09d26e0b0a5dc859c074865cb9b11ab78c80f28406fd0240", "firstIndex": 12348029615},
|
||||||
{"blockNumber": 18623431, "blockId": "0x8c4cb2f13501d9788820280c6f16692d0737258c3896f1e4bded32d838febf7f", "firstIndex": 12415138965},
|
{"blockNumber": 18623223, "blockId": "0xd3aec1f98cea30e870d0f530194e9a72e225eb45eefe435e38da5967eb2fa470", "firstIndex": 12415139522},
|
||||||
{"blockNumber": 18675470, "blockId": "0x523b73c19ea8b3ae32ef141a83ef9855e667ebf51443cfcabd1a06659359062a", "firstIndex": 12482247454},
|
{"blockNumber": 18675228, "blockId": "0x24deaef2508038bddf8e9020f95128ae34eb1786f786c3f98df0bdf95f3e97cc", "firstIndex": 12482248123},
|
||||||
{"blockNumber": 18725728, "blockId": "0x0cfbd131eb5dad51488238079fba29a63eebb5c32d1a543cb072e48dc2104ef3", "firstIndex": 12549356369},
|
{"blockNumber": 18725495, "blockId": "0x2e5a7edd7337b20e862741e116680a472089426dbc2b0eb5f1c984f8d6da935b", "firstIndex": 12549357121},
|
||||||
{"blockNumber": 18778387, "blockId": "0xc4906c77af8058b9f172a4f0e8788c7887f05caa5ac752b38b5387080f74ae49", "firstIndex": 12616465992},
|
{"blockNumber": 18778174, "blockId": "0xe734a1084fa5eeff427bba8e8d3623181a30dd9bad128fc22de9b15dffd0e549", "firstIndex": 12616466131},
|
||||||
{"blockNumber": 18835044, "blockId": "0x49c5e07f409a841dc81f3ef8417f1951f8fcc13c90134f9d2a0cd11938f9fa36", "firstIndex": 12683575082},
|
{"blockNumber": 18834807, "blockId": "0x0924a55ef4f9c2605261433c5b236d47645484efa44b34dc9f15b7c2e6b47a74", "firstIndex": 12683575000},
|
||||||
{"blockNumber": 18883308, "blockId": "0x386a58dd5f79a419eeb05075b07b3ff3bc836a265c9688854a504223b1d6a830", "firstIndex": 12750683753},
|
{"blockNumber": 18883054, "blockId": "0xef638ec491a1cf685b22bf4072e41710440d6133a53e31250762825247d3eb64", "firstIndex": 12750683712},
|
||||||
{"blockNumber": 18933635, "blockId": "0xd3881292147589bd2e192769e5c9175b5d03a453fe1ef3c4b5b6858ac9402a2f", "firstIndex": 12817792470},
|
{"blockNumber": 18933405, "blockId": "0x6e9eefc2e121d13e6c04544ea370fe8543afeb36fef3a8e2ea68afb079738c8c", "firstIndex": 12817792510},
|
||||||
{"blockNumber": 18988254, "blockId": "0xcbe72dfa15428ac21b9c59c703ceaa0eb4b2205927687261d7aaed3dbb3783ea", "firstIndex": 12884882858},
|
{"blockNumber": 18988033, "blockId": "0x4c98c0dbb6a7217609c4b277fe7ff9e2c32c8d000ee628a3f37b2b296e1ca421", "firstIndex": 12884901389},
|
||||||
{"blockNumber": 19041325, "blockId": "0x92b077e1c2f8819da728f0307c914fdcd57eba14ea07d9a45c28d1ed8ffff576", "firstIndex": 12952010530},
|
{"blockNumber": 19041096, "blockId": "0x61a219a23d111cd07861ff47b89d4b2840c0ab5421d5d55a6f1fe43da3f33b98", "firstIndex": 12952010147},
|
||||||
{"blockNumber": 19089163, "blockId": "0x43f8ab2d3dfc34c8e18cba903074d54e235dc546f19c4eb78245a522c266c84e", "firstIndex": 13019119228},
|
{"blockNumber": 19088914, "blockId": "0xefb26ba58447e50e9b820e0b0d16c08da45793a824af12a2e1f38b6f46b7e36a", "firstIndex": 13019118891},
|
||||||
{"blockNumber": 19140629, "blockId": "0xab7b7ae5424b18105a13b657fa6099d4ab67fde5baff39fe6e4de707397e995c", "firstIndex": 13086228236},
|
{"blockNumber": 19140413, "blockId": "0x91dbb13623fc4d5a4e462dfa0a03c92bf5301948dd4b2c3e5fddd2bc88856d47", "firstIndex": 13086228137},
|
||||||
{"blockNumber": 19192118, "blockId": "0x451327e6a5cf6ce1c8c14c01687dc5f719f3c2176f46bac4f264616256e30d1c", "firstIndex": 13153337116},
|
{"blockNumber": 19191876, "blockId": "0xdd7f97af7ad206b2636656ed4722fe1c47c6ba9fa5531066785acbe4f8d4c4ad", "firstIndex": 13153336551},
|
||||||
{"blockNumber": 19237836, "blockId": "0x9b260d6be369557d1dc88aca423e2697e697d941d1b726c183015b5649e248c8", "firstIndex": 13220445421},
|
{"blockNumber": 19237651, "blockId": "0xf1e875f314314abe3654b667c6443c772dd67c525c52877b06515ea8fc5a391b", "firstIndex": 13220444812},
|
||||||
{"blockNumber": 19291271, "blockId": "0x4878c28d79e1f71bc11e062eb61cb52ae6a18b670b0f9bea38b477944615078e", "firstIndex": 13287554254},
|
{"blockNumber": 19291032, "blockId": "0x9eda269ac47957b619d2a8c408b5efc8cfb168a46bfde351f43325fa337fce47", "firstIndex": 13287553967},
|
||||||
{"blockNumber": 19344448, "blockId": "0x56243b9ad863bf90953fe9aa6e64a426629384db1190e70dce79575d30595f7e", "firstIndex": 13354663659},
|
{"blockNumber": 19344225, "blockId": "0x62859b78d45f589f679fc6a3bf266a2e0aa906fd61d787755ec51cfadc05eaf6", "firstIndex": 13354663338},
|
||||||
{"blockNumber": 19394948, "blockId": "0x195173b64dda7908d6aa39a63c8bdd29ec181d401e369d513be1308550d0ddcb", "firstIndex": 13421771935},
|
{"blockNumber": 19394709, "blockId": "0x7cda3d193bcfe8ddbc89b85e98c814dbbe31a54ccab52ab7738ecd003061f3c8", "firstIndex": 13421772549},
|
||||||
{"blockNumber": 19443075, "blockId": "0xd39c1d60996475e65d1ab5b4e755f510ca466564a8155d35db6667988d6c0e44", "firstIndex": 13488880427},
|
{"blockNumber": 19442850, "blockId": "0xd95f3f8bab5b91c3e1f848c9455936850bf92cf6a5086b817f6f81031bc0f81e", "firstIndex": 13488880704},
|
||||||
{"blockNumber": 19488383, "blockId": "0x28956eb8856fa8db59c02585016b8baf43bc44bc35b00bdaf8a6babe51101c5c", "firstIndex": 13555977105},
|
{"blockNumber": 19488177, "blockId": "0x3a1a9623ee332d6decada9359cf84eeafb81fffa997d6cf4f3efcc92e98e9310", "firstIndex": 13555989570},
|
||||||
{"blockNumber": 19534584, "blockId": "0x2421c97b0f140185d4c20943cd4ed7d7424468482feb76e3003a1cc69da3fd7b", "firstIndex": 13623097580},
|
{"blockNumber": 19534365, "blockId": "0x5c7a8ee7cbba4894ea412cc335895a9a7d3369d35779bcdc97a6c24b6a81a7ba", "firstIndex": 13623097446},
|
||||||
{"blockNumber": 19579602, "blockId": "0x25f96529028e9f51c59aec9ce8de282b7dd67066fd46a1694130698ed0f40d8b", "firstIndex": 13690207623},
|
{"blockNumber": 19579409, "blockId": "0x4280f5f76cb0f9947f9da1cb9de6c4b6e65b37b3a3c174f5fb29d360cf389ffb", "firstIndex": 13690206790},
|
||||||
{"blockNumber": 19621517, "blockId": "0x4f6f6e0a0488f3d51823bc4b07c292348c259b1866968f77ee76b66b37101c75", "firstIndex": 13757315529},
|
{"blockNumber": 19621406, "blockId": "0x0a98ca72e97fd295c7c73263b17185d74dbe427f41c616a5d5454faa5a1c63a0", "firstIndex": 13757316653},
|
||||||
{"blockNumber": 19665085, "blockId": "0x00f9315f89681b44bff46f1bad8894bc6dfae1c459d3d6520f9881861304a496", "firstIndex": 13824425382},
|
{"blockNumber": 19664868, "blockId": "0xc8c53d89b7a849861f3daaf9503e6397a0340cecb085850c3636bee6ea2b7189", "firstIndex": 13824424608},
|
||||||
{"blockNumber": 19709229, "blockId": "0x24e022b21ae1ba8a3e8c87cb9734aa1d1810fc4a69fe147d3ebb1ff0df8bcc15", "firstIndex": 13891534799},
|
{"blockNumber": 19709011, "blockId": "0xf65babc88ef6a9eb2ffce9a6844adf895995f65a2facd1956f5df17ca68dbf94", "firstIndex": 13891534141},
|
||||||
{"blockNumber": 19755387, "blockId": "0x77f184b7183b1a351760d242041249464b42cfaa6fbc4326f352b06bb3b21a02", "firstIndex": 13958642483},
|
{"blockNumber": 19755170, "blockId": "0xf903882449eeb86d69af33b6797099275e82d8787334a02a42a2168dbd739b95", "firstIndex": 13958642627},
|
||||||
{"blockNumber": 19803894, "blockId": "0xf37eb1b054a6d61272940361f386eb744cded84d15c3250a7eabadede257371c", "firstIndex": 14025751618},
|
{"blockNumber": 19803666, "blockId": "0xa8a975f570db082a3771790bb1fe405667dde4674ff49e31092687fa92727e36", "firstIndex": 14025752433},
|
||||||
{"blockNumber": 19847885, "blockId": "0x4659649fa8a3b4bbe8978673ba9a22ae20352c7052b676d373b5a51b1967ffa4", "firstIndex": 14092848654},
|
{"blockNumber": 19847730, "blockId": "0x89d479a4b4d9faa7af3e3f61d13a7a9c80a11c4adf7cd018859eb0ddba30bdd5", "firstIndex": 14092860598},
|
||||||
{"blockNumber": 19894193, "blockId": "0x15606bdc0f1a710bd69443c7154d4979aece9329977b65990c9b39d6df84ed5c", "firstIndex": 14159970181},
|
{"blockNumber": 19894138, "blockId": "0x740278e6dc79cfd2b030780868a1b8e1520dbae0e8d3ee0a3ef43c84c83c6e0a", "firstIndex": 14159952129},
|
||||||
{"blockNumber": 19938551, "blockId": "0x6a8f4571924ed902bd8e71bf8ed9cc9d72cabeabc410277c8f0fc2b477d00eb7", "firstIndex": 14227077892},
|
{"blockNumber": 19938334, "blockId": "0x05ae7ce9813235c19baa57658bc5c8e160130328a1fd2cc58d2baf2d9a4ae097", "firstIndex": 14227078393},
|
||||||
{"blockNumber": 19985354, "blockId": "0x7b6fb6376410b4d9e5d7ee02f78b2054e005dd2976eea47fc714f66b967dc285", "firstIndex": 14294187965},
|
{"blockNumber": 19985138, "blockId": "0x511c8876a93a77fa473ae0d29e25d8163162c09b7212f506be0ea73840ea3971", "firstIndex": 14294187397},
|
||||||
{"blockNumber": 20028440, "blockId": "0x9b37440b71c24756b8855b8012432b84276ae94c80aa1ccc8b70a7705992103c", "firstIndex": 14361296503},
|
{"blockNumber": 20028221, "blockId": "0x64379baedf429cfa65df076142a7d9909d7e369d6aa6b8e161bb686944d169ff", "firstIndex": 14361296446},
|
||||||
{"blockNumber": 20071780, "blockId": "0xa2ed129f343f3d60419772ec5635edcd36b8680c9419b6626e2bc84b230c709b", "firstIndex": 14428405230},
|
{"blockNumber": 20071555, "blockId": "0x4f43d8b1091d2bd0c6b080ce51bce08aae6be605e00889be3cdd17cb80614ff8", "firstIndex": 14428405409},
|
||||||
{"blockNumber": 20113832, "blockId": "0xe7a610e8bcbf8ded141ebc7142de03dfc54b1bcc79e3bf8d07fad4e42b665bba", "firstIndex": 14495512019},
|
{"blockNumber": 20113611, "blockId": "0xebbf87409ef6732a53513414926b0aa998a7269f9e9717a3acbe96a33c2de937", "firstIndex": 14495514255},
|
||||||
{"blockNumber": 20156854, "blockId": "0xbe09704f65a70ef8843d9c8e511ddc989ea139dbe94cdfe37f52b03620d62385", "firstIndex": 14562622430},
|
{"blockNumber": 20156628, "blockId": "0x70218108c0669f42c4ac1afff80947cf4a0a2fd8e9300b31d45bbe330a5159c9", "firstIndex": 14562622257},
|
||||||
{"blockNumber": 20200135, "blockId": "0x9a58c34d5f77342e94065d119905c000223cd988c4b11f1539fff20737159630", "firstIndex": 14629731923},
|
{"blockNumber": 20199886, "blockId": "0x1d6aaa4b041eb0cc9caed34347bb943e50a139caf8998d781ff4f06d4aa727dc", "firstIndex": 14629732017},
|
||||||
{"blockNumber": 20244389, "blockId": "0x1e733f0db9ef21183107259b3c2408c78fa5a01469928cd295f3ea7e8eedda45", "firstIndex": 14696840011},
|
{"blockNumber": 20244148, "blockId": "0x37fed57b6945a815ec56c84c6261e90cf9f3883d9cbffc62b70d9722c1f0f363", "firstIndex": 14696839730},
|
||||||
{"blockNumber": 20288489, "blockId": "0xb5ad7edd86b181226c8c7be0a08069e3955234e797426843fff9de0f57ec59cc", "firstIndex": 14763949714},
|
{"blockNumber": 20288249, "blockId": "0x1d9fe664431e093c4ef6139ad35fea767a2e66825e605cfea9e91d1738665619", "firstIndex": 14763948803},
|
||||||
{"blockNumber": 20333582, "blockId": "0x8040c209f5cd1738ee0f85c2f1db7c43a420d148680c7390fd1701b9f0bb671a", "firstIndex": 14831058335},
|
{"blockNumber": 20333358, "blockId": "0x1ac7c1362791507057b7e87d7118b4f61c2919c8ebdb498ecf7d64a59ba3d2e2", "firstIndex": 14831058814},
|
||||||
{"blockNumber": 20377087, "blockId": "0x08fdc4cd246b6ae9d4a45646b0aed6af3bb330eb6cd4c8b93646157e7b002b84", "firstIndex": 14898167722},
|
{"blockNumber": 20376855, "blockId": "0xf6a19eac8a402f591079a4aa7ff57349c350ec96d683a031e4d85c05bc0541b2", "firstIndex": 14898167076},
|
||||||
{"blockNumber": 20421699, "blockId": "0x5a2912b5fc2f02df33b655155990f92dcaacda5b75427fe3d87fb38f36b1c17d", "firstIndex": 14965275691},
|
{"blockNumber": 20421474, "blockId": "0xe8767aa7516b632dc8c0fed3a366273ef14bd7b8c2212998b7105fb80b4c0d9b", "firstIndex": 14965276285},
|
||||||
{"blockNumber": 20467194, "blockId": "0x3deaf4325c461004b090b0261996c645ab529c1471feaf7dc2bbe1f128180297", "firstIndex": 15032385211},
|
{"blockNumber": 20466974, "blockId": "0xafa2d2e6c9594762c163c339069cb15aa9fd27d301268892e12f99a3f2912ade", "firstIndex": 15032384674},
|
||||||
{"blockNumber": 20512397, "blockId": "0x37e39697ec1b7683a6202be250ffaee7a1102e8030f87550b94af05ec66cec83", "firstIndex": 15099493973},
|
{"blockNumber": 20512183, "blockId": "0xc1c51f9372d781d7ac0a1a7aa052503bbde3e1706bf65f225b0f6a6eed93d055", "firstIndex": 15099493832},
|
||||||
{"blockNumber": 20557443, "blockId": "0x8e9c04468f3111eab8b1f6a58b277862c624861c237cadecc53ec249bd811bda", "firstIndex": 15166602882},
|
{"blockNumber": 20557251, "blockId": "0xa905087c15e2b12b19cd23f20089b471cd9815dcff73842d2043e13a276fcc55", "firstIndex": 15166601921},
|
||||||
{"blockNumber": 20595899, "blockId": "0x9787555fe57e4650002257eb2c88f1ef435b99d406e33fe2f889be180123ef25", "firstIndex": 15233709908},
|
{"blockNumber": 20595654, "blockId": "0x9e7772dd946f65e7569f34f6896d8e597ac8ff88700b871de21ff578c0c995e6", "firstIndex": 15233711474},
|
||||||
{"blockNumber": 20638606, "blockId": "0x70681cffd159ce2e580dbbbe8fa6b5343dbcb081429cdda6c577e615bef4ef05", "firstIndex": 15300820678},
|
{"blockNumber": 20638340, "blockId": "0xc08b46af83db6f0e5d1acad7020bacd59d0f18df72651d32c9b60edd0351a886", "firstIndex": 15300820584},
|
||||||
{"blockNumber": 20683605, "blockId": "0xb32662d5e241132ffe2249caea67f5746a6f4382297b2ac87c81e2794faf1f7a", "firstIndex": 15367929350},
|
{"blockNumber": 20683359, "blockId": "0x7ec93a1f1d211c24d93ce7e344634efef680a6388374cf3831d250ecd63711f9", "firstIndex": 15367929168},
|
||||||
{"blockNumber": 20728630, "blockId": "0x15a817c846928b673032d5eacd0cff7a04217d268457aa30a322ecca32be4d49", "firstIndex": 15435037830},
|
{"blockNumber": 20728401, "blockId": "0x4ad4124c2595abcf4477cac4eb70c0c9372bbd48f2066c7ac5b8e9f94817ab48", "firstIndex": 15435038303},
|
||||||
{"blockNumber": 20771519, "blockId": "0x542bc7b9804bbc45f4be470f4dc56f215a4dec71fed71eba2ffc804afd262b95", "firstIndex": 15502145990},
|
{"blockNumber": 20771272, "blockId": "0x68fd6b12fdb4add8b2957105a21b571c7dcb114c6c2ca02f5fa40730a108f864", "firstIndex": 15502146509},
|
||||||
{"blockNumber": 20815097, "blockId": "0x798cdd51c964fcf18561d70095d9613b84ba836817972799c9dfd0bfbe1e042b", "firstIndex": 15569256033},
|
{"blockNumber": 20814862, "blockId": "0x4e7f640bf3c135b2442ca4c744023021af163e8d45e8d776fb7051c49d79fcff", "firstIndex": 15569256173},
|
||||||
{"blockNumber": 20857859, "blockId": "0xfb5bb066d419a651d8e0186569eb4e8d8bcd5181d8f02e0d578b5dfe2fc738dd", "firstIndex": 15636364671},
|
{"blockNumber": 20857627, "blockId": "0x9b023bffed12530b5a68db263bb621a147e0cf02b30ec39a82b82a1fdeb7ca36", "firstIndex": 15636364955},
|
||||||
{"blockNumber": 20896890, "blockId": "0x834b8d6fad779e4cf8214128f6c93d7387b6d6279e517f6f0a284b5d831cc3ae", "firstIndex": 15703472902},
|
{"blockNumber": 20896662, "blockId": "0x8c3adf694b8520ed1edd38282b2f58cf383426176628b5be6330a56882e2a07e", "firstIndex": 15703473445},
|
||||||
{"blockNumber": 20939387, "blockId": "0x7adee7c78420c711efa216c61e0b561e581d7ff0331efd91ee16a609b34cfdc2", "firstIndex": 15770582325},
|
{"blockNumber": 20939156, "blockId": "0x0649e2559f767da945a674c9d6c700628109e18d0757ad33496a228a827413a4", "firstIndex": 15770581979},
|
||||||
{"blockNumber": 20981303, "blockId": "0x6f5d7b0cc6dad5eb258176e07de21795a8347d68f7303f06934046e0236bea6d", "firstIndex": 15837691713},
|
{"blockNumber": 20981054, "blockId": "0xebf0ecca671b833f77df70106cf1171d4dd3fa0f062607e4845569073997f1cd", "firstIndex": 15837691319},
|
||||||
{"blockNumber": 21023216, "blockId": "0x96cfe35a45df1297a36f42c59ebe706ab0473dfbf59ce910b5c5a8dbf696de1c", "firstIndex": 15904799667},
|
{"blockNumber": 21022980, "blockId": "0x07479520c08a727c42e3616aca7fc4435773f4ef277d84369190263159606d71", "firstIndex": 15904799391},
|
||||||
{"blockNumber": 21068378, "blockId": "0x93753875ff330d922b23f823203198f3b1bb8833367c6b6a8f896ff54be2c12d", "firstIndex": 15971909040},
|
{"blockNumber": 21068139, "blockId": "0x669cfd03b293a61815588cb9cef928a512d328c1fe9191fe6b281573f429f8b8", "firstIndex": 15971908604},
|
||||||
{"blockNumber": 21112445, "blockId": "0x6ac02fa6ae486b86aba562eaf6f3d883befaa8ebedcfd8d74bdb7368d42deee3", "firstIndex": 16039003625},
|
{"blockNumber": 21112368, "blockId": "0x98957aedaf8b0483be208e8d16a3e6d73ff217e732f3649650671c92c8fb57a5", "firstIndex": 16039007815},
|
||||||
{"blockNumber": 21155992, "blockId": "0x25f76896b4b693bafb79e9a535e2bf00ed62a577e35209749346e8e79a60bb71", "firstIndex": 16106126344},
|
{"blockNumber": 21155756, "blockId": "0xc301e40988fbe19b1254ab3abe2f78fe0cd35259898be02476179a041926f777", "firstIndex": 16106127130},
|
||||||
{"blockNumber": 21200962, "blockId": "0x725f2befe913cb2659d262e2d3b6f79a706b31c557d52669471da22347ec8287", "firstIndex": 16173235265},
|
{"blockNumber": 21200717, "blockId": "0x8d35b199ee65c5ccf4ca0fc22b50282850cd88b72580679f1568eea67d3431e8", "firstIndex": 16173235593},
|
||||||
{"blockNumber": 21244663, "blockId": "0x6778c4194f54e70939da38853daddb22bfaf160d35617ab05d0f5c476741147b", "firstIndex": 16240344735},
|
{"blockNumber": 21244396, "blockId": "0xe7ec084eb8a7125fe26c4ef64fdbb3e0a727b2d882fb1e4fdad1d7fa3dc55fd2", "firstIndex": 16240343803},
|
||||||
{"blockNumber": 21290273, "blockId": "0x433ac819c40bd3061205fe0ece0645eec73f54a0a5c1559c981f983345bc0154", "firstIndex": 16307453543},
|
{"blockNumber": 21290031, "blockId": "0x8bb31b883d30875b7ed8a01c35a6f51e603b8d974c4e74af20fb9c723e5ac5df", "firstIndex": 16307452772},
|
||||||
{"blockNumber": 21336156, "blockId": "0x261dc8c1639d505624150d2388d15ed10bfb4c3ce9c0c327a4ec26531689a097", "firstIndex": 16374562466},
|
{"blockNumber": 21335893, "blockId": "0xd0976b7c946a7556e607e47a02d2cfcccd259508e2828b9c4faa5c7105a597a8", "firstIndex": 16374562657},
|
||||||
{"blockNumber": 21378880, "blockId": "0x5c78b2b70553140dfdfdd4f415b98f88e74f74662315834038fd99042277d917", "firstIndex": 16441671104},
|
{"blockNumber": 21378611, "blockId": "0x72d42953f013aeb7c84bb22c9e07828b92f73885b20c208af612874df8fe85ed", "firstIndex": 16441671192},
|
||||||
{"blockNumber": 21421613, "blockId": "0x854532f9d1c77627b763f9cbc7099a653d59554ed57fa763bc218834c82955fe", "firstIndex": 16508780351},
|
{"blockNumber": 21421343, "blockId": "0x663b3cddcf3f7cfa59ed29b4894e43fa784c07576cfec897ff1a3838235ecb50", "firstIndex": 16508779766},
|
||||||
{"blockNumber": 21466875, "blockId": "0xb8b83cc62084e948235ef4b5973bf7fd988fa28bcaa72f7d38ad8e50de729618", "firstIndex": 16575888599},
|
{"blockNumber": 21466598, "blockId": "0xe04ebd60289dbcc09a27e053e7b240a59e928e2a76a85a6fa4044ee387c46d18", "firstIndex": 16575888836},
|
||||||
{"blockNumber": 21511942, "blockId": "0xe806a28bc1b7f8cd752c8ceedbe081d49773d4558a9fb95e3357c0c07172522d", "firstIndex": 16642996907},
|
{"blockNumber": 21511717, "blockId": "0x5ea9863a0b504f381010ff383d60a56390ba9cef162d9d5a077b1884d2adac98", "firstIndex": 16642998234},
|
||||||
{"blockNumber": 21550291, "blockId": "0x1f3e26d303e7a2a9b0614f12f62b189da365b3947c5fe2d99ed2711b37fe7daa", "firstIndex": 16710106826},
|
{"blockNumber": 21550050, "blockId": "0x2a7b3e635c80521887ca3ebda04541090ec720dd817cd06fcba61e7ae0f78a4f", "firstIndex": 16710106733},
|
||||||
{"blockNumber": 21592690, "blockId": "0xa1408cfbc693faee4425e8fd9e83a181be535c33f874b56c3a7a114404c4f686", "firstIndex": 16777215566},
|
{"blockNumber": 21592440, "blockId": "0xc7095268d0d53cb5a069c2ea7107cc42172bb1b817f04154938e6b52bdbb369c", "firstIndex": 16777215261},
|
||||||
{"blockNumber": 21636275, "blockId": "0x704734c2d0351f8ccd38721a9a4b80c063368afaaa857518d98498180a502bba", "firstIndex": 16844323959},
|
{"blockNumber": 21636007, "blockId": "0x55f463b932053ebfc02728a12c2cdfb2cb4700a115cde686c9ab22bb4c336ecb", "firstIndex": 16844324844},
|
||||||
{"blockNumber": 21681066, "blockId": "0x1e738568ed393395c498b109ad61c0286747318aae0364936f19a7b6aba94aef", "firstIndex": 16911433076},
|
{"blockNumber": 21680799, "blockId": "0x4521d473aa7f5150f920c66fe639b20f30cb373b32e425fcb7dcce9803b506be", "firstIndex": 16911431255},
|
||||||
{"blockNumber": 21725592, "blockId": "0xee87b7948e25a7498a247c616a0fbaa27f21b004e11fc56f2a20c03791ed8122", "firstIndex": 16978540993}
|
{"blockNumber": 21725330, "blockId": "0x793876007ce3594df603628766b139a02273ceee43d5b3ca2d0ca2f13a5fc5d9", "firstIndex": 16978541626},
|
||||||
|
{"blockNumber": 21771310, "blockId": "0xd0db23bb28d6e39917348b1879dd560c73354ea6d7d0bbee0b7a8fcbcede1091", "firstIndex": 17045650902},
|
||||||
|
{"blockNumber": 21811348, "blockId": "0x8165948c08db34aeb8cc2a3e331a00af2d09fbff9c466019fb2f2892ca3f7b71", "firstIndex": 17112760024},
|
||||||
|
{"blockNumber": 21851615, "blockId": "0x3083e8f4fbb4d726ef19b1a5bce20e639a0418eac384f9967f24c7697a7e2dfc", "firstIndex": 17179868870},
|
||||||
|
{"blockNumber": 21894041, "blockId": "0x9b0776a020374e4985f6a7e1199596bedd387ff085f65224d724ab11955c56fe", "firstIndex": 17246977342},
|
||||||
|
{"blockNumber": 21932218, "blockId": "0xe9c50eddc21759d3ab790e2babba56f4b8d38eb739f1b561bc337a1ba6e15393", "firstIndex": 17314085541},
|
||||||
|
{"blockNumber": 21959188, "blockId": "0x6b9c482cc4822af2ad62a359b923062556ab6a046d1a39a8243b764848690601", "firstIndex": 17381193886},
|
||||||
|
{"blockNumber": 21994911, "blockId": "0x0d99ef9dd42dd1c62fc5249eb4f618e7672ab93fa0ba7545c77360371cf972e5", "firstIndex": 17448302795},
|
||||||
|
{"blockNumber": 22026007, "blockId": "0xf7cdc7f6694f2c2ed31fa8a607f65cfa59d0dd7d7424ab5c017f959ae2982c71", "firstIndex": 17515413036},
|
||||||
|
{"blockNumber": 22059890, "blockId": "0x82b768a0dddefda2eefd3a33596ea2be075312f1dd4b01f6b0d377faca2af98b", "firstIndex": 17582521768}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,63 +1,68 @@
|
||||||
[
|
[
|
||||||
{"blockNumber": 3246675, "blockId": "0x36bf7de9e1f151963088ca3efa206b6e78411d699d2f64f3bf86895294275e0b", "firstIndex": 67107286},
|
{"blockNumber": 3246675, "blockId": "0x36bf7de9e1f151963088ca3efa206b6e78411d699d2f64f3bf86895294275e0b", "firstIndex": 67108765},
|
||||||
{"blockNumber": 3575582, "blockId": "0x08931012467636d3b67ae187790951daed2bb6423f9cd94e166df787b856788d", "firstIndex": 134217672},
|
{"blockNumber": 3575560, "blockId": "0x4652e3bee440f946aeaa3358c9a62b9bc4d41f663737ab00fded00c2662bfa29", "firstIndex": 134217644},
|
||||||
{"blockNumber": 3694264, "blockId": "0x1f35f276a3c78e5942ee285fcbd0c687691853c599a2f5b174ea88f653bc9514", "firstIndex": 201326578},
|
{"blockNumber": 3694262, "blockId": "0x433573f97e563ca04fa53e0d0eb019d0ffe9dd032a05ee5b33ce7705aedfd34d", "firstIndex": 201316990},
|
||||||
{"blockNumber": 3725632, "blockId": "0x3bcb264c56c3eeab6c8588145f09dff3fb5f821d9fc1e7b92264b14314dae553", "firstIndex": 268433636},
|
{"blockNumber": 3725628, "blockId": "0x1e25ebd76b9e2a2007bfdd7c82433cce7dae8beb190d249c82bf83d0cd177735", "firstIndex": 268426577},
|
||||||
{"blockNumber": 3795390, "blockId": "0x2d1ef2815bb8e018b275fa65540b98265285016aff12596bd89a3b1442d248eb", "firstIndex": 335542953},
|
{"blockNumber": 3795378, "blockId": "0xca999083e01d5947212fb878d529abecdd18a6012997b0d5326afcf6908f17e5", "firstIndex": 335543438},
|
||||||
{"blockNumber": 3856683, "blockId": "0x8a9a46d6f53975cd9ec829c3c307a99fb62b8428cefb63ffe06d17143649c3ee", "firstIndex": 402648835},
|
{"blockNumber": 3856681, "blockId": "0x48148cd35de3de6c626f76ce5d97cfc6acd88772af69c0aef3d640c29ba82096", "firstIndex": 402641717},
|
||||||
{"blockNumber": 3869370, "blockId": "0x2e8c04e7e5e96d09260b65d77b1770b4105b0db2ee7d638c48f086b8afac17db", "firstIndex": 469759276},
|
{"blockNumber": 3869367, "blockId": "0x08bafccf9ece7b72e4e069fc3c7493fbf25732881758917df2e8f9a51fc2c75f", "firstIndex": 469761225},
|
||||||
{"blockNumber": 3938357, "blockId": "0xf20f2cdbcc412d5340e31955d14a6526ea748ba99b5ec70b6615bdb18bcd4cfb", "firstIndex": 536868027},
|
{"blockNumber": 3938346, "blockId": "0xc638eb890c0e65ce1169ef0bb6b74dede2f4f6144ff8a5739c4894ff41a22fa2", "firstIndex": 536865235},
|
||||||
{"blockNumber": 3984894, "blockId": "0x0bcd886b3cebb884d5beeaf5ad15ee1514968b5ad07177297c7d9c00f27aa406", "firstIndex": 603968430},
|
{"blockNumber": 3984892, "blockId": "0x6a7782f0765b0f0c406b3cb107fd8bb14c6906293d9bdc5cc00e081bfd1ae59f", "firstIndex": 603972697},
|
||||||
{"blockNumber": 4002664, "blockId": "0x7d3575b6ca685468fa5a5fa9ff9d5fac4415b0a67a3ed87d3530f127db32fff4", "firstIndex": 671088417},
|
{"blockNumber": 4002660, "blockId": "0xda473de053602bc42fcbb074a32c908303f7f6db2ed8c38192665dce80276702", "firstIndex": 671087183},
|
||||||
{"blockNumber": 4113187, "blockId": "0x3a5313ac5b602134bb73535b22801261e891ccb7bd660ab20e0a536dc46d3e13", "firstIndex": 738197016},
|
{"blockNumber": 4113149, "blockId": "0xd1782f677262226194725028858da83e672748e409fe1c21bdd77c07be0662c8", "firstIndex": 738197365},
|
||||||
{"blockNumber": 4260758, "blockId": "0xe30fb9a304d3602896a5716d310f67ba34ccef7f809a3ead4b2d991cb9ee4eb0", "firstIndex": 805306270},
|
{"blockNumber": 4260733, "blockId": "0xc356600819e49d311963312157c481fd9be43a36ad040a0512fd17559c78d394", "firstIndex": 805305957},
|
||||||
{"blockNumber": 4391131, "blockId": "0x3958478c1c3be9b7caedbcc96230ed446d711e56580e324bc2fcf903fc87c90f", "firstIndex": 872415115},
|
{"blockNumber": 4391073, "blockId": "0x06f903dc765b4b0ca1a40847eb74d30b0b51904a70c46f2e836dc5b3ea3dd8d3", "firstIndex": 872415067},
|
||||||
{"blockNumber": 4515650, "blockId": "0x46a3a7b97a9dff4ef4dc2c1cc5cd501f2182d9548655b77b5e07a2dbb41071a4", "firstIndex": 939523930},
|
{"blockNumber": 4515567, "blockId": "0xe99d3849755a1b4ec9a65d003260c111d4886e29ad6243fc750c72dbc79dbe4c", "firstIndex": 939523746},
|
||||||
{"blockNumber": 4634818, "blockId": "0x2197d0dd3925c1d7ba3e2c4eef20035b68efc0a2506f76ddd9e481e0ce8ca6e1", "firstIndex": 1006628557},
|
{"blockNumber": 4634815, "blockId": "0x9f281e749b192ef58242ff9fccd496a9075c30bd28c61ed4ce6487fc2d167e5c", "firstIndex": 1006629595},
|
||||||
{"blockNumber": 4718295, "blockId": "0xcce7bb4af1a41e6056ef68192e60c738be01ac3e071ed1ec52cead08a39995ce", "firstIndex": 1073734698},
|
{"blockNumber": 4718286, "blockId": "0x23d2a40ec3ae059a45006ba651a70f308b6b282829b9cfdf2534e4311e34050f", "firstIndex": 1073731435},
|
||||||
{"blockNumber": 4753438, "blockId": "0xa60e043728a369cdf39a399bd7a903085ee9386f38176947578e5692b4b01f65", "firstIndex": 1140843192},
|
{"blockNumber": 4753427, "blockId": "0x6df7295f9ccb45a95e6cc72a8ee56bda992513b3bf4baa3d62219871a0b5a912", "firstIndex": 1140843105},
|
||||||
{"blockNumber": 4786522, "blockId": "0x10629cadc00e65f193fa4d10ecd2bf1855e442814c4a409d19aae9eb895dce13", "firstIndex": 1207956586},
|
{"blockNumber": 4786511, "blockId": "0x705c79435411c1af81385a1eca34343427eceb3f6af72e7f665552d6b0eceb6c", "firstIndex": 1207957185},
|
||||||
{"blockNumber": 4811706, "blockId": "0xf1e94111f0086733bdcb4a653486a8b94ec998b61dda0af0fd465c9b4e344f87", "firstIndex": 1275058221},
|
{"blockNumber": 4811696, "blockId": "0x69a6e60d1b958b469feafb1dca97f38f97620a90c21ed92f90080f6443ee6c78", "firstIndex": 1275061401},
|
||||||
{"blockNumber": 4841796, "blockId": "0xa530f7dd72881ac831affdc579c9d75f6d4b6853b1f1894d320bd9047df5f9eb", "firstIndex": 1342177155},
|
{"blockNumber": 4841770, "blockId": "0x0a0e9d2d3d177601a478428297b5b9a42124166fefe42f2221c7a612c31e7ca1", "firstIndex": 1342174442},
|
||||||
{"blockNumber": 4914835, "blockId": "0xbd8321e354f72c4190225f8ed63d4aba794b3b568677d985e099cb62d9d36bae", "firstIndex": 1409286143},
|
{"blockNumber": 4914785, "blockId": "0x5ca0e12230aeacbce9064dff15dafb9f24e20b4a737f7d04df8549008b829fa3", "firstIndex": 1409284680},
|
||||||
{"blockNumber": 4992519, "blockId": "0x4a06a5a4aa5bc52151937cc1c0f8da691a0282e94aab8b73b9faa87da8d028de", "firstIndex": 1476384367},
|
{"blockNumber": 4992516, "blockId": "0xb9cb1700d8b65615fc3a019b2e9b2ece3b4f1e0e2fcfc01ff40bcf53e7291b10", "firstIndex": 1476387066},
|
||||||
{"blockNumber": 5088668, "blockId": "0xb7d5ee03c08ed3936348eeb3931be8f804e61f2b09debf305967c6a7bbf007e0", "firstIndex": 1543502599},
|
{"blockNumber": 5088617, "blockId": "0x33122f693a264fb2ab626232fac5e2714010fd65bdceb772109511f7c9497333", "firstIndex": 1543503849},
|
||||||
{"blockNumber": 5155029, "blockId": "0x84f590dfc2e11f1ca53c1757ac3c508d56f55ee24d6ca5501895974be4250d76", "firstIndex": 1610605837},
|
{"blockNumber": 5155024, "blockId": "0x187716822dd6ab9c21138ae5a8e763197a5e7ec48bf0e756c5e6fa2c9f2f24bf", "firstIndex": 1610604247},
|
||||||
{"blockNumber": 5204413, "blockId": "0xeaf2c3fb6f927c16d38fab08b34303867b87470558612404c7f9e3256b80c5b9", "firstIndex": 1677720841},
|
{"blockNumber": 5204373, "blockId": "0x753b6495979ca90a1b915edad6af33c58bbabe68b45f95c7645113ec1d35d0e6", "firstIndex": 1677721200},
|
||||||
{"blockNumber": 5269957, "blockId": "0x596e0b2e8e4c18c803b61767320fe32c063153d870c94e4a08e9a68cbaa582a9", "firstIndex": 1744825147},
|
{"blockNumber": 5269952, "blockId": "0xcbb0409ed824631120d6951b55537143d9a1c82ca6dd6255d2eb31c57844685c", "firstIndex": 1744829248},
|
||||||
{"blockNumber": 5337678, "blockId": "0x7b2d54f8af1ecaaaab994e137d4421d8236c1c10d9a7bdcb9e5500db7a3fe9a3", "firstIndex": 1811939316},
|
{"blockNumber": 5337623, "blockId": "0x0b460658511c4ae5205c038430789f9b31f3c08ba4acc06d273b7a13a149cf8b", "firstIndex": 1811939255},
|
||||||
{"blockNumber": 5399058, "blockId": "0xb61ef16d55c96682fb62b0110a2dbc50d8eff2526be4121ece3690700611c71b", "firstIndex": 1879046044},
|
{"blockNumber": 5399044, "blockId": "0x9d07e37321e2b019f4837cc4f95f103da87ecdcb77e131e9d42d8643b0446524", "firstIndex": 1879041131},
|
||||||
{"blockNumber": 5422707, "blockId": "0xdabcab7c0cc9cb9f22f7507a1076c87831cb1afed9d0aa5bcd93f22266720c91", "firstIndex": 1946156915},
|
{"blockNumber": 5422692, "blockId": "0x9d9e27614635989788e32f15cd7a0abf7470dccf3336b77547baeb3423b629ca", "firstIndex": 1946154968},
|
||||||
{"blockNumber": 5454264, "blockId": "0xe1bde812906605ce662f5fd9f01b49c7331fb25f52ab5b12d35ea2b4da5458fe", "firstIndex": 2013259168},
|
{"blockNumber": 5454259, "blockId": "0x01e694443d471d3411fe0b52720fd4a189e687b14cc8ede116f5e93f0ad96bb6", "firstIndex": 2013265148},
|
||||||
{"blockNumber": 5498898, "blockId": "0x9533d9c5353d22f8a235e95831cfbf4d5a7220a430ca23494526a9d3aa866fe8", "firstIndex": 2080374321},
|
{"blockNumber": 5498863, "blockId": "0xc4cb906c96d9f80b830b8add25318c38b3ff857c1bd577cd9cae0a324a068ffc", "firstIndex": 2080373677},
|
||||||
{"blockNumber": 5554801, "blockId": "0xe7b320bbecb19f1e99dd6ce4aed1efc754d7b2022e1f80389e8a21413c465f55", "firstIndex": 2147476253},
|
{"blockNumber": 5554788, "blockId": "0x9b934b2d66723559d82e0f4cd49a2497234fe892248cb2f46c13f6a9585cfddd", "firstIndex": 2147475372},
|
||||||
{"blockNumber": 5594725, "blockId": "0xce6750be4a5b3e0fe152dd02308e94f7d56b254852a7e9acef6e14105053d7d1", "firstIndex": 2214591591},
|
{"blockNumber": 5594711, "blockId": "0x840c0b7889b8c882cfa0eceb516dd73043b51c0e5a0c1be849a0e2a5dda7e842", "firstIndex": 2214592267},
|
||||||
{"blockNumber": 5645198, "blockId": "0x5d42d39999c546f37001d5f613732fb54032384dd71a686d3664d2c8a1337752", "firstIndex": 2281696503},
|
{"blockNumber": 5645179, "blockId": "0x188873a43506fee33349bc33df4a55059401e98dc7f0a5d488a0bc5c87dfd431", "firstIndex": 2281695869},
|
||||||
{"blockNumber": 5687659, "blockId": "0x3ed941be39a33ffa69cf3531a67f5a25f712ba05db890ff377f60d26842e4b1c", "firstIndex": 2348801751},
|
{"blockNumber": 5687634, "blockId": "0x7ea8d7a2afccf795a2a02eb00746d89db57f13f8936cf7ab0f0a7db1b1ceb341", "firstIndex": 2348806824},
|
||||||
{"blockNumber": 5727823, "blockId": "0xaf699b6c4cd58181bd609a66990b8edb5d1b94d5ff1ab732ded35ce7b8373353", "firstIndex": 2415917178},
|
{"blockNumber": 5727808, "blockId": "0x3f3eaf36c8e0271403737676907eac15312927c1d60ce814337654b7d7f2b2bd", "firstIndex": 2415915517},
|
||||||
{"blockNumber": 5784505, "blockId": "0x621c740d04ea41f70a2f0537e21e5b96169aea8a8efee0ae5527717e5c40aa64", "firstIndex": 2483024581},
|
{"blockNumber": 5784480, "blockId": "0x10ec5adf01449c29550f5117f09ecafc49fc614d7da5886cf01619950827f850", "firstIndex": 2483023750},
|
||||||
{"blockNumber": 5843958, "blockId": "0xec122204a4e4698748f55a1c9f8582c46bacda029aee4de1a234e67e3288e6b1", "firstIndex": 2550136761},
|
{"blockNumber": 5843906, "blockId": "0x9e6e14b3fba395a9ae7b3f1295f33a12d0f8b9f10e1aaab1649a90a56a323676", "firstIndex": 2550136398},
|
||||||
{"blockNumber": 5906359, "blockId": "0x8af5ce73fbd7a6110fb8b19b75a7322456ece88fcfa1614c745f1a65f4e915c1", "firstIndex": 2617245617},
|
{"blockNumber": 5906280, "blockId": "0x2188869a164e9c19232f6702a5233dc27a2304839159dd7230cc93ebdfc6c048", "firstIndex": 2617245012},
|
||||||
{"blockNumber": 5977944, "blockId": "0xbc8186258298a4f376124989cfb7b22c2bea6603a5245bb6c505c5fc45844bbd", "firstIndex": 2684350982},
|
{"blockNumber": 5977929, "blockId": "0xb247181ed597d9473c2c6e5762ae45a05f328d8df215fdac83d19ae4c028109a", "firstIndex": 2684347033},
|
||||||
{"blockNumber": 6051571, "blockId": "0x54f9df9d9d73d1aa1cfcd6f372377c6013ecba2a1ed158d3c304f4fca51dae58", "firstIndex": 2751463209},
|
{"blockNumber": 6051479, "blockId": "0x0e8634c95dac31b7c835b44d0a14290e9212b31b9c3f621997ad1cca2d8ab0ba", "firstIndex": 2751463372},
|
||||||
{"blockNumber": 6118461, "blockId": "0xfea757fad3f763c62a514a9c24924934539ca56620bd811f83e9cc2e671f0cf0", "firstIndex": 2818572283},
|
{"blockNumber": 6118422, "blockId": "0xa642c4457d4b63d68a5502bdba2355616e34495bf3ab2d8518a45ded54a16be4", "firstIndex": 2818563217},
|
||||||
{"blockNumber": 6174385, "blockId": "0x2d8d0226e58f7516c13f9e1c9cf3ea65bb520fa1dfd7249dc9ea34a4e1fd430d", "firstIndex": 2885681036},
|
{"blockNumber": 6174274, "blockId": "0xbb9808bc56b5f14636e654bdd6d50d35b31345255926341ef3ddb54840095bcc", "firstIndex": 2885680274},
|
||||||
{"blockNumber": 6276318, "blockId": "0xa922e9d54fd062b658c4866ed218632ddd51f250d671628a42968bb912d3ed5d", "firstIndex": 2952789983},
|
{"blockNumber": 6276207, "blockId": "0x7ae027a18889e1b60a46ea3e5f2759035f3d9041de68eca0b154068ec533db59", "firstIndex": 2952789656},
|
||||||
{"blockNumber": 6368452, "blockId": "0x8d3d7466a7c9ca7298f82c37c38b0f64ec04522d2ed2e2349f8edc020c57f2c4", "firstIndex": 3019898695},
|
{"blockNumber": 6368344, "blockId": "0x8b4401f89589d9e99259e6c05c18b1780e96b65027caf9d83edf80390d317f66", "firstIndex": 3019898378},
|
||||||
{"blockNumber": 6470810, "blockId": "0x9887c35542835ee81153fa0e4d8a9e6f170b6e14fc78d8c7f3d900d0a70434f1", "firstIndex": 3087007578},
|
{"blockNumber": 6470718, "blockId": "0x0e2f8de093392c38750581c41e93c2fb1c0f6676b65c9af52792f3c56e894457", "firstIndex": 3087007589},
|
||||||
{"blockNumber": 6553334, "blockId": "0x7b0d89a0282c18785fcc108dbdc9d45dd9d63b7084ddc676df9e9504585a5969", "firstIndex": 3154115987},
|
{"blockNumber": 6553237, "blockId": "0xa6c4f3a1fe3b4e116c367fcbb1ae98e0f25570fdb2f1eadee2681deb39462c1e", "firstIndex": 3154116356},
|
||||||
{"blockNumber": 6663825, "blockId": "0xff6cec99324a89d6d36275c17a4569f0cba203fe5b0350f155a7d5445e0ed419", "firstIndex": 3221224775},
|
{"blockNumber": 6663750, "blockId": "0x9049748ddf655c7cc2ccbe2d36010b3a67ae011d114d32b1c812a7a53102f27f", "firstIndex": 3221225375},
|
||||||
{"blockNumber": 6767082, "blockId": "0xe10a96a7194f98bf262f0cb1cdfb4d3b9a2072139dfcbe3f1eb01419e353044e", "firstIndex": 3288334139},
|
{"blockNumber": 6766894, "blockId": "0xc98188fb313b1beb7fc4f415b4a74c363903b3b5e0172437d79446bc011238b5", "firstIndex": 3288334172},
|
||||||
{"blockNumber": 6886709, "blockId": "0x20f6a5d986913025ad5b6b6387d818e49a3caf838326f4002c1439ca61313be5", "firstIndex": 3355442979},
|
{"blockNumber": 6886576, "blockId": "0x4ae8237a94198c82c266f01e472fdcd3ae150c84ecf714205a9be672f1e705b8", "firstIndex": 3355443040},
|
||||||
{"blockNumber": 6978948, "blockId": "0xd7c3024765245ec49e6a48b076d540bc91f57f2ccc125e17d60dd37bb669f843", "firstIndex": 3422551908},
|
{"blockNumber": 6978746, "blockId": "0xb2b69ce29c5c9c46c5cbc6e96260c34313d8b0b4a739cf4091c98f37093aa732", "firstIndex": 3422552017},
|
||||||
{"blockNumber": 7098891, "blockId": "0x05114c037e1b4d69a46d74a974be9bce45e87ad2226a59b44dd17f98dd2fd0d1", "firstIndex": 3489659530},
|
{"blockNumber": 7098871, "blockId": "0x9ab2b681feeb38287a1b689fa64a50efd3407b6331fd6896187cad98a29ce107", "firstIndex": 3489660879},
|
||||||
{"blockNumber": 7203157, "blockId": "0xc0f610014fcd9f2850274b58179d474f0947676fd0639b2884316467c631811d", "firstIndex": 3556769512},
|
{"blockNumber": 7203023, "blockId": "0xdedfff5985c1c93d476120d2afbaa61967bae4edabb9711c7794a1b1cd453aa1", "firstIndex": 3556769365},
|
||||||
{"blockNumber": 7256735, "blockId": "0x0324c15b3b23fd82c2962dd167618e77e60ebeac5a2c87f672caddc9732337b3", "firstIndex": 3623876508},
|
{"blockNumber": 7256709, "blockId": "0xc078041cffc1802b6342fd2ba5a92ff8076ac0f5b72b4a77ba75cd486fe1b3c9", "firstIndex": 3623876563},
|
||||||
{"blockNumber": 7307851, "blockId": "0x8e23280d1a3aec877d7758413ed20299d381aa43e7e2fc6f381ad96e8ff0acef", "firstIndex": 3690987098},
|
{"blockNumber": 7307744, "blockId": "0xdf8dcdd4af9213a79587eb2f4d91f4111da74f99207ee05e4ae50bcb4f8d5435", "firstIndex": 3690986225},
|
||||||
{"blockNumber": 7369389, "blockId": "0xbf6436eb2b88539945d6673141a14cb79ffc1e7db2b57176acf8e02ff3b6fcd3", "firstIndex": 3758096287},
|
{"blockNumber": 7369268, "blockId": "0x62315823621a38a1f138e193b85259988fcc15f4a74d0cf19a412920bcdcad98", "firstIndex": 3758096030},
|
||||||
{"blockNumber": 7445220, "blockId": "0x147619f74815283d834ac08ff494fb4791207b3949c64b2623f11ff6141ee7a7", "firstIndex": 3825204992},
|
{"blockNumber": 7445109, "blockId": "0x8b668ac1274a8dcc9526eb115c2f67bd56f6657b5072c7542da2252daca10fef", "firstIndex": 3825204921},
|
||||||
{"blockNumber": 7511632, "blockId": "0x5094d64868f419e6ac3d253d19d5feda76564a0d56d7bbf8a822dff1c2261b30", "firstIndex": 3892314047},
|
{"blockNumber": 7511512, "blockId": "0x056ad7411652aa64849c67705a86e42221cb88f7fb6a7012ab7d3d5b9a30eb76", "firstIndex": 3892313524},
|
||||||
{"blockNumber": 7557280, "blockId": "0x54aba9351a1ba51873645221aa7c991024da1fe468a600ddb6e2559351d9c28f", "firstIndex": 3959422859},
|
{"blockNumber": 7557259, "blockId": "0xef660b97661f073b7c7319b69451e16d26ecaed54f9237e209999d137da2bfd4", "firstIndex": 3959415096},
|
||||||
{"blockNumber": 7606304, "blockId": "0xbbe2fed08cf0b0ff2cb6ae9fd7257843f77a04a7d4cafb06d7a4bedea6ab0c98", "firstIndex": 4026531690}
|
{"blockNumber": 7606260, "blockId": "0x9f5f06ad381166261780864bf17ad4d3cdd475f87ba51fa7f9ba621bf0ac0acb", "firstIndex": 4026521703},
|
||||||
|
{"blockNumber": 7654244, "blockId": "0xefe5b537435001203741bf445ca26466baf7ad3f63c2bba94f0f658aed8c244b", "firstIndex": 4093627258},
|
||||||
|
{"blockNumber": 7700433, "blockId": "0x89af6e8c5aa934a9139944b3de7a15232069479dba387e0fdd043ad36156c8bf", "firstIndex": 4160749200},
|
||||||
|
{"blockNumber": 7730079, "blockId": "0x08e0d511a93e2a9c004b3456d77d687ae86247417ada1cdd1f85332a62dfed1d", "firstIndex": 4227846795},
|
||||||
|
{"blockNumber": 7777515, "blockId": "0xeba8faed2e12bb9ed5e7fad19dd82662f15f6f4f512a0d232eedf1e676712428", "firstIndex": 4294966082},
|
||||||
|
{"blockNumber": 7828860, "blockId": "0x62c054bd24be351dc4777460ee922a75fdcea5c9830455cbac6fa29552719c85", "firstIndex": 4362076087},
|
||||||
|
{"blockNumber": 7869890, "blockId": "0x5664bcfa6151f798781e22bea4f9a2c796d097402350cb131e4e3c78e13e461a", "firstIndex": 4429183267}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ type FilterMaps struct {
|
||||||
indexLock sync.RWMutex
|
indexLock sync.RWMutex
|
||||||
indexedRange filterMapsRange
|
indexedRange filterMapsRange
|
||||||
indexedView *ChainView // always consistent with the log index
|
indexedView *ChainView // always consistent with the log index
|
||||||
|
hasTempRange bool
|
||||||
|
|
||||||
// also accessed by indexer and matcher backend but no locking needed.
|
// also accessed by indexer and matcher backend but no locking needed.
|
||||||
filterMapCache *lru.Cache[uint32, filterMap]
|
filterMapCache *lru.Cache[uint32, filterMap]
|
||||||
|
|
@ -94,12 +95,12 @@ type FilterMaps struct {
|
||||||
ptrTailUnindexMap uint32
|
ptrTailUnindexMap uint32
|
||||||
|
|
||||||
targetView *ChainView
|
targetView *ChainView
|
||||||
matcherSyncRequest *FilterMapsMatcherBackend
|
matcherSyncRequests []*FilterMapsMatcherBackend
|
||||||
|
historyCutoff uint64
|
||||||
finalBlock, lastFinal uint64
|
finalBlock, lastFinal uint64
|
||||||
lastFinalEpoch uint32
|
lastFinalEpoch uint32
|
||||||
stop bool
|
stop bool
|
||||||
targetViewCh chan *ChainView
|
targetCh chan targetUpdate
|
||||||
finalBlockCh chan uint64
|
|
||||||
blockProcessingCh chan bool
|
blockProcessingCh chan bool
|
||||||
blockProcessing bool
|
blockProcessing bool
|
||||||
matcherSyncCh chan *FilterMapsMatcherBackend
|
matcherSyncCh chan *FilterMapsMatcherBackend
|
||||||
|
|
@ -145,24 +146,23 @@ func (a FilterRow) Equal(b FilterRow) bool {
|
||||||
// filterMapsRange describes the rendered range of filter maps and the range
|
// filterMapsRange describes the rendered range of filter maps and the range
|
||||||
// of fully rendered blocks.
|
// of fully rendered blocks.
|
||||||
type filterMapsRange struct {
|
type filterMapsRange struct {
|
||||||
initialized bool
|
initialized bool
|
||||||
headBlockIndexed bool
|
headIndexed bool
|
||||||
headBlockDelimiter uint64 // zero if afterLastIndexedBlock != targetBlockNumber
|
headDelimiter uint64 // zero if headIndexed is false
|
||||||
// if initialized then all maps are rendered between firstRenderedMap and
|
// if initialized then all maps are rendered in the maps range
|
||||||
// afterLastRenderedMap-1
|
maps common.Range[uint32]
|
||||||
firstRenderedMap, afterLastRenderedMap uint32
|
|
||||||
// if tailPartialEpoch > 0 then maps between firstRenderedMap-mapsPerEpoch and
|
// if tailPartialEpoch > 0 then maps between firstRenderedMap-mapsPerEpoch and
|
||||||
// firstRenderedMap-mapsPerEpoch+tailPartialEpoch-1 are rendered
|
// firstRenderedMap-mapsPerEpoch+tailPartialEpoch-1 are rendered
|
||||||
tailPartialEpoch uint32
|
tailPartialEpoch uint32
|
||||||
// if initialized then all log values belonging to blocks between
|
// if initialized then all log values in the blocks range are fully
|
||||||
// firstIndexedBlock and afterLastIndexedBlock are fully rendered
|
// rendered
|
||||||
// blockLvPointers are available between firstIndexedBlock and afterLastIndexedBlock-1
|
// blockLvPointers are available in the blocks range
|
||||||
firstIndexedBlock, afterLastIndexedBlock uint64
|
blocks common.Range[uint64]
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasIndexedBlocks returns true if the range has at least one fully indexed block.
|
// hasIndexedBlocks returns true if the range has at least one fully indexed block.
|
||||||
func (fmr *filterMapsRange) hasIndexedBlocks() bool {
|
func (fmr *filterMapsRange) hasIndexedBlocks() bool {
|
||||||
return fmr.initialized && fmr.afterLastIndexedBlock > fmr.firstIndexedBlock
|
return fmr.initialized && !fmr.blocks.IsEmpty() && !fmr.maps.IsEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
// lastBlockOfMap is used for caching the (number, id) pairs belonging to the
|
// lastBlockOfMap is used for caching the (number, id) pairs belonging to the
|
||||||
|
|
@ -183,7 +183,7 @@ type Config struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFilterMaps creates a new FilterMaps and starts the indexer.
|
// NewFilterMaps creates a new FilterMaps and starts the indexer.
|
||||||
func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, params Params, config Config) *FilterMaps {
|
func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, historyCutoff, finalBlock uint64, params Params, config Config) *FilterMaps {
|
||||||
rs, initialized, err := rawdb.ReadFilterMapsRange(db)
|
rs, initialized, err := rawdb.ReadFilterMapsRange(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error reading log index range", "error", err)
|
log.Error("Error reading log index range", "error", err)
|
||||||
|
|
@ -193,22 +193,19 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, params Params, c
|
||||||
db: db,
|
db: db,
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
waitIdleCh: make(chan chan bool),
|
waitIdleCh: make(chan chan bool),
|
||||||
targetViewCh: make(chan *ChainView, 1),
|
targetCh: make(chan targetUpdate, 1),
|
||||||
finalBlockCh: make(chan uint64, 1),
|
|
||||||
blockProcessingCh: make(chan bool, 1),
|
blockProcessingCh: make(chan bool, 1),
|
||||||
history: config.History,
|
history: config.History,
|
||||||
disabled: config.Disabled,
|
disabled: config.Disabled,
|
||||||
exportFileName: config.ExportFileName,
|
exportFileName: config.ExportFileName,
|
||||||
Params: params,
|
Params: params,
|
||||||
indexedRange: filterMapsRange{
|
indexedRange: filterMapsRange{
|
||||||
initialized: initialized,
|
initialized: initialized,
|
||||||
headBlockIndexed: rs.HeadBlockIndexed,
|
headIndexed: rs.HeadIndexed,
|
||||||
headBlockDelimiter: rs.HeadBlockDelimiter,
|
headDelimiter: rs.HeadDelimiter,
|
||||||
firstIndexedBlock: rs.FirstIndexedBlock,
|
blocks: common.NewRange(rs.BlocksFirst, rs.BlocksAfterLast-rs.BlocksFirst),
|
||||||
afterLastIndexedBlock: rs.AfterLastIndexedBlock,
|
maps: common.NewRange(rs.MapsFirst, rs.MapsAfterLast-rs.MapsFirst),
|
||||||
firstRenderedMap: rs.FirstRenderedMap,
|
tailPartialEpoch: rs.TailPartialEpoch,
|
||||||
afterLastRenderedMap: rs.AfterLastRenderedMap,
|
|
||||||
tailPartialEpoch: rs.TailPartialEpoch,
|
|
||||||
},
|
},
|
||||||
matcherSyncCh: make(chan *FilterMapsMatcherBackend),
|
matcherSyncCh: make(chan *FilterMapsMatcherBackend),
|
||||||
matchers: make(map[*FilterMapsMatcherBackend]struct{}),
|
matchers: make(map[*FilterMapsMatcherBackend]struct{}),
|
||||||
|
|
@ -223,24 +220,23 @@ func NewFilterMaps(db ethdb.KeyValueStore, initView *ChainView, params Params, c
|
||||||
f.targetView = initView
|
f.targetView = initView
|
||||||
if f.indexedRange.initialized {
|
if f.indexedRange.initialized {
|
||||||
f.indexedView = f.initChainView(f.targetView)
|
f.indexedView = f.initChainView(f.targetView)
|
||||||
f.indexedRange.headBlockIndexed = f.indexedRange.afterLastIndexedBlock == f.indexedView.headNumber+1
|
f.indexedRange.headIndexed = f.indexedRange.blocks.AfterLast() == f.indexedView.headNumber+1
|
||||||
if !f.indexedRange.headBlockIndexed {
|
if !f.indexedRange.headIndexed {
|
||||||
f.indexedRange.headBlockDelimiter = 0
|
f.indexedRange.headDelimiter = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.indexedRange.hasIndexedBlocks() {
|
if f.indexedRange.hasIndexedBlocks() {
|
||||||
log.Info("Initialized log indexer",
|
log.Info("Initialized log indexer",
|
||||||
"first block", f.indexedRange.firstIndexedBlock, "last block", f.indexedRange.afterLastIndexedBlock-1,
|
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
"first map", f.indexedRange.firstRenderedMap, "last map", f.indexedRange.afterLastRenderedMap-1,
|
"first map", f.indexedRange.maps.First(), "last map", f.indexedRange.maps.Last(),
|
||||||
"head indexed", f.indexedRange.headBlockIndexed)
|
"head indexed", f.indexedRange.headIndexed)
|
||||||
}
|
}
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the indexer.
|
// Start starts the indexer.
|
||||||
func (f *FilterMaps) Start() {
|
func (f *FilterMaps) Start() {
|
||||||
if !f.testDisableSnapshots && f.indexedRange.initialized && f.indexedRange.headBlockIndexed &&
|
if !f.testDisableSnapshots && f.indexedRange.hasIndexedBlocks() && f.indexedRange.headIndexed {
|
||||||
f.indexedRange.firstRenderedMap < f.indexedRange.afterLastRenderedMap {
|
|
||||||
// previous target head rendered; load last map as snapshot
|
// previous target head rendered; load last map as snapshot
|
||||||
if err := f.loadHeadSnapshot(); err != nil {
|
if err := f.loadHeadSnapshot(); err != nil {
|
||||||
log.Error("Could not load head filter map snapshot", "error", err)
|
log.Error("Could not load head filter map snapshot", "error", err)
|
||||||
|
|
@ -262,7 +258,7 @@ func (f *FilterMaps) Stop() {
|
||||||
// Note that the returned view might be shorter than the existing index if
|
// Note that the returned view might be shorter than the existing index if
|
||||||
// the latest maps are not consistent with targetView.
|
// the latest maps are not consistent with targetView.
|
||||||
func (f *FilterMaps) initChainView(chainView *ChainView) *ChainView {
|
func (f *FilterMaps) initChainView(chainView *ChainView) *ChainView {
|
||||||
mapIndex := f.indexedRange.afterLastRenderedMap
|
mapIndex := f.indexedRange.maps.AfterLast()
|
||||||
for {
|
for {
|
||||||
var ok bool
|
var ok bool
|
||||||
mapIndex, ok = f.lastMapBoundaryBefore(mapIndex)
|
mapIndex, ok = f.lastMapBoundaryBefore(mapIndex)
|
||||||
|
|
@ -332,12 +328,10 @@ func (f *FilterMaps) init() error {
|
||||||
}
|
}
|
||||||
if bestLen > 0 {
|
if bestLen > 0 {
|
||||||
cp := checkpoints[bestIdx][bestLen-1]
|
cp := checkpoints[bestIdx][bestLen-1]
|
||||||
fmr.firstIndexedBlock = cp.BlockNumber + 1
|
fmr.blocks = common.NewRange(cp.BlockNumber+1, 0)
|
||||||
fmr.afterLastIndexedBlock = cp.BlockNumber + 1
|
fmr.maps = common.NewRange(uint32(bestLen)<<f.logMapsPerEpoch, 0)
|
||||||
fmr.firstRenderedMap = uint32(bestLen) << f.logMapsPerEpoch
|
|
||||||
fmr.afterLastRenderedMap = uint32(bestLen) << f.logMapsPerEpoch
|
|
||||||
}
|
}
|
||||||
f.setRange(batch, f.targetView, fmr)
|
f.setRange(batch, f.targetView, fmr, false)
|
||||||
return batch.Write()
|
return batch.Write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,19 +374,20 @@ func (f *FilterMaps) removeDbWithPrefix(prefix []byte, action string) bool {
|
||||||
// setRange updates the indexed chain view and covered range and also adds the
|
// setRange updates the indexed chain view and covered range and also adds the
|
||||||
// changes to the given batch.
|
// changes to the given batch.
|
||||||
// Note that this function assumes that the index write lock is being held.
|
// Note that this function assumes that the index write lock is being held.
|
||||||
func (f *FilterMaps) setRange(batch ethdb.KeyValueWriter, newView *ChainView, newRange filterMapsRange) {
|
func (f *FilterMaps) setRange(batch ethdb.KeyValueWriter, newView *ChainView, newRange filterMapsRange, isTempRange bool) {
|
||||||
f.indexedView = newView
|
f.indexedView = newView
|
||||||
f.indexedRange = newRange
|
f.indexedRange = newRange
|
||||||
|
f.hasTempRange = isTempRange
|
||||||
f.updateMatchersValidRange()
|
f.updateMatchersValidRange()
|
||||||
if newRange.initialized {
|
if newRange.initialized {
|
||||||
rs := rawdb.FilterMapsRange{
|
rs := rawdb.FilterMapsRange{
|
||||||
HeadBlockIndexed: newRange.headBlockIndexed,
|
HeadIndexed: newRange.headIndexed,
|
||||||
HeadBlockDelimiter: newRange.headBlockDelimiter,
|
HeadDelimiter: newRange.headDelimiter,
|
||||||
FirstIndexedBlock: newRange.firstIndexedBlock,
|
BlocksFirst: newRange.blocks.First(),
|
||||||
AfterLastIndexedBlock: newRange.afterLastIndexedBlock,
|
BlocksAfterLast: newRange.blocks.AfterLast(),
|
||||||
FirstRenderedMap: newRange.firstRenderedMap,
|
MapsFirst: newRange.maps.First(),
|
||||||
AfterLastRenderedMap: newRange.afterLastRenderedMap,
|
MapsAfterLast: newRange.maps.AfterLast(),
|
||||||
TailPartialEpoch: newRange.tailPartialEpoch,
|
TailPartialEpoch: newRange.tailPartialEpoch,
|
||||||
}
|
}
|
||||||
rawdb.WriteFilterMapsRange(batch, rs)
|
rawdb.WriteFilterMapsRange(batch, rs)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -410,7 +405,7 @@ func (f *FilterMaps) setRange(batch ethdb.KeyValueWriter, newView *ChainView, ne
|
||||||
// called from outside the indexerLoop goroutine.
|
// called from outside the indexerLoop goroutine.
|
||||||
func (f *FilterMaps) getLogByLvIndex(lvIndex uint64) (*types.Log, error) {
|
func (f *FilterMaps) getLogByLvIndex(lvIndex uint64) (*types.Log, error) {
|
||||||
mapIndex := uint32(lvIndex >> f.logValuesPerMap)
|
mapIndex := uint32(lvIndex >> f.logValuesPerMap)
|
||||||
if mapIndex < f.indexedRange.firstRenderedMap || mapIndex >= f.indexedRange.afterLastRenderedMap {
|
if !f.indexedRange.maps.Includes(mapIndex) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
// find possible block range based on map to block pointers
|
// find possible block range based on map to block pointers
|
||||||
|
|
@ -425,8 +420,8 @@ func (f *FilterMaps) getLogByLvIndex(lvIndex uint64) (*types.Log, error) {
|
||||||
return nil, fmt.Errorf("failed to retrieve last block of map %d before searched log value index %d: %v", mapIndex, lvIndex, err)
|
return nil, fmt.Errorf("failed to retrieve last block of map %d before searched log value index %d: %v", mapIndex, lvIndex, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if firstBlockNumber < f.indexedRange.firstIndexedBlock {
|
if firstBlockNumber < f.indexedRange.blocks.First() {
|
||||||
firstBlockNumber = f.indexedRange.firstIndexedBlock
|
firstBlockNumber = f.indexedRange.blocks.First()
|
||||||
}
|
}
|
||||||
// find block with binary search based on block to log value index pointers
|
// find block with binary search based on block to log value index pointers
|
||||||
for firstBlockNumber < lastBlockNumber {
|
for firstBlockNumber < lastBlockNumber {
|
||||||
|
|
@ -453,6 +448,11 @@ func (f *FilterMaps) getLogByLvIndex(lvIndex uint64) (*types.Log, error) {
|
||||||
// iterate through receipts to find the exact log starting at lvIndex
|
// iterate through receipts to find the exact log starting at lvIndex
|
||||||
for _, receipt := range receipts {
|
for _, receipt := range receipts {
|
||||||
for _, log := range receipt.Logs {
|
for _, log := range receipt.Logs {
|
||||||
|
l := uint64(len(log.Topics) + 1)
|
||||||
|
r := f.valuesPerMap - lvPointer%f.valuesPerMap
|
||||||
|
if l > r {
|
||||||
|
lvPointer += r // skip to map boundary
|
||||||
|
}
|
||||||
if lvPointer > lvIndex {
|
if lvPointer > lvIndex {
|
||||||
// lvIndex does not point to the first log value (address value)
|
// lvIndex does not point to the first log value (address value)
|
||||||
// generated by a log as true matches should always do, so it
|
// generated by a log as true matches should always do, so it
|
||||||
|
|
@ -462,7 +462,7 @@ func (f *FilterMaps) getLogByLvIndex(lvIndex uint64) (*types.Log, error) {
|
||||||
if lvPointer == lvIndex {
|
if lvPointer == lvIndex {
|
||||||
return log, nil // potential match
|
return log, nil // potential match
|
||||||
}
|
}
|
||||||
lvPointer += uint64(len(log.Topics) + 1)
|
lvPointer += l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -580,8 +580,8 @@ func (f *FilterMaps) mapRowIndex(mapIndex, rowIndex uint32) uint64 {
|
||||||
// Note that this function assumes that the indexer read lock is being held when
|
// Note that this function assumes that the indexer read lock is being held when
|
||||||
// called from outside the indexerLoop goroutine.
|
// called from outside the indexerLoop goroutine.
|
||||||
func (f *FilterMaps) getBlockLvPointer(blockNumber uint64) (uint64, error) {
|
func (f *FilterMaps) getBlockLvPointer(blockNumber uint64) (uint64, error) {
|
||||||
if blockNumber >= f.indexedRange.afterLastIndexedBlock && f.indexedRange.headBlockIndexed {
|
if blockNumber >= f.indexedRange.blocks.AfterLast() && f.indexedRange.headIndexed {
|
||||||
return f.indexedRange.headBlockDelimiter, nil
|
return f.indexedRange.headDelimiter, nil
|
||||||
}
|
}
|
||||||
if lvPointer, ok := f.lvPointerCache.Get(blockNumber); ok {
|
if lvPointer, ok := f.lvPointerCache.Get(blockNumber); ok {
|
||||||
return lvPointer, nil
|
return lvPointer, nil
|
||||||
|
|
@ -658,26 +658,28 @@ func (f *FilterMaps) deleteTailEpoch(epoch uint32) error {
|
||||||
firstBlock++
|
firstBlock++
|
||||||
}
|
}
|
||||||
fmr := f.indexedRange
|
fmr := f.indexedRange
|
||||||
if f.indexedRange.firstRenderedMap == firstMap &&
|
if f.indexedRange.maps.First() == firstMap &&
|
||||||
f.indexedRange.afterLastRenderedMap > firstMap+f.mapsPerEpoch &&
|
f.indexedRange.maps.AfterLast() > firstMap+f.mapsPerEpoch &&
|
||||||
f.indexedRange.tailPartialEpoch == 0 {
|
f.indexedRange.tailPartialEpoch == 0 {
|
||||||
fmr.firstRenderedMap = firstMap + f.mapsPerEpoch
|
fmr.maps.SetFirst(firstMap + f.mapsPerEpoch)
|
||||||
fmr.firstIndexedBlock = lastBlock + 1
|
fmr.blocks.SetFirst(lastBlock + 1)
|
||||||
} else if f.indexedRange.firstRenderedMap == firstMap+f.mapsPerEpoch {
|
} else if f.indexedRange.maps.First() == firstMap+f.mapsPerEpoch {
|
||||||
fmr.tailPartialEpoch = 0
|
fmr.tailPartialEpoch = 0
|
||||||
} else {
|
} else {
|
||||||
return errors.New("invalid tail epoch number")
|
return errors.New("invalid tail epoch number")
|
||||||
}
|
}
|
||||||
f.setRange(f.db, f.indexedView, fmr)
|
f.setRange(f.db, f.indexedView, fmr, false)
|
||||||
rawdb.DeleteFilterMapRows(f.db, f.mapRowIndex(firstMap, 0), f.mapRowIndex(firstMap+f.mapsPerEpoch, 0))
|
first := f.mapRowIndex(firstMap, 0)
|
||||||
|
count := f.mapRowIndex(firstMap+f.mapsPerEpoch, 0) - first
|
||||||
|
rawdb.DeleteFilterMapRows(f.db, common.NewRange(first, count))
|
||||||
for mapIndex := firstMap; mapIndex < firstMap+f.mapsPerEpoch; mapIndex++ {
|
for mapIndex := firstMap; mapIndex < firstMap+f.mapsPerEpoch; mapIndex++ {
|
||||||
f.filterMapCache.Remove(mapIndex)
|
f.filterMapCache.Remove(mapIndex)
|
||||||
}
|
}
|
||||||
rawdb.DeleteFilterMapLastBlocks(f.db, firstMap, firstMap+f.mapsPerEpoch-1) // keep last enrty
|
rawdb.DeleteFilterMapLastBlocks(f.db, common.NewRange(firstMap, f.mapsPerEpoch-1)) // keep last enrty
|
||||||
for mapIndex := firstMap; mapIndex < firstMap+f.mapsPerEpoch-1; mapIndex++ {
|
for mapIndex := firstMap; mapIndex < firstMap+f.mapsPerEpoch-1; mapIndex++ {
|
||||||
f.lastBlockCache.Remove(mapIndex)
|
f.lastBlockCache.Remove(mapIndex)
|
||||||
}
|
}
|
||||||
rawdb.DeleteBlockLvPointers(f.db, firstBlock, lastBlock) // keep last enrty
|
rawdb.DeleteBlockLvPointers(f.db, common.NewRange(firstBlock, lastBlock-firstBlock)) // keep last enrty
|
||||||
for blockNumber := firstBlock; blockNumber < lastBlock; blockNumber++ {
|
for blockNumber := firstBlock; blockNumber < lastBlock; blockNumber++ {
|
||||||
f.lvPointerCache.Remove(blockNumber)
|
f.lvPointerCache.Remove(blockNumber)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,28 +66,25 @@ func (f *FilterMaps) indexerLoop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type targetUpdate struct {
|
||||||
|
targetView *ChainView
|
||||||
|
historyCutoff, finalBlock uint64
|
||||||
|
}
|
||||||
|
|
||||||
// SetTargetView sets a new target chain view for the indexer to render.
|
// SetTargetView sets a new target chain view for the indexer to render.
|
||||||
// Note that SetTargetView never blocks.
|
// Note that SetTargetView never blocks.
|
||||||
func (f *FilterMaps) SetTargetView(targetView *ChainView) {
|
func (f *FilterMaps) SetTarget(targetView *ChainView, historyCutoff, finalBlock uint64) {
|
||||||
if targetView == nil {
|
if targetView == nil {
|
||||||
panic("nil targetView")
|
panic("nil targetView")
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-f.targetViewCh:
|
case <-f.targetCh:
|
||||||
case f.targetViewCh <- targetView:
|
case f.targetCh <- targetUpdate{
|
||||||
return
|
targetView: targetView,
|
||||||
}
|
historyCutoff: historyCutoff,
|
||||||
}
|
finalBlock: finalBlock,
|
||||||
}
|
}:
|
||||||
|
|
||||||
// SetFinalBlock sets the finalized block number used for exporting checkpoints.
|
|
||||||
// Note that SetFinalBlock never blocks.
|
|
||||||
func (f *FilterMaps) SetFinalBlock(finalBlock uint64) {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-f.finalBlockCh:
|
|
||||||
case f.finalBlockCh <- finalBlock:
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,33 +136,35 @@ func (f *FilterMaps) processEvents() {
|
||||||
// processSingleEvent processes a single event either in a blocking or
|
// processSingleEvent processes a single event either in a blocking or
|
||||||
// non-blocking manner.
|
// non-blocking manner.
|
||||||
func (f *FilterMaps) processSingleEvent(blocking bool) bool {
|
func (f *FilterMaps) processSingleEvent(blocking bool) bool {
|
||||||
if f.matcherSyncRequest != nil && f.targetHeadIndexed() {
|
if !f.hasTempRange {
|
||||||
f.matcherSyncRequest.synced()
|
for _, mb := range f.matcherSyncRequests {
|
||||||
f.matcherSyncRequest = nil
|
mb.synced()
|
||||||
|
}
|
||||||
|
f.matcherSyncRequests = nil
|
||||||
}
|
}
|
||||||
if blocking {
|
if blocking {
|
||||||
select {
|
select {
|
||||||
case targetView := <-f.targetViewCh:
|
case target := <-f.targetCh:
|
||||||
f.setTargetView(targetView)
|
f.setTarget(target)
|
||||||
case f.finalBlock = <-f.finalBlockCh:
|
case mb := <-f.matcherSyncCh:
|
||||||
case f.matcherSyncRequest = <-f.matcherSyncCh:
|
f.matcherSyncRequests = append(f.matcherSyncRequests, mb)
|
||||||
case f.blockProcessing = <-f.blockProcessingCh:
|
case f.blockProcessing = <-f.blockProcessingCh:
|
||||||
case <-f.closeCh:
|
case <-f.closeCh:
|
||||||
f.stop = true
|
f.stop = true
|
||||||
case ch := <-f.waitIdleCh:
|
case ch := <-f.waitIdleCh:
|
||||||
select {
|
select {
|
||||||
case targetView := <-f.targetViewCh:
|
case target := <-f.targetCh:
|
||||||
f.setTargetView(targetView)
|
f.setTarget(target)
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
ch <- !f.blockProcessing && f.targetHeadIndexed()
|
ch <- !f.blockProcessing && f.targetHeadIndexed()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
select {
|
select {
|
||||||
case targetView := <-f.targetViewCh:
|
case target := <-f.targetCh:
|
||||||
f.setTargetView(targetView)
|
f.setTarget(target)
|
||||||
case f.finalBlock = <-f.finalBlockCh:
|
case mb := <-f.matcherSyncCh:
|
||||||
case f.matcherSyncRequest = <-f.matcherSyncCh:
|
f.matcherSyncRequests = append(f.matcherSyncRequests, mb)
|
||||||
case f.blockProcessing = <-f.blockProcessingCh:
|
case f.blockProcessing = <-f.blockProcessingCh:
|
||||||
case <-f.closeCh:
|
case <-f.closeCh:
|
||||||
f.stop = true
|
f.stop = true
|
||||||
|
|
@ -177,8 +176,10 @@ func (f *FilterMaps) processSingleEvent(blocking bool) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setTargetView updates the target chain view of the iterator.
|
// setTargetView updates the target chain view of the iterator.
|
||||||
func (f *FilterMaps) setTargetView(targetView *ChainView) {
|
func (f *FilterMaps) setTarget(target targetUpdate) {
|
||||||
f.targetView = targetView
|
f.targetView = target.targetView
|
||||||
|
f.historyCutoff = target.historyCutoff
|
||||||
|
f.finalBlock = target.finalBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
// tryIndexHead tries to render head maps according to the current targetView
|
// tryIndexHead tries to render head maps according to the current targetView
|
||||||
|
|
@ -196,20 +197,20 @@ func (f *FilterMaps) tryIndexHead() bool {
|
||||||
f.lastLogHeadIndex = time.Now()
|
f.lastLogHeadIndex = time.Now()
|
||||||
f.startedHeadIndexAt = f.lastLogHeadIndex
|
f.startedHeadIndexAt = f.lastLogHeadIndex
|
||||||
f.startedHeadIndex = true
|
f.startedHeadIndex = true
|
||||||
f.ptrHeadIndex = f.indexedRange.afterLastIndexedBlock
|
f.ptrHeadIndex = f.indexedRange.blocks.AfterLast()
|
||||||
}
|
}
|
||||||
if _, err := headRenderer.run(func() bool {
|
if _, err := headRenderer.run(func() bool {
|
||||||
f.processEvents()
|
f.processEvents()
|
||||||
return f.stop
|
return f.stop
|
||||||
}, func() {
|
}, func() {
|
||||||
f.tryUnindexTail()
|
f.tryUnindexTail()
|
||||||
if f.indexedRange.hasIndexedBlocks() && f.indexedRange.afterLastIndexedBlock >= f.ptrHeadIndex &&
|
if f.indexedRange.hasIndexedBlocks() && f.indexedRange.blocks.AfterLast() >= f.ptrHeadIndex &&
|
||||||
((!f.loggedHeadIndex && time.Since(f.startedHeadIndexAt) > headLogDelay) ||
|
((!f.loggedHeadIndex && time.Since(f.startedHeadIndexAt) > headLogDelay) ||
|
||||||
time.Since(f.lastLogHeadIndex) > logFrequency) {
|
time.Since(f.lastLogHeadIndex) > logFrequency) {
|
||||||
log.Info("Log index head rendering in progress",
|
log.Info("Log index head rendering in progress",
|
||||||
"first block", f.indexedRange.firstIndexedBlock, "last block", f.indexedRange.afterLastIndexedBlock-1,
|
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
"processed", f.indexedRange.afterLastIndexedBlock-f.ptrHeadIndex,
|
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
|
||||||
"remaining", f.indexedView.headNumber+1-f.indexedRange.afterLastIndexedBlock,
|
"remaining", f.indexedView.headNumber-f.indexedRange.blocks.Last(),
|
||||||
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
|
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
|
||||||
f.loggedHeadIndex = true
|
f.loggedHeadIndex = true
|
||||||
f.lastLogHeadIndex = time.Now()
|
f.lastLogHeadIndex = time.Now()
|
||||||
|
|
@ -218,10 +219,10 @@ func (f *FilterMaps) tryIndexHead() bool {
|
||||||
log.Error("Log index head rendering failed", "error", err)
|
log.Error("Log index head rendering failed", "error", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if f.loggedHeadIndex {
|
if f.loggedHeadIndex && f.indexedRange.hasIndexedBlocks() {
|
||||||
log.Info("Log index head rendering finished",
|
log.Info("Log index head rendering finished",
|
||||||
"first block", f.indexedRange.firstIndexedBlock, "last block", f.indexedRange.afterLastIndexedBlock-1,
|
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
"processed", f.indexedRange.afterLastIndexedBlock-f.ptrHeadIndex,
|
"processed", f.indexedRange.blocks.AfterLast()-f.ptrHeadIndex,
|
||||||
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
|
"elapsed", common.PrettyDuration(time.Since(f.startedHeadIndexAt)))
|
||||||
}
|
}
|
||||||
f.loggedHeadIndex, f.startedHeadIndex = false, false
|
f.loggedHeadIndex, f.startedHeadIndex = false, false
|
||||||
|
|
@ -234,7 +235,11 @@ func (f *FilterMaps) tryIndexHead() bool {
|
||||||
// rendered according to targetView and is suspended as soon as the targetView
|
// rendered according to targetView and is suspended as soon as the targetView
|
||||||
// is changed.
|
// is changed.
|
||||||
func (f *FilterMaps) tryIndexTail() bool {
|
func (f *FilterMaps) tryIndexTail() bool {
|
||||||
for firstEpoch := f.indexedRange.firstRenderedMap >> f.logMapsPerEpoch; firstEpoch > 0 && f.needTailEpoch(firstEpoch-1); {
|
for {
|
||||||
|
firstEpoch := f.indexedRange.maps.First() >> f.logMapsPerEpoch
|
||||||
|
if firstEpoch == 0 || !f.needTailEpoch(firstEpoch-1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
f.processEvents()
|
f.processEvents()
|
||||||
if f.stop || !f.targetHeadIndexed() {
|
if f.stop || !f.targetHeadIndexed() {
|
||||||
return false
|
return false
|
||||||
|
|
@ -242,25 +247,25 @@ func (f *FilterMaps) tryIndexTail() bool {
|
||||||
// resume process if tail rendering was interrupted because of head rendering
|
// resume process if tail rendering was interrupted because of head rendering
|
||||||
tailRenderer := f.tailRenderer
|
tailRenderer := f.tailRenderer
|
||||||
f.tailRenderer = nil
|
f.tailRenderer = nil
|
||||||
if tailRenderer != nil && tailRenderer.afterLastMap != f.indexedRange.firstRenderedMap {
|
if tailRenderer != nil && tailRenderer.renderBefore != f.indexedRange.maps.First() {
|
||||||
tailRenderer = nil
|
tailRenderer = nil
|
||||||
}
|
}
|
||||||
if tailRenderer == nil {
|
if tailRenderer == nil {
|
||||||
var err error
|
var err error
|
||||||
tailRenderer, err = f.renderMapsBefore(f.indexedRange.firstRenderedMap)
|
tailRenderer, err = f.renderMapsBefore(f.indexedRange.maps.First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error creating log index tail renderer", "error", err)
|
log.Error("Error creating log index tail renderer", "error", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tailRenderer == nil {
|
if tailRenderer == nil {
|
||||||
return true
|
break
|
||||||
}
|
}
|
||||||
if !f.startedTailIndex {
|
if !f.startedTailIndex {
|
||||||
f.lastLogTailIndex = time.Now()
|
f.lastLogTailIndex = time.Now()
|
||||||
f.startedTailIndexAt = f.lastLogTailIndex
|
f.startedTailIndexAt = f.lastLogTailIndex
|
||||||
f.startedTailIndex = true
|
f.startedTailIndex = true
|
||||||
f.ptrTailIndex = f.indexedRange.firstIndexedBlock - f.tailPartialBlocks()
|
f.ptrTailIndex = f.indexedRange.blocks.First() - f.tailPartialBlocks()
|
||||||
}
|
}
|
||||||
done, err := tailRenderer.run(func() bool {
|
done, err := tailRenderer.run(func() bool {
|
||||||
f.processEvents()
|
f.processEvents()
|
||||||
|
|
@ -268,14 +273,14 @@ func (f *FilterMaps) tryIndexTail() bool {
|
||||||
}, func() {
|
}, func() {
|
||||||
tpb, ttb := f.tailPartialBlocks(), f.tailTargetBlock()
|
tpb, ttb := f.tailPartialBlocks(), f.tailTargetBlock()
|
||||||
remaining := uint64(1)
|
remaining := uint64(1)
|
||||||
if f.indexedRange.firstIndexedBlock > ttb+tpb {
|
if f.indexedRange.blocks.First() > ttb+tpb {
|
||||||
remaining = f.indexedRange.firstIndexedBlock - ttb - tpb
|
remaining = f.indexedRange.blocks.First() - ttb - tpb
|
||||||
}
|
}
|
||||||
if f.indexedRange.hasIndexedBlocks() && f.ptrTailIndex >= f.indexedRange.firstIndexedBlock &&
|
if f.indexedRange.hasIndexedBlocks() && f.ptrTailIndex >= f.indexedRange.blocks.First() &&
|
||||||
(!f.loggedTailIndex || time.Since(f.lastLogTailIndex) > logFrequency) {
|
(!f.loggedTailIndex || time.Since(f.lastLogTailIndex) > logFrequency) {
|
||||||
log.Info("Log index tail rendering in progress",
|
log.Info("Log index tail rendering in progress",
|
||||||
"first block", f.indexedRange.firstIndexedBlock, "last block", f.indexedRange.afterLastIndexedBlock-1,
|
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
"processed", f.ptrTailIndex-f.indexedRange.firstIndexedBlock+tpb,
|
"processed", f.ptrTailIndex-f.indexedRange.blocks.First()+tpb,
|
||||||
"remaining", remaining,
|
"remaining", remaining,
|
||||||
"next tail epoch percentage", f.indexedRange.tailPartialEpoch*100/f.mapsPerEpoch,
|
"next tail epoch percentage", f.indexedRange.tailPartialEpoch*100/f.mapsPerEpoch,
|
||||||
"elapsed", common.PrettyDuration(time.Since(f.startedTailIndexAt)))
|
"elapsed", common.PrettyDuration(time.Since(f.startedTailIndexAt)))
|
||||||
|
|
@ -283,7 +288,8 @@ func (f *FilterMaps) tryIndexTail() bool {
|
||||||
f.lastLogTailIndex = time.Now()
|
f.lastLogTailIndex = time.Now()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && f.needTailEpoch(firstEpoch-1) {
|
||||||
|
// stop silently if cutoff point has move beyond epoch boundary while rendering
|
||||||
log.Error("Log index tail rendering failed", "error", err)
|
log.Error("Log index tail rendering failed", "error", err)
|
||||||
}
|
}
|
||||||
if !done {
|
if !done {
|
||||||
|
|
@ -291,10 +297,10 @@ func (f *FilterMaps) tryIndexTail() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.loggedTailIndex {
|
if f.loggedTailIndex && f.indexedRange.hasIndexedBlocks() {
|
||||||
log.Info("Log index tail rendering finished",
|
log.Info("Log index tail rendering finished",
|
||||||
"first block", f.indexedRange.firstIndexedBlock, "last block", f.indexedRange.afterLastIndexedBlock-1,
|
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
"processed", f.ptrTailIndex-f.indexedRange.firstIndexedBlock,
|
"processed", f.ptrTailIndex-f.indexedRange.blocks.First(),
|
||||||
"elapsed", common.PrettyDuration(time.Since(f.startedTailIndexAt)))
|
"elapsed", common.PrettyDuration(time.Since(f.startedTailIndexAt)))
|
||||||
f.loggedTailIndex = false
|
f.loggedTailIndex = false
|
||||||
}
|
}
|
||||||
|
|
@ -307,7 +313,7 @@ func (f *FilterMaps) tryIndexTail() bool {
|
||||||
// data from the database and is also called while running head indexing.
|
// data from the database and is also called while running head indexing.
|
||||||
func (f *FilterMaps) tryUnindexTail() bool {
|
func (f *FilterMaps) tryUnindexTail() bool {
|
||||||
for {
|
for {
|
||||||
firstEpoch := (f.indexedRange.firstRenderedMap - f.indexedRange.tailPartialEpoch) >> f.logMapsPerEpoch
|
firstEpoch := (f.indexedRange.maps.First() - f.indexedRange.tailPartialEpoch) >> f.logMapsPerEpoch
|
||||||
if f.needTailEpoch(firstEpoch) {
|
if f.needTailEpoch(firstEpoch) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -318,19 +324,19 @@ func (f *FilterMaps) tryUnindexTail() bool {
|
||||||
if !f.startedTailUnindex {
|
if !f.startedTailUnindex {
|
||||||
f.startedTailUnindexAt = time.Now()
|
f.startedTailUnindexAt = time.Now()
|
||||||
f.startedTailUnindex = true
|
f.startedTailUnindex = true
|
||||||
f.ptrTailUnindexMap = f.indexedRange.firstRenderedMap - f.indexedRange.tailPartialEpoch
|
f.ptrTailUnindexMap = f.indexedRange.maps.First() - f.indexedRange.tailPartialEpoch
|
||||||
f.ptrTailUnindexBlock = f.indexedRange.firstIndexedBlock - f.tailPartialBlocks()
|
f.ptrTailUnindexBlock = f.indexedRange.blocks.First() - f.tailPartialBlocks()
|
||||||
}
|
}
|
||||||
if err := f.deleteTailEpoch(firstEpoch); err != nil {
|
if err := f.deleteTailEpoch(firstEpoch); err != nil {
|
||||||
log.Error("Log index tail epoch unindexing failed", "error", err)
|
log.Error("Log index tail epoch unindexing failed", "error", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.startedTailUnindex {
|
if f.startedTailUnindex && f.indexedRange.hasIndexedBlocks() {
|
||||||
log.Info("Log index tail unindexing finished",
|
log.Info("Log index tail unindexing finished",
|
||||||
"first block", f.indexedRange.firstIndexedBlock, "last block", f.indexedRange.afterLastIndexedBlock-1,
|
"first block", f.indexedRange.blocks.First(), "last block", f.indexedRange.blocks.Last(),
|
||||||
"removed maps", f.indexedRange.firstRenderedMap-f.ptrTailUnindexMap,
|
"removed maps", f.indexedRange.maps.First()-f.ptrTailUnindexMap,
|
||||||
"removed blocks", f.indexedRange.firstIndexedBlock-f.tailPartialBlocks()-f.ptrTailUnindexBlock,
|
"removed blocks", f.indexedRange.blocks.First()-f.tailPartialBlocks()-f.ptrTailUnindexBlock,
|
||||||
"elapsed", common.PrettyDuration(time.Since(f.startedTailUnindexAt)))
|
"elapsed", common.PrettyDuration(time.Since(f.startedTailUnindexAt)))
|
||||||
f.startedTailUnindex = false
|
f.startedTailUnindex = false
|
||||||
}
|
}
|
||||||
|
|
@ -340,23 +346,32 @@ func (f *FilterMaps) tryUnindexTail() bool {
|
||||||
// needTailEpoch returns true if the given tail epoch needs to be kept
|
// needTailEpoch returns true if the given tail epoch needs to be kept
|
||||||
// according to the current tail target, false if it can be removed.
|
// according to the current tail target, false if it can be removed.
|
||||||
func (f *FilterMaps) needTailEpoch(epoch uint32) bool {
|
func (f *FilterMaps) needTailEpoch(epoch uint32) bool {
|
||||||
firstEpoch := f.indexedRange.firstRenderedMap >> f.logMapsPerEpoch
|
firstEpoch := f.indexedRange.maps.First() >> f.logMapsPerEpoch
|
||||||
if epoch > firstEpoch {
|
if epoch > firstEpoch {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (epoch+1)<<f.logMapsPerEpoch >= f.indexedRange.maps.AfterLast() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if epoch+1 < firstEpoch {
|
if epoch+1 < firstEpoch {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
tailTarget := f.tailTargetBlock()
|
if epoch > 0 {
|
||||||
if tailTarget < f.indexedRange.firstIndexedBlock {
|
lastBlockOfPrevEpoch, _, err := f.getLastBlockOfMap(epoch<<f.logMapsPerEpoch - 1)
|
||||||
return true
|
if err != nil {
|
||||||
|
log.Error("Could not get last block of previous epoch", "epoch", epoch-1, "error", err)
|
||||||
|
return epoch >= firstEpoch
|
||||||
|
}
|
||||||
|
if f.historyCutoff > lastBlockOfPrevEpoch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tailLvIndex, err := f.getBlockLvPointer(tailTarget)
|
lastBlockOfEpoch, _, err := f.getLastBlockOfMap((epoch+1)<<f.logMapsPerEpoch - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Could not get log value index of tail block", "error", err)
|
log.Error("Could not get last block of epoch", "epoch", epoch, "error", err)
|
||||||
return true
|
return epoch >= firstEpoch
|
||||||
}
|
}
|
||||||
return uint64(epoch+1)<<(f.logValuesPerMap+f.logMapsPerEpoch) >= tailLvIndex
|
return f.tailTargetBlock() <= lastBlockOfEpoch
|
||||||
}
|
}
|
||||||
|
|
||||||
// tailTargetBlock returns the target value for the tail block number according
|
// tailTargetBlock returns the target value for the tail block number according
|
||||||
|
|
@ -374,15 +389,15 @@ func (f *FilterMaps) tailPartialBlocks() uint64 {
|
||||||
if f.indexedRange.tailPartialEpoch == 0 {
|
if f.indexedRange.tailPartialEpoch == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
end, _, err := f.getLastBlockOfMap(f.indexedRange.firstRenderedMap - f.mapsPerEpoch + f.indexedRange.tailPartialEpoch - 1)
|
end, _, err := f.getLastBlockOfMap(f.indexedRange.maps.First() - f.mapsPerEpoch + f.indexedRange.tailPartialEpoch - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error fetching last block of map", "mapIndex", f.indexedRange.firstRenderedMap-f.mapsPerEpoch+f.indexedRange.tailPartialEpoch-1, "error", err)
|
log.Error("Error fetching last block of map", "mapIndex", f.indexedRange.maps.First()-f.mapsPerEpoch+f.indexedRange.tailPartialEpoch-1, "error", err)
|
||||||
}
|
}
|
||||||
var start uint64
|
var start uint64
|
||||||
if f.indexedRange.firstRenderedMap-f.mapsPerEpoch > 0 {
|
if f.indexedRange.maps.First()-f.mapsPerEpoch > 0 {
|
||||||
start, _, err = f.getLastBlockOfMap(f.indexedRange.firstRenderedMap - f.mapsPerEpoch - 1)
|
start, _, err = f.getLastBlockOfMap(f.indexedRange.maps.First() - f.mapsPerEpoch - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error fetching last block of map", "mapIndex", f.indexedRange.firstRenderedMap-f.mapsPerEpoch-1, "error", err)
|
log.Error("Error fetching last block of map", "mapIndex", f.indexedRange.maps.First()-f.mapsPerEpoch-1, "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return end - start
|
return end - start
|
||||||
|
|
@ -391,5 +406,5 @@ func (f *FilterMaps) tailPartialBlocks() uint64 {
|
||||||
// targetHeadIndexed returns true if the current log index is consistent with
|
// targetHeadIndexed returns true if the current log index is consistent with
|
||||||
// targetView with its head block fully rendered.
|
// targetView with its head block fully rendered.
|
||||||
func (f *FilterMaps) targetHeadIndexed() bool {
|
func (f *FilterMaps) targetHeadIndexed() bool {
|
||||||
return equalViews(f.targetView, f.indexedView) && f.indexedRange.headBlockIndexed
|
return equalViews(f.targetView, f.indexedView) && f.indexedRange.headIndexed
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,16 +48,35 @@ func TestIndexerRandomRange(t *testing.T) {
|
||||||
defer ts.close()
|
defer ts.close()
|
||||||
|
|
||||||
forks := make([][]common.Hash, 10)
|
forks := make([][]common.Hash, 10)
|
||||||
ts.chain.addBlocks(1000, 5, 2, 4, false) // 51 log values per block
|
ts.chain.addBlocks(1000, 5, 2, 4, false)
|
||||||
for i := range forks {
|
for i := range forks {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
forkBlock := rand.Intn(1000)
|
forkBlock := rand.Intn(1000)
|
||||||
ts.chain.setHead(forkBlock)
|
ts.chain.setHead(forkBlock)
|
||||||
ts.chain.addBlocks(1000-forkBlock, 5, 2, 4, false) // 51 log values per block
|
ts.chain.addBlocks(1000-forkBlock, 5, 2, 4, false)
|
||||||
}
|
}
|
||||||
forks[i] = ts.chain.getCanonicalChain()
|
forks[i] = ts.chain.getCanonicalChain()
|
||||||
}
|
}
|
||||||
lvPerBlock := uint64(51)
|
expspos := func(block uint64) uint64 { // expected position of block start
|
||||||
|
if block == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
logCount := (block - 1) * 5 * 2
|
||||||
|
mapIndex := logCount / 3
|
||||||
|
spos := mapIndex*16 + (logCount%3)*5
|
||||||
|
if mapIndex == 0 || logCount%3 != 0 {
|
||||||
|
spos++
|
||||||
|
}
|
||||||
|
return spos
|
||||||
|
}
|
||||||
|
expdpos := func(block uint64) uint64 { // expected position of delimiter
|
||||||
|
if block == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
logCount := block * 5 * 2
|
||||||
|
mapIndex := (logCount - 1) / 3
|
||||||
|
return mapIndex*16 + (logCount-mapIndex*3)*5
|
||||||
|
}
|
||||||
ts.setHistory(0, false)
|
ts.setHistory(0, false)
|
||||||
var (
|
var (
|
||||||
history int
|
history int
|
||||||
|
|
@ -115,23 +134,26 @@ func TestIndexerRandomRange(t *testing.T) {
|
||||||
}
|
}
|
||||||
var tailEpoch uint32
|
var tailEpoch uint32
|
||||||
if tailBlock > 0 {
|
if tailBlock > 0 {
|
||||||
tailLvPtr := (tailBlock - 1) * lvPerBlock // no logs in genesis block, only delimiter
|
tailLvPtr := expspos(tailBlock) - 1
|
||||||
tailEpoch = uint32(tailLvPtr >> (testParams.logValuesPerMap + testParams.logMapsPerEpoch))
|
tailEpoch = uint32(tailLvPtr >> (testParams.logValuesPerMap + testParams.logMapsPerEpoch))
|
||||||
}
|
}
|
||||||
|
tailLvPtr := uint64(tailEpoch) << (testParams.logValuesPerMap + testParams.logMapsPerEpoch) // first available lv ptr
|
||||||
var expTailBlock uint64
|
var expTailBlock uint64
|
||||||
if tailEpoch > 0 {
|
if tailEpoch > 0 {
|
||||||
tailLvPtr := uint64(tailEpoch) << (testParams.logValuesPerMap + testParams.logMapsPerEpoch) // first available lv ptr
|
for expspos(expTailBlock) <= tailLvPtr {
|
||||||
// (expTailBlock-1)*lvPerBlock >= tailLvPtr
|
expTailBlock++
|
||||||
expTailBlock = (tailLvPtr + lvPerBlock*2 - 1) / lvPerBlock
|
}
|
||||||
}
|
}
|
||||||
if ts.fm.indexedRange.afterLastIndexedBlock != uint64(head+1) {
|
if ts.fm.indexedRange.blocks.Last() != uint64(head) {
|
||||||
ts.t.Fatalf("Invalid index head (expected #%d, got #%d)", head, ts.fm.indexedRange.afterLastIndexedBlock-1)
|
ts.t.Fatalf("Invalid index head (expected #%d, got #%d)", head, ts.fm.indexedRange.blocks.Last())
|
||||||
}
|
}
|
||||||
if ts.fm.indexedRange.headBlockDelimiter != uint64(head)*lvPerBlock {
|
expHeadDelimiter := expdpos(uint64(head))
|
||||||
ts.t.Fatalf("Invalid index head delimiter pointer (expected %d, got %d)", uint64(head)*lvPerBlock, ts.fm.indexedRange.headBlockDelimiter)
|
if ts.fm.indexedRange.headDelimiter != expHeadDelimiter {
|
||||||
|
ts.t.Fatalf("Invalid index head delimiter pointer (expected %d, got %d)", expHeadDelimiter, ts.fm.indexedRange.headDelimiter)
|
||||||
}
|
}
|
||||||
if ts.fm.indexedRange.firstIndexedBlock != expTailBlock {
|
|
||||||
ts.t.Fatalf("Invalid index tail block (expected #%d, got #%d)", expTailBlock, ts.fm.indexedRange.firstIndexedBlock)
|
if ts.fm.indexedRange.blocks.First() != expTailBlock {
|
||||||
|
ts.t.Fatalf("Invalid index tail block (expected #%d, got #%d)", expTailBlock, ts.fm.indexedRange.blocks.First())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -235,7 +257,7 @@ func (ts *testSetup) setHistory(history uint64, noHistory bool) {
|
||||||
History: history,
|
History: history,
|
||||||
Disabled: noHistory,
|
Disabled: noHistory,
|
||||||
}
|
}
|
||||||
ts.fm = NewFilterMaps(ts.db, view, ts.params, config)
|
ts.fm = NewFilterMaps(ts.db, view, 0, 0, ts.params, config)
|
||||||
ts.fm.testDisableSnapshots = ts.testDisableSnapshots
|
ts.fm.testDisableSnapshots = ts.testDisableSnapshots
|
||||||
ts.fm.Start()
|
ts.fm.Start()
|
||||||
}
|
}
|
||||||
|
|
@ -420,7 +442,7 @@ func (tc *testChain) setTargetHead() {
|
||||||
if tc.ts.fm != nil {
|
if tc.ts.fm != nil {
|
||||||
if !tc.ts.fm.disabled {
|
if !tc.ts.fm.disabled {
|
||||||
//tc.ts.fm.targetViewCh <- NewChainView(tc, head.Number.Uint64(), head.Hash())
|
//tc.ts.fm.targetViewCh <- NewChainView(tc, head.Number.Uint64(), head.Hash())
|
||||||
tc.ts.fm.SetTargetView(NewChainView(tc, head.Number.Uint64(), head.Hash()))
|
tc.ts.fm.SetTarget(NewChainView(tc, head.Number.Uint64(), head.Hash()), 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,12 +46,12 @@ var (
|
||||||
// mapRenderer represents a process that renders filter maps in a specified
|
// mapRenderer represents a process that renders filter maps in a specified
|
||||||
// range according to the actual targetView.
|
// range according to the actual targetView.
|
||||||
type mapRenderer struct {
|
type mapRenderer struct {
|
||||||
f *FilterMaps
|
f *FilterMaps
|
||||||
afterLastMap uint32
|
renderBefore uint32
|
||||||
currentMap *renderedMap
|
currentMap *renderedMap
|
||||||
finishedMaps map[uint32]*renderedMap
|
finishedMaps map[uint32]*renderedMap
|
||||||
firstFinished, afterLastFinished uint32
|
finished common.Range[uint32]
|
||||||
iterator *logIterator
|
iterator *logIterator
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderedMap represents a single filter map that is being rendered in memory.
|
// renderedMap represents a single filter map that is being rendered in memory.
|
||||||
|
|
@ -74,22 +74,22 @@ func (r *renderedMap) firstBlock() uint64 {
|
||||||
// specified map index boundary, starting from the latest available starting
|
// specified map index boundary, starting from the latest available starting
|
||||||
// point that is consistent with the current targetView.
|
// point that is consistent with the current targetView.
|
||||||
// The renderer ensures that filterMapsRange, indexedView and the actual map
|
// The renderer ensures that filterMapsRange, indexedView and the actual map
|
||||||
// data are always consistent with each other. If afterLastMap is greater than
|
// data are always consistent with each other. If renderBefore is greater than
|
||||||
// the latest existing rendered map then indexedView is updated to targetView,
|
// the latest existing rendered map then indexedView is updated to targetView,
|
||||||
// otherwise it is checked that the rendered range is consistent with both
|
// otherwise it is checked that the rendered range is consistent with both
|
||||||
// views.
|
// views.
|
||||||
func (f *FilterMaps) renderMapsBefore(afterLastMap uint32) (*mapRenderer, error) {
|
func (f *FilterMaps) renderMapsBefore(renderBefore uint32) (*mapRenderer, error) {
|
||||||
nextMap, startBlock, startLvPtr, err := f.lastCanonicalMapBoundaryBefore(afterLastMap)
|
nextMap, startBlock, startLvPtr, err := f.lastCanonicalMapBoundaryBefore(renderBefore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if snapshot := f.lastCanonicalSnapshotBefore(afterLastMap); snapshot != nil && snapshot.mapIndex >= nextMap {
|
if snapshot := f.lastCanonicalSnapshotBefore(renderBefore); snapshot != nil && snapshot.mapIndex >= nextMap {
|
||||||
return f.renderMapsFromSnapshot(snapshot)
|
return f.renderMapsFromSnapshot(snapshot)
|
||||||
}
|
}
|
||||||
if nextMap >= afterLastMap {
|
if nextMap >= renderBefore {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return f.renderMapsFromMapBoundary(nextMap, afterLastMap, startBlock, startLvPtr)
|
return f.renderMapsFromMapBoundary(nextMap, renderBefore, startBlock, startLvPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderMapsFromSnapshot creates a mapRenderer that starts rendering from a
|
// renderMapsFromSnapshot creates a mapRenderer that starts rendering from a
|
||||||
|
|
@ -108,17 +108,16 @@ func (f *FilterMaps) renderMapsFromSnapshot(cp *renderedMap) (*mapRenderer, erro
|
||||||
lastBlock: cp.lastBlock,
|
lastBlock: cp.lastBlock,
|
||||||
blockLvPtrs: cp.blockLvPtrs,
|
blockLvPtrs: cp.blockLvPtrs,
|
||||||
},
|
},
|
||||||
finishedMaps: make(map[uint32]*renderedMap),
|
finishedMaps: make(map[uint32]*renderedMap),
|
||||||
firstFinished: cp.mapIndex,
|
finished: common.NewRange(cp.mapIndex, 0),
|
||||||
afterLastFinished: cp.mapIndex,
|
renderBefore: math.MaxUint32,
|
||||||
afterLastMap: math.MaxUint32,
|
iterator: iter,
|
||||||
iterator: iter,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderMapsFromMapBoundary creates a mapRenderer that starts rendering at a
|
// renderMapsFromMapBoundary creates a mapRenderer that starts rendering at a
|
||||||
// map boundary.
|
// map boundary.
|
||||||
func (f *FilterMaps) renderMapsFromMapBoundary(firstMap, afterLastMap uint32, startBlock, startLvPtr uint64) (*mapRenderer, error) {
|
func (f *FilterMaps) renderMapsFromMapBoundary(firstMap, renderBefore uint32, startBlock, startLvPtr uint64) (*mapRenderer, error) {
|
||||||
iter, err := f.newLogIteratorFromMapBoundary(firstMap, startBlock, startLvPtr)
|
iter, err := f.newLogIteratorFromMapBoundary(firstMap, startBlock, startLvPtr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create log iterator from map boundary %d: %v", firstMap, err)
|
return nil, fmt.Errorf("failed to create log iterator from map boundary %d: %v", firstMap, err)
|
||||||
|
|
@ -130,22 +129,21 @@ func (f *FilterMaps) renderMapsFromMapBoundary(firstMap, afterLastMap uint32, st
|
||||||
mapIndex: firstMap,
|
mapIndex: firstMap,
|
||||||
lastBlock: iter.blockNumber,
|
lastBlock: iter.blockNumber,
|
||||||
},
|
},
|
||||||
finishedMaps: make(map[uint32]*renderedMap),
|
finishedMaps: make(map[uint32]*renderedMap),
|
||||||
firstFinished: firstMap,
|
finished: common.NewRange(firstMap, 0),
|
||||||
afterLastFinished: firstMap,
|
renderBefore: renderBefore,
|
||||||
afterLastMap: afterLastMap,
|
iterator: iter,
|
||||||
iterator: iter,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// lastCanonicalSnapshotBefore returns the latest cached snapshot that matches
|
// lastCanonicalSnapshotBefore returns the latest cached snapshot that matches
|
||||||
// the current targetView.
|
// the current targetView.
|
||||||
func (f *FilterMaps) lastCanonicalSnapshotBefore(afterLastMap uint32) *renderedMap {
|
func (f *FilterMaps) lastCanonicalSnapshotBefore(renderBefore uint32) *renderedMap {
|
||||||
var best *renderedMap
|
var best *renderedMap
|
||||||
for _, blockNumber := range f.renderSnapshots.Keys() {
|
for _, blockNumber := range f.renderSnapshots.Keys() {
|
||||||
if cp, _ := f.renderSnapshots.Get(blockNumber); cp != nil && blockNumber < f.indexedRange.afterLastIndexedBlock &&
|
if cp, _ := f.renderSnapshots.Get(blockNumber); cp != nil && blockNumber < f.indexedRange.blocks.AfterLast() &&
|
||||||
blockNumber <= f.targetView.headNumber && f.targetView.getBlockId(blockNumber) == cp.lastBlockId &&
|
blockNumber <= f.targetView.headNumber && f.targetView.getBlockId(blockNumber) == cp.lastBlockId &&
|
||||||
cp.mapIndex < afterLastMap && (best == nil || blockNumber > best.lastBlock) {
|
cp.mapIndex < renderBefore && (best == nil || blockNumber > best.lastBlock) {
|
||||||
best = cp
|
best = cp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -158,11 +156,11 @@ func (f *FilterMaps) lastCanonicalSnapshotBefore(afterLastMap uint32) *renderedM
|
||||||
// or the boundary of a currently rendered map.
|
// or the boundary of a currently rendered map.
|
||||||
// Along with the next map index where the rendering can be started, the number
|
// Along with the next map index where the rendering can be started, the number
|
||||||
// and starting log value pointer of the last block is also returned.
|
// and starting log value pointer of the last block is also returned.
|
||||||
func (f *FilterMaps) lastCanonicalMapBoundaryBefore(afterLastMap uint32) (nextMap uint32, startBlock, startLvPtr uint64, err error) {
|
func (f *FilterMaps) lastCanonicalMapBoundaryBefore(renderBefore uint32) (nextMap uint32, startBlock, startLvPtr uint64, err error) {
|
||||||
if !f.indexedRange.initialized {
|
if !f.indexedRange.initialized {
|
||||||
return 0, 0, 0, nil
|
return 0, 0, 0, nil
|
||||||
}
|
}
|
||||||
mapIndex := afterLastMap
|
mapIndex := renderBefore
|
||||||
for {
|
for {
|
||||||
var ok bool
|
var ok bool
|
||||||
if mapIndex, ok = f.lastMapBoundaryBefore(mapIndex); !ok {
|
if mapIndex, ok = f.lastMapBoundaryBefore(mapIndex); !ok {
|
||||||
|
|
@ -187,27 +185,30 @@ func (f *FilterMaps) lastCanonicalMapBoundaryBefore(afterLastMap uint32) (nextMa
|
||||||
|
|
||||||
// lastMapBoundaryBefore returns the latest map boundary before the specified
|
// lastMapBoundaryBefore returns the latest map boundary before the specified
|
||||||
// map index.
|
// map index.
|
||||||
func (f *FilterMaps) lastMapBoundaryBefore(mapIndex uint32) (uint32, bool) {
|
func (f *FilterMaps) lastMapBoundaryBefore(renderBefore uint32) (uint32, bool) {
|
||||||
if !f.indexedRange.initialized || f.indexedRange.afterLastRenderedMap == 0 {
|
if !f.indexedRange.initialized || f.indexedRange.maps.AfterLast() == 0 || renderBefore == 0 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
if mapIndex > f.indexedRange.afterLastRenderedMap {
|
afterLastFullMap := f.indexedRange.maps.AfterLast()
|
||||||
mapIndex = f.indexedRange.afterLastRenderedMap
|
if afterLastFullMap > 0 && f.indexedRange.headIndexed {
|
||||||
|
afterLastFullMap-- // last map is not full
|
||||||
}
|
}
|
||||||
if mapIndex > f.indexedRange.firstRenderedMap {
|
firstRendered := min(renderBefore-1, afterLastFullMap)
|
||||||
return mapIndex - 1, true
|
if firstRendered == 0 {
|
||||||
|
return 0, false
|
||||||
}
|
}
|
||||||
if mapIndex+f.mapsPerEpoch > f.indexedRange.firstRenderedMap {
|
if firstRendered >= f.indexedRange.maps.First() {
|
||||||
if mapIndex > f.indexedRange.firstRenderedMap-f.mapsPerEpoch+f.indexedRange.tailPartialEpoch {
|
return firstRendered - 1, true
|
||||||
mapIndex = f.indexedRange.firstRenderedMap - f.mapsPerEpoch + f.indexedRange.tailPartialEpoch
|
}
|
||||||
}
|
if firstRendered+f.mapsPerEpoch > f.indexedRange.maps.First() {
|
||||||
|
firstRendered = min(firstRendered, f.indexedRange.maps.First()-f.mapsPerEpoch+f.indexedRange.tailPartialEpoch)
|
||||||
} else {
|
} else {
|
||||||
mapIndex = (mapIndex >> f.logMapsPerEpoch) << f.logMapsPerEpoch
|
firstRendered = (firstRendered >> f.logMapsPerEpoch) << f.logMapsPerEpoch
|
||||||
}
|
}
|
||||||
if mapIndex == 0 {
|
if firstRendered == 0 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return mapIndex - 1, true
|
return firstRendered - 1, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// emptyFilterMap returns an empty filter map.
|
// emptyFilterMap returns an empty filter map.
|
||||||
|
|
@ -218,19 +219,19 @@ func (f *FilterMaps) emptyFilterMap() filterMap {
|
||||||
// loadHeadSnapshot loads the last rendered map from the database and creates
|
// loadHeadSnapshot loads the last rendered map from the database and creates
|
||||||
// a snapshot.
|
// a snapshot.
|
||||||
func (f *FilterMaps) loadHeadSnapshot() error {
|
func (f *FilterMaps) loadHeadSnapshot() error {
|
||||||
fm, err := f.getFilterMap(f.indexedRange.afterLastRenderedMap - 1)
|
fm, err := f.getFilterMap(f.indexedRange.maps.Last())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to load head snapshot map %d: %v", f.indexedRange.afterLastRenderedMap-1, err)
|
return fmt.Errorf("failed to load head snapshot map %d: %v", f.indexedRange.maps.Last(), err)
|
||||||
}
|
}
|
||||||
lastBlock, _, err := f.getLastBlockOfMap(f.indexedRange.afterLastRenderedMap - 1)
|
lastBlock, _, err := f.getLastBlockOfMap(f.indexedRange.maps.Last())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to retrieve last block of head snapshot map %d: %v", f.indexedRange.afterLastRenderedMap-1, err)
|
return fmt.Errorf("failed to retrieve last block of head snapshot map %d: %v", f.indexedRange.maps.Last(), err)
|
||||||
}
|
}
|
||||||
var firstBlock uint64
|
var firstBlock uint64
|
||||||
if f.indexedRange.afterLastRenderedMap > 1 {
|
if f.indexedRange.maps.AfterLast() > 1 {
|
||||||
prevLastBlock, _, err := f.getLastBlockOfMap(f.indexedRange.afterLastRenderedMap - 2)
|
prevLastBlock, _, err := f.getLastBlockOfMap(f.indexedRange.maps.Last() - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to retrieve last block of map %d before head snapshot: %v", f.indexedRange.afterLastRenderedMap-2, err)
|
return fmt.Errorf("failed to retrieve last block of map %d before head snapshot: %v", f.indexedRange.maps.Last()-1, err)
|
||||||
}
|
}
|
||||||
firstBlock = prevLastBlock + 1
|
firstBlock = prevLastBlock + 1
|
||||||
}
|
}
|
||||||
|
|
@ -241,14 +242,14 @@ func (f *FilterMaps) loadHeadSnapshot() error {
|
||||||
return fmt.Errorf("failed to retrieve log value pointer of head snapshot block %d: %v", firstBlock+uint64(i), err)
|
return fmt.Errorf("failed to retrieve log value pointer of head snapshot block %d: %v", firstBlock+uint64(i), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.renderSnapshots.Add(f.indexedRange.afterLastIndexedBlock-1, &renderedMap{
|
f.renderSnapshots.Add(f.indexedRange.blocks.Last(), &renderedMap{
|
||||||
filterMap: fm,
|
filterMap: fm,
|
||||||
mapIndex: f.indexedRange.afterLastRenderedMap - 1,
|
mapIndex: f.indexedRange.maps.Last(),
|
||||||
lastBlock: f.indexedRange.afterLastIndexedBlock - 1,
|
lastBlock: f.indexedRange.blocks.Last(),
|
||||||
lastBlockId: f.indexedView.getBlockId(f.indexedRange.afterLastIndexedBlock - 1),
|
lastBlockId: f.indexedView.getBlockId(f.indexedRange.blocks.Last()),
|
||||||
blockLvPtrs: lvPtrs,
|
blockLvPtrs: lvPtrs,
|
||||||
finished: true,
|
finished: true,
|
||||||
headDelimiter: f.indexedRange.headBlockDelimiter,
|
headDelimiter: f.indexedRange.headDelimiter,
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -277,14 +278,14 @@ func (r *mapRenderer) run(stopCb func() bool, writeCb func()) (bool, error) {
|
||||||
}
|
}
|
||||||
// map finished
|
// map finished
|
||||||
r.finishedMaps[r.currentMap.mapIndex] = r.currentMap
|
r.finishedMaps[r.currentMap.mapIndex] = r.currentMap
|
||||||
r.afterLastFinished++
|
r.finished.SetLast(r.finished.AfterLast())
|
||||||
if len(r.finishedMaps) >= maxMapsPerBatch || r.afterLastFinished&(r.f.baseRowGroupLength-1) == 0 {
|
if len(r.finishedMaps) >= maxMapsPerBatch || r.finished.AfterLast()&(r.f.baseRowGroupLength-1) == 0 {
|
||||||
if err := r.writeFinishedMaps(stopCb); err != nil {
|
if err := r.writeFinishedMaps(stopCb); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
writeCb()
|
writeCb()
|
||||||
}
|
}
|
||||||
if r.afterLastFinished == r.afterLastMap || r.iterator.finished {
|
if r.finished.AfterLast() == r.renderBefore || r.iterator.finished {
|
||||||
if err := r.writeFinishedMaps(stopCb); err != nil {
|
if err := r.writeFinishedMaps(stopCb); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +294,7 @@ func (r *mapRenderer) run(stopCb func() bool, writeCb func()) (bool, error) {
|
||||||
}
|
}
|
||||||
r.currentMap = &renderedMap{
|
r.currentMap = &renderedMap{
|
||||||
filterMap: r.f.emptyFilterMap(),
|
filterMap: r.f.emptyFilterMap(),
|
||||||
mapIndex: r.afterLastFinished,
|
mapIndex: r.finished.AfterLast(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -323,11 +324,6 @@ func (r *mapRenderer) renderCurrentMap(stopCb func() bool) (bool, error) {
|
||||||
}
|
}
|
||||||
waitCnt = 0
|
waitCnt = 0
|
||||||
}
|
}
|
||||||
r.currentMap.lastBlock = r.iterator.blockNumber
|
|
||||||
if r.iterator.delimiter {
|
|
||||||
r.currentMap.lastBlock++
|
|
||||||
r.currentMap.blockLvPtrs = append(r.currentMap.blockLvPtrs, r.iterator.lvIndex+1)
|
|
||||||
}
|
|
||||||
if logValue := r.iterator.getValueHash(); logValue != (common.Hash{}) {
|
if logValue := r.iterator.getValueHash(); logValue != (common.Hash{}) {
|
||||||
lvp, cached := rowMappingCache.Get(logValue)
|
lvp, cached := rowMappingCache.Get(logValue)
|
||||||
if !cached {
|
if !cached {
|
||||||
|
|
@ -346,9 +342,15 @@ func (r *mapRenderer) renderCurrentMap(stopCb func() bool) (bool, error) {
|
||||||
if err := r.iterator.next(); err != nil {
|
if err := r.iterator.next(); err != nil {
|
||||||
return false, fmt.Errorf("failed to advance log iterator at %d while rendering map %d: %v", r.iterator.lvIndex, r.currentMap.mapIndex, err)
|
return false, fmt.Errorf("failed to advance log iterator at %d while rendering map %d: %v", r.iterator.lvIndex, r.currentMap.mapIndex, err)
|
||||||
}
|
}
|
||||||
if !r.f.testDisableSnapshots && r.afterLastMap >= r.f.indexedRange.afterLastRenderedMap &&
|
if !r.iterator.skipToBoundary {
|
||||||
(r.iterator.delimiter || r.iterator.finished) {
|
r.currentMap.lastBlock = r.iterator.blockNumber
|
||||||
r.makeSnapshot()
|
if r.iterator.blockStart {
|
||||||
|
r.currentMap.blockLvPtrs = append(r.currentMap.blockLvPtrs, r.iterator.lvIndex)
|
||||||
|
}
|
||||||
|
if !r.f.testDisableSnapshots && r.renderBefore >= r.f.indexedRange.maps.AfterLast() &&
|
||||||
|
(r.iterator.delimiter || r.iterator.finished) {
|
||||||
|
r.makeSnapshot()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if r.iterator.finished {
|
if r.iterator.finished {
|
||||||
|
|
@ -390,19 +392,23 @@ func (r *mapRenderer) writeFinishedMaps(pauseCb func() bool) error {
|
||||||
}
|
}
|
||||||
// do not exit while in partially written state but do allow processing
|
// do not exit while in partially written state but do allow processing
|
||||||
// events and pausing while block processing is in progress
|
// events and pausing while block processing is in progress
|
||||||
|
r.f.indexLock.Unlock()
|
||||||
pauseCb()
|
pauseCb()
|
||||||
|
r.f.indexLock.Lock()
|
||||||
batch = r.f.db.NewBatch()
|
batch = r.f.db.NewBatch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.f.setRange(batch, r.f.indexedView, tempRange)
|
if tempRange != r.f.indexedRange {
|
||||||
|
r.f.setRange(batch, r.f.indexedView, tempRange, true)
|
||||||
|
}
|
||||||
// add or update filter rows
|
// add or update filter rows
|
||||||
for rowIndex := uint32(0); rowIndex < r.f.mapHeight; rowIndex++ {
|
for rowIndex := uint32(0); rowIndex < r.f.mapHeight; rowIndex++ {
|
||||||
var (
|
var (
|
||||||
mapIndices []uint32
|
mapIndices []uint32
|
||||||
rows []FilterRow
|
rows []FilterRow
|
||||||
)
|
)
|
||||||
for mapIndex := r.firstFinished; mapIndex < r.afterLastFinished; mapIndex++ {
|
for mapIndex := range r.finished.Iter() {
|
||||||
row := r.finishedMaps[mapIndex].filterMap[rowIndex]
|
row := r.finishedMaps[mapIndex].filterMap[rowIndex]
|
||||||
if fm, _ := r.f.filterMapCache.Get(mapIndex); fm != nil && row.Equal(fm[rowIndex]) {
|
if fm, _ := r.f.filterMapCache.Get(mapIndex); fm != nil && row.Equal(fm[rowIndex]) {
|
||||||
continue
|
continue
|
||||||
|
|
@ -410,8 +416,8 @@ func (r *mapRenderer) writeFinishedMaps(pauseCb func() bool) error {
|
||||||
mapIndices = append(mapIndices, mapIndex)
|
mapIndices = append(mapIndices, mapIndex)
|
||||||
rows = append(rows, row)
|
rows = append(rows, row)
|
||||||
}
|
}
|
||||||
if newRange.afterLastRenderedMap == r.afterLastFinished { // head updated; remove future entries
|
if newRange.maps.AfterLast() == r.finished.AfterLast() { // head updated; remove future entries
|
||||||
for mapIndex := r.afterLastFinished; mapIndex < oldRange.afterLastRenderedMap; mapIndex++ {
|
for mapIndex := r.finished.AfterLast(); mapIndex < oldRange.maps.AfterLast(); mapIndex++ {
|
||||||
if fm, _ := r.f.filterMapCache.Get(mapIndex); fm != nil && len(fm[rowIndex]) == 0 {
|
if fm, _ := r.f.filterMapCache.Get(mapIndex); fm != nil && len(fm[rowIndex]) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -425,24 +431,24 @@ func (r *mapRenderer) writeFinishedMaps(pauseCb func() bool) error {
|
||||||
checkWriteCnt()
|
checkWriteCnt()
|
||||||
}
|
}
|
||||||
// update filter map cache
|
// update filter map cache
|
||||||
if newRange.afterLastRenderedMap == r.afterLastFinished {
|
if newRange.maps.AfterLast() == r.finished.AfterLast() {
|
||||||
// head updated; cache new head maps and remove future entries
|
// head updated; cache new head maps and remove future entries
|
||||||
for mapIndex := r.firstFinished; mapIndex < r.afterLastFinished; mapIndex++ {
|
for mapIndex := range r.finished.Iter() {
|
||||||
r.f.filterMapCache.Add(mapIndex, r.finishedMaps[mapIndex].filterMap)
|
r.f.filterMapCache.Add(mapIndex, r.finishedMaps[mapIndex].filterMap)
|
||||||
}
|
}
|
||||||
for mapIndex := r.afterLastFinished; mapIndex < oldRange.afterLastRenderedMap; mapIndex++ {
|
for mapIndex := r.finished.AfterLast(); mapIndex < oldRange.maps.AfterLast(); mapIndex++ {
|
||||||
r.f.filterMapCache.Remove(mapIndex)
|
r.f.filterMapCache.Remove(mapIndex)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// head not updated; do not cache maps during tail rendering because we
|
// head not updated; do not cache maps during tail rendering because we
|
||||||
// need head maps to be available in the cache
|
// need head maps to be available in the cache
|
||||||
for mapIndex := r.firstFinished; mapIndex < r.afterLastFinished; mapIndex++ {
|
for mapIndex := range r.finished.Iter() {
|
||||||
r.f.filterMapCache.Remove(mapIndex)
|
r.f.filterMapCache.Remove(mapIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add or update block pointers
|
// add or update block pointers
|
||||||
blockNumber := r.finishedMaps[r.firstFinished].firstBlock()
|
blockNumber := r.finishedMaps[r.finished.First()].firstBlock()
|
||||||
for mapIndex := r.firstFinished; mapIndex < r.afterLastFinished; mapIndex++ {
|
for mapIndex := range r.finished.Iter() {
|
||||||
renderedMap := r.finishedMaps[mapIndex]
|
renderedMap := r.finishedMaps[mapIndex]
|
||||||
r.f.storeLastBlockOfMap(batch, mapIndex, renderedMap.lastBlock, renderedMap.lastBlockId)
|
r.f.storeLastBlockOfMap(batch, mapIndex, renderedMap.lastBlock, renderedMap.lastBlockId)
|
||||||
checkWriteCnt()
|
checkWriteCnt()
|
||||||
|
|
@ -455,19 +461,19 @@ func (r *mapRenderer) writeFinishedMaps(pauseCb func() bool) error {
|
||||||
blockNumber++
|
blockNumber++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if newRange.afterLastRenderedMap == r.afterLastFinished { // head updated; remove future entries
|
if newRange.maps.AfterLast() == r.finished.AfterLast() { // head updated; remove future entries
|
||||||
for mapIndex := r.afterLastFinished; mapIndex < oldRange.afterLastRenderedMap; mapIndex++ {
|
for mapIndex := r.finished.AfterLast(); mapIndex < oldRange.maps.AfterLast(); mapIndex++ {
|
||||||
r.f.deleteLastBlockOfMap(batch, mapIndex)
|
r.f.deleteLastBlockOfMap(batch, mapIndex)
|
||||||
checkWriteCnt()
|
checkWriteCnt()
|
||||||
}
|
}
|
||||||
for ; blockNumber < oldRange.afterLastIndexedBlock; blockNumber++ {
|
for ; blockNumber < oldRange.blocks.AfterLast(); blockNumber++ {
|
||||||
r.f.deleteBlockLvPointer(batch, blockNumber)
|
r.f.deleteBlockLvPointer(batch, blockNumber)
|
||||||
checkWriteCnt()
|
checkWriteCnt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.finishedMaps = make(map[uint32]*renderedMap)
|
r.finishedMaps = make(map[uint32]*renderedMap)
|
||||||
r.firstFinished = r.afterLastFinished
|
r.finished.SetFirst(r.finished.AfterLast())
|
||||||
r.f.setRange(batch, renderedView, newRange)
|
r.f.setRange(batch, renderedView, newRange, false)
|
||||||
if err := batch.Write(); err != nil {
|
if err := batch.Write(); err != nil {
|
||||||
log.Crit("Error writing log index update batch", "error", err)
|
log.Crit("Error writing log index update batch", "error", err)
|
||||||
}
|
}
|
||||||
|
|
@ -481,33 +487,33 @@ func (r *mapRenderer) writeFinishedMaps(pauseCb func() bool) error {
|
||||||
// range to the unchanged region until all new map data is committed.
|
// range to the unchanged region until all new map data is committed.
|
||||||
func (r *mapRenderer) getTempRange() (filterMapsRange, error) {
|
func (r *mapRenderer) getTempRange() (filterMapsRange, error) {
|
||||||
tempRange := r.f.indexedRange
|
tempRange := r.f.indexedRange
|
||||||
if err := tempRange.addRenderedRange(r.firstFinished, r.firstFinished, r.afterLastMap, r.f.mapsPerEpoch); err != nil {
|
if err := tempRange.addRenderedRange(r.finished.First(), r.finished.First(), r.renderBefore, r.f.mapsPerEpoch); err != nil {
|
||||||
return filterMapsRange{}, fmt.Errorf("failed to update temporary rendered range: %v", err)
|
return filterMapsRange{}, fmt.Errorf("failed to update temporary rendered range: %v", err)
|
||||||
}
|
}
|
||||||
if tempRange.firstRenderedMap != r.f.indexedRange.firstRenderedMap {
|
if tempRange.maps.First() != r.f.indexedRange.maps.First() {
|
||||||
// first rendered map changed; update first indexed block
|
// first rendered map changed; update first indexed block
|
||||||
if tempRange.firstRenderedMap > 0 {
|
if tempRange.maps.First() > 0 {
|
||||||
lastBlock, _, err := r.f.getLastBlockOfMap(tempRange.firstRenderedMap - 1)
|
firstBlock, _, err := r.f.getLastBlockOfMap(tempRange.maps.First() - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return filterMapsRange{}, fmt.Errorf("failed to retrieve last block of map %d before temporary range: %v", tempRange.firstRenderedMap-1, err)
|
return filterMapsRange{}, fmt.Errorf("failed to retrieve last block of map %d before temporary range: %v", tempRange.maps.First()-1, err)
|
||||||
}
|
}
|
||||||
tempRange.firstIndexedBlock = lastBlock + 1
|
tempRange.blocks.SetFirst(firstBlock + 1) // firstBlock is probably partially rendered
|
||||||
} else {
|
} else {
|
||||||
tempRange.firstIndexedBlock = 0
|
tempRange.blocks.SetFirst(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tempRange.afterLastRenderedMap != r.f.indexedRange.afterLastRenderedMap {
|
if tempRange.maps.AfterLast() != r.f.indexedRange.maps.AfterLast() {
|
||||||
// first rendered map changed; update first indexed block
|
// last rendered map changed; update last indexed block
|
||||||
if tempRange.afterLastRenderedMap > 0 {
|
if !tempRange.maps.IsEmpty() {
|
||||||
lastBlock, _, err := r.f.getLastBlockOfMap(tempRange.afterLastRenderedMap - 1)
|
lastBlock, _, err := r.f.getLastBlockOfMap(tempRange.maps.Last())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return filterMapsRange{}, fmt.Errorf("failed to retrieve last block of map %d at the end of temporary range: %v", tempRange.afterLastRenderedMap-1, err)
|
return filterMapsRange{}, fmt.Errorf("failed to retrieve last block of map %d at the end of temporary range: %v", tempRange.maps.Last(), err)
|
||||||
}
|
}
|
||||||
tempRange.afterLastIndexedBlock = lastBlock
|
tempRange.blocks.SetAfterLast(lastBlock) // lastBlock is probably partially rendered
|
||||||
} else {
|
} else {
|
||||||
tempRange.afterLastIndexedBlock = 0
|
tempRange.blocks.SetAfterLast(0)
|
||||||
}
|
}
|
||||||
tempRange.headBlockDelimiter = 0
|
tempRange.headDelimiter = 0
|
||||||
}
|
}
|
||||||
return tempRange, nil
|
return tempRange, nil
|
||||||
}
|
}
|
||||||
|
|
@ -517,39 +523,39 @@ func (r *mapRenderer) getTempRange() (filterMapsRange, error) {
|
||||||
func (r *mapRenderer) getUpdatedRange() (filterMapsRange, error) {
|
func (r *mapRenderer) getUpdatedRange() (filterMapsRange, error) {
|
||||||
// update filterMapsRange
|
// update filterMapsRange
|
||||||
newRange := r.f.indexedRange
|
newRange := r.f.indexedRange
|
||||||
if err := newRange.addRenderedRange(r.firstFinished, r.afterLastFinished, r.afterLastMap, r.f.mapsPerEpoch); err != nil {
|
if err := newRange.addRenderedRange(r.finished.First(), r.finished.AfterLast(), r.renderBefore, r.f.mapsPerEpoch); err != nil {
|
||||||
return filterMapsRange{}, fmt.Errorf("failed to update rendered range: %v", err)
|
return filterMapsRange{}, fmt.Errorf("failed to update rendered range: %v", err)
|
||||||
}
|
}
|
||||||
if newRange.firstRenderedMap != r.f.indexedRange.firstRenderedMap {
|
if newRange.maps.First() != r.f.indexedRange.maps.First() {
|
||||||
// first rendered map changed; update first indexed block
|
// first rendered map changed; update first indexed block
|
||||||
if newRange.firstRenderedMap > 0 {
|
if newRange.maps.First() > 0 {
|
||||||
lastBlock, _, err := r.f.getLastBlockOfMap(newRange.firstRenderedMap - 1)
|
firstBlock, _, err := r.f.getLastBlockOfMap(newRange.maps.First() - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return filterMapsRange{}, fmt.Errorf("failed to retrieve last block of map %d before rendered range: %v", newRange.firstRenderedMap-1, err)
|
return filterMapsRange{}, fmt.Errorf("failed to retrieve last block of map %d before rendered range: %v", newRange.maps.First()-1, err)
|
||||||
}
|
}
|
||||||
newRange.firstIndexedBlock = lastBlock + 1
|
newRange.blocks.SetFirst(firstBlock + 1) // firstBlock is probably partially rendered
|
||||||
} else {
|
} else {
|
||||||
newRange.firstIndexedBlock = 0
|
newRange.blocks.SetFirst(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if newRange.afterLastRenderedMap == r.afterLastFinished {
|
if newRange.maps.AfterLast() == r.finished.AfterLast() {
|
||||||
// last rendered map changed; update last indexed block and head pointers
|
// last rendered map changed; update last indexed block and head pointers
|
||||||
lm := r.finishedMaps[r.afterLastFinished-1]
|
lm := r.finishedMaps[r.finished.Last()]
|
||||||
newRange.headBlockIndexed = lm.finished
|
newRange.headIndexed = lm.finished
|
||||||
if lm.finished {
|
if lm.finished {
|
||||||
newRange.afterLastIndexedBlock = r.f.targetView.headNumber + 1
|
newRange.blocks.SetLast(r.f.targetView.headNumber)
|
||||||
if lm.lastBlock != r.f.targetView.headNumber {
|
if lm.lastBlock != r.f.targetView.headNumber {
|
||||||
panic("map rendering finished but last block != head block")
|
panic("map rendering finished but last block != head block")
|
||||||
}
|
}
|
||||||
newRange.headBlockDelimiter = lm.headDelimiter
|
newRange.headDelimiter = lm.headDelimiter
|
||||||
} else {
|
} else {
|
||||||
newRange.afterLastIndexedBlock = lm.lastBlock
|
newRange.blocks.SetAfterLast(lm.lastBlock) // lastBlock is probably partially rendered
|
||||||
newRange.headBlockDelimiter = 0
|
newRange.headDelimiter = 0
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// last rendered map not replaced; ensure that target chain view matches
|
// last rendered map not replaced; ensure that target chain view matches
|
||||||
// indexed chain view on the rendered section
|
// indexed chain view on the rendered section
|
||||||
if lastBlock := r.finishedMaps[r.afterLastFinished-1].lastBlock; !matchViews(r.f.indexedView, r.f.targetView, lastBlock) {
|
if lastBlock := r.finishedMaps[r.finished.Last()].lastBlock; !matchViews(r.f.indexedView, r.f.targetView, lastBlock) {
|
||||||
return filterMapsRange{}, errChainUpdate
|
return filterMapsRange{}, errChainUpdate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -571,9 +577,9 @@ func (fmr *filterMapsRange) addRenderedRange(firstRendered, afterLastRendered, a
|
||||||
m uint32
|
m uint32
|
||||||
d int
|
d int
|
||||||
}
|
}
|
||||||
endpoints := []endpoint{{fmr.firstRenderedMap, 1}, {fmr.afterLastRenderedMap, -1}, {firstRendered, 1}, {afterLastRendered, -101}, {afterLastRemoved, 100}}
|
endpoints := []endpoint{{fmr.maps.First(), 1}, {fmr.maps.AfterLast(), -1}, {firstRendered, 1}, {afterLastRendered, -101}, {afterLastRemoved, 100}}
|
||||||
if fmr.tailPartialEpoch > 0 {
|
if fmr.tailPartialEpoch > 0 {
|
||||||
endpoints = append(endpoints, []endpoint{{fmr.firstRenderedMap - mapsPerEpoch, 1}, {fmr.firstRenderedMap - mapsPerEpoch + fmr.tailPartialEpoch, -1}}...)
|
endpoints = append(endpoints, []endpoint{{fmr.maps.First() - mapsPerEpoch, 1}, {fmr.maps.First() - mapsPerEpoch + fmr.tailPartialEpoch, -1}}...)
|
||||||
}
|
}
|
||||||
sort.Slice(endpoints, func(i, j int) bool { return endpoints[i].m < endpoints[j].m })
|
sort.Slice(endpoints, func(i, j int) bool { return endpoints[i].m < endpoints[j].m })
|
||||||
var (
|
var (
|
||||||
|
|
@ -596,14 +602,12 @@ func (fmr *filterMapsRange) addRenderedRange(firstRendered, afterLastRendered, a
|
||||||
case 0:
|
case 0:
|
||||||
// Initialized database, but no finished maps yet.
|
// Initialized database, but no finished maps yet.
|
||||||
fmr.tailPartialEpoch = 0
|
fmr.tailPartialEpoch = 0
|
||||||
fmr.firstRenderedMap = firstRendered
|
fmr.maps = common.NewRange(firstRendered, 0)
|
||||||
fmr.afterLastRenderedMap = firstRendered
|
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
// One rendered section (no partial tail epoch).
|
// One rendered section (no partial tail epoch).
|
||||||
fmr.tailPartialEpoch = 0
|
fmr.tailPartialEpoch = 0
|
||||||
fmr.firstRenderedMap = merged[0]
|
fmr.maps = common.NewRange(merged[0], merged[1]-merged[0])
|
||||||
fmr.afterLastRenderedMap = merged[1]
|
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
// Two rendered sections (with a gap).
|
// Two rendered sections (with a gap).
|
||||||
|
|
@ -613,8 +617,7 @@ func (fmr *filterMapsRange) addRenderedRange(firstRendered, afterLastRendered, a
|
||||||
return fmt.Errorf("invalid tail partial epoch: %v", merged)
|
return fmt.Errorf("invalid tail partial epoch: %v", merged)
|
||||||
}
|
}
|
||||||
fmr.tailPartialEpoch = merged[1] - merged[0]
|
fmr.tailPartialEpoch = merged[1] - merged[0]
|
||||||
fmr.firstRenderedMap = merged[2]
|
fmr.maps = common.NewRange(merged[2], merged[3]-merged[2])
|
||||||
fmr.afterLastRenderedMap = merged[3]
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid number of rendered sections: %v", merged)
|
return fmt.Errorf("invalid number of rendered sections: %v", merged)
|
||||||
|
|
@ -624,12 +627,13 @@ func (fmr *filterMapsRange) addRenderedRange(firstRendered, afterLastRendered, a
|
||||||
|
|
||||||
// logIterator iterates on the linear log value index range.
|
// logIterator iterates on the linear log value index range.
|
||||||
type logIterator struct {
|
type logIterator struct {
|
||||||
chainView *ChainView
|
params *Params
|
||||||
blockNumber uint64
|
chainView *ChainView
|
||||||
receipts types.Receipts
|
blockNumber uint64
|
||||||
blockStart, delimiter, finished bool
|
receipts types.Receipts
|
||||||
txIndex, logIndex, topicIndex int
|
blockStart, delimiter, skipToBoundary, finished bool
|
||||||
lvIndex uint64
|
txIndex, logIndex, topicIndex int
|
||||||
|
lvIndex uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
var errUnindexedRange = errors.New("unindexed range")
|
var errUnindexedRange = errors.New("unindexed range")
|
||||||
|
|
@ -641,12 +645,12 @@ func (f *FilterMaps) newLogIteratorFromBlockDelimiter(blockNumber uint64) (*logI
|
||||||
if blockNumber > f.targetView.headNumber {
|
if blockNumber > f.targetView.headNumber {
|
||||||
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", blockNumber, f.targetView.headNumber)
|
return nil, fmt.Errorf("iterator entry point %d after target chain head block %d", blockNumber, f.targetView.headNumber)
|
||||||
}
|
}
|
||||||
if blockNumber < f.indexedRange.firstIndexedBlock || blockNumber >= f.indexedRange.afterLastIndexedBlock {
|
if !f.indexedRange.blocks.Includes(blockNumber) {
|
||||||
return nil, errUnindexedRange
|
return nil, errUnindexedRange
|
||||||
}
|
}
|
||||||
var lvIndex uint64
|
var lvIndex uint64
|
||||||
if f.indexedRange.headBlockIndexed && blockNumber+1 == f.indexedRange.afterLastIndexedBlock {
|
if f.indexedRange.headIndexed && blockNumber+1 == f.indexedRange.blocks.AfterLast() {
|
||||||
lvIndex = f.indexedRange.headBlockDelimiter
|
lvIndex = f.indexedRange.headDelimiter
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
lvIndex, err = f.getBlockLvPointer(blockNumber + 1)
|
lvIndex, err = f.getBlockLvPointer(blockNumber + 1)
|
||||||
|
|
@ -656,13 +660,16 @@ func (f *FilterMaps) newLogIteratorFromBlockDelimiter(blockNumber uint64) (*logI
|
||||||
lvIndex--
|
lvIndex--
|
||||||
}
|
}
|
||||||
finished := blockNumber == f.targetView.headNumber
|
finished := blockNumber == f.targetView.headNumber
|
||||||
return &logIterator{
|
l := &logIterator{
|
||||||
chainView: f.targetView,
|
chainView: f.targetView,
|
||||||
|
params: &f.Params,
|
||||||
blockNumber: blockNumber,
|
blockNumber: blockNumber,
|
||||||
finished: finished,
|
finished: finished,
|
||||||
delimiter: !finished,
|
delimiter: !finished,
|
||||||
lvIndex: lvIndex,
|
lvIndex: lvIndex,
|
||||||
}, nil
|
}
|
||||||
|
l.enforceValidState()
|
||||||
|
return l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLogIteratorFromMapBoundary creates a logIterator starting at the given
|
// newLogIteratorFromMapBoundary creates a logIterator starting at the given
|
||||||
|
|
@ -679,12 +686,13 @@ func (f *FilterMaps) newLogIteratorFromMapBoundary(mapIndex uint32, startBlock,
|
||||||
// initialize iterator at block start
|
// initialize iterator at block start
|
||||||
l := &logIterator{
|
l := &logIterator{
|
||||||
chainView: f.targetView,
|
chainView: f.targetView,
|
||||||
|
params: &f.Params,
|
||||||
blockNumber: startBlock,
|
blockNumber: startBlock,
|
||||||
receipts: receipts,
|
receipts: receipts,
|
||||||
blockStart: true,
|
blockStart: true,
|
||||||
lvIndex: startLvPtr,
|
lvIndex: startLvPtr,
|
||||||
}
|
}
|
||||||
l.nextValid()
|
l.enforceValidState()
|
||||||
targetIndex := uint64(mapIndex) << f.logValuesPerMap
|
targetIndex := uint64(mapIndex) << f.logValuesPerMap
|
||||||
if l.lvIndex > targetIndex {
|
if l.lvIndex > targetIndex {
|
||||||
return nil, fmt.Errorf("log value pointer %d of last block of map is after map boundary %d", l.lvIndex, targetIndex)
|
return nil, fmt.Errorf("log value pointer %d of last block of map is after map boundary %d", l.lvIndex, targetIndex)
|
||||||
|
|
@ -713,7 +721,7 @@ func (l *logIterator) updateChainView(cv *ChainView) bool {
|
||||||
|
|
||||||
// getValueHash returns the log value hash at the current position.
|
// getValueHash returns the log value hash at the current position.
|
||||||
func (l *logIterator) getValueHash() common.Hash {
|
func (l *logIterator) getValueHash() common.Hash {
|
||||||
if l.delimiter || l.finished {
|
if l.delimiter || l.finished || l.skipToBoundary {
|
||||||
return common.Hash{}
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
log := l.receipts[l.txIndex].Logs[l.logIndex]
|
log := l.receipts[l.txIndex].Logs[l.logIndex]
|
||||||
|
|
@ -725,6 +733,13 @@ func (l *logIterator) getValueHash() common.Hash {
|
||||||
|
|
||||||
// next moves the iterator to the next log value index.
|
// next moves the iterator to the next log value index.
|
||||||
func (l *logIterator) next() error {
|
func (l *logIterator) next() error {
|
||||||
|
if l.skipToBoundary {
|
||||||
|
l.lvIndex++
|
||||||
|
if l.lvIndex%l.params.valuesPerMap == 0 {
|
||||||
|
l.skipToBoundary = false
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if l.finished {
|
if l.finished {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -741,18 +756,26 @@ func (l *logIterator) next() error {
|
||||||
l.blockStart = false
|
l.blockStart = false
|
||||||
}
|
}
|
||||||
l.lvIndex++
|
l.lvIndex++
|
||||||
l.nextValid()
|
l.enforceValidState()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nextValid updates the internal transaction, log and topic index pointers
|
// enforceValidState updates the internal transaction, log and topic index pointers
|
||||||
// to the next existing log value of the given block if necessary.
|
// to the next existing log value of the given block if necessary.
|
||||||
// Note that nextValid does not advance the log value index pointer.
|
// Note that enforceValidState does not advance the log value index pointer.
|
||||||
func (l *logIterator) nextValid() {
|
func (l *logIterator) enforceValidState() {
|
||||||
|
if l.delimiter || l.finished || l.skipToBoundary {
|
||||||
|
return
|
||||||
|
}
|
||||||
for ; l.txIndex < len(l.receipts); l.txIndex++ {
|
for ; l.txIndex < len(l.receipts); l.txIndex++ {
|
||||||
receipt := l.receipts[l.txIndex]
|
receipt := l.receipts[l.txIndex]
|
||||||
for ; l.logIndex < len(receipt.Logs); l.logIndex++ {
|
for ; l.logIndex < len(receipt.Logs); l.logIndex++ {
|
||||||
log := receipt.Logs[l.logIndex]
|
log := receipt.Logs[l.logIndex]
|
||||||
|
if l.topicIndex == 0 && uint64(len(log.Topics)+1) > l.params.valuesPerMap-l.lvIndex%l.params.valuesPerMap {
|
||||||
|
// next log would be split by map boundary; skip to boundary
|
||||||
|
l.skipToBoundary = true
|
||||||
|
return
|
||||||
|
}
|
||||||
if l.topicIndex <= len(log.Topics) {
|
if l.topicIndex <= len(log.Topics) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,9 @@ type SyncRange struct {
|
||||||
// block range where the index has not changed since the last matcher sync
|
// block range where the index has not changed since the last matcher sync
|
||||||
// and therefore the set of matches found in this region is guaranteed to
|
// and therefore the set of matches found in this region is guaranteed to
|
||||||
// be valid and complete.
|
// be valid and complete.
|
||||||
Valid bool
|
ValidBlocks common.Range[uint64]
|
||||||
FirstValid, LastValid uint64
|
|
||||||
// block range indexed according to the given chain head.
|
// block range indexed according to the given chain head.
|
||||||
Indexed bool
|
IndexedBlocks common.Range[uint64]
|
||||||
FirstIndexed, LastIndexed uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPotentialMatches returns a list of logs that are potential matches for the
|
// GetPotentialMatches returns a list of logs that are potential matches for the
|
||||||
|
|
@ -75,7 +73,6 @@ type SyncRange struct {
|
||||||
// Also note that the returned list may contain false positives.
|
// Also note that the returned list may contain false positives.
|
||||||
func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock, lastBlock uint64, addresses []common.Address, topics [][]common.Hash) ([]*types.Log, error) {
|
func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock, lastBlock uint64, addresses []common.Address, topics [][]common.Hash) ([]*types.Log, error) {
|
||||||
params := backend.GetParams()
|
params := backend.GetParams()
|
||||||
var getLogStats runtimeStats
|
|
||||||
// find the log value index range to search
|
// find the log value index range to search
|
||||||
firstIndex, err := backend.GetBlockLvPointer(ctx, firstBlock)
|
firstIndex, err := backend.GetBlockLvPointer(ctx, firstBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -88,8 +85,6 @@ func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock
|
||||||
if lastIndex > 0 {
|
if lastIndex > 0 {
|
||||||
lastIndex--
|
lastIndex--
|
||||||
}
|
}
|
||||||
firstMap, lastMap := uint32(firstIndex>>params.logValuesPerMap), uint32(lastIndex>>params.logValuesPerMap)
|
|
||||||
firstEpoch, lastEpoch := firstMap>>params.logMapsPerEpoch, lastMap>>params.logMapsPerEpoch
|
|
||||||
|
|
||||||
// build matcher according to the given filter criteria
|
// build matcher according to the given filter criteria
|
||||||
matchers := make([]matcher, len(topics)+1)
|
matchers := make([]matcher, len(topics)+1)
|
||||||
|
|
@ -117,45 +112,45 @@ func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock
|
||||||
// matchers signal a match for consecutive log value indices.
|
// matchers signal a match for consecutive log value indices.
|
||||||
matcher := newMatchSequence(params, matchers)
|
matcher := newMatchSequence(params, matchers)
|
||||||
|
|
||||||
// processEpoch returns the potentially matching logs from the given epoch.
|
m := &matcherEnv{
|
||||||
processEpoch := func(epochIndex uint32) ([]*types.Log, error) {
|
ctx: ctx,
|
||||||
var logs []*types.Log
|
backend: backend,
|
||||||
// create a list of map indices to process
|
params: params,
|
||||||
fm, lm := epochIndex<<params.logMapsPerEpoch, (epochIndex+1)<<params.logMapsPerEpoch-1
|
matcher: matcher,
|
||||||
if fm < firstMap {
|
firstIndex: firstIndex,
|
||||||
fm = firstMap
|
lastIndex: lastIndex,
|
||||||
}
|
firstMap: uint32(firstIndex >> params.logValuesPerMap),
|
||||||
if lm > lastMap {
|
lastMap: uint32(lastIndex >> params.logValuesPerMap),
|
||||||
lm = lastMap
|
|
||||||
}
|
|
||||||
//
|
|
||||||
mapIndices := make([]uint32, lm+1-fm)
|
|
||||||
for i := range mapIndices {
|
|
||||||
mapIndices[i] = fm + uint32(i)
|
|
||||||
}
|
|
||||||
// find potential matches
|
|
||||||
matches, err := getAllMatches(ctx, matcher, mapIndices)
|
|
||||||
if err != nil {
|
|
||||||
return logs, err
|
|
||||||
}
|
|
||||||
// get the actual logs located at the matching log value indices
|
|
||||||
var st int
|
|
||||||
getLogStats.setState(&st, stGetLog)
|
|
||||||
defer getLogStats.setState(&st, stNone)
|
|
||||||
for _, m := range matches {
|
|
||||||
if m == nil {
|
|
||||||
return nil, ErrMatchAll
|
|
||||||
}
|
|
||||||
mlogs, err := getLogsFromMatches(ctx, backend, firstIndex, lastIndex, m)
|
|
||||||
if err != nil {
|
|
||||||
return logs, err
|
|
||||||
}
|
|
||||||
logs = append(logs, mlogs...)
|
|
||||||
}
|
|
||||||
getLogStats.addAmount(st, int64(len(logs)))
|
|
||||||
return logs, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
res, err := m.process()
|
||||||
|
|
||||||
|
if doRuntimeStats {
|
||||||
|
log.Info("Log search finished", "elapsed", time.Since(start))
|
||||||
|
for i, ma := range matchers {
|
||||||
|
for j, m := range ma.(matchAny) {
|
||||||
|
log.Info("Single matcher stats", "matchSequence", i, "matchAny", j)
|
||||||
|
m.(*singleMatcher).stats.print()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info("Get log stats")
|
||||||
|
m.getLogStats.print()
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type matcherEnv struct {
|
||||||
|
getLogStats runtimeStats // 64 bit aligned
|
||||||
|
ctx context.Context
|
||||||
|
backend MatcherBackend
|
||||||
|
params *Params
|
||||||
|
matcher matcher
|
||||||
|
firstIndex, lastIndex uint64
|
||||||
|
firstMap, lastMap uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *matcherEnv) process() ([]*types.Log, error) {
|
||||||
type task struct {
|
type task struct {
|
||||||
epochIndex uint32
|
epochIndex uint32
|
||||||
logs []*types.Log
|
logs []*types.Log
|
||||||
|
|
@ -175,18 +170,18 @@ func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock
|
||||||
if task == nil {
|
if task == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
task.logs, task.err = processEpoch(task.epochIndex)
|
task.logs, task.err = m.processEpoch(task.epochIndex)
|
||||||
close(task.done)
|
close(task.done)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
for range 4 {
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go worker()
|
go worker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firstEpoch, lastEpoch := m.firstMap>>m.params.logMapsPerEpoch, m.lastMap>>m.params.logMapsPerEpoch
|
||||||
var logs []*types.Log
|
var logs []*types.Log
|
||||||
// startEpoch is the next task to send whenever a worker can accept it.
|
// startEpoch is the next task to send whenever a worker can accept it.
|
||||||
// waitEpoch is the next task we are waiting for to finish in order to append
|
// waitEpoch is the next task we are waiting for to finish in order to append
|
||||||
|
|
@ -220,30 +215,58 @@ func GetPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if doRuntimeStats {
|
return logs, nil
|
||||||
log.Info("Log search finished", "elapsed", time.Since(start))
|
}
|
||||||
for i, ma := range matchers {
|
|
||||||
for j, m := range ma.(matchAny) {
|
// processEpoch returns the potentially matching logs from the given epoch.
|
||||||
log.Info("Single matcher stats", "matchSequence", i, "matchAny", j)
|
func (m *matcherEnv) processEpoch(epochIndex uint32) ([]*types.Log, error) {
|
||||||
m.(*singleMatcher).stats.print()
|
var logs []*types.Log
|
||||||
}
|
// create a list of map indices to process
|
||||||
}
|
fm, lm := epochIndex<<m.params.logMapsPerEpoch, (epochIndex+1)<<m.params.logMapsPerEpoch-1
|
||||||
log.Info("Get log stats")
|
if fm < m.firstMap {
|
||||||
getLogStats.print()
|
fm = m.firstMap
|
||||||
}
|
}
|
||||||
|
if lm > m.lastMap {
|
||||||
|
lm = m.lastMap
|
||||||
|
}
|
||||||
|
//
|
||||||
|
mapIndices := make([]uint32, lm+1-fm)
|
||||||
|
for i := range mapIndices {
|
||||||
|
mapIndices[i] = fm + uint32(i)
|
||||||
|
}
|
||||||
|
// find potential matches
|
||||||
|
matches, err := m.getAllMatches(mapIndices)
|
||||||
|
if err != nil {
|
||||||
|
return logs, err
|
||||||
|
}
|
||||||
|
// get the actual logs located at the matching log value indices
|
||||||
|
var st int
|
||||||
|
m.getLogStats.setState(&st, stGetLog)
|
||||||
|
defer m.getLogStats.setState(&st, stNone)
|
||||||
|
for _, match := range matches {
|
||||||
|
if match == nil {
|
||||||
|
return nil, ErrMatchAll
|
||||||
|
}
|
||||||
|
mlogs, err := m.getLogsFromMatches(match)
|
||||||
|
if err != nil {
|
||||||
|
return logs, err
|
||||||
|
}
|
||||||
|
logs = append(logs, mlogs...)
|
||||||
|
}
|
||||||
|
m.getLogStats.addAmount(st, int64(len(logs)))
|
||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLogsFromMatches returns the list of potentially matching logs located at
|
// getLogsFromMatches returns the list of potentially matching logs located at
|
||||||
// the given list of matching log indices. Matches outside the firstIndex to
|
// the given list of matching log indices. Matches outside the firstIndex to
|
||||||
// lastIndex range are not returned.
|
// lastIndex range are not returned.
|
||||||
func getLogsFromMatches(ctx context.Context, backend MatcherBackend, firstIndex, lastIndex uint64, matches potentialMatches) ([]*types.Log, error) {
|
func (m *matcherEnv) getLogsFromMatches(matches potentialMatches) ([]*types.Log, error) {
|
||||||
var logs []*types.Log
|
var logs []*types.Log
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
if match < firstIndex || match > lastIndex {
|
if match < m.firstIndex || match > m.lastIndex {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log, err := backend.GetLogByLvIndex(ctx, match)
|
log, err := m.backend.GetLogByLvIndex(m.ctx, match)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return logs, fmt.Errorf("failed to retrieve log at index %d: %v", match, err)
|
return logs, fmt.Errorf("failed to retrieve log at index %d: %v", match, err)
|
||||||
}
|
}
|
||||||
|
|
@ -254,6 +277,28 @@ func getLogsFromMatches(ctx context.Context, backend MatcherBackend, firstIndex,
|
||||||
return logs, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAllMatches creates an instance for a given matcher and set of map indices,
|
||||||
|
// iterates through mapping layers and collects all results, then returns all
|
||||||
|
// results in the same order as the map indices were specified.
|
||||||
|
func (m *matcherEnv) getAllMatches(mapIndices []uint32) ([]potentialMatches, error) {
|
||||||
|
instance := m.matcher.newInstance(mapIndices)
|
||||||
|
resultsMap := make(map[uint32]potentialMatches)
|
||||||
|
for layerIndex := uint32(0); len(resultsMap) < len(mapIndices); layerIndex++ {
|
||||||
|
results, err := instance.getMatchesForLayer(m.ctx, layerIndex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, result := range results {
|
||||||
|
resultsMap[result.mapIndex] = result.matches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matches := make([]potentialMatches, len(mapIndices))
|
||||||
|
for i, mapIndex := range mapIndices {
|
||||||
|
matches[i] = resultsMap[mapIndex]
|
||||||
|
}
|
||||||
|
return matches, nil
|
||||||
|
}
|
||||||
|
|
||||||
// matcher defines a general abstraction for any matcher configuration that
|
// matcher defines a general abstraction for any matcher configuration that
|
||||||
// can instantiate a matcherInstance.
|
// can instantiate a matcherInstance.
|
||||||
type matcher interface {
|
type matcher interface {
|
||||||
|
|
@ -281,28 +326,6 @@ type matcherResult struct {
|
||||||
matches potentialMatches
|
matches potentialMatches
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAllMatches creates an instance for a given matcher and set of map indices,
|
|
||||||
// iterates through mapping layers and collects all results, then returns all
|
|
||||||
// results in the same order as the map indices were specified.
|
|
||||||
func getAllMatches(ctx context.Context, matcher matcher, mapIndices []uint32) ([]potentialMatches, error) {
|
|
||||||
instance := matcher.newInstance(mapIndices)
|
|
||||||
resultsMap := make(map[uint32]potentialMatches)
|
|
||||||
for layerIndex := uint32(0); len(resultsMap) < len(mapIndices); layerIndex++ {
|
|
||||||
results, err := instance.getMatchesForLayer(ctx, layerIndex)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, result := range results {
|
|
||||||
resultsMap[result.mapIndex] = result.matches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
matches := make([]potentialMatches, len(mapIndices))
|
|
||||||
for i, mapIndex := range mapIndices {
|
|
||||||
matches[i] = resultsMap[mapIndex]
|
|
||||||
}
|
|
||||||
return matches, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// singleMatcher implements matcher by returning matches for a single log value hash.
|
// singleMatcher implements matcher by returning matches for a single log value hash.
|
||||||
type singleMatcher struct {
|
type singleMatcher struct {
|
||||||
backend MatcherBackend
|
backend MatcherBackend
|
||||||
|
|
@ -550,24 +573,18 @@ type matchSequence struct {
|
||||||
// newInstance creates a new instance of matchSequence.
|
// newInstance creates a new instance of matchSequence.
|
||||||
func (m *matchSequence) newInstance(mapIndices []uint32) matcherInstance {
|
func (m *matchSequence) newInstance(mapIndices []uint32) matcherInstance {
|
||||||
// determine set of indices to request from next matcher
|
// determine set of indices to request from next matcher
|
||||||
nextIndices := make([]uint32, 0, len(mapIndices)*3/2)
|
|
||||||
needMatched := make(map[uint32]struct{})
|
needMatched := make(map[uint32]struct{})
|
||||||
baseRequested := make(map[uint32]struct{})
|
baseRequested := make(map[uint32]struct{})
|
||||||
nextRequested := make(map[uint32]struct{})
|
nextRequested := make(map[uint32]struct{})
|
||||||
for _, mapIndex := range mapIndices {
|
for _, mapIndex := range mapIndices {
|
||||||
needMatched[mapIndex] = struct{}{}
|
needMatched[mapIndex] = struct{}{}
|
||||||
baseRequested[mapIndex] = struct{}{}
|
baseRequested[mapIndex] = struct{}{}
|
||||||
if _, ok := nextRequested[mapIndex]; !ok {
|
nextRequested[mapIndex] = struct{}{}
|
||||||
nextIndices = append(nextIndices, mapIndex)
|
|
||||||
nextRequested[mapIndex] = struct{}{}
|
|
||||||
}
|
|
||||||
nextIndices = append(nextIndices, mapIndex+1)
|
|
||||||
nextRequested[mapIndex+1] = struct{}{}
|
|
||||||
}
|
}
|
||||||
return &matchSequenceInstance{
|
return &matchSequenceInstance{
|
||||||
matchSequence: m,
|
matchSequence: m,
|
||||||
baseInstance: m.base.newInstance(mapIndices),
|
baseInstance: m.base.newInstance(mapIndices),
|
||||||
nextInstance: m.next.newInstance(nextIndices),
|
nextInstance: m.next.newInstance(mapIndices),
|
||||||
needMatched: needMatched,
|
needMatched: needMatched,
|
||||||
baseRequested: baseRequested,
|
baseRequested: baseRequested,
|
||||||
nextRequested: nextRequested,
|
nextRequested: nextRequested,
|
||||||
|
|
@ -687,12 +704,9 @@ func (m *matchSequenceInstance) getMatchesForLayer(ctx context.Context, layerInd
|
||||||
if _, ok := m.nextRequested[mapIndex]; ok {
|
if _, ok := m.nextRequested[mapIndex]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := m.nextRequested[mapIndex+1]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
matchedResults = append(matchedResults, matcherResult{
|
matchedResults = append(matchedResults, matcherResult{
|
||||||
mapIndex: mapIndex,
|
mapIndex: mapIndex,
|
||||||
matches: m.params.matchResults(mapIndex, m.offset, m.baseResults[mapIndex], m.nextResults[mapIndex], m.nextResults[mapIndex+1]),
|
matches: m.params.matchResults(mapIndex, m.offset, m.baseResults[mapIndex], m.nextResults[mapIndex]),
|
||||||
})
|
})
|
||||||
delete(m.needMatched, mapIndex)
|
delete(m.needMatched, mapIndex)
|
||||||
}
|
}
|
||||||
|
|
@ -715,9 +729,6 @@ func (m *matchSequenceInstance) dropIndices(dropIndices []uint32) {
|
||||||
if m.dropNext(mapIndex) {
|
if m.dropNext(mapIndex) {
|
||||||
dropNext = append(dropNext, mapIndex)
|
dropNext = append(dropNext, mapIndex)
|
||||||
}
|
}
|
||||||
if m.dropNext(mapIndex + 1) {
|
|
||||||
dropNext = append(dropNext, mapIndex+1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m.nextInstance.dropIndices(dropNext)
|
m.nextInstance.dropIndices(dropNext)
|
||||||
}
|
}
|
||||||
|
|
@ -743,9 +754,6 @@ func (m *matchSequenceInstance) evalBase(ctx context.Context, layerIndex uint32)
|
||||||
if m.dropNext(r.mapIndex) {
|
if m.dropNext(r.mapIndex) {
|
||||||
dropIndices = append(dropIndices, r.mapIndex)
|
dropIndices = append(dropIndices, r.mapIndex)
|
||||||
}
|
}
|
||||||
if m.dropNext(r.mapIndex + 1) {
|
|
||||||
dropIndices = append(dropIndices, r.mapIndex+1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if len(dropIndices) > 0 {
|
if len(dropIndices) > 0 {
|
||||||
m.nextInstance.dropIndices(dropIndices)
|
m.nextInstance.dropIndices(dropIndices)
|
||||||
|
|
@ -771,9 +779,6 @@ func (m *matchSequenceInstance) evalNext(ctx context.Context, layerIndex uint32)
|
||||||
}
|
}
|
||||||
m.mergeNextStats(stats)
|
m.mergeNextStats(stats)
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
if r.mapIndex > 0 && m.dropBase(r.mapIndex-1) {
|
|
||||||
dropIndices = append(dropIndices, r.mapIndex-1)
|
|
||||||
}
|
|
||||||
if m.dropBase(r.mapIndex) {
|
if m.dropBase(r.mapIndex) {
|
||||||
dropIndices = append(dropIndices, r.mapIndex)
|
dropIndices = append(dropIndices, r.mapIndex)
|
||||||
}
|
}
|
||||||
|
|
@ -792,12 +797,7 @@ func (m *matchSequenceInstance) dropBase(mapIndex uint32) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if _, ok := m.needMatched[mapIndex]; ok {
|
if _, ok := m.needMatched[mapIndex]; ok {
|
||||||
if next := m.nextResults[mapIndex]; next == nil ||
|
if next := m.nextResults[mapIndex]; next == nil || len(next) > 0 {
|
||||||
(len(next) > 0 && next[len(next)-1] >= (uint64(mapIndex)<<m.params.logValuesPerMap)+m.offset) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if nextNext := m.nextResults[mapIndex+1]; nextNext == nil ||
|
|
||||||
(len(nextNext) > 0 && nextNext[0] < (uint64(mapIndex+1)<<m.params.logValuesPerMap)+m.offset) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -812,15 +812,8 @@ func (m *matchSequenceInstance) dropNext(mapIndex uint32) bool {
|
||||||
if _, ok := m.nextRequested[mapIndex]; !ok {
|
if _, ok := m.nextRequested[mapIndex]; !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if _, ok := m.needMatched[mapIndex-1]; ok {
|
|
||||||
if prevBase := m.baseResults[mapIndex-1]; prevBase == nil ||
|
|
||||||
(len(prevBase) > 0 && prevBase[len(prevBase)-1]+m.offset >= (uint64(mapIndex)<<m.params.logValuesPerMap)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, ok := m.needMatched[mapIndex]; ok {
|
if _, ok := m.needMatched[mapIndex]; ok {
|
||||||
if base := m.baseResults[mapIndex]; base == nil ||
|
if base := m.baseResults[mapIndex]; base == nil || len(base) > 0 {
|
||||||
(len(base) > 0 && base[0]+m.offset < (uint64(mapIndex+1)<<m.params.logValuesPerMap)) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -833,59 +826,39 @@ func (m *matchSequenceInstance) dropNext(mapIndex uint32) bool {
|
||||||
// results at mapIndex and mapIndex+1. Note that acquiring nextNextRes may be
|
// results at mapIndex and mapIndex+1. Note that acquiring nextNextRes may be
|
||||||
// skipped and it can be substituted with an empty list if baseRes has no potential
|
// skipped and it can be substituted with an empty list if baseRes has no potential
|
||||||
// matches that could be sequence matched with anything that could be in nextNextRes.
|
// matches that could be sequence matched with anything that could be in nextNextRes.
|
||||||
func (params *Params) matchResults(mapIndex uint32, offset uint64, baseRes, nextRes, nextNextRes potentialMatches) potentialMatches {
|
func (params *Params) matchResults(mapIndex uint32, offset uint64, baseRes, nextRes potentialMatches) potentialMatches {
|
||||||
if nextRes == nil || (baseRes != nil && len(baseRes) == 0) {
|
if nextRes == nil || (baseRes != nil && len(baseRes) == 0) {
|
||||||
// if nextRes is a wild card or baseRes is empty then the sequence matcher
|
// if nextRes is a wild card or baseRes is empty then the sequence matcher
|
||||||
// result equals baseRes.
|
// result equals baseRes.
|
||||||
return baseRes
|
return baseRes
|
||||||
}
|
}
|
||||||
if len(nextRes) > 0 {
|
if baseRes == nil || len(nextRes) == 0 {
|
||||||
// discard items from nextRes whose corresponding base matcher results
|
// if baseRes is a wild card or nextRes is empty then the sequence matcher
|
||||||
// with the negative offset applied would be located at mapIndex-1.
|
// result is the items of nextRes with a negative offset applied.
|
||||||
start := 0
|
result := make(potentialMatches, 0, len(nextRes))
|
||||||
for start < len(nextRes) && nextRes[start] < uint64(mapIndex)<<params.logValuesPerMap+offset {
|
min := (uint64(mapIndex) << params.logValuesPerMap) + offset
|
||||||
start++
|
for _, v := range nextRes {
|
||||||
|
if v >= min {
|
||||||
|
result = append(result, v-offset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
nextRes = nextRes[start:]
|
return result
|
||||||
}
|
}
|
||||||
if len(nextNextRes) > 0 {
|
// iterate through baseRes and nextRes in parallel and collect matching results.
|
||||||
// discard items from nextNextRes whose corresponding base matcher results
|
maxLen := len(baseRes)
|
||||||
// with the negative offset applied would still be located at mapIndex+1.
|
if l := len(nextRes); l < maxLen {
|
||||||
stop := 0
|
maxLen = l
|
||||||
for stop < len(nextNextRes) && nextNextRes[stop] < uint64(mapIndex+1)<<params.logValuesPerMap+offset {
|
|
||||||
stop++
|
|
||||||
}
|
|
||||||
nextNextRes = nextNextRes[:stop]
|
|
||||||
}
|
}
|
||||||
maxLen := len(nextRes) + len(nextNextRes)
|
|
||||||
if maxLen == 0 {
|
|
||||||
return nextRes
|
|
||||||
}
|
|
||||||
if len(baseRes) < maxLen {
|
|
||||||
maxLen = len(baseRes)
|
|
||||||
}
|
|
||||||
// iterate through baseRes, nextRes and nextNextRes and collect matching results.
|
|
||||||
matchedRes := make(potentialMatches, 0, maxLen)
|
matchedRes := make(potentialMatches, 0, maxLen)
|
||||||
for _, nextRes := range []potentialMatches{nextRes, nextNextRes} {
|
for len(nextRes) > 0 && len(baseRes) > 0 {
|
||||||
if baseRes != nil {
|
if nextRes[0] > baseRes[0]+offset {
|
||||||
for len(nextRes) > 0 && len(baseRes) > 0 {
|
baseRes = baseRes[1:]
|
||||||
if nextRes[0] > baseRes[0]+offset {
|
} else if nextRes[0] < baseRes[0]+offset {
|
||||||
baseRes = baseRes[1:]
|
nextRes = nextRes[1:]
|
||||||
} else if nextRes[0] < baseRes[0]+offset {
|
|
||||||
nextRes = nextRes[1:]
|
|
||||||
} else {
|
|
||||||
matchedRes = append(matchedRes, baseRes[0])
|
|
||||||
baseRes = baseRes[1:]
|
|
||||||
nextRes = nextRes[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// baseRes is a wild card so just return next matcher results with
|
matchedRes = append(matchedRes, baseRes[0])
|
||||||
// negative offset.
|
baseRes = baseRes[1:]
|
||||||
for len(nextRes) > 0 {
|
nextRes = nextRes[1:]
|
||||||
matchedRes = append(matchedRes, nextRes[0]-offset)
|
|
||||||
nextRes = nextRes[1:]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matchedRes
|
return matchedRes
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package filtermaps
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -27,9 +28,8 @@ type FilterMapsMatcherBackend struct {
|
||||||
f *FilterMaps
|
f *FilterMaps
|
||||||
|
|
||||||
// these fields should be accessed under f.matchersLock mutex.
|
// these fields should be accessed under f.matchersLock mutex.
|
||||||
valid bool
|
validBlocks common.Range[uint64]
|
||||||
firstValid, lastValid uint64
|
syncCh chan SyncRange
|
||||||
syncCh chan SyncRange
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMatcherBackend returns a FilterMapsMatcherBackend after registering it in
|
// NewMatcherBackend returns a FilterMapsMatcherBackend after registering it in
|
||||||
|
|
@ -43,11 +43,9 @@ func (f *FilterMaps) NewMatcherBackend() *FilterMapsMatcherBackend {
|
||||||
f.indexLock.RUnlock()
|
f.indexLock.RUnlock()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
fm := &FilterMapsMatcherBackend{
|
fm := &FilterMapsMatcherBackend{f: f}
|
||||||
f: f,
|
if f.indexedRange.initialized {
|
||||||
valid: f.indexedRange.initialized && f.indexedRange.afterLastIndexedBlock > f.indexedRange.firstIndexedBlock,
|
fm.validBlocks = f.indexedRange.blocks
|
||||||
firstValid: f.indexedRange.firstIndexedBlock,
|
|
||||||
lastValid: f.indexedRange.afterLastIndexedBlock - 1,
|
|
||||||
}
|
}
|
||||||
f.matchers[fm] = struct{}{}
|
f.matchers[fm] = struct{}{}
|
||||||
return fm
|
return fm
|
||||||
|
|
@ -122,28 +120,16 @@ func (fm *FilterMapsMatcherBackend) synced() {
|
||||||
fm.f.indexLock.RUnlock()
|
fm.f.indexLock.RUnlock()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var (
|
indexedBlocks := fm.f.indexedRange.blocks
|
||||||
indexed bool
|
if !fm.f.indexedRange.headIndexed && !indexedBlocks.IsEmpty() {
|
||||||
lastIndexed, subLastIndexed uint64
|
indexedBlocks.SetAfterLast(indexedBlocks.Last()) // remove partially indexed last block
|
||||||
)
|
|
||||||
if !fm.f.indexedRange.headBlockIndexed {
|
|
||||||
subLastIndexed = 1
|
|
||||||
}
|
|
||||||
if fm.f.indexedRange.afterLastIndexedBlock-subLastIndexed > fm.f.indexedRange.firstIndexedBlock {
|
|
||||||
indexed, lastIndexed = true, fm.f.indexedRange.afterLastIndexedBlock-subLastIndexed-1
|
|
||||||
}
|
}
|
||||||
fm.syncCh <- SyncRange{
|
fm.syncCh <- SyncRange{
|
||||||
HeadNumber: fm.f.indexedView.headNumber,
|
HeadNumber: fm.f.targetView.headNumber,
|
||||||
Valid: fm.valid,
|
ValidBlocks: fm.validBlocks,
|
||||||
FirstValid: fm.firstValid,
|
IndexedBlocks: indexedBlocks,
|
||||||
LastValid: fm.lastValid,
|
|
||||||
Indexed: indexed,
|
|
||||||
FirstIndexed: fm.f.indexedRange.firstIndexedBlock,
|
|
||||||
LastIndexed: lastIndexed,
|
|
||||||
}
|
}
|
||||||
fm.valid = indexed
|
fm.validBlocks = indexedBlocks
|
||||||
fm.firstValid = fm.f.indexedRange.firstIndexedBlock
|
|
||||||
fm.lastValid = lastIndexed
|
|
||||||
fm.syncCh = nil
|
fm.syncCh = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,20 +173,10 @@ func (f *FilterMaps) updateMatchersValidRange() {
|
||||||
defer f.matchersLock.Unlock()
|
defer f.matchersLock.Unlock()
|
||||||
|
|
||||||
for fm := range f.matchers {
|
for fm := range f.matchers {
|
||||||
if !f.indexedRange.hasIndexedBlocks() {
|
if !f.indexedRange.initialized {
|
||||||
fm.valid = false
|
fm.validBlocks = common.Range[uint64]{}
|
||||||
}
|
|
||||||
if !fm.valid {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if fm.firstValid < f.indexedRange.firstIndexedBlock {
|
fm.validBlocks = fm.validBlocks.Intersection(f.indexedRange.blocks)
|
||||||
fm.firstValid = f.indexedRange.firstIndexedBlock
|
|
||||||
}
|
|
||||||
if fm.lastValid >= f.indexedRange.afterLastIndexedBlock {
|
|
||||||
fm.lastValid = f.indexedRange.afterLastIndexedBlock - 1
|
|
||||||
}
|
|
||||||
if fm.firstValid > fm.lastValid {
|
|
||||||
fm.valid = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,17 @@ func TestCreation(t *testing.T) {
|
||||||
{123, 2740434112, ID{Hash: checksumToBytes(0xdfbd9bed), Next: 0}}, // Future Prague block
|
{123, 2740434112, ID{Hash: checksumToBytes(0xdfbd9bed), Next: 0}}, // Future Prague block
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// Hoodi test cases
|
||||||
|
{
|
||||||
|
params.HoodiChainConfig,
|
||||||
|
core.DefaultHoodiGenesisBlock().ToBlock(),
|
||||||
|
[]testcase{
|
||||||
|
{0, 0, ID{Hash: checksumToBytes(0xbef71d30), Next: 1742999832}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London, Paris, Shanghai, Cancun block
|
||||||
|
{123, 1742999831, ID{Hash: checksumToBytes(0xbef71d30), Next: 1742999832}}, // Last Cancun block
|
||||||
|
{123, 1742999832, ID{Hash: checksumToBytes(0x0929e24e), Next: 0}}, // First Prague block
|
||||||
|
{123, 2740434112, ID{Hash: checksumToBytes(0x0929e24e), Next: 0}}, // Future Prague block
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
for j, ttt := range tt.cases {
|
for j, ttt := range tt.cases {
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,8 @@ func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.Gene
|
||||||
genesis = DefaultSepoliaGenesisBlock()
|
genesis = DefaultSepoliaGenesisBlock()
|
||||||
case params.HoleskyGenesisHash:
|
case params.HoleskyGenesisHash:
|
||||||
genesis = DefaultHoleskyGenesisBlock()
|
genesis = DefaultHoleskyGenesisBlock()
|
||||||
|
case params.HoodiGenesisHash:
|
||||||
|
genesis = DefaultHoodiGenesisBlock()
|
||||||
}
|
}
|
||||||
if genesis != nil {
|
if genesis != nil {
|
||||||
return genesis.Alloc, nil
|
return genesis.Alloc, nil
|
||||||
|
|
@ -431,6 +433,8 @@ func (g *Genesis) chainConfigOrDefault(ghash common.Hash, stored *params.ChainCo
|
||||||
return params.HoleskyChainConfig
|
return params.HoleskyChainConfig
|
||||||
case ghash == params.SepoliaGenesisHash:
|
case ghash == params.SepoliaGenesisHash:
|
||||||
return params.SepoliaChainConfig
|
return params.SepoliaChainConfig
|
||||||
|
case ghash == params.HoodiGenesisHash:
|
||||||
|
return params.HoodiChainConfig
|
||||||
default:
|
default:
|
||||||
return stored
|
return stored
|
||||||
}
|
}
|
||||||
|
|
@ -625,6 +629,18 @@ func DefaultHoleskyGenesisBlock() *Genesis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultHoodiGenesisBlock returns the Hoodi network genesis block.
|
||||||
|
func DefaultHoodiGenesisBlock() *Genesis {
|
||||||
|
return &Genesis{
|
||||||
|
Config: params.HoodiChainConfig,
|
||||||
|
Nonce: 0x1234,
|
||||||
|
GasLimit: 0x2255100,
|
||||||
|
Difficulty: big.NewInt(0x01),
|
||||||
|
Timestamp: 1742212800,
|
||||||
|
Alloc: decodePrealloc(hoodiAllocData),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
||||||
func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
|
func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
|
||||||
// Override the default period to the user requested one
|
// Override the default period to the user requested one
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -104,6 +104,15 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
||||||
},
|
},
|
||||||
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
|
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "custom block in DB, genesis == hoodi",
|
||||||
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||||
|
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||||
|
customg.Commit(db, tdb)
|
||||||
|
return SetupGenesisBlock(db, tdb, DefaultHoodiGenesisBlock())
|
||||||
|
},
|
||||||
|
wantErr: &GenesisMismatchError{Stored: customghash, New: params.HoodiGenesisHash},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "compatible config in DB",
|
name: "compatible config in DB",
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||||
|
|
@ -178,6 +187,8 @@ func TestGenesisHashes(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{DefaultGenesisBlock(), params.MainnetGenesisHash},
|
{DefaultGenesisBlock(), params.MainnetGenesisHash},
|
||||||
{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
|
{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
|
||||||
|
{DefaultHoleskyGenesisBlock(), params.HoleskyGenesisHash},
|
||||||
|
{DefaultHoodiGenesisBlock(), params.HoodiGenesisHash},
|
||||||
} {
|
} {
|
||||||
// Test via MustCommit
|
// Test via MustCommit
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
|
|
||||||
|
|
@ -356,8 +356,8 @@ func WriteFilterMapBaseRows(db ethdb.KeyValueWriter, mapRowIndex uint64, rows []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteFilterMapRows(db ethdb.KeyValueRangeDeleter, firstMapRowIndex, afterLastMapRowIndex uint64) {
|
func DeleteFilterMapRows(db ethdb.KeyValueRangeDeleter, mapRows common.Range[uint64]) {
|
||||||
if err := db.DeleteRange(filterMapRowKey(firstMapRowIndex, false), filterMapRowKey(afterLastMapRowIndex, false)); err != nil {
|
if err := db.DeleteRange(filterMapRowKey(mapRows.First(), false), filterMapRowKey(mapRows.AfterLast(), false)); err != nil {
|
||||||
log.Crit("Failed to delete range of filter map rows", "err", err)
|
log.Crit("Failed to delete range of filter map rows", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -396,8 +396,8 @@ func DeleteFilterMapLastBlock(db ethdb.KeyValueWriter, mapIndex uint32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteFilterMapLastBlocks(db ethdb.KeyValueRangeDeleter, firstMapIndex, afterLastMapIndex uint32) {
|
func DeleteFilterMapLastBlocks(db ethdb.KeyValueRangeDeleter, maps common.Range[uint32]) {
|
||||||
if err := db.DeleteRange(filterMapLastBlockKey(firstMapIndex), filterMapLastBlockKey(afterLastMapIndex)); err != nil {
|
if err := db.DeleteRange(filterMapLastBlockKey(maps.First()), filterMapLastBlockKey(maps.AfterLast())); err != nil {
|
||||||
log.Crit("Failed to delete range of filter map last block pointers", "err", err)
|
log.Crit("Failed to delete range of filter map last block pointers", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -433,8 +433,8 @@ func DeleteBlockLvPointer(db ethdb.KeyValueWriter, blockNumber uint64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteBlockLvPointers(db ethdb.KeyValueRangeDeleter, firstBlockNumber, afterLastBlockNumber uint64) {
|
func DeleteBlockLvPointers(db ethdb.KeyValueRangeDeleter, blocks common.Range[uint64]) {
|
||||||
if err := db.DeleteRange(filterMapBlockLVKey(firstBlockNumber), filterMapBlockLVKey(afterLastBlockNumber)); err != nil {
|
if err := db.DeleteRange(filterMapBlockLVKey(blocks.First()), filterMapBlockLVKey(blocks.AfterLast())); err != nil {
|
||||||
log.Crit("Failed to delete range of block log value pointers", "err", err)
|
log.Crit("Failed to delete range of block log value pointers", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -442,10 +442,11 @@ func DeleteBlockLvPointers(db ethdb.KeyValueRangeDeleter, firstBlockNumber, afte
|
||||||
// FilterMapsRange is a storage representation of the block range covered by the
|
// FilterMapsRange is a storage representation of the block range covered by the
|
||||||
// filter maps structure and the corresponting log value index range.
|
// filter maps structure and the corresponting log value index range.
|
||||||
type FilterMapsRange struct {
|
type FilterMapsRange struct {
|
||||||
HeadBlockIndexed bool
|
HeadIndexed bool
|
||||||
HeadBlockDelimiter uint64
|
HeadDelimiter uint64
|
||||||
FirstIndexedBlock, AfterLastIndexedBlock uint64
|
BlocksFirst, BlocksAfterLast uint64
|
||||||
FirstRenderedMap, AfterLastRenderedMap, TailPartialEpoch uint32
|
MapsFirst, MapsAfterLast uint32
|
||||||
|
TailPartialEpoch uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFilterMapsRange retrieves the filter maps range data. Note that if the
|
// ReadFilterMapsRange retrieves the filter maps range data. Note that if the
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ func TestDeleteBloomBits(t *testing.T) {
|
||||||
for s := uint64(0); s < 2; s++ {
|
for s := uint64(0); s < 2; s++ {
|
||||||
WriteBloomBits(db, i, s, params.MainnetGenesisHash, []byte{0x01, 0x02})
|
WriteBloomBits(db, i, s, params.MainnetGenesisHash, []byte{0x01, 0x02})
|
||||||
WriteBloomBits(db, i, s, params.SepoliaGenesisHash, []byte{0x01, 0x02})
|
WriteBloomBits(db, i, s, params.SepoliaGenesisHash, []byte{0x01, 0x02})
|
||||||
|
WriteBloomBits(db, i, s, params.HoodiGenesisHash, []byte{0x01, 0x02})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
check := func(bit uint, section uint64, head common.Hash, exist bool) {
|
check := func(bit uint, section uint64, head common.Hash, exist bool) {
|
||||||
|
|
@ -133,24 +134,31 @@ func TestDeleteBloomBits(t *testing.T) {
|
||||||
// Check the existence of written data.
|
// Check the existence of written data.
|
||||||
check(0, 0, params.MainnetGenesisHash, true)
|
check(0, 0, params.MainnetGenesisHash, true)
|
||||||
check(0, 0, params.SepoliaGenesisHash, true)
|
check(0, 0, params.SepoliaGenesisHash, true)
|
||||||
|
check(0, 0, params.HoodiGenesisHash, true)
|
||||||
|
|
||||||
// Check the existence of deleted data.
|
// Check the existence of deleted data.
|
||||||
DeleteBloombits(db, 0, 0, 1)
|
DeleteBloombits(db, 0, 0, 1)
|
||||||
check(0, 0, params.MainnetGenesisHash, false)
|
check(0, 0, params.MainnetGenesisHash, false)
|
||||||
check(0, 0, params.SepoliaGenesisHash, false)
|
check(0, 0, params.SepoliaGenesisHash, false)
|
||||||
|
check(0, 0, params.HoodiGenesisHash, false)
|
||||||
check(0, 1, params.MainnetGenesisHash, true)
|
check(0, 1, params.MainnetGenesisHash, true)
|
||||||
check(0, 1, params.SepoliaGenesisHash, true)
|
check(0, 1, params.SepoliaGenesisHash, true)
|
||||||
|
check(0, 1, params.HoodiGenesisHash, true)
|
||||||
|
|
||||||
// Check the existence of deleted data.
|
// Check the existence of deleted data.
|
||||||
DeleteBloombits(db, 0, 0, 2)
|
DeleteBloombits(db, 0, 0, 2)
|
||||||
check(0, 0, params.MainnetGenesisHash, false)
|
check(0, 0, params.MainnetGenesisHash, false)
|
||||||
check(0, 0, params.SepoliaGenesisHash, false)
|
check(0, 0, params.SepoliaGenesisHash, false)
|
||||||
|
check(0, 0, params.HoodiGenesisHash, false)
|
||||||
check(0, 1, params.MainnetGenesisHash, false)
|
check(0, 1, params.MainnetGenesisHash, false)
|
||||||
check(0, 1, params.SepoliaGenesisHash, false)
|
check(0, 1, params.SepoliaGenesisHash, false)
|
||||||
|
check(0, 1, params.HoodiGenesisHash, false)
|
||||||
|
|
||||||
// Bit1 shouldn't be affect.
|
// Bit1 shouldn't be affect.
|
||||||
check(1, 0, params.MainnetGenesisHash, true)
|
check(1, 0, params.MainnetGenesisHash, true)
|
||||||
check(1, 0, params.SepoliaGenesisHash, true)
|
check(1, 0, params.SepoliaGenesisHash, true)
|
||||||
|
check(1, 0, params.HoodiGenesisHash, true)
|
||||||
check(1, 1, params.MainnetGenesisHash, true)
|
check(1, 1, params.MainnetGenesisHash, true)
|
||||||
check(1, 1, params.SepoliaGenesisHash, true)
|
check(1, 1, params.SepoliaGenesisHash, true)
|
||||||
|
check(1, 1, params.HoodiGenesisHash, true)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,21 @@ const (
|
||||||
ChainFreezerReceiptTable = "receipts"
|
ChainFreezerReceiptTable = "receipts"
|
||||||
)
|
)
|
||||||
|
|
||||||
// chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables.
|
// chainFreezerTableConfigs configures the settings for tables in the chain freezer.
|
||||||
// Hashes and difficulties don't compress well.
|
// Compression is disabled for hashes as they don't compress well. Additionally,
|
||||||
var chainFreezerNoSnappy = map[string]bool{
|
// tail truncation is disabled for the header and hash tables, as these are intended
|
||||||
ChainFreezerHeaderTable: false,
|
// to be retained long-term.
|
||||||
ChainFreezerHashTable: true,
|
var chainFreezerTableConfigs = map[string]freezerTableConfig{
|
||||||
ChainFreezerBodiesTable: false,
|
ChainFreezerHeaderTable: {noSnappy: false, prunable: false},
|
||||||
ChainFreezerReceiptTable: false,
|
ChainFreezerHashTable: {noSnappy: true, prunable: false},
|
||||||
|
ChainFreezerBodiesTable: {noSnappy: false, prunable: true},
|
||||||
|
ChainFreezerReceiptTable: {noSnappy: false, prunable: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
// freezerTableConfig contains the settings for a freezer table.
|
||||||
|
type freezerTableConfig struct {
|
||||||
|
noSnappy bool // disables item compression
|
||||||
|
prunable bool // true for tables that can be pruned by TruncateTail
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -58,13 +66,13 @@ const (
|
||||||
stateHistoryStorageData = "storage.data"
|
stateHistoryStorageData = "storage.data"
|
||||||
)
|
)
|
||||||
|
|
||||||
// stateFreezerNoSnappy configures whether compression is disabled for the state freezer.
|
// stateFreezerTableConfigs configures the settings for tables in the state freezer.
|
||||||
var stateFreezerNoSnappy = map[string]bool{
|
var stateFreezerTableConfigs = map[string]freezerTableConfig{
|
||||||
stateHistoryMeta: true,
|
stateHistoryMeta: {noSnappy: true, prunable: true},
|
||||||
stateHistoryAccountIndex: false,
|
stateHistoryAccountIndex: {noSnappy: false, prunable: true},
|
||||||
stateHistoryStorageIndex: false,
|
stateHistoryStorageIndex: {noSnappy: false, prunable: true},
|
||||||
stateHistoryAccountData: false,
|
stateHistoryAccountData: {noSnappy: false, prunable: true},
|
||||||
stateHistoryStorageData: false,
|
stateHistoryStorageData: {noSnappy: false, prunable: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
// The list of identifiers of ancient stores.
|
// The list of identifiers of ancient stores.
|
||||||
|
|
@ -85,7 +93,7 @@ var freezers = []string{ChainFreezerName, MerkleStateFreezerName, VerkleStateFre
|
||||||
// state freezer.
|
// state freezer.
|
||||||
func NewStateFreezer(ancientDir string, verkle bool, readOnly bool) (ethdb.ResettableAncientStore, error) {
|
func NewStateFreezer(ancientDir string, verkle bool, readOnly bool) (ethdb.ResettableAncientStore, error) {
|
||||||
if ancientDir == "" {
|
if ancientDir == "" {
|
||||||
return NewMemoryFreezer(readOnly, stateFreezerNoSnappy), nil
|
return NewMemoryFreezer(readOnly, stateFreezerTableConfigs), nil
|
||||||
}
|
}
|
||||||
var name string
|
var name string
|
||||||
if verkle {
|
if verkle {
|
||||||
|
|
@ -93,5 +101,5 @@ func NewStateFreezer(ancientDir string, verkle bool, readOnly bool) (ethdb.Reset
|
||||||
} else {
|
} else {
|
||||||
name = filepath.Join(ancientDir, MerkleStateFreezerName)
|
name = filepath.Join(ancientDir, MerkleStateFreezerName)
|
||||||
}
|
}
|
||||||
return newResettableFreezer(name, "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy)
|
return newResettableFreezer(name, "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerTableConfigs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ func (info *freezerInfo) size() common.StorageSize {
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
func inspect(name string, order map[string]bool, reader ethdb.AncientReader) (freezerInfo, error) {
|
func inspect(name string, order map[string]freezerTableConfig, reader ethdb.AncientReader) (freezerInfo, error) {
|
||||||
info := freezerInfo{name: name}
|
info := freezerInfo{name: name}
|
||||||
for t := range order {
|
for t := range order {
|
||||||
size, err := reader.AncientSize(t)
|
size, err := reader.AncientSize(t)
|
||||||
|
|
@ -82,7 +82,7 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
||||||
for _, freezer := range freezers {
|
for _, freezer := range freezers {
|
||||||
switch freezer {
|
switch freezer {
|
||||||
case ChainFreezerName:
|
case ChainFreezerName:
|
||||||
info, err := inspect(ChainFreezerName, chainFreezerNoSnappy, db)
|
info, err := inspect(ChainFreezerName, chainFreezerTableConfigs, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +99,7 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
info, err := inspect(freezer, stateFreezerNoSnappy, f)
|
info, err := inspect(freezer, stateFreezerTableConfigs, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -119,13 +119,13 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
||||||
func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64) error {
|
func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64) error {
|
||||||
var (
|
var (
|
||||||
path string
|
path string
|
||||||
tables map[string]bool
|
tables map[string]freezerTableConfig
|
||||||
)
|
)
|
||||||
switch freezerName {
|
switch freezerName {
|
||||||
case ChainFreezerName:
|
case ChainFreezerName:
|
||||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
path, tables = resolveChainFreezerDir(ancient), chainFreezerTableConfigs
|
||||||
case MerkleStateFreezerName, VerkleStateFreezerName:
|
case MerkleStateFreezerName, VerkleStateFreezerName:
|
||||||
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
path, tables = filepath.Join(ancient, freezerName), stateFreezerTableConfigs
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,9 @@ func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFre
|
||||||
freezer ethdb.AncientStore
|
freezer ethdb.AncientStore
|
||||||
)
|
)
|
||||||
if datadir == "" {
|
if datadir == "" {
|
||||||
freezer = NewMemoryFreezer(readonly, chainFreezerNoSnappy)
|
freezer = NewMemoryFreezer(readonly, chainFreezerTableConfigs)
|
||||||
} else {
|
} else {
|
||||||
freezer, err = NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerNoSnappy)
|
freezer, err = NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerTableConfigs)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ type Freezer struct {
|
||||||
//
|
//
|
||||||
// The 'tables' argument defines the data tables. If the value of a map
|
// The 'tables' argument defines the data tables. If the value of a map
|
||||||
// entry is true, snappy compression is disabled for the table.
|
// entry is true, snappy compression is disabled for the table.
|
||||||
func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*Freezer, error) {
|
func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]freezerTableConfig) (*Freezer, error) {
|
||||||
// Create the initial freezer object
|
// Create the initial freezer object
|
||||||
var (
|
var (
|
||||||
readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
|
readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
|
||||||
|
|
@ -121,8 +121,8 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the tables.
|
// Create the tables.
|
||||||
for name, disableSnappy := range tables {
|
for name, config := range tables {
|
||||||
table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, maxTableSize, disableSnappy, readonly)
|
table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, maxTableSize, config, readonly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for _, table := range freezer.tables {
|
for _, table := range freezer.tables {
|
||||||
table.Close()
|
table.Close()
|
||||||
|
|
@ -301,7 +301,8 @@ func (f *Freezer) TruncateHead(items uint64) (uint64, error) {
|
||||||
return oitems, nil
|
return oitems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TruncateTail discards any recent data below the provided threshold number.
|
// TruncateTail discards all data below the specified threshold. Note that only
|
||||||
|
// 'prunable' tables will be truncated.
|
||||||
func (f *Freezer) TruncateTail(tail uint64) (uint64, error) {
|
func (f *Freezer) TruncateTail(tail uint64) (uint64, error) {
|
||||||
if f.readonly {
|
if f.readonly {
|
||||||
return 0, errReadOnly
|
return 0, errReadOnly
|
||||||
|
|
@ -314,8 +315,10 @@ func (f *Freezer) TruncateTail(tail uint64) (uint64, error) {
|
||||||
return old, nil
|
return old, nil
|
||||||
}
|
}
|
||||||
for _, table := range f.tables {
|
for _, table := range f.tables {
|
||||||
if err := table.truncateTail(tail); err != nil {
|
if table.config.prunable {
|
||||||
return 0, err
|
if err := table.truncateTail(tail); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.tail.Store(tail)
|
f.tail.Store(tail)
|
||||||
|
|
@ -343,56 +346,77 @@ func (f *Freezer) validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
head uint64
|
head uint64
|
||||||
tail uint64
|
prunedTail *uint64
|
||||||
name string
|
|
||||||
)
|
)
|
||||||
// Hack to get boundary of any table
|
// get any head value
|
||||||
for kind, table := range f.tables {
|
for _, table := range f.tables {
|
||||||
head = table.items.Load()
|
head = table.items.Load()
|
||||||
tail = table.itemHidden.Load()
|
|
||||||
name = kind
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Now check every table against those boundaries.
|
|
||||||
for kind, table := range f.tables {
|
for kind, table := range f.tables {
|
||||||
|
// all tables have to have the same head
|
||||||
if head != table.items.Load() {
|
if head != table.items.Load() {
|
||||||
return fmt.Errorf("freezer tables %s and %s have differing head: %d != %d", kind, name, table.items.Load(), head)
|
return fmt.Errorf("freezer table %s has a differing head: %d != %d", kind, table.items.Load(), head)
|
||||||
}
|
}
|
||||||
if tail != table.itemHidden.Load() {
|
if !table.config.prunable {
|
||||||
return fmt.Errorf("freezer tables %s and %s have differing tail: %d != %d", kind, name, table.itemHidden.Load(), tail)
|
// non-prunable tables have to start at 0
|
||||||
|
if table.itemHidden.Load() != 0 {
|
||||||
|
return fmt.Errorf("non-prunable freezer table '%s' has a non-zero tail: %d", kind, table.itemHidden.Load())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// prunable tables have to have the same length
|
||||||
|
if prunedTail == nil {
|
||||||
|
tmp := table.itemHidden.Load()
|
||||||
|
prunedTail = &tmp
|
||||||
|
}
|
||||||
|
if *prunedTail != table.itemHidden.Load() {
|
||||||
|
return fmt.Errorf("freezer table %s has differing tail: %d != %d", kind, table.itemHidden.Load(), *prunedTail)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if prunedTail == nil {
|
||||||
|
tmp := uint64(0)
|
||||||
|
prunedTail = &tmp
|
||||||
|
}
|
||||||
|
|
||||||
f.frozen.Store(head)
|
f.frozen.Store(head)
|
||||||
f.tail.Store(tail)
|
f.tail.Store(*prunedTail)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// repair truncates all data tables to the same length.
|
// repair truncates all data tables to the same length.
|
||||||
func (f *Freezer) repair() error {
|
func (f *Freezer) repair() error {
|
||||||
var (
|
var (
|
||||||
head = uint64(math.MaxUint64)
|
head = uint64(math.MaxUint64)
|
||||||
tail = uint64(0)
|
prunedTail = uint64(0)
|
||||||
)
|
)
|
||||||
|
// get the minimal head and the maximum tail
|
||||||
for _, table := range f.tables {
|
for _, table := range f.tables {
|
||||||
items := table.items.Load()
|
head = min(head, table.items.Load())
|
||||||
if head > items {
|
prunedTail = max(prunedTail, table.itemHidden.Load())
|
||||||
head = items
|
|
||||||
}
|
|
||||||
hidden := table.itemHidden.Load()
|
|
||||||
if hidden > tail {
|
|
||||||
tail = hidden
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for _, table := range f.tables {
|
// apply the pruning
|
||||||
|
for kind, table := range f.tables {
|
||||||
|
// all tables need to have the same head
|
||||||
if err := table.truncateHead(head); err != nil {
|
if err := table.truncateHead(head); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := table.truncateTail(tail); err != nil {
|
if !table.config.prunable {
|
||||||
return err
|
// non-prunable tables have to start at 0
|
||||||
|
if table.itemHidden.Load() != 0 {
|
||||||
|
panic(fmt.Sprintf("non-prunable freezer table %s has non-zero tail: %v", kind, table.itemHidden.Load()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// prunable tables have to have the same length
|
||||||
|
if err := table.truncateTail(prunedTail); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.frozen.Store(head)
|
f.frozen.Store(head)
|
||||||
f.tail.Store(tail)
|
f.tail.Store(prunedTail)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ type freezerTableBatch struct {
|
||||||
// newBatch creates a new batch for the freezer table.
|
// newBatch creates a new batch for the freezer table.
|
||||||
func (t *freezerTable) newBatch() *freezerTableBatch {
|
func (t *freezerTable) newBatch() *freezerTableBatch {
|
||||||
batch := &freezerTableBatch{t: t}
|
batch := &freezerTableBatch{t: t}
|
||||||
if !t.noCompression {
|
if !t.config.noSnappy {
|
||||||
batch.sb = new(snappyBuffer)
|
batch.sb = new(snappyBuffer)
|
||||||
}
|
}
|
||||||
batch.reset()
|
batch.reset()
|
||||||
|
|
|
||||||
|
|
@ -30,17 +30,19 @@ import (
|
||||||
|
|
||||||
// memoryTable is used to store a list of sequential items in memory.
|
// memoryTable is used to store a list of sequential items in memory.
|
||||||
type memoryTable struct {
|
type memoryTable struct {
|
||||||
name string // Table name
|
|
||||||
items uint64 // Number of stored items in the table, including the deleted ones
|
items uint64 // Number of stored items in the table, including the deleted ones
|
||||||
offset uint64 // Number of deleted items from the table
|
offset uint64 // Number of deleted items from the table
|
||||||
data [][]byte // List of rlp-encoded items, sort in order
|
data [][]byte // List of rlp-encoded items, sort in order
|
||||||
size uint64 // Total memory size occupied by the table
|
size uint64 // Total memory size occupied by the table
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
|
|
||||||
|
name string
|
||||||
|
config freezerTableConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMemoryTable initializes the memory table.
|
// newMemoryTable initializes the memory table.
|
||||||
func newMemoryTable(name string) *memoryTable {
|
func newMemoryTable(name string, config freezerTableConfig) *memoryTable {
|
||||||
return &memoryTable{name: name}
|
return &memoryTable{name: name, config: config}
|
||||||
}
|
}
|
||||||
|
|
||||||
// has returns an indicator whether the specified data exists.
|
// has returns an indicator whether the specified data exists.
|
||||||
|
|
@ -218,10 +220,10 @@ type MemoryFreezer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMemoryFreezer initializes an in-memory freezer instance.
|
// NewMemoryFreezer initializes an in-memory freezer instance.
|
||||||
func NewMemoryFreezer(readonly bool, tableName map[string]bool) *MemoryFreezer {
|
func NewMemoryFreezer(readonly bool, tableName map[string]freezerTableConfig) *MemoryFreezer {
|
||||||
tables := make(map[string]*memoryTable)
|
tables := make(map[string]*memoryTable)
|
||||||
for name := range tableName {
|
for name, cfg := range tableName {
|
||||||
tables[name] = newMemoryTable(name)
|
tables[name] = newMemoryTable(name, cfg)
|
||||||
}
|
}
|
||||||
return &MemoryFreezer{
|
return &MemoryFreezer{
|
||||||
writeBatch: newMemoryBatch(),
|
writeBatch: newMemoryBatch(),
|
||||||
|
|
@ -368,7 +370,9 @@ func (f *MemoryFreezer) TruncateHead(items uint64) (uint64, error) {
|
||||||
return old, nil
|
return old, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TruncateTail discards any recent data below the provided threshold number.
|
// TruncateTail discards all data below the provided threshold number.
|
||||||
|
// Note this will only truncate 'prunable' tables. Block headers and canonical
|
||||||
|
// hashes cannot be truncated at this time.
|
||||||
func (f *MemoryFreezer) TruncateTail(tail uint64) (uint64, error) {
|
func (f *MemoryFreezer) TruncateTail(tail uint64) (uint64, error) {
|
||||||
f.lock.Lock()
|
f.lock.Lock()
|
||||||
defer f.lock.Unlock()
|
defer f.lock.Unlock()
|
||||||
|
|
@ -381,8 +385,10 @@ func (f *MemoryFreezer) TruncateTail(tail uint64) (uint64, error) {
|
||||||
return old, nil
|
return old, nil
|
||||||
}
|
}
|
||||||
for _, table := range f.tables {
|
for _, table := range f.tables {
|
||||||
if err := table.truncateTail(tail); err != nil {
|
if table.config.prunable {
|
||||||
return 0, err
|
if err := table.truncateTail(tail); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.tail = tail
|
f.tail = tail
|
||||||
|
|
@ -412,8 +418,8 @@ func (f *MemoryFreezer) Reset() error {
|
||||||
defer f.lock.Unlock()
|
defer f.lock.Unlock()
|
||||||
|
|
||||||
tables := make(map[string]*memoryTable)
|
tables := make(map[string]*memoryTable)
|
||||||
for name := range f.tables {
|
for name, table := range f.tables {
|
||||||
tables[name] = newMemoryTable(name)
|
tables[name] = newMemoryTable(name, table.config)
|
||||||
}
|
}
|
||||||
f.tables = tables
|
f.tables = tables
|
||||||
f.items, f.tail = 0, 0
|
f.items, f.tail = 0, 0
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,22 @@ import (
|
||||||
|
|
||||||
func TestMemoryFreezer(t *testing.T) {
|
func TestMemoryFreezer(t *testing.T) {
|
||||||
ancienttest.TestAncientSuite(t, func(kinds []string) ethdb.AncientStore {
|
ancienttest.TestAncientSuite(t, func(kinds []string) ethdb.AncientStore {
|
||||||
tables := make(map[string]bool)
|
tables := make(map[string]freezerTableConfig)
|
||||||
for _, kind := range kinds {
|
for _, kind := range kinds {
|
||||||
tables[kind] = true
|
tables[kind] = freezerTableConfig{
|
||||||
|
noSnappy: true,
|
||||||
|
prunable: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NewMemoryFreezer(false, tables)
|
return NewMemoryFreezer(false, tables)
|
||||||
})
|
})
|
||||||
ancienttest.TestResettableAncientSuite(t, func(kinds []string) ethdb.ResettableAncientStore {
|
ancienttest.TestResettableAncientSuite(t, func(kinds []string) ethdb.ResettableAncientStore {
|
||||||
tables := make(map[string]bool)
|
tables := make(map[string]freezerTableConfig)
|
||||||
for _, kind := range kinds {
|
for _, kind := range kinds {
|
||||||
tables[kind] = true
|
tables[kind] = freezerTableConfig{
|
||||||
|
noSnappy: true,
|
||||||
|
prunable: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NewMemoryFreezer(false, tables)
|
return NewMemoryFreezer(false, tables)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ type resettableFreezer struct {
|
||||||
//
|
//
|
||||||
// The reset function will delete directory atomically and re-create the
|
// The reset function will delete directory atomically and re-create the
|
||||||
// freezer from scratch.
|
// freezer from scratch.
|
||||||
func newResettableFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*resettableFreezer, error) {
|
func newResettableFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]freezerTableConfig) (*resettableFreezer, error) {
|
||||||
if err := cleanup(datadir); err != nil {
|
if err := cleanup(datadir); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,11 +100,11 @@ type freezerTable struct {
|
||||||
// should never be lower than itemOffset.
|
// should never be lower than itemOffset.
|
||||||
itemHidden atomic.Uint64
|
itemHidden atomic.Uint64
|
||||||
|
|
||||||
noCompression bool // if true, disables snappy compression. Note: does not work retroactively
|
config freezerTableConfig // if true, disables snappy compression. Note: does not work retroactively
|
||||||
readonly bool
|
readonly bool
|
||||||
maxFileSize uint32 // Max file size for data-files
|
maxFileSize uint32 // Max file size for data-files
|
||||||
name string
|
name string
|
||||||
path string
|
path string
|
||||||
|
|
||||||
head *os.File // File descriptor for the data head of the table
|
head *os.File // File descriptor for the data head of the table
|
||||||
index *os.File // File descriptor for the indexEntry file of the table
|
index *os.File // File descriptor for the indexEntry file of the table
|
||||||
|
|
@ -125,20 +125,20 @@ type freezerTable struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFreezerTable opens the given path as a freezer table.
|
// newFreezerTable opens the given path as a freezer table.
|
||||||
func newFreezerTable(path, name string, disableSnappy, readonly bool) (*freezerTable, error) {
|
func newFreezerTable(path, name string, config freezerTableConfig, readonly bool) (*freezerTable, error) {
|
||||||
return newTable(path, name, metrics.NewInactiveMeter(), metrics.NewInactiveMeter(), metrics.NewGauge(), freezerTableSize, disableSnappy, readonly)
|
return newTable(path, name, metrics.NewInactiveMeter(), metrics.NewInactiveMeter(), metrics.NewGauge(), freezerTableSize, config, readonly)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTable opens a freezer table, creating the data and index files if they are
|
// newTable opens a freezer table, creating the data and index files if they are
|
||||||
// non-existent. Both files are truncated to the shortest common length to ensure
|
// non-existent. Both files are truncated to the shortest common length to ensure
|
||||||
// they don't go out of sync.
|
// they don't go out of sync.
|
||||||
func newTable(path string, name string, readMeter, writeMeter *metrics.Meter, sizeGauge *metrics.Gauge, maxFilesize uint32, noCompression, readonly bool) (*freezerTable, error) {
|
func newTable(path string, name string, readMeter, writeMeter *metrics.Meter, sizeGauge *metrics.Gauge, maxFilesize uint32, config freezerTableConfig, readonly bool) (*freezerTable, error) {
|
||||||
// Ensure the containing directory exists and open the indexEntry file
|
// Ensure the containing directory exists and open the indexEntry file
|
||||||
if err := os.MkdirAll(path, 0755); err != nil {
|
if err := os.MkdirAll(path, 0755); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var idxName string
|
var idxName string
|
||||||
if noCompression {
|
if config.noSnappy {
|
||||||
idxName = fmt.Sprintf("%s.ridx", name) // raw index file
|
idxName = fmt.Sprintf("%s.ridx", name) // raw index file
|
||||||
} else {
|
} else {
|
||||||
idxName = fmt.Sprintf("%s.cidx", name) // compressed index file
|
idxName = fmt.Sprintf("%s.cidx", name) // compressed index file
|
||||||
|
|
@ -176,19 +176,19 @@ func newTable(path string, name string, readMeter, writeMeter *metrics.Meter, si
|
||||||
}
|
}
|
||||||
// Create the table and repair any past inconsistency
|
// Create the table and repair any past inconsistency
|
||||||
tab := &freezerTable{
|
tab := &freezerTable{
|
||||||
index: index,
|
index: index,
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
lastSync: time.Now(),
|
lastSync: time.Now(),
|
||||||
files: make(map[uint32]*os.File),
|
files: make(map[uint32]*os.File),
|
||||||
readMeter: readMeter,
|
readMeter: readMeter,
|
||||||
writeMeter: writeMeter,
|
writeMeter: writeMeter,
|
||||||
sizeGauge: sizeGauge,
|
sizeGauge: sizeGauge,
|
||||||
name: name,
|
name: name,
|
||||||
path: path,
|
path: path,
|
||||||
logger: log.New("database", path, "table", name),
|
logger: log.New("database", path, "table", name),
|
||||||
noCompression: noCompression,
|
config: config,
|
||||||
readonly: readonly,
|
readonly: readonly,
|
||||||
maxFileSize: maxFilesize,
|
maxFileSize: maxFilesize,
|
||||||
}
|
}
|
||||||
if err := tab.repair(); err != nil {
|
if err := tab.repair(); err != nil {
|
||||||
tab.Close()
|
tab.Close()
|
||||||
|
|
@ -871,7 +871,7 @@ func (t *freezerTable) openFile(num uint32, opener func(string) (*os.File, error
|
||||||
var exist bool
|
var exist bool
|
||||||
if f, exist = t.files[num]; !exist {
|
if f, exist = t.files[num]; !exist {
|
||||||
var name string
|
var name string
|
||||||
if t.noCompression {
|
if t.config.noSnappy {
|
||||||
name = fmt.Sprintf("%s.%04d.rdat", t.name, num)
|
name = fmt.Sprintf("%s.%04d.rdat", t.name, num)
|
||||||
} else {
|
} else {
|
||||||
name = fmt.Sprintf("%s.%04d.cdat", t.name, num)
|
name = fmt.Sprintf("%s.%04d.cdat", t.name, num)
|
||||||
|
|
@ -987,13 +987,13 @@ func (t *freezerTable) RetrieveItems(start, count, maxBytes uint64) ([][]byte, e
|
||||||
item := diskData[offset : offset+diskSize]
|
item := diskData[offset : offset+diskSize]
|
||||||
offset += diskSize
|
offset += diskSize
|
||||||
decompressedSize := diskSize
|
decompressedSize := diskSize
|
||||||
if !t.noCompression {
|
if !t.config.noSnappy {
|
||||||
decompressedSize, _ = snappy.DecodedLen(item)
|
decompressedSize, _ = snappy.DecodedLen(item)
|
||||||
}
|
}
|
||||||
if i > 0 && maxBytes != 0 && uint64(outputSize+decompressedSize) > maxBytes {
|
if i > 0 && maxBytes != 0 && uint64(outputSize+decompressedSize) > maxBytes {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !t.noCompression {
|
if !t.config.noSnappy {
|
||||||
data, err := snappy.Decode(nil, item)
|
data, err := snappy.Decode(nil, item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func TestFreezerBasics(t *testing.T) {
|
||||||
// set cutoff at 50 bytes
|
// set cutoff at 50 bytes
|
||||||
f, err := newTable(os.TempDir(),
|
f, err := newTable(os.TempDir(),
|
||||||
fmt.Sprintf("unittest-%d", rand.Uint64()),
|
fmt.Sprintf("unittest-%d", rand.Uint64()),
|
||||||
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false)
|
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ func TestFreezerBasicsClosing(t *testing.T) {
|
||||||
f *freezerTable
|
f *freezerTable
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +98,7 @@ func TestFreezerBasicsClosing(t *testing.T) {
|
||||||
require.NoError(t, batch.commit())
|
require.NoError(t, batch.commit())
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ func TestFreezerBasicsClosing(t *testing.T) {
|
||||||
t.Fatalf("test %d, got \n%x != \n%x", y, got, exp)
|
t.Fatalf("test %d, got \n%x != \n%x", y, got, exp)
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +130,7 @@ func TestFreezerRepairDanglingHead(t *testing.T) {
|
||||||
|
|
||||||
// Fill table
|
// Fill table
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +159,7 @@ func TestFreezerRepairDanglingHead(t *testing.T) {
|
||||||
|
|
||||||
// Now open it again
|
// Now open it again
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +182,7 @@ func TestFreezerRepairDanglingHeadLarge(t *testing.T) {
|
||||||
|
|
||||||
// Fill a table and close it
|
// Fill a table and close it
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +208,7 @@ func TestFreezerRepairDanglingHeadLarge(t *testing.T) {
|
||||||
|
|
||||||
// Now open it again
|
// Now open it again
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -231,7 +231,7 @@ func TestFreezerRepairDanglingHeadLarge(t *testing.T) {
|
||||||
|
|
||||||
// And if we open it, we should now be able to read all of them (new values)
|
// And if we open it, we should now be able to read all of them (new values)
|
||||||
{
|
{
|
||||||
f, _ := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, _ := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
for y := 1; y < 255; y++ {
|
for y := 1; y < 255; y++ {
|
||||||
exp := getChunk(15, ^y)
|
exp := getChunk(15, ^y)
|
||||||
got, err := f.Retrieve(uint64(y))
|
got, err := f.Retrieve(uint64(y))
|
||||||
|
|
@ -253,7 +253,7 @@ func TestSnappyDetection(t *testing.T) {
|
||||||
|
|
||||||
// Open with snappy
|
// Open with snappy
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -264,7 +264,7 @@ func TestSnappyDetection(t *testing.T) {
|
||||||
|
|
||||||
// Open with snappy
|
// Open with snappy
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +277,7 @@ func TestSnappyDetection(t *testing.T) {
|
||||||
|
|
||||||
// Open without snappy
|
// Open without snappy
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, false, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: false}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -308,7 +308,7 @@ func TestFreezerRepairDanglingIndex(t *testing.T) {
|
||||||
|
|
||||||
// Fill a table and close it
|
// Fill a table and close it
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +344,7 @@ func TestFreezerRepairDanglingIndex(t *testing.T) {
|
||||||
// 45, 45, 15
|
// 45, 45, 15
|
||||||
// with 3+3+1 items
|
// with 3+3+1 items
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -365,7 +365,7 @@ func TestFreezerTruncate(t *testing.T) {
|
||||||
|
|
||||||
// Fill table
|
// Fill table
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -381,7 +381,7 @@ func TestFreezerTruncate(t *testing.T) {
|
||||||
|
|
||||||
// Reopen, truncate
|
// Reopen, truncate
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -406,7 +406,7 @@ func TestFreezerRepairFirstFile(t *testing.T) {
|
||||||
|
|
||||||
// Fill table
|
// Fill table
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -439,7 +439,7 @@ func TestFreezerRepairFirstFile(t *testing.T) {
|
||||||
|
|
||||||
// Reopen
|
// Reopen
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -474,7 +474,7 @@ func TestFreezerReadAndTruncate(t *testing.T) {
|
||||||
|
|
||||||
// Fill table
|
// Fill table
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -490,7 +490,7 @@ func TestFreezerReadAndTruncate(t *testing.T) {
|
||||||
|
|
||||||
// Reopen and read all files
|
// Reopen and read all files
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -521,7 +521,7 @@ func TestFreezerOffset(t *testing.T) {
|
||||||
fname := fmt.Sprintf("offset-%d", rand.Uint64())
|
fname := fmt.Sprintf("offset-%d", rand.Uint64())
|
||||||
|
|
||||||
// Fill table
|
// Fill table
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -545,7 +545,7 @@ func TestFreezerOffset(t *testing.T) {
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
// Now open again
|
// Now open again
|
||||||
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false)
|
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -597,7 +597,7 @@ func TestFreezerOffset(t *testing.T) {
|
||||||
|
|
||||||
// Check that existing items have been moved to index 1M.
|
// Check that existing items have been moved to index 1M.
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -631,7 +631,7 @@ func TestTruncateTail(t *testing.T) {
|
||||||
fname := fmt.Sprintf("truncate-tail-%d", rand.Uint64())
|
fname := fmt.Sprintf("truncate-tail-%d", rand.Uint64())
|
||||||
|
|
||||||
// Fill table
|
// Fill table
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -682,7 +682,7 @@ func TestTruncateTail(t *testing.T) {
|
||||||
|
|
||||||
// Reopen the table, the deletion information should be persisted as well
|
// Reopen the table, the deletion information should be persisted as well
|
||||||
f.Close()
|
f.Close()
|
||||||
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false)
|
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -716,7 +716,7 @@ func TestTruncateTail(t *testing.T) {
|
||||||
|
|
||||||
// Reopen the table, the above testing should still pass
|
// Reopen the table, the above testing should still pass
|
||||||
f.Close()
|
f.Close()
|
||||||
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false)
|
f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -772,7 +772,7 @@ func TestTruncateHead(t *testing.T) {
|
||||||
fname := fmt.Sprintf("truncate-head-blow-tail-%d", rand.Uint64())
|
fname := fmt.Sprintf("truncate-head-blow-tail-%d", rand.Uint64())
|
||||||
|
|
||||||
// Fill table
|
// Fill table
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -883,7 +883,7 @@ func TestSequentialRead(t *testing.T) {
|
||||||
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
|
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
|
||||||
fname := fmt.Sprintf("batchread-%d", rand.Uint64())
|
fname := fmt.Sprintf("batchread-%d", rand.Uint64())
|
||||||
{ // Fill table
|
{ // Fill table
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -893,7 +893,7 @@ func TestSequentialRead(t *testing.T) {
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
{ // Open it, iterate, verify iteration
|
{ // Open it, iterate, verify iteration
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -914,7 +914,7 @@ func TestSequentialRead(t *testing.T) {
|
||||||
}
|
}
|
||||||
{ // Open it, iterate, verify byte limit. The byte limit is less than item
|
{ // Open it, iterate, verify byte limit. The byte limit is less than item
|
||||||
// size, so each lookup should only return one item
|
// size, so each lookup should only return one item
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -943,7 +943,7 @@ func TestSequentialReadByteLimit(t *testing.T) {
|
||||||
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
|
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
|
||||||
fname := fmt.Sprintf("batchread-2-%d", rand.Uint64())
|
fname := fmt.Sprintf("batchread-2-%d", rand.Uint64())
|
||||||
{ // Fill table
|
{ // Fill table
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -965,7 +965,7 @@ func TestSequentialReadByteLimit(t *testing.T) {
|
||||||
{100, 109, 10},
|
{100, 109, 10},
|
||||||
} {
|
} {
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -993,7 +993,7 @@ func TestSequentialReadNoByteLimit(t *testing.T) {
|
||||||
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
|
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
|
||||||
fname := fmt.Sprintf("batchread-3-%d", rand.Uint64())
|
fname := fmt.Sprintf("batchread-3-%d", rand.Uint64())
|
||||||
{ // Fill table
|
{ // Fill table
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1011,7 +1011,7 @@ func TestSequentialReadNoByteLimit(t *testing.T) {
|
||||||
{31, 30},
|
{31, 30},
|
||||||
} {
|
} {
|
||||||
{
|
{
|
||||||
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, true, false)
|
f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1038,7 +1038,7 @@ func TestFreezerReadonly(t *testing.T) {
|
||||||
// Case 1: Check it fails on non-existent file.
|
// Case 1: Check it fails on non-existent file.
|
||||||
_, err := newTable(tmpdir,
|
_, err := newTable(tmpdir,
|
||||||
fmt.Sprintf("readonlytest-%d", rand.Uint64()),
|
fmt.Sprintf("readonlytest-%d", rand.Uint64()),
|
||||||
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, true)
|
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, true)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("readonly table instantiation should fail for non-existent table")
|
t.Fatal("readonly table instantiation should fail for non-existent table")
|
||||||
}
|
}
|
||||||
|
|
@ -1053,7 +1053,7 @@ func TestFreezerReadonly(t *testing.T) {
|
||||||
idxFile.Write(make([]byte, 17))
|
idxFile.Write(make([]byte, 17))
|
||||||
idxFile.Close()
|
idxFile.Close()
|
||||||
_, err = newTable(tmpdir, fname,
|
_, err = newTable(tmpdir, fname,
|
||||||
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, true)
|
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, true)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("readonly table instantiation should fail for invalid index size")
|
t.Errorf("readonly table instantiation should fail for invalid index size")
|
||||||
}
|
}
|
||||||
|
|
@ -1063,7 +1063,7 @@ func TestFreezerReadonly(t *testing.T) {
|
||||||
// again in readonly triggers an error.
|
// again in readonly triggers an error.
|
||||||
fname = fmt.Sprintf("readonlytest-%d", rand.Uint64())
|
fname = fmt.Sprintf("readonlytest-%d", rand.Uint64())
|
||||||
f, err := newTable(tmpdir, fname,
|
f, err := newTable(tmpdir, fname,
|
||||||
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false)
|
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to instantiate table: %v", err)
|
t.Fatalf("failed to instantiate table: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1076,7 +1076,7 @@ func TestFreezerReadonly(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
_, err = newTable(tmpdir, fname,
|
_, err = newTable(tmpdir, fname,
|
||||||
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, true)
|
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, true)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("readonly table instantiation should fail for corrupt table file")
|
t.Errorf("readonly table instantiation should fail for corrupt table file")
|
||||||
}
|
}
|
||||||
|
|
@ -1085,7 +1085,7 @@ func TestFreezerReadonly(t *testing.T) {
|
||||||
// Should be successful.
|
// Should be successful.
|
||||||
fname = fmt.Sprintf("readonlytest-%d", rand.Uint64())
|
fname = fmt.Sprintf("readonlytest-%d", rand.Uint64())
|
||||||
f, err = newTable(tmpdir, fname,
|
f, err = newTable(tmpdir, fname,
|
||||||
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false)
|
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to instantiate table: %v\n", err)
|
t.Fatalf("failed to instantiate table: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1094,7 +1094,7 @@ func TestFreezerReadonly(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
f, err = newTable(tmpdir, fname,
|
f, err = newTable(tmpdir, fname,
|
||||||
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, true)
|
metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1234,7 +1234,7 @@ func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
|
||||||
|
|
||||||
func runRandTest(rt randTest) bool {
|
func runRandTest(rt randTest) bool {
|
||||||
fname := fmt.Sprintf("randtest-%d", rand.Uint64())
|
fname := fmt.Sprintf("randtest-%d", rand.Uint64())
|
||||||
f, err := newTable(os.TempDir(), fname, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false)
|
f, err := newTable(os.TempDir(), fname, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to initialize table")
|
panic("failed to initialize table")
|
||||||
}
|
}
|
||||||
|
|
@ -1243,7 +1243,7 @@ func runRandTest(rt randTest) bool {
|
||||||
switch step.op {
|
switch step.op {
|
||||||
case opReload:
|
case opReload:
|
||||||
f.Close()
|
f.Close()
|
||||||
f, err = newTable(os.TempDir(), fname, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false)
|
f, err = newTable(os.TempDir(), fname, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rt[i].err = fmt.Errorf("failed to reload table %v", err)
|
rt[i].err = fmt.Errorf("failed to reload table %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1381,7 +1381,7 @@ func TestIndexValidation(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
fn := fmt.Sprintf("t-%d", rand.Uint64())
|
fn := fmt.Sprintf("t-%d", rand.Uint64())
|
||||||
f, err := newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 10*dataSize, true, false)
|
f, err := newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 10*dataSize, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1392,7 +1392,7 @@ func TestIndexValidation(t *testing.T) {
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
// reopen the table, corruption should be truncated
|
// reopen the table, corruption should be truncated
|
||||||
f, err = newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 100, true, false)
|
f, err = newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 100, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1422,7 +1422,7 @@ func TestFlushOffsetTracking(t *testing.T) {
|
||||||
fileSize = 100
|
fileSize = 100
|
||||||
)
|
)
|
||||||
fn := fmt.Sprintf("t-%d", rand.Uint64())
|
fn := fmt.Sprintf("t-%d", rand.Uint64())
|
||||||
f, err := newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), fileSize, true, false)
|
f, err := newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), fileSize, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1533,7 +1533,7 @@ func TestTailTruncationCrash(t *testing.T) {
|
||||||
fileSize = 100
|
fileSize = 100
|
||||||
)
|
)
|
||||||
fn := fmt.Sprintf("t-%d", rand.Uint64())
|
fn := fmt.Sprintf("t-%d", rand.Uint64())
|
||||||
f, err := newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), fileSize, true, false)
|
f, err := newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), fileSize, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1563,7 +1563,7 @@ func TestTailTruncationCrash(t *testing.T) {
|
||||||
// the offset
|
// the offset
|
||||||
f.metadata.setFlushOffset(31*indexEntrySize, true)
|
f.metadata.setFlushOffset(31*indexEntrySize, true)
|
||||||
|
|
||||||
f, err = newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), fileSize, true, false)
|
f, err = newTable(os.TempDir(), fn, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), fileSize, freezerTableConfig{noSnappy: true}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var freezerTestTableDef = map[string]bool{"test": true}
|
var freezerTestTableDef = map[string]freezerTableConfig{"test": {noSnappy: true}}
|
||||||
|
|
||||||
func TestFreezerModify(t *testing.T) {
|
func TestFreezerModify(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
@ -47,7 +47,7 @@ func TestFreezerModify(t *testing.T) {
|
||||||
valuesRLP = append(valuesRLP, iv)
|
valuesRLP = append(valuesRLP, iv)
|
||||||
}
|
}
|
||||||
|
|
||||||
tables := map[string]bool{"raw": true, "rlp": false}
|
tables := map[string]freezerTableConfig{"raw": {noSnappy: true}, "rlp": {noSnappy: false}}
|
||||||
f, _ := newFreezerForTesting(t, tables)
|
f, _ := newFreezerForTesting(t, tables)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
|
@ -111,7 +111,7 @@ func TestFreezerModifyRollback(t *testing.T) {
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
// Reopen and check that the rolled-back data doesn't reappear.
|
// Reopen and check that the rolled-back data doesn't reappear.
|
||||||
tables := map[string]bool{"test": true}
|
tables := map[string]freezerTableConfig{"test": {noSnappy: true}}
|
||||||
f2, err := NewFreezer(dir, "", false, 2049, tables)
|
f2, err := NewFreezer(dir, "", false, 2049, tables)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't reopen freezer after failed ModifyAncients: %v", err)
|
t.Fatalf("can't reopen freezer after failed ModifyAncients: %v", err)
|
||||||
|
|
@ -249,7 +249,7 @@ func TestFreezerConcurrentModifyTruncate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFreezerReadonlyValidate(t *testing.T) {
|
func TestFreezerReadonlyValidate(t *testing.T) {
|
||||||
tables := map[string]bool{"a": true, "b": true}
|
tables := map[string]freezerTableConfig{"a": {noSnappy: true}, "b": {noSnappy: true}}
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
// Open non-readonly freezer and fill individual tables
|
// Open non-readonly freezer and fill individual tables
|
||||||
// with different amount of data.
|
// with different amount of data.
|
||||||
|
|
@ -285,7 +285,7 @@ func TestFreezerReadonlyValidate(t *testing.T) {
|
||||||
func TestFreezerConcurrentReadonly(t *testing.T) {
|
func TestFreezerConcurrentReadonly(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
tables := map[string]bool{"a": true}
|
tables := map[string]freezerTableConfig{"a": {noSnappy: true}}
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
|
|
||||||
f, err := NewFreezer(dir, "", false, 2049, tables)
|
f, err := NewFreezer(dir, "", false, 2049, tables)
|
||||||
|
|
@ -333,7 +333,7 @@ func TestFreezerConcurrentReadonly(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFreezerForTesting(t *testing.T, tables map[string]bool) (*Freezer, string) {
|
func newFreezerForTesting(t *testing.T, tables map[string]freezerTableConfig) (*Freezer, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
|
|
@ -379,7 +379,7 @@ func checkAncientCount(t *testing.T, f *Freezer, kind string, n uint64) {
|
||||||
|
|
||||||
func TestFreezerCloseSync(t *testing.T) {
|
func TestFreezerCloseSync(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
f, _ := newFreezerForTesting(t, map[string]bool{"a": true, "b": true})
|
f, _ := newFreezerForTesting(t, map[string]freezerTableConfig{"a": {noSnappy: true}, "b": {noSnappy: true}})
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
// Now, close and sync. This mimics the behaviour if the node is shut down,
|
// Now, close and sync. This mimics the behaviour if the node is shut down,
|
||||||
|
|
@ -401,17 +401,23 @@ func TestFreezerCloseSync(t *testing.T) {
|
||||||
|
|
||||||
func TestFreezerSuite(t *testing.T) {
|
func TestFreezerSuite(t *testing.T) {
|
||||||
ancienttest.TestAncientSuite(t, func(kinds []string) ethdb.AncientStore {
|
ancienttest.TestAncientSuite(t, func(kinds []string) ethdb.AncientStore {
|
||||||
tables := make(map[string]bool)
|
tables := make(map[string]freezerTableConfig)
|
||||||
for _, kind := range kinds {
|
for _, kind := range kinds {
|
||||||
tables[kind] = true
|
tables[kind] = freezerTableConfig{
|
||||||
|
noSnappy: true,
|
||||||
|
prunable: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
f, _ := newFreezerForTesting(t, tables)
|
f, _ := newFreezerForTesting(t, tables)
|
||||||
return f
|
return f
|
||||||
})
|
})
|
||||||
ancienttest.TestResettableAncientSuite(t, func(kinds []string) ethdb.ResettableAncientStore {
|
ancienttest.TestResettableAncientSuite(t, func(kinds []string) ethdb.ResettableAncientStore {
|
||||||
tables := make(map[string]bool)
|
tables := make(map[string]freezerTableConfig)
|
||||||
for _, kind := range kinds {
|
for _, kind := range kinds {
|
||||||
tables[kind] = true
|
tables[kind] = freezerTableConfig{
|
||||||
|
noSnappy: true,
|
||||||
|
prunable: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
f, _ := newResettableFreezer(t.TempDir(), "", false, 2048, tables)
|
f, _ := newResettableFreezer(t.TempDir(), "", false, 2048, tables)
|
||||||
return f
|
return f
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue