diff --git a/accounts/abi/bind/v2/contract_linking_test.go b/accounts/abi/bind/v2/contract_linking_test.go index 81266800dc..30e10d215f 100644 --- a/accounts/abi/bind/v2/contract_linking_test.go +++ b/accounts/abi/bind/v2/contract_linking_test.go @@ -155,7 +155,6 @@ func testLinkCase(t *testing.T, tcInput linkTestCaseInput) { } func TestContractLinking(t *testing.T) { - testLinkCase(t, linkTestCaseInput{ map[rune][]rune{ 'a': {'b', 'c', 'd', 'e'}}, @@ -240,14 +239,15 @@ func TestContractLinking(t *testing.T) { map[rune]struct{}{'a': {}}, map[rune]struct{}{}}) - // two contracts share some dependencies. one contract is marked as an override. all dependencies for the non-override - // contract will be deployed + // two contracts share some dependencies. one contract is marked as an override. only the override contract + // is not deployed. its dependencies are all deployed (even the ones not used by f), and the ones shared with f + // are not redeployed testLinkCase(t, linkTestCaseInput{map[rune][]rune{ 'a': {'b', 'c', 'd', 'e'}, 'f': {'g', 'c', 'd', 'h'}}, map[rune]struct{}{'a': {}}, map[rune]struct{}{ - 'f': {}, 'g': {}, 'c': {}, 'd': {}, 'h': {}, + 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, }}) // test nested libraries that share deps at different levels of the tree... with override. @@ -260,7 +260,7 @@ func TestContractLinking(t *testing.T) { 'i': {}, }, map[rune]struct{}{ - 'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'm': {}, + 'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'j': {}, 'k': {}, 'l': {}, 'm': {}, }}) // TODO: same as the above case but nested one level of dependencies deep (?) } diff --git a/accounts/abi/bind/v2/lib.go b/accounts/abi/bind/v2/lib.go index b3a064ba24..b7e65b2b13 100644 --- a/accounts/abi/bind/v2/lib.go +++ b/accounts/abi/bind/v2/lib.go @@ -95,7 +95,13 @@ func (d *depTreeBuilder) buildDepTrees(pattern, contract string) { if _, ok := d.subtrees[depPattern]; ok { continue } + if _, ok := d.overrides[depPattern]; ok { + continue + } + + // this library was referenced by another contract. it's not a dependency tree root. delete(d.roots, depPattern) + d.buildDepTrees(depPattern, d.contracts[depPattern]) node.nodes = append(node.nodes, d.subtrees[depPattern]) } @@ -103,25 +109,16 @@ func (d *depTreeBuilder) buildDepTrees(pattern, contract string) { } func (d *depTreeBuilder) BuildDepTrees() (roots []*depTreeNode) { - for pattern, _ := range d.contracts { - d.roots[pattern] = struct{}{} - } for pattern, contract := range d.contracts { if _, ok := d.subtrees[pattern]; ok { continue } - reMatchSpecificPattern, err := regexp.Compile("__\\$([a-f0-9]+)\\$__") - if err != nil { - panic(err) - } - for _, match := range reMatchSpecificPattern.FindAllStringSubmatch(contract, -1) { - depPattern := match[1] - delete(d.roots, depPattern) - if _, ok := d.subtrees[depPattern]; ok { - continue - } - d.buildDepTrees(depPattern, d.contracts[depPattern]) + if _, ok := d.overrides[pattern]; ok { + continue } + // pattern has not been explored, it's potentially a root + d.roots[pattern] = struct{}{} + d.buildDepTrees(pattern, contract) } for pattern, _ := range d.roots { roots = append(roots, d.subtrees[pattern]) @@ -184,16 +181,21 @@ func LinkAndDeploy(deployParams DeploymentParams, deploy func(input, deployer [] treeBuilder := depTreeBuilder{ overrides: deployParams.Overrides, contracts: unlinkedContracts, + subtrees: make(map[string]*depTreeNode), + roots: make(map[string]struct{}), } deps := treeBuilder.BuildDepTrees() for _, tr := range deps { // TODO: instantiate deployer with its tree? + deployer := treeDeployer{ deploy: deploy, deployedAddrs: make(map[string]common.Address), - deployerTxs: make(map[string]*types.Transaction), - input: map[string][]byte{tr.pattern: deployParams.Inputs[tr.pattern]}} + deployerTxs: make(map[string]*types.Transaction)} + if deployParams.Inputs != nil { + deployer.input = map[string][]byte{tr.pattern: deployParams.Inputs[tr.pattern]} + } deployer.linkAndDeploy(tr) res, err := deployer.Result() if err != nil {