AssembleTaprootScriptTree constructs a new fully indexed tapscript tree given a series of leaf nodes. A combination of a recursive data structure, and an array-based representation are used to both generate the tree and also accumulate all the necessary inclusion proofs in the same path. See the com
(leaves ...TapLeaf)
| 624 | // also accumulate all the necessary inclusion proofs in the same path. See the |
| 625 | // comment of blockchain.BuildMerkleTreeStore for further details. |
| 626 | func AssembleTaprootScriptTree(leaves ...TapLeaf) *IndexedTapScriptTree { |
| 627 | // If there's only a single leaf, then that becomes our root. |
| 628 | if len(leaves) == 1 { |
| 629 | // A lone leaf has no additional inclusion proof, as a verifier |
| 630 | // will just hash the leaf as the sole branch. |
| 631 | leaf := leaves[0] |
| 632 | return &IndexedTapScriptTree{ |
| 633 | RootNode: leaf, |
| 634 | LeafProofIndex: map[chainhash.Hash]int{ |
| 635 | leaf.TapHash(): 0, |
| 636 | }, |
| 637 | LeafMerkleProofs: []TapscriptProof{ |
| 638 | { |
| 639 | TapLeaf: leaf, |
| 640 | RootNode: leaf, |
| 641 | InclusionProof: nil, |
| 642 | }, |
| 643 | }, |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | // We'll start out by populating the leaf index which maps a leave's |
| 648 | // taphash to its index within the tree. |
| 649 | scriptTree := NewIndexedTapScriptTree(len(leaves)) |
| 650 | for i, leaf := range leaves { |
| 651 | leafHash := leaf.TapHash() |
| 652 | scriptTree.LeafProofIndex[leafHash] = i |
| 653 | } |
| 654 | |
| 655 | var branches []TapBranch |
| 656 | for i := 0; i < len(leaves); i += 2 { |
| 657 | // If there's only a single leaf left, then we'll merge this |
| 658 | // with the last branch we have. |
| 659 | if i == len(leaves)-1 { |
| 660 | branchToMerge := branches[len(branches)-1] |
| 661 | leaf := leaves[i] |
| 662 | newBranch := NewTapBranch(branchToMerge, leaf) |
| 663 | |
| 664 | branches[len(branches)-1] = newBranch |
| 665 | |
| 666 | // The leaf includes the existing branch within its |
| 667 | // inclusion proof. |
| 668 | branchHash := branchToMerge.TapHash() |
| 669 | |
| 670 | scriptTree.LeafMerkleProofs[i].TapLeaf = leaf |
| 671 | scriptTree.LeafMerkleProofs[i].InclusionProof = append( |
| 672 | scriptTree.LeafMerkleProofs[i].InclusionProof, |
| 673 | branchHash[:]..., |
| 674 | ) |
| 675 | |
| 676 | // We'll also add this right hash to the inclusion of |
| 677 | // the left and right nodes of the branch. |
| 678 | lastLeafHash := leaf.TapHash() |
| 679 | |
| 680 | leftLeafHash := branchToMerge.Left().TapHash() |
| 681 | leftLeafIndex := scriptTree.LeafProofIndex[leftLeafHash] |
| 682 | scriptTree.LeafMerkleProofs[leftLeafIndex].InclusionProof = append( |
| 683 | scriptTree.LeafMerkleProofs[leftLeafIndex].InclusionProof, |
searching dependent graphs…