rework contract deployment API
This commit is contained in:
parent
cc04aa4e9e
commit
5ba939f50c
|
@ -38,9 +38,9 @@ var (
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $contract := .Contracts}}
|
{{range $contract := .Contracts}}
|
||||||
var {{$contract.Type}}LibraryDeps = map[string]*bind.MetaData{
|
var {{$contract.Type}}LibraryDeps = map[string]string{
|
||||||
{{range $name, $pattern := .AllLibraries -}}
|
{{range $name, $pattern := .AllLibraries -}}
|
||||||
"{{$pattern}}": {{$name}}MetaData,
|
"{{$name}}": "{{$pattern}}",
|
||||||
{{ end}}
|
{{ end}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,19 +18,26 @@ type ContractInstance struct {
|
||||||
Backend bind.ContractBackend
|
Backend bind.ContractBackend
|
||||||
}
|
}
|
||||||
|
|
||||||
func deployDeps(backend bind.ContractBackend, auth *bind.TransactOpts, constructorInputs map[string][]byte, contracts map[string]string) (deploymentTxs map[common.Address]*types.Transaction, deployAddrs map[common.Address]struct{}, err error) {
|
func deployContract(backend bind.ContractBackend, auth *bind.TransactOpts, constructor []byte, contract string) (deploymentTx *types.Transaction, deploymentAddr common.Address, err error) {
|
||||||
for pattern, contractBin := range contracts {
|
contractBinBytes, err := hex.DecodeString(contract[2:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, common.Address{}, fmt.Errorf("contract bytecode is not a hex string: %s", contractBinBytes[2:])
|
||||||
|
}
|
||||||
|
addr, tx, _, err := bind.DeployContractRaw(auth, contractBinBytes, backend, constructor)
|
||||||
|
if err != nil {
|
||||||
|
return nil, common.Address{}, fmt.Errorf("failed to deploy contract: %v", err)
|
||||||
|
}
|
||||||
|
return tx, addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deployLibs(backend bind.ContractBackend, auth *bind.TransactOpts, contracts map[string]string) (deploymentTxs map[common.Address]*types.Transaction, deployAddrs map[common.Address]struct{}, err error) {
|
||||||
|
for _, contractBin := range contracts {
|
||||||
contractBinBytes, err := hex.DecodeString(contractBin[2:])
|
contractBinBytes, err := hex.DecodeString(contractBin[2:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return deploymentTxs, deployAddrs, fmt.Errorf("contract bytecode is not a hex string: %s", contractBin[2:])
|
return deploymentTxs, deployAddrs, fmt.Errorf("contract bytecode is not a hex string: %s", contractBin[2:])
|
||||||
}
|
}
|
||||||
var constructorInput []byte
|
// TODO: can pass nil for constructor?
|
||||||
if inp, ok := constructorInputs[pattern]; ok {
|
addr, tx, _, err := bind.DeployContractRaw(auth, contractBinBytes, backend, []byte{})
|
||||||
constructorInput = inp
|
|
||||||
} else {
|
|
||||||
constructorInput = make([]byte, 0) // TODO check if we can pass a nil byte slice here.
|
|
||||||
}
|
|
||||||
addr, tx, _, err := bind.DeployContractRaw(auth, contractBinBytes, backend, constructorInput)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return deploymentTxs, deployAddrs, fmt.Errorf("failed to deploy contract: %v", err)
|
return deploymentTxs, deployAddrs, fmt.Errorf("failed to deploy contract: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +48,22 @@ func deployDeps(backend bind.ContractBackend, auth *bind.TransactOpts, construct
|
||||||
return deploymentTxs, deployAddrs, nil
|
return deploymentTxs, deployAddrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkDeps(deps *map[string]string, linked *map[string]common.Address) (deployableDeps map[string]string) {
|
func linkContract(contract string, linkedLibs map[string]common.Address) (deployableContract string, err error) {
|
||||||
|
reMatchSpecificPattern, err := regexp.Compile("__\\$([a-f0-9]+)\\$__")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// link in any library the contract depends on
|
||||||
|
for _, match := range reMatchSpecificPattern.FindAllStringSubmatch(contract, -1) {
|
||||||
|
matchingPattern := match[1]
|
||||||
|
addr := linkedLibs[matchingPattern]
|
||||||
|
contract = strings.ReplaceAll(contract, matchingPattern, addr.String())
|
||||||
|
}
|
||||||
|
return contract, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func linkLibs(deps *map[string]string, linked *map[string]common.Address) (deployableDeps map[string]string) {
|
||||||
reMatchSpecificPattern, err := regexp.Compile("__\\$([a-f0-9]+)\\$__")
|
reMatchSpecificPattern, err := regexp.Compile("__\\$([a-f0-9]+)\\$__")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -72,25 +94,23 @@ func linkDeps(deps *map[string]string, linked *map[string]common.Address) (deplo
|
||||||
return deployableDeps
|
return deployableDeps
|
||||||
}
|
}
|
||||||
|
|
||||||
func LinkAndDeployContractsWithOverride(auth *bind.TransactOpts, backend bind.ContractBackend, constructorInputs map[string][]byte, contracts, libs map[string]string, overrides map[string]common.Address) (allDeployTxs map[common.Address]*types.Transaction, allDeployAddrs map[common.Address]struct{}, err error) {
|
func LinkAndDeployContractWithOverrides(auth *bind.TransactOpts, backend bind.ContractBackend, constructorInputs []byte, contract *bind.MetaData, libs map[string]string, overrides map[string]common.Address) (allDeployTxs map[common.Address]*types.Transaction, allDeployAddrs map[common.Address]struct{}, err error) {
|
||||||
var depsToDeploy map[string]string // map of pattern -> unlinked binary for deps we will deploy
|
|
||||||
|
|
||||||
// initialize the set of already-deployed contracts with given override addresses
|
// initialize the set of already-deployed contracts with given override addresses
|
||||||
linked := make(map[string]common.Address)
|
linked := make(map[string]common.Address)
|
||||||
for pattern, deployAddr := range overrides {
|
for pattern, deployAddr := range overrides {
|
||||||
linked[pattern] = deployAddr
|
linked[pattern] = deployAddr
|
||||||
if _, ok := contracts[pattern]; ok {
|
if _, ok := libs[pattern]; ok {
|
||||||
delete(contracts, pattern)
|
delete(libs, pattern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// link and deploy dynamic libraries
|
// link and deploy dynamic libraries
|
||||||
for {
|
for {
|
||||||
deployableDeps := linkDeps(&depsToDeploy, &linked)
|
deployableDeps := linkLibs(&libs, &linked)
|
||||||
if len(deployableDeps) == 0 {
|
if len(deployableDeps) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
deployTxs, deployAddrs, err := deployDeps(backend, auth, constructorInputs, deployableDeps)
|
deployTxs, deployAddrs, err := deployLibs(backend, auth, deployableDeps)
|
||||||
for addr, _ := range deployAddrs {
|
for addr, _ := range deployAddrs {
|
||||||
allDeployAddrs[addr] = struct{}{}
|
allDeployAddrs[addr] = struct{}{}
|
||||||
}
|
}
|
||||||
|
@ -101,17 +121,14 @@ func LinkAndDeployContractsWithOverride(auth *bind.TransactOpts, backend bind.Co
|
||||||
return deployTxs, allDeployAddrs, err
|
return deployTxs, allDeployAddrs, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
linkedContract, err := linkContract(contract.Bin, linked)
|
||||||
|
if err != nil {
|
||||||
|
return allDeployTxs, allDeployAddrs, err
|
||||||
|
}
|
||||||
// link and deploy the contracts
|
// link and deploy the contracts
|
||||||
contractBins := make(map[string]string)
|
contractTx, contractAddr, err := deployContract(backend, auth, constructorInputs, linkedContract)
|
||||||
linkedContracts := linkDeps(&contractBins, &linked)
|
allDeployAddrs[contractAddr] = struct{}{}
|
||||||
deployTxs, deployAddrs, err := deployDeps(backend, auth, constructorInputs, linkedContracts)
|
allDeployTxs[contractAddr] = contractTx
|
||||||
for addr, _ := range deployAddrs {
|
|
||||||
allDeployAddrs[addr] = struct{}{}
|
|
||||||
}
|
|
||||||
for addr, tx := range deployTxs {
|
|
||||||
allDeployTxs[addr] = tx
|
|
||||||
}
|
|
||||||
return allDeployTxs, allDeployAddrs, err
|
return allDeployTxs, allDeployAddrs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,12 +163,13 @@ func TestDeployment(t *testing.T) {
|
||||||
|
|
||||||
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stdout, log.LevelDebug, true)))
|
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stdout, log.LevelDebug, true)))
|
||||||
|
|
||||||
///LinkAndDeployContractsWithOverride(&opts, bindBackend, v2_test)
|
// TODO: add public interface for deploy library, deploy contract (or make them same method?)
|
||||||
deployTxs, err := DeployContracts(&opts, bindBackend, []byte{}, v2_testcase_library.TestArrayLibraryDeps)
|
// want to allow more flexibility.
|
||||||
|
txs, _, err := LinkAndDeployContractWithOverrides(&opts, bindBackend, []byte{}, v2_testcase_library.TestArrayMetaData, v2_testcase_library.TestArrayLibraryDeps, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %+v\n", err)
|
t.Fatalf("err: %+v\n", err)
|
||||||
}
|
}
|
||||||
for _, tx := range deployTxs {
|
for _, tx := range txs {
|
||||||
fmt.Println("waiting for deployment")
|
fmt.Println("waiting for deployment")
|
||||||
_, err = bind.WaitDeployed(context.Background(), &bindBackend, tx)
|
_, err = bind.WaitDeployed(context.Background(), &bindBackend, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue