Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2d47fde
move inline string ABIs to separate files and embed them (#383)
ceyonur Dec 2, 2022
557d1f4
Merge branch 'master' into precompile-improvements-main
ceyonur Dec 16, 2022
77ce3c3
replace getByKey with getByAddress (#395)
ceyonur Dec 22, 2022
e3b7ff3
Merge branch 'master' into precompile-improvements-main
ceyonur Dec 27, 2022
9e5c8c4
rework on panics in precompiles (#418)
ceyonur Dec 27, 2022
8868a99
Precompile Specific Packages (#420)
ceyonur Jan 6, 2023
357d9e6
rename fee manager config struct (#427)
ceyonur Jan 12, 2023
1add41a
Generalized upgrades rb (#434)
ceyonur Feb 16, 2023
6770536
Precompile improvements merge (#513)
aaronbuchwald Feb 16, 2023
7f4c66b
review fixes
ceyonur Feb 16, 2023
aa152c9
merge
Feb 16, 2023
77751e4
minor nits
Feb 16, 2023
ce23fca
fix precompile generator
ceyonur Feb 16, 2023
4bd2442
Merge branch 'precompile-improvements-main' of github.com:ava-labs/su…
ceyonur Feb 16, 2023
f806ad4
fix fee manager config test
ceyonur Feb 16, 2023
ea3c13b
remove debug files
ceyonur Feb 16, 2023
39e16d8
Update core/state_processor.go
ceyonur Feb 17, 2023
9a63a87
fix comments
ceyonur Feb 17, 2023
c9a5811
restore statedb ordering
ceyonur Feb 17, 2023
9868f4e
Merge branch 'precompile-improvements-main' of github.com:ava-labs/su…
ceyonur Feb 17, 2023
81fb4a9
fix configure in reward manager
ceyonur Feb 17, 2023
d518651
precompiles: adds a regression test for the IsDisabled case in Avalan…
Feb 17, 2023
c81b44b
Rename configs: alternative (#520)
Feb 17, 2023
7f13c45
Merge branch 'master' into precompile-improvements-main
aaronbuchwald Feb 17, 2023
aa6842d
move blackhole check to module registerer (#523)
ceyonur Feb 17, 2023
8ca09a3
precompile: improve test structure (#517)
Feb 18, 2023
1b995e2
Merge branch 'master' into precompile-improvements-main
aaronbuchwald Feb 21, 2023
e8b55cf
Merge branch 'master' into precompile-improvements-main
aaronbuchwald Feb 21, 2023
c5c1017
nit improvements (#529)
ceyonur Feb 21, 2023
9059a09
Rename new config (#528)
ceyonur Feb 21, 2023
9a8a85d
precompile: just nits (#534)
Feb 22, 2023
c004080
Merge branch 'master' into precompile-improvements-main
ceyonur Feb 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 15 additions & 61 deletions accounts/abi/bind/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ const (
readAllowListFuncKey = "readAllowList"
)

type BindHook func(lang Lang, pkg string, types []string, contracts map[string]*tmplContract, structs map[string]*tmplStruct) (data interface{}, templateSource string, err error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a comment to describe the Bindhook?


// Lang is a target programming language selector to generate bindings for.
type Lang int

Expand Down Expand Up @@ -101,7 +103,11 @@ func isKeyWord(arg string) bool {
// 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, libs map[string]string, aliases map[string]string, isPrecompile bool) (string, error) {
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) {
return bindHelper(types, abis, bytecodes, fsigs, pkg, lang, libs, aliases, nil)
}

func bindHelper(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string, aliases map[string]string, bindHook BindHook) (string, error) {
var (
// contracts is the map of each individual contract requested binding
contracts = make(map[string]*tmplContract)
Expand Down Expand Up @@ -155,7 +161,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
normalizedName := methodNormalizer[lang](alias(aliases, original.Name))

// Ensure there is no duplicated identifier
var identifiers = callIdentifiers
identifiers := callIdentifiers

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: undo unneeded change

if !original.IsConstant() {
identifiers = transactIdentifiers
}
Expand All @@ -178,11 +184,6 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
normalized.Outputs = make([]abi.Argument, len(original.Outputs))
copy(normalized.Outputs, original.Outputs)
for j, output := range normalized.Outputs {
if isPrecompile {
if output.Name == "" {
return "", fmt.Errorf("ABI outputs for %s require a name to generate the precompile binding, re-generate the ABI from a Solidity source file with all named outputs", normalized.Name)
}
}
if output.Name != "" {
normalized.Outputs[j].Name = capitalise(output.Name)
}
Expand Down Expand Up @@ -291,19 +292,14 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
templateSource string
)

// Generate the contract template data according to contract type (precompile/non)
if isPrecompile {
if lang != LangGo {
return "", errors.New("only GoLang binding for precompiled contracts is supported yet")
}

if len(contracts) != 1 {
return "", errors.New("cannot generate more than 1 contract")
// Generate the contract template data according to hook
if bindHook != nil {
var err error
data, templateSource, err = bindHook(lang, pkg, types, contracts, structs)
if err != nil {
return "", err
}
precompileType := types[0]
firstContract := contracts[precompileType]
data, templateSource = createPrecompileDataAndTemplate(firstContract, structs)
} else {
} else { // default to generate contract binding
templateSource = tmplSource[lang]
data = &tmplData{
Package: pkg,
Expand Down Expand Up @@ -710,45 +706,3 @@ func hasStruct(t abi.Type) bool {
return false
}
}

func createPrecompileDataAndTemplate(contract *tmplContract, structs map[string]*tmplStruct) (interface{}, string) {
funcs := make(map[string]*tmplMethod)

for k, v := range contract.Transacts {
funcs[k] = v
}

for k, v := range contract.Calls {
funcs[k] = v
}
isAllowList := allowListEnabled(funcs)
if isAllowList {
// remove these functions as we will directly inherit AllowList
delete(funcs, readAllowListFuncKey)
delete(funcs, setAdminFuncKey)
delete(funcs, setEnabledFuncKey)
delete(funcs, setNoneFuncKey)
}

precompileContract := &tmplPrecompileContract{
tmplContract: contract,
AllowList: isAllowList,
Funcs: funcs,
}

data := &tmplPrecompileData{
Contract: precompileContract,
Structs: structs,
}
return data, tmplSourcePrecompileGo
}

func allowListEnabled(funcs map[string]*tmplMethod) bool {
keys := []string{readAllowListFuncKey, setAdminFuncKey, setEnabledFuncKey, setNoneFuncKey}
for _, key := range keys {
if _, ok := funcs[key]; !ok {
return false
}
}
return true
}
4 changes: 2 additions & 2 deletions accounts/abi/bind/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2099,7 +2099,7 @@ func golangBindings(t *testing.T, overload bool) {
types = []string{tt.name}
}
// 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, false)
bind, err := Bind(types, tt.abi, tt.bytecode, tt.fsigs, "bindtest", LangGo, tt.libs, tt.aliases)
if err != nil {
t.Fatalf("test %d: failed to generate binding: %v", i, err)
}
Expand Down Expand Up @@ -2529,7 +2529,7 @@ public class Test {
},
}
for i, c := range cases {
binding, err := Bind([]string{c.name}, []string{c.abi}, []string{c.bytecode}, nil, "bindtest", LangJava, nil, nil, false)
binding, err := Bind([]string{c.name}, []string{c.abi}, []string{c.bytecode}, nil, "bindtest", LangJava, nil, nil)
if err != nil {
t.Fatalf("test %d: failed to generate binding: %v", i, err)
}
Expand Down
123 changes: 123 additions & 0 deletions accounts/abi/bind/precompile_bind.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// (c) 2019-2020, Ava Labs, Inc.
//
// This file is a derived work, based on the go-ethereum library whose original
// notices appear below.
//
// It is distributed under a license compatible with the licensing terms of the
// original code from which it is derived.
//
// Much love to the original authors for their work.
// **********
// 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 generates Ethereum contract Go bindings.
//
// 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
package bind

import (
"errors"
"fmt"
)

// PrecompileBind generates a Go binding for a precompiled contract. It returns config binding and contract binding.
func PrecompileBind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string, aliases map[string]string, abifilename string) (string, string, error) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can re call fsigs something more descriptive such as fnSigs or funcSigs?

// create hooks
configHook := createPrecompileHook(abifilename, tmplSourcePrecompileConfigGo)
contractHook := createPrecompileHook(abifilename, tmplSourcePrecompileContractGo)

configBind, err := bindHelper(types, abis, bytecodes, fsigs, pkg, lang, libs, aliases, configHook)
if err != nil {
return "", "", err
}
contractBind, err := bindHelper(types, abis, bytecodes, fsigs, pkg, lang, libs, aliases, contractHook)

return configBind, contractBind, err
}

func createPrecompileHook(abifilename string, template string) BindHook {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we comment here to describe function as well?

var bindHook BindHook = func(lang Lang, pkg string, types []string, contracts map[string]*tmplContract, structs map[string]*tmplStruct) (interface{}, string, error) {
// verify first
if lang != LangGo {
return nil, "", errors.New("only GoLang binding for precompiled contracts is supported yet")
}

if len(types) != 1 {
return nil, "", errors.New("cannot generate more than 1 contract")
}
funcs := make(map[string]*tmplMethod)

contract := contracts[types[0]]

for k, v := range contract.Transacts {
if err := checkOutputName(*v); err != nil {
return nil, "", err
}
funcs[k] = v
}

for k, v := range contract.Calls {
if err := checkOutputName(*v); err != nil {
return nil, "", err
}
funcs[k] = v
}
isAllowList := allowListEnabled(funcs)
if isAllowList {
// remove these functions as we will directly inherit AllowList

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we expand this comment, what does it mean to "directly inherit" in this context?

delete(funcs, readAllowListFuncKey)
delete(funcs, setAdminFuncKey)
delete(funcs, setEnabledFuncKey)
delete(funcs, setNoneFuncKey)
}

precompileContract := &tmplPrecompileContract{
tmplContract: contract,
AllowList: isAllowList,
Funcs: funcs,
ABIFilename: abifilename,
}

data := &tmplPrecompileData{
Contract: precompileContract,
Structs: structs,
Package: pkg,
}
return data, template, nil
}
return bindHook
}

func allowListEnabled(funcs map[string]*tmplMethod) bool {
keys := []string{readAllowListFuncKey, setAdminFuncKey, setEnabledFuncKey, setNoneFuncKey}
for _, key := range keys {
if _, ok := funcs[key]; !ok {
return false
}
}
return true
}

func checkOutputName(method tmplMethod) error {
for _, output := range method.Original.Outputs {
if output.Name == "" {
return fmt.Errorf("ABI outputs for %s require a name to generate the precompile binding, re-generate the ABI from a Solidity source file with all named outputs", method.Original.Name)
}
}
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var bindFailedTests = []struct {
{"type":"function","name":"anonOutput","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"}]}
]
`},
"ABI outputs for AnonOutput require a name to generate the precompile binding, re-generate the ABI from a Solidity source file with all named outputs",
"ABI outputs for anonOutput require a name to generate the precompile binding, re-generate the ABI from a Solidity source file with all named outputs",
nil,
nil,
nil,
Expand All @@ -64,7 +64,7 @@ var bindFailedTests = []struct {
{"type":"function","name":"anonOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"","type":"string"}]}
]
`},
"ABI outputs for AnonOutputs require a name to generate the precompile binding, re-generate the ABI from a Solidity source file with all named outputs",
"ABI outputs for anonOutputs require a name to generate the precompile binding, re-generate the ABI from a Solidity source file with all named outputs",
nil,
nil,
nil,
Expand All @@ -79,7 +79,7 @@ var bindFailedTests = []struct {
{"type":"function","name":"mixedOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"str","type":"string"}]}
]
`},
"ABI outputs for MixedOutputs require a name to generate the precompile binding, re-generate the ABI from a Solidity source file with all named outputs",
"ABI outputs for mixedOutputs require a name to generate the precompile binding, re-generate the ABI from a Solidity source file with all named outputs",
nil,
nil,
nil,
Expand All @@ -96,7 +96,7 @@ func golangBindingsFailure(t *testing.T) {
for i, tt := range bindFailedTests {
t.Run(tt.name, func(t *testing.T) {
// Generate the binding
_, err := Bind([]string{tt.name}, tt.abi, tt.bytecode, tt.fsigs, "bindtest", LangGo, tt.libs, tt.aliases, true)
_, _, err := PrecompileBind([]string{tt.name}, tt.abi, tt.bytecode, tt.fsigs, "bindtest", LangGo, tt.libs, tt.aliases, "")
if err == nil {
t.Fatalf("test %d: no error occurred but was expected", i)
}
Expand Down
Loading