From fb26a5843e2613635fd97efc84529d3adca169ff Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Tue, 7 Jan 2025 17:52:03 +0700 Subject: [PATCH] address some recent feedback. add docs about what the binder and contractBinder structs are used for. --- accounts/abi/bind/bindv2.go | 64 ++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/accounts/abi/bind/bindv2.go b/accounts/abi/bind/bindv2.go index 55e91b18e7..ee624b3cc5 100644 --- a/accounts/abi/bind/bindv2.go +++ b/accounts/abi/bind/bindv2.go @@ -3,7 +3,6 @@ package bind import ( "bytes" "fmt" - "github.com/ethereum/go-ethereum/accounts/abi" "go/format" "reflect" "regexp" @@ -11,6 +10,8 @@ import ( "strings" "text/template" "unicode" + + "github.com/ethereum/go-ethereum/accounts/abi" ) // underlyingBindType returns the underlying Go type represented by the given type, panicking if it is not a pointer type. @@ -27,8 +28,23 @@ func isPointerType(typ abi.Type) bool { return typ.GetType().Kind() == reflect.Pointer } +// 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. type binder struct { - // contracts is the map of each individual contract requested binding + // 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 redeclared structs shared by passed contracts. @@ -38,33 +54,15 @@ type binder struct { aliases map[string]string } -// registerIdentifier applies alias renaming, name normalization (conversion 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 (b *contractBinder) registerIdentifier(identifiers map[string]bool, original string) (normalized string, err error) { - normalized = abi.ToCamelCase(alias(b.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 -} - // BindStructType register 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 +// 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. +// It also sanitizes/converts information contained in the ABI definition into a data-format that is amenable for rendering the templates. type contractBinder struct { binder *binder calls map[string]*tmplMethod @@ -88,6 +86,26 @@ func newContractBinder(binder *binder) *contractBinder { } } +// registerIdentifier applies alias renaming, name normalization (conversion 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 (b *contractBinder) registerIdentifier(identifiers map[string]bool, original string) (normalized string, err error) { + normalized = abi.ToCamelCase(alias(b.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.