From c293caade9424adda1a7f8f64d2b4277eb70d348 Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Tue, 10 Dec 2024 15:57:36 +0700 Subject: [PATCH] tests working now --- accounts/abi/bind/v2/contract_linking_test.go | 3 + accounts/abi/bind/v2/lib.go | 91 ++++++++++++------- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/accounts/abi/bind/v2/contract_linking_test.go b/accounts/abi/bind/v2/contract_linking_test.go index 30e10d215f..ffe157fc0a 100644 --- a/accounts/abi/bind/v2/contract_linking_test.go +++ b/accounts/abi/bind/v2/contract_linking_test.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "golang.org/x/exp/rand" + "runtime/debug" "testing" ) @@ -144,6 +145,7 @@ func testLinkCase(t *testing.T, tcInput linkTestCaseInput) { } if len(res.Addrs) != len(tcInput.expectDeployed) { + debug.PrintStack() t.Fatalf("got %d deployed contracts. expected %d.\n", len(res.Addrs), len(tcInput.expectDeployed)) } for contract, _ := range tcInput.expectDeployed { @@ -164,6 +166,7 @@ func TestContractLinking(t *testing.T) { }, }) + fmt.Println("2") testLinkCase(t, linkTestCaseInput{ map[rune][]rune{ 'a': {'b', 'c', 'd', 'e'}, diff --git a/accounts/abi/bind/v2/lib.go b/accounts/abi/bind/v2/lib.go index b7e65b2b13..c834e0b2d7 100644 --- a/accounts/abi/bind/v2/lib.go +++ b/accounts/abi/bind/v2/lib.go @@ -70,58 +70,66 @@ type depTreeBuilder struct { // map of pattern to unlinked contract bytecode (for libraries or contracts) contracts map[string]string // map of pattern to subtree represented by contract - subtrees map[string]*depTreeNode - + subtrees map[string]any // map of nodes that aren't referenced by other dependencies (these can be libraries too if user is doing lib-only deployment) roots map[string]struct{} } + type depTreeNode struct { pattern string unlinkedCode string - nodes []*depTreeNode + nodes []any +} + +type overrideNode struct { + pattern string + addr common.Address } func (d *depTreeBuilder) buildDepTrees(pattern, contract string) { - reMatchSpecificPattern, err := regexp.Compile("__\\$([a-f0-9]+)\\$__") - if err != nil { - panic(err) + // if the node is in the subtree set already, bail out early + if _, ok := d.subtrees[pattern]; ok { + return } - node := &depTreeNode{ - pattern: pattern, - unlinkedCode: contract, - } - for _, match := range reMatchSpecificPattern.FindAllStringSubmatch(contract, -1) { - depPattern := match[1] - if _, ok := d.subtrees[depPattern]; ok { - continue + if addr, ok := d.overrides[pattern]; ok { + node := &overrideNode{ + pattern: pattern, + addr: addr, } - if _, ok := d.overrides[depPattern]; ok { - continue + d.subtrees[pattern] = node + } else { + node := &depTreeNode{ + pattern: pattern, + unlinkedCode: contract, } + // if the node is an override node: add it to the node map but don't recurse on it. + // else if the node is depNode: recurse on it, and add it to the dep map. + reMatchSpecificPattern, err := regexp.Compile("__\\$([a-f0-9]+)\\$__") + if err != nil { + panic(err) + } + for _, match := range reMatchSpecificPattern.FindAllStringSubmatch(contract, -1) { + depPattern := match[1] + d.buildDepTrees(depPattern, d.contracts[depPattern]) + node.nodes = append(node.nodes, d.subtrees[depPattern]) - // 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]) + // this dep can't be a root dependency if it is referenced by other contracts. + delete(d.roots, depPattern) + } + d.subtrees[pattern] = node } - d.subtrees[pattern] = node } func (d *depTreeBuilder) BuildDepTrees() (roots []*depTreeNode) { for pattern, contract := range d.contracts { - if _, ok := d.subtrees[pattern]; ok { - continue - } - 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]) + switch node := d.subtrees[pattern].(type) { + case *depTreeNode: + roots = append(roots, node) + } } return roots } @@ -134,15 +142,28 @@ type treeDeployer struct { err error } -func (d *treeDeployer) linkAndDeploy(node *depTreeNode) { +func (d *treeDeployer) linkAndDeploy(n any) { + node, ok := n.(*depTreeNode) + if !ok { + // this was an override node + return + } + for _, childNode := range node.nodes { d.linkAndDeploy(childNode) } // link in all node dependencies and produce the deployer bytecode deployerCode := node.unlinkedCode + for _, c := range node.nodes { + switch child := c.(type) { + case *depTreeNode: + deployerCode = strings.ReplaceAll(deployerCode, "__$"+child.pattern+"$__", strings.ToLower(d.deployedAddrs[child.pattern].String()[2:])) + case *overrideNode: + deployerCode = strings.ReplaceAll(deployerCode, "__$"+child.pattern+"$__", strings.ToLower(child.addr.String()[2:])) + default: + panic("invalid node type") + } - for _, child := range node.nodes { - deployerCode = strings.ReplaceAll(deployerCode, "__$"+child.pattern+"$__", strings.ToLower(d.deployedAddrs[child.pattern].String()[2:])) } // deploy the contract. @@ -175,13 +196,13 @@ func LinkAndDeploy(deployParams DeploymentParams, deploy func(input, deployer [] Addrs: make(map[string]common.Address), } for _, meta := range deployParams.Contracts { - unlinkedContracts[meta.Pattern] = meta.Bin + unlinkedContracts[meta.Pattern] = meta.Bin[2:] } // TODO: instantiate this using constructor treeBuilder := depTreeBuilder{ overrides: deployParams.Overrides, contracts: unlinkedContracts, - subtrees: make(map[string]*depTreeNode), + subtrees: make(map[string]any), roots: make(map[string]struct{}), }