accounts/abi/bind: parse ABI once#22583
Conversation
|
What is the full example? I'm wondering about the scope, really, because |
|
Oh you're right, that will clash with other definitions |
|
How about something like this? That makes it still load dynamically, but does so thread-safe and does not clutter the global scope with a lot of random things. The package foo
type parsedAbi struct {
mu sync.Mutex
sigs map[string]string
bin []byte
ab *abi.ABI
}
func (p *parsedAbi) getAbi(source string) (*abi.ABI, error) {
p.mu.Lock()
defer p.mu.Unlock()
if p.ab != nil {
return p.ab
}
if parsed, err := abi.JSON(strings.NewReader(source)); err != nil {
return nil, err
} else {
p.ab = parsed
}
}
var reverter = &parsedAbi{
sigs: map[string]string{"7da3c3ab": "revert()"},
bin: common.FromHex("0x6080604052348015600f57600080fd5b5060ab8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80637da3c3ab14602d575b600080fd5b60336035565b005b6040805162461bcd60e51b815260206004820152601160248201527072657665727420726561736f6e2031323360781b604482015290519081900360640190fdfea265627a7a72315820e8c3f899c32798b10b8d46594292b9e3d2271f011100fb17b6d3a6469f50c8c964736f6c63430005100032"),
}
// DeployReverter deploys a new Ethereum contract, binding an instance of Reverter to it.
func DeployReverter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Reverter, error) {
rAbi, err := reverter.getAbi(ReverterABI)
if err != nil {
return common.Address{}, nil, nil, err
}
address, tx, contract, err := bind.DeployContract(auth, rAbi, rAbi.bin, backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &Reverter{ReverterCaller: ReverterCaller{contract: contract}, ReverterTransactor: ReverterTransactor{contract: contract}, ReverterFilterer: ReverterFilterer{contract: contract}}, nil
} |
|
@holiman I like it, however that would break the api as package foo
type ParsedAbi struct {
mu sync.Mutex
Sigs map[string]string
Bin []byte
ABI string
ab *abi.ABI
}
func (p *ParsedAbi) getAbi() (*abi.ABI, error) {
p.mu.Lock()
defer p.mu.Unlock()
if p.ab != nil {
return p.ab
}
if parsed, err := abi.JSON(strings.NewReader(p.ABI)); err != nil {
return nil, err
} else {
p.ab = parsed
}
}
// ReverterMetaData contains all meta data concerning the Reverter
var ReverterMetaData = &ParsedAbi{
Sigs: map[string]string{"7da3c3ab": "revert()"},
ABI: "[{\"constant\":false,\"inputs\":[],\"name\":\"revert\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
Bin: common.FromHex("0x6080604052348015600f57600080fd5b5060ab8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80637da3c3ab14602d575b600080fd5b60336035565b005b6040805162461bcd60e51b815260206004820152601160248201527072657665727420726561736f6e2031323360781b604482015290519081900360640190fdfea265627a7a72315820e8c3f899c32798b10b8d46594292b9e3d2271f011100fb17b6d3a6469f50c8c964736f6c63430005100032"),
}
// DeployReverter deploys a new Ethereum contract, binding an instance of Reverter to it.
func DeployReverter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Reverter, error) {
rAbi, err := ReverterMetaData.getAbi()
if err != nil {
return common.Address{}, nil, nil, err
}
address, tx, contract, err := bind.DeployContract(auth, rAbi, rAbi.Bin, backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &Reverter{ReverterCaller: ReverterCaller{contract: contract}, ReverterTransactor: ReverterTransactor{contract: contract}, ReverterFilterer: ReverterFilterer{contract: contract}}, nil
} |
|
Yeah, that looks good to me. If you don't want to break the api, maybe keep them, but remove then at some point? Something like: |
8319056 to
aa29458
Compare
aa29458 to
8d38133
Compare
This moves the initialization of the parsedABI object from the Deploy()
function into a var that gets executed on startup. This means deploying
the same contract multiple times becomes faster, as the ABI doesn't have
to be parsed every time. It does increase the memory usage by requiring
everyone to hold the ABI object in memory even if the contract is not
going to be deployed.
closes #22269
example: (updated)