mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
accounts/abi/bind: link dependent libs in deploy (#19718)
This commit is contained in:
parent
7455b91800
commit
993bc6963e
4 changed files with 206 additions and 51 deletions
|
|
@ -30,6 +30,7 @@ import (
|
|||
"unicode"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
)
|
||||
|
||||
// Lang is a target programming language selector to generate bindings for.
|
||||
|
|
@ -43,10 +44,13 @@ const (
|
|||
// to be used as is in client code, but rather as an intermediate struct which
|
||||
// enforces compile time type safety and naming convention opposed to having to
|
||||
// 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) (string, error) {
|
||||
func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string) (string, error) {
|
||||
// Process each individual contract requested binding
|
||||
contracts := make(map[string]*tmplContract)
|
||||
|
||||
// Map used to flag each encountered library as such
|
||||
isLib := make(map[string]struct{})
|
||||
|
||||
for i := 0; i < len(types); i++ {
|
||||
// Parse the actual ABI to generate the binding for
|
||||
evmABI, err := abi.JSON(strings.NewReader(abis[i]))
|
||||
|
|
@ -115,23 +119,47 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
|||
// Append the event to the accumulator list
|
||||
events[original.Name] = &tmplEvent{Original: original, Normalized: normalized}
|
||||
}
|
||||
|
||||
contracts[types[i]] = &tmplContract{
|
||||
Type: capitalise(types[i]),
|
||||
InputABI: strings.ReplaceAll(strippedABI, "\"", "\\\""),
|
||||
InputBin: strings.TrimSpace(bytecodes[i]),
|
||||
InputBin: strings.TrimPrefix(strings.TrimSpace(bytecodes[i]), "0x"),
|
||||
Constructor: evmABI.Constructor,
|
||||
Calls: calls,
|
||||
Transacts: transacts,
|
||||
Events: events,
|
||||
Libraries: make(map[string]string),
|
||||
}
|
||||
// Function 4-byte signatures are stored in the same sequence
|
||||
// as types, if available.
|
||||
if len(fsigs) > i {
|
||||
contracts[types[i]].FuncSigs = fsigs[i]
|
||||
}
|
||||
// Parse library references.
|
||||
for pattern, name := range libs {
|
||||
matched, err := regexp.Match("__\\$"+pattern+"\\$__", []byte(contracts[types[i]].InputBin))
|
||||
if err != nil {
|
||||
log.Error("Could not search for pattern", "pattern", pattern, "contract", contracts[types[i]], "err", err)
|
||||
}
|
||||
if matched {
|
||||
contracts[types[i]].Libraries[pattern] = name
|
||||
// keep track that this type is a library
|
||||
if _, ok := isLib[name]; !ok {
|
||||
isLib[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if that type has already been identified as a library
|
||||
for i := 0; i < len(types); i++ {
|
||||
_, ok := isLib[types[i]]
|
||||
contracts[types[i]].Library = ok
|
||||
}
|
||||
// Generate the contract template data content and render it
|
||||
data := &tmplData{
|
||||
Package: pkg,
|
||||
Contracts: contracts,
|
||||
Libraries: libs,
|
||||
}
|
||||
buffer := new(bytes.Buffer)
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -22,6 +22,7 @@ import "github.com/XinFinOrg/XDPoSChain/accounts/abi"
|
|||
type tmplData struct {
|
||||
Package string // Name of the package to place the generated file in
|
||||
Contracts map[string]*tmplContract // List of contracts to generate into this file
|
||||
Libraries map[string]string // Map the bytecode's link pattern to the library name
|
||||
}
|
||||
|
||||
// tmplContract contains the data needed to generate an individual contract binding.
|
||||
|
|
@ -34,6 +35,8 @@ type tmplContract struct {
|
|||
Calls map[string]*tmplMethod // Contract calls that only read state data
|
||||
Transacts map[string]*tmplMethod // Contract calls that write state data
|
||||
Events map[string]*tmplEvent // Contract events accessors
|
||||
Libraries map[string]string // Same as tmplData, but filtered to only keep what the contract needs
|
||||
Library bool
|
||||
}
|
||||
|
||||
// tmplMethod is a wrapper around an abi.Method that contains a few preprocessed
|
||||
|
|
@ -95,15 +98,14 @@ var (
|
|||
{{if $contract.FuncSigs}}
|
||||
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
|
||||
var {{.Type}}FuncSigs = map[string]string{
|
||||
{{range $strsig, $binsig := .FuncSigs}}
|
||||
"{{$binsig}}": "{{$strsig}}",
|
||||
{{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}",
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .InputBin}}
|
||||
// {{.Type}}Bin is the compiled bytecode used for deploying new contracts.
|
||||
const {{.Type}}Bin = ` + "`" + `{{.InputBin}}` + "`" + `
|
||||
var {{.Type}}Bin = "0x{{.InputBin}}"
|
||||
|
||||
// Deploy{{.Type}} deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
|
||||
func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) {
|
||||
|
|
@ -111,6 +113,10 @@ var (
|
|||
if err != nil {
|
||||
return common.Address{}, nil, nil, err
|
||||
}
|
||||
{{range $pattern, $name := .Libraries}}
|
||||
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend)
|
||||
{{$contract.Type}}Bin = strings.Replace({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:], -1)
|
||||
{{end}}
|
||||
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
|
||||
if err != nil {
|
||||
return common.Address{}, nil, nil, err
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/compiler"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
|
@ -136,6 +137,7 @@ func abigen(c *cli.Context) error {
|
|||
bins []string
|
||||
types []string
|
||||
sigs []map[string]string
|
||||
libs = make(map[string]string)
|
||||
)
|
||||
if c.String(solFlag.Name) != "" || c.String(vyFlag.Name) != "" || c.String(abiFlag.Name) == "-" {
|
||||
// Generate the list of types to exclude from binding
|
||||
|
|
@ -184,6 +186,9 @@ func abigen(c *cli.Context) error {
|
|||
|
||||
nameParts := strings.Split(name, ":")
|
||||
types = append(types, nameParts[len(nameParts)-1])
|
||||
|
||||
libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36]
|
||||
libs[libPattern] = nameParts[len(nameParts)-1]
|
||||
}
|
||||
} else {
|
||||
// Otherwise load up the ABI, optional bytecode and type name from the parameters
|
||||
|
|
@ -211,7 +216,7 @@ func abigen(c *cli.Context) error {
|
|||
types = append(types, kind)
|
||||
}
|
||||
// Generate the contract binding
|
||||
code, err := bind.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), lang)
|
||||
code, err := bind.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), lang, libs)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to generate ABI binding: %v\n", err)
|
||||
os.Exit(-1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue