github.com/btcsuite/btcd@v0.24.0/txscript/taproot.go (about) 1 // Copyright (c) 2013-2022 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package txscript 6 7 import ( 8 "bytes" 9 "fmt" 10 11 "github.com/btcsuite/btcd/btcec/v2" 12 "github.com/btcsuite/btcd/btcec/v2/schnorr" 13 "github.com/btcsuite/btcd/chaincfg/chainhash" 14 "github.com/btcsuite/btcd/wire" 15 secp "github.com/decred/dcrd/dcrec/secp256k1/v4" 16 ) 17 18 // TapscriptLeafVersion represents the various possible versions of a tapscript 19 // leaf version. Leaf versions are used to define, or introduce new script 20 // semantics, under the base taproot execution model. 21 // 22 // TODO(roasbeef): add validation here as well re proper prefix, etc? 23 type TapscriptLeafVersion uint8 24 25 const ( 26 // BaseLeafVersion is the base tapscript leaf version. The semantics of 27 // this version are defined in BIP 342. 28 BaseLeafVersion TapscriptLeafVersion = 0xc0 29 ) 30 31 const ( 32 // ControlBlockBaseSize is the base size of a control block. This 33 // includes the initial byte for the leaf version, and then serialized 34 // schnorr public key. 35 ControlBlockBaseSize = 33 36 37 // ControlBlockNodeSize is the size of a given merkle branch hash in 38 // the control block. 39 ControlBlockNodeSize = 32 40 41 // ControlBlockMaxNodeCount is the max number of nodes that can be 42 // included in a control block. This value represents a merkle tree of 43 // depth 2^128. 44 ControlBlockMaxNodeCount = 128 45 46 // ControlBlockMaxSize is the max possible size of a control block. 47 // This simulates revealing a leaf from the largest possible tapscript 48 // tree. 49 ControlBlockMaxSize = ControlBlockBaseSize + (ControlBlockNodeSize * 50 ControlBlockMaxNodeCount) 51 ) 52 53 // VerifyTaprootKeySpend attempts to verify a top-level taproot key spend, 54 // returning a non-nil error if the passed signature is invalid. If a sigCache 55 // is passed in, then the sig cache will be consulted to skip full verification 56 // of a signature that has already been seen. Witness program here should be 57 // the 32-byte x-only schnorr output public key. 58 // 59 // NOTE: The TxSigHashes MUST be passed in and fully populated. 60 func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, 61 inputIndex int, prevOuts PrevOutputFetcher, hashCache *TxSigHashes, 62 sigCache *SigCache) error { 63 64 // First, we'll need to extract the public key from the witness 65 // program. 66 rawKey := witnessProgram 67 68 // Extract the annex if it exists, so we can compute the proper proper 69 // sighash below. 70 var annex []byte 71 witness := tx.TxIn[inputIndex].Witness 72 if isAnnexedWitness(witness) { 73 annex, _ = extractAnnex(witness) 74 } 75 76 // Now that we have the public key, we can create a new top-level 77 // keyspend verifier that'll handle all the sighash and schnorr 78 // specifics for us. 79 keySpendVerifier, err := newTaprootSigVerifier( 80 rawKey, rawSig, tx, inputIndex, prevOuts, sigCache, 81 hashCache, annex, 82 ) 83 if err != nil { 84 return err 85 } 86 87 valid := keySpendVerifier.Verify() 88 if valid { 89 return nil 90 } 91 92 return scriptError(ErrTaprootSigInvalid, "") 93 } 94 95 // ControlBlock houses the structured witness input for a taproot spend. This 96 // includes the internal taproot key, the leaf version, and finally a nearly 97 // complete merkle inclusion proof for the main taproot commitment. 98 // 99 // TODO(roasbeef): method to serialize control block that commits to even 100 // y-bit, which pops up everywhere even tho 32 byte keys 101 type ControlBlock struct { 102 // InternalKey is the internal public key in the taproot commitment. 103 InternalKey *btcec.PublicKey 104 105 // OutputKeyYIsOdd denotes if the y coordinate of the output key (the 106 // key placed in the actual taproot output is odd. 107 OutputKeyYIsOdd bool 108 109 // LeafVersion is the specified leaf version of the tapscript leaf that 110 // the InclusionProof below is based off of. 111 LeafVersion TapscriptLeafVersion 112 113 // InclusionProof is a series of merkle branches that when hashed 114 // pairwise, starting with the revealed script, will yield the taproot 115 // commitment root. 116 InclusionProof []byte 117 } 118 119 // ToBytes returns the control block in a format suitable for using as part of 120 // a witness spending a tapscript output. 121 func (c *ControlBlock) ToBytes() ([]byte, error) { 122 var b bytes.Buffer 123 124 // The first byte of the control block is the leaf version byte XOR'd with 125 // the parity of the y coordinate of the public key. 126 yParity := byte(0) 127 if c.OutputKeyYIsOdd { 128 yParity = 1 129 } 130 131 // The first byte is a combination of the leaf version, using the lowest 132 // bit to encode the single bit that denotes if the yo coordinate if odd or 133 // even. 134 leafVersionAndParity := byte(c.LeafVersion) | yParity 135 if err := b.WriteByte(leafVersionAndParity); err != nil { 136 return nil, err 137 } 138 139 // Next, we encode the raw 32 byte schnorr public key 140 if _, err := b.Write(schnorr.SerializePubKey(c.InternalKey)); err != nil { 141 return nil, err 142 } 143 144 // Finally, we'll write out the inclusion proof as is, without any length 145 // prefix. 146 if _, err := b.Write(c.InclusionProof); err != nil { 147 return nil, err 148 } 149 150 return b.Bytes(), nil 151 } 152 153 // RootHash calculates the root hash of a tapscript given the revealed script. 154 func (c *ControlBlock) RootHash(revealedScript []byte) []byte { 155 // We'll start by creating a new tapleaf from the revealed script, 156 // this'll serve as the initial hash we'll use to incrementally 157 // reconstruct the merkle root using the control block elements. 158 merkleAccumulator := NewTapLeaf(c.LeafVersion, revealedScript).TapHash() 159 160 // Now that we have our initial hash, we'll parse the control block one 161 // node at a time to build up our merkle accumulator into the taproot 162 // commitment. 163 // 164 // The control block is a series of nodes that serve as an inclusion 165 // proof as we can start hashing with our leaf, with each internal 166 // branch, until we reach the root. 167 numNodes := len(c.InclusionProof) / ControlBlockNodeSize 168 for nodeOffset := 0; nodeOffset < numNodes; nodeOffset++ { 169 // Extract the new node using our index to serve as a 32-byte 170 // offset. 171 leafOffset := 32 * nodeOffset 172 nextNode := c.InclusionProof[leafOffset : leafOffset+32] 173 174 merkleAccumulator = tapBranchHash(merkleAccumulator[:], nextNode) 175 } 176 177 return merkleAccumulator[:] 178 } 179 180 // ParseControlBlock attempts to parse the raw bytes of a control block. An 181 // error is returned if the control block isn't well formed, or can't be 182 // parsed. 183 func ParseControlBlock(ctrlBlock []byte) (*ControlBlock, error) { 184 // The control block minimally must contain 33 bytes (for the leaf 185 // version and internal key) along with at least a single value 186 // comprising the merkle proof. If not, then it's invalid. 187 switch { 188 // The control block must minimally have 33 bytes for the internal 189 // public key and script leaf version. 190 case len(ctrlBlock) < ControlBlockBaseSize: 191 str := fmt.Sprintf("min size is %v bytes, control block "+ 192 "is %v bytes", ControlBlockBaseSize, len(ctrlBlock)) 193 return nil, scriptError(ErrControlBlockTooSmall, str) 194 195 // The control block can't be larger than a proof for the largest 196 // possible tapscript merkle tree with 2^128 leaves. 197 case len(ctrlBlock) > ControlBlockMaxSize: 198 str := fmt.Sprintf("max size is %v, control block is %v bytes", 199 ControlBlockMaxSize, len(ctrlBlock)) 200 return nil, scriptError(ErrControlBlockTooLarge, str) 201 202 // Ignoring the fixed sized portion, we expect the total number of 203 // remaining bytes to be a multiple of the node size, which is 32 204 // bytes. 205 case (len(ctrlBlock)-ControlBlockBaseSize)%ControlBlockNodeSize != 0: 206 str := fmt.Sprintf("control block proof is not a multiple "+ 207 "of 32: %v", len(ctrlBlock)-ControlBlockBaseSize) 208 return nil, scriptError(ErrControlBlockInvalidLength, str) 209 } 210 211 // With the basic sanity checking complete, we can now parse the 212 // control block. 213 leafVersion := TapscriptLeafVersion(ctrlBlock[0] & TaprootLeafMask) 214 215 // Extract the parity of the y coordinate of the internal key. 216 var yIsOdd bool 217 if ctrlBlock[0]&0x01 == 0x01 { 218 yIsOdd = true 219 } 220 221 // Next, we'll parse the public key, which is the 32 bytes following 222 // the leaf version. 223 rawKey := ctrlBlock[1:33] 224 pubKey, err := schnorr.ParsePubKey(rawKey) 225 if err != nil { 226 return nil, err 227 } 228 229 // The rest of the bytes are the control block itself, which encodes a 230 // merkle proof of inclusion. 231 proofBytes := ctrlBlock[33:] 232 233 return &ControlBlock{ 234 InternalKey: pubKey, 235 OutputKeyYIsOdd: yIsOdd, 236 LeafVersion: leafVersion, 237 InclusionProof: proofBytes, 238 }, nil 239 } 240 241 // ComputeTaprootOutputKey calculates a top-level taproot output key given an 242 // internal key, and tapscript merkle root. The final key is derived as: 243 // taprootKey = internalKey + (h_tapTweak(internalKey || merkleRoot)*G). 244 func ComputeTaprootOutputKey(pubKey *btcec.PublicKey, 245 scriptRoot []byte) *btcec.PublicKey { 246 247 // This routine only operates on x-only public keys where the public 248 // key always has an even y coordinate, so we'll re-parse it as such. 249 internalKey, _ := schnorr.ParsePubKey(schnorr.SerializePubKey(pubKey)) 250 251 // First, we'll compute the tap tweak hash that commits to the internal 252 // key and the merkle script root. 253 tapTweakHash := chainhash.TaggedHash( 254 chainhash.TagTapTweak, schnorr.SerializePubKey(internalKey), 255 scriptRoot, 256 ) 257 258 // With the tap tweek computed, we'll need to convert the merkle root 259 // into something in the domain we can manipulate: a scalar value mod 260 // N. 261 var tweakScalar btcec.ModNScalar 262 tweakScalar.SetBytes((*[32]byte)(tapTweakHash)) 263 264 // Next, we'll need to convert the internal key to jacobian coordinates 265 // as the routines we need only operate on this type. 266 var internalPoint btcec.JacobianPoint 267 internalKey.AsJacobian(&internalPoint) 268 269 // With our intermediate data obtained, we'll now compute: 270 // 271 // taprootKey = internalPoint + (tapTweak*G). 272 var tPoint, taprootKey btcec.JacobianPoint 273 btcec.ScalarBaseMultNonConst(&tweakScalar, &tPoint) 274 btcec.AddNonConst(&internalPoint, &tPoint, &taprootKey) 275 276 // Finally, we'll convert the key back to affine coordinates so we can 277 // return the format of public key we usually use. 278 taprootKey.ToAffine() 279 280 return btcec.NewPublicKey(&taprootKey.X, &taprootKey.Y) 281 } 282 283 // ComputeTaprootKeyNoScript calculates the top-level taproot output key given 284 // an internal key, and a desire that the only way an output can be spent is 285 // with the keyspend path. This is useful for normal wallet operations that 286 // don't need any other additional spending conditions. 287 func ComputeTaprootKeyNoScript(internalKey *btcec.PublicKey) *btcec.PublicKey { 288 // We'll compute a custom tap tweak hash that just commits to the key, 289 // rather than an actual root hash. 290 fakeScriptroot := []byte{} 291 292 return ComputeTaprootOutputKey(internalKey, fakeScriptroot) 293 } 294 295 // TweakTaprootPrivKey applies the same operation as ComputeTaprootOutputKey, 296 // but on the private key instead. The final key is derived as: privKey + 297 // h_tapTweak(internalKey || merkleRoot) % N, where N is the order of the 298 // secp256k1 curve, and merkleRoot is the root hash of the tapscript tree. 299 func TweakTaprootPrivKey(privKey btcec.PrivateKey, 300 scriptRoot []byte) *btcec.PrivateKey { 301 302 // If the corresponding public key has an odd y coordinate, then we'll 303 // negate the private key as specified in BIP 341. 304 privKeyScalar := privKey.Key 305 pubKeyBytes := privKey.PubKey().SerializeCompressed() 306 if pubKeyBytes[0] == secp.PubKeyFormatCompressedOdd { 307 privKeyScalar.Negate() 308 } 309 310 // Next, we'll compute the tap tweak hash that commits to the internal 311 // key and the merkle script root. We'll snip off the extra parity byte 312 // from the compressed serialization and use that directly. 313 schnorrKeyBytes := pubKeyBytes[1:] 314 tapTweakHash := chainhash.TaggedHash( 315 chainhash.TagTapTweak, schnorrKeyBytes, scriptRoot, 316 ) 317 318 // Map the private key to a ModNScalar which is needed to perform 319 // operation mod the curve order. 320 var tweakScalar btcec.ModNScalar 321 tweakScalar.SetBytes((*[32]byte)(tapTweakHash)) 322 323 // Now that we have the private key in its may negated form, we'll add 324 // the script root as a tweak. As we're using a ModNScalar all 325 // operations are already normalized mod the curve order. 326 privTweak := privKeyScalar.Add(&tweakScalar) 327 328 return btcec.PrivKeyFromScalar(privTweak) 329 } 330 331 // VerifyTaprootLeafCommitment attempts to verify a taproot commitment of the 332 // revealed script within the taprootWitnessProgram (a schnorr public key) 333 // given the required information included in the control block. An error is 334 // returned if the reconstructed taproot commitment (a function of the merkle 335 // root and the internal key) doesn't match the passed witness program. 336 func VerifyTaprootLeafCommitment(controlBlock *ControlBlock, 337 taprootWitnessProgram []byte, revealedScript []byte) error { 338 339 // First, we'll calculate the root hash from the given proof and 340 // revealed script. 341 rootHash := controlBlock.RootHash(revealedScript) 342 343 // Next, we'll construct the final commitment (creating the external or 344 // taproot output key) as a function of this commitment and the 345 // included internal key: taprootKey = internalKey + (tPoint*G). 346 taprootKey := ComputeTaprootOutputKey( 347 controlBlock.InternalKey, rootHash, 348 ) 349 350 // If we convert the taproot key to a witness program (we just need to 351 // serialize the public key), then it should exactly match the witness 352 // program passed in. 353 expectedWitnessProgram := schnorr.SerializePubKey(taprootKey) 354 if !bytes.Equal(expectedWitnessProgram, taprootWitnessProgram) { 355 356 return scriptError(ErrTaprootMerkleProofInvalid, "") 357 } 358 359 // Finally, we'll verify that the parity of the y coordinate of the 360 // public key we've derived matches the control block. 361 derivedYIsOdd := (taprootKey.SerializeCompressed()[0] == 362 secp.PubKeyFormatCompressedOdd) 363 if controlBlock.OutputKeyYIsOdd != derivedYIsOdd { 364 str := fmt.Sprintf("control block y is odd: %v, derived "+ 365 "parity is odd: %v", controlBlock.OutputKeyYIsOdd, 366 derivedYIsOdd) 367 return scriptError(ErrTaprootOutputKeyParityMismatch, str) 368 } 369 370 // Otherwise, if we reach here, the commitment opening is valid and 371 // execution can continue. 372 return nil 373 } 374 375 // TapNode represents an abstract node in a tapscript merkle tree. A node is 376 // either a branch or a leaf. 377 type TapNode interface { 378 // TapHash returns the hash of the node. This will either be a tagged 379 // hash derived from a branch, or a leaf. 380 TapHash() chainhash.Hash 381 382 // Left returns the left node. If this is a leaf node, this may be nil. 383 Left() TapNode 384 385 // Right returns the right node. If this is a leaf node, this may be 386 // nil. 387 Right() TapNode 388 } 389 390 // TapLeaf represents a leaf in a tapscript tree. A leaf has two components: 391 // the leaf version, and the script associated with that leaf version. 392 type TapLeaf struct { 393 // LeafVersion is the leaf version of this leaf. 394 LeafVersion TapscriptLeafVersion 395 396 // Script is the script to be validated based on the specified leaf 397 // version. 398 Script []byte 399 } 400 401 // Left rights the left node for this leaf. As this is a leaf the left node is 402 // nil. 403 func (t TapLeaf) Left() TapNode { 404 return nil 405 } 406 407 // Right rights the right node for this leaf. As this is a leaf the right node 408 // is nil. 409 func (t TapLeaf) Right() TapNode { 410 return nil 411 } 412 413 // NewBaseTapLeaf returns a new TapLeaf for the specified script, using the 414 // current base leaf version (BIP 342). 415 func NewBaseTapLeaf(script []byte) TapLeaf { 416 return TapLeaf{ 417 Script: script, 418 LeafVersion: BaseLeafVersion, 419 } 420 } 421 422 // NewTapLeaf returns a new TapLeaf with the given leaf version and script to 423 // be committed to. 424 func NewTapLeaf(leafVersion TapscriptLeafVersion, script []byte) TapLeaf { 425 return TapLeaf{ 426 LeafVersion: leafVersion, 427 Script: script, 428 } 429 } 430 431 // TapHash returns the hash digest of the target taproot script leaf. The 432 // digest is computed as: h_tapleaf(leafVersion || compactSizeof(script) || 433 // script). 434 func (t TapLeaf) TapHash() chainhash.Hash { 435 // TODO(roasbeef): cache these and the branch due to the recursive 436 // call, so memoize 437 438 // The leaf encoding is: leafVersion || compactSizeof(script) || 439 // script, where compactSizeof returns the compact size needed to 440 // encode the value. 441 var leafEncoding bytes.Buffer 442 443 _ = leafEncoding.WriteByte(byte(t.LeafVersion)) 444 _ = wire.WriteVarBytes(&leafEncoding, 0, t.Script) 445 446 return *chainhash.TaggedHash(chainhash.TagTapLeaf, leafEncoding.Bytes()) 447 } 448 449 // TapBranch represents an internal branch in the tapscript tree. The left or 450 // right nodes may either be another branch, leaves, or a combination of both. 451 type TapBranch struct { 452 // leftNode is the left node, this cannot be nil. 453 leftNode TapNode 454 455 // rightNode is the right node, this cannot be nil. 456 rightNode TapNode 457 } 458 459 // NewTapBranch creates a new internal branch from a left and right node. 460 func NewTapBranch(l, r TapNode) TapBranch { 461 462 return TapBranch{ 463 leftNode: l, 464 rightNode: r, 465 } 466 } 467 468 // Left is the left node of the branch, this might be a leaf or another 469 // branch. 470 func (t TapBranch) Left() TapNode { 471 return t.leftNode 472 } 473 474 // Right is the right node of a branch, this might be a leaf or another branch. 475 func (t TapBranch) Right() TapNode { 476 return t.rightNode 477 } 478 479 // TapHash returns the hash digest of the taproot internal branch given a left 480 // and right node. The final hash digest is: h_tapbranch(leftNode || 481 // rightNode), where leftNode is the lexicographically smaller of the two nodes. 482 func (t TapBranch) TapHash() chainhash.Hash { 483 leftHash := t.leftNode.TapHash() 484 rightHash := t.rightNode.TapHash() 485 return tapBranchHash(leftHash[:], rightHash[:]) 486 } 487 488 // tapBranchHash takes the raw tap hashes of the right and left nodes and 489 // hashes them into a branch. See The TapBranch method for the specifics. 490 func tapBranchHash(l, r []byte) chainhash.Hash { 491 if bytes.Compare(l[:], r[:]) > 0 { 492 l, r = r, l 493 } 494 495 return *chainhash.TaggedHash( 496 chainhash.TagTapBranch, l[:], r[:], 497 ) 498 } 499 500 // TapscriptProof is a proof of inclusion that a given leaf (a script and leaf 501 // version) is included within a top-level taproot output commitment. 502 type TapscriptProof struct { 503 // TapLeaf is the leaf that we want to prove inclusion for. 504 TapLeaf 505 506 // RootNode is the root of the tapscript tree, this will be used to 507 // compute what the final output key looks like. 508 RootNode TapNode 509 510 // InclusionProof is the tail end of the control block that contains 511 // the series of hashes (the sibling hashes up the tree), that when 512 // hashed together allow us to re-derive the top level taproot output. 513 InclusionProof []byte 514 } 515 516 // ToControlBlock maps the tapscript proof into a fully valid control block 517 // that can be used as a witness item for a tapscript spend. 518 func (t *TapscriptProof) ToControlBlock(internalKey *btcec.PublicKey) ControlBlock { 519 // Compute the total level output commitment based on the populated 520 // root node. 521 rootHash := t.RootNode.TapHash() 522 taprootKey := ComputeTaprootOutputKey( 523 internalKey, rootHash[:], 524 ) 525 526 // With the commitment computed we can obtain the bit that denotes if 527 // the resulting key has an odd y coordinate or not. 528 var outputKeyYIsOdd bool 529 if taprootKey.SerializeCompressed()[0] == 530 secp.PubKeyFormatCompressedOdd { 531 532 outputKeyYIsOdd = true 533 } 534 535 return ControlBlock{ 536 InternalKey: internalKey, 537 OutputKeyYIsOdd: outputKeyYIsOdd, 538 LeafVersion: t.TapLeaf.LeafVersion, 539 InclusionProof: t.InclusionProof, 540 } 541 } 542 543 // IndexedTapScriptTree reprints a fully contracted tapscript tree. The 544 // RootNode can be used to traverse down the full tree. In addition, complete 545 // inclusion proofs for each leaf are included as well, with an index into the 546 // slice of proof based on the tap leaf hash of a given leaf. 547 type IndexedTapScriptTree struct { 548 // RootNode is the root of the tapscript tree. RootNode.TapHash() can 549 // be used to extract the hash needed to derive the taptweak committed 550 // to in the taproot output. 551 RootNode TapNode 552 553 // LeafMerkleProofs is a slice that houses the series of merkle 554 // inclusion proofs for each leaf based on the input order of the 555 // leaves. 556 LeafMerkleProofs []TapscriptProof 557 558 // LeafProofIndex maps the TapHash() of a given leaf node to the index 559 // within the LeafMerkleProofs array above. This can be used to 560 // retrieve the inclusion proof for a given script when constructing 561 // the witness stack and control block for spending a tapscript path. 562 LeafProofIndex map[chainhash.Hash]int 563 } 564 565 // NewIndexedTapScriptTree creates a new empty tapscript tree that has enough 566 // space to hold information for the specified amount of leaves. 567 func NewIndexedTapScriptTree(numLeaves int) *IndexedTapScriptTree { 568 return &IndexedTapScriptTree{ 569 LeafMerkleProofs: make([]TapscriptProof, numLeaves), 570 LeafProofIndex: make(map[chainhash.Hash]int, numLeaves), 571 } 572 } 573 574 // hashTapNodes takes a left and right now, and returns the left and right tap 575 // hashes, along with the new combined node. If both nodes are nil, nil 576 // pointers are returned. If the right now is nil, then the left node is passed 577 // in, which effectively will "lift" the node up in the tree as long as it 578 // doesn't have any siblings. 579 func hashTapNodes(left, right TapNode) (*chainhash.Hash, *chainhash.Hash, TapNode) { 580 switch { 581 // If there's no left child, then this is a "nil" portion of the array 582 // tree, so well thread thru nil. 583 case left == nil: 584 return nil, nil, nil 585 586 // If there's no right child, then this is a single node that'll be 587 // passed all the way up the tree as it has no children. 588 case right == nil: 589 return nil, nil, left 590 } 591 592 // The result of hashing two nodes will always be a branch, so we start 593 // with that. 594 leftHash := left.TapHash() 595 rightHash := right.TapHash() 596 597 return &leftHash, &rightHash, NewTapBranch(left, right) 598 } 599 600 // leafDescendants is a recursive algorithm that returns all the leaf nodes 601 // that are a decedents of this tree. This is used to collect the series of 602 // nodes we need to extend the inclusion proof of each time we go up in the 603 // tree. 604 func leafDescendants(node TapNode) []TapNode { 605 // A leaf node has no decedents, so we just return it directly. 606 if node.Left() == nil && node.Right() == nil { 607 return []TapNode{node} 608 } 609 610 // Otherwise, get the descendants of the left and right sub-trees to 611 // return. 612 leftLeaves := leafDescendants(node.Left()) 613 rightLeaves := leafDescendants(node.Right()) 614 615 return append(leftLeaves, rightLeaves...) 616 } 617 618 // AssembleTaprootScriptTree constructs a new fully indexed tapscript tree 619 // given a series of leaf nodes. A combination of a recursive data structure, 620 // and an array-based representation are used to both generate the tree and 621 // also accumulate all the necessary inclusion proofs in the same path. See the 622 // comment of blockchain.BuildMerkleTreeStore for further details. 623 func AssembleTaprootScriptTree(leaves ...TapLeaf) *IndexedTapScriptTree { 624 // If there's only a single leaf, then that becomes our root. 625 if len(leaves) == 1 { 626 // A lone leaf has no additional inclusion proof, as a verifier 627 // will just hash the leaf as the sole branch. 628 leaf := leaves[0] 629 return &IndexedTapScriptTree{ 630 RootNode: leaf, 631 LeafProofIndex: map[chainhash.Hash]int{ 632 leaf.TapHash(): 0, 633 }, 634 LeafMerkleProofs: []TapscriptProof{ 635 { 636 TapLeaf: leaf, 637 RootNode: leaf, 638 InclusionProof: nil, 639 }, 640 }, 641 } 642 } 643 644 // We'll start out by populating the leaf index which maps a leave's 645 // taphash to its index within the tree. 646 scriptTree := NewIndexedTapScriptTree(len(leaves)) 647 for i, leaf := range leaves { 648 leafHash := leaf.TapHash() 649 scriptTree.LeafProofIndex[leafHash] = i 650 } 651 652 var branches []TapBranch 653 for i := 0; i < len(leaves); i += 2 { 654 // If there's only a single leaf left, then we'll merge this 655 // with the last branch we have. 656 if i == len(leaves)-1 { 657 branchToMerge := branches[len(branches)-1] 658 leaf := leaves[i] 659 newBranch := NewTapBranch(branchToMerge, leaf) 660 661 branches[len(branches)-1] = newBranch 662 663 // The leaf includes the existing branch within its 664 // inclusion proof. 665 branchHash := branchToMerge.TapHash() 666 667 scriptTree.LeafMerkleProofs[i].TapLeaf = leaf 668 scriptTree.LeafMerkleProofs[i].InclusionProof = append( 669 scriptTree.LeafMerkleProofs[i].InclusionProof, 670 branchHash[:]..., 671 ) 672 673 // We'll also add this right hash to the inclusion of 674 // the left and right nodes of the branch. 675 lastLeafHash := leaf.TapHash() 676 677 leftLeafHash := branchToMerge.Left().TapHash() 678 leftLeafIndex := scriptTree.LeafProofIndex[leftLeafHash] 679 scriptTree.LeafMerkleProofs[leftLeafIndex].InclusionProof = append( 680 scriptTree.LeafMerkleProofs[leftLeafIndex].InclusionProof, 681 lastLeafHash[:]..., 682 ) 683 684 rightLeafHash := branchToMerge.Right().TapHash() 685 rightLeafIndex := scriptTree.LeafProofIndex[rightLeafHash] 686 scriptTree.LeafMerkleProofs[rightLeafIndex].InclusionProof = append( 687 scriptTree.LeafMerkleProofs[rightLeafIndex].InclusionProof, 688 lastLeafHash[:]..., 689 ) 690 691 continue 692 } 693 694 // While we still have leaves left, we'll combine two of them 695 // into a new branch node. 696 left, right := leaves[i], leaves[i+1] 697 nextBranch := NewTapBranch(left, right) 698 branches = append(branches, nextBranch) 699 700 // The left node will use the right node as part of its 701 // inclusion proof, and vice versa. 702 leftHash := left.TapHash() 703 rightHash := right.TapHash() 704 705 scriptTree.LeafMerkleProofs[i].TapLeaf = left 706 scriptTree.LeafMerkleProofs[i].InclusionProof = append( 707 scriptTree.LeafMerkleProofs[i].InclusionProof, 708 rightHash[:]..., 709 ) 710 711 scriptTree.LeafMerkleProofs[i+1].TapLeaf = right 712 scriptTree.LeafMerkleProofs[i+1].InclusionProof = append( 713 scriptTree.LeafMerkleProofs[i+1].InclusionProof, 714 leftHash[:]..., 715 ) 716 } 717 718 // In this second phase, we'll merge all the leaf branches we have one 719 // by one until we have our final root. 720 var rootNode TapNode 721 for len(branches) != 0 { 722 // When we only have a single branch left, then that becomes 723 // our root. 724 if len(branches) == 1 { 725 rootNode = branches[0] 726 break 727 } 728 729 left, right := branches[0], branches[1] 730 731 newBranch := NewTapBranch(left, right) 732 733 branches = branches[2:] 734 735 branches = append(branches, newBranch) 736 737 // Accumulate the sibling hash of this new branch for all the 738 // leaves that are its children. 739 leftLeafDescendants := leafDescendants(left) 740 rightLeafDescendants := leafDescendants(right) 741 742 leftHash, rightHash := left.TapHash(), right.TapHash() 743 744 // For each left hash that's a leaf descendants, well add the 745 // right sibling as that sibling is needed to construct the new 746 // internal branch we just created. We also do the same for the 747 // siblings of the right node. 748 for _, leftLeaf := range leftLeafDescendants { 749 leafHash := leftLeaf.TapHash() 750 leafIndex := scriptTree.LeafProofIndex[leafHash] 751 752 scriptTree.LeafMerkleProofs[leafIndex].InclusionProof = append( 753 scriptTree.LeafMerkleProofs[leafIndex].InclusionProof, 754 rightHash[:]..., 755 ) 756 } 757 for _, rightLeaf := range rightLeafDescendants { 758 leafHash := rightLeaf.TapHash() 759 leafIndex := scriptTree.LeafProofIndex[leafHash] 760 761 scriptTree.LeafMerkleProofs[leafIndex].InclusionProof = append( 762 scriptTree.LeafMerkleProofs[leafIndex].InclusionProof, 763 leftHash[:]..., 764 ) 765 } 766 } 767 768 // Populate the top level root node pointer, as well as the pointer in 769 // each proof. 770 scriptTree.RootNode = rootNode 771 for i := range scriptTree.LeafMerkleProofs { 772 scriptTree.LeafMerkleProofs[i].RootNode = rootNode 773 } 774 775 return scriptTree 776 } 777 778 // PayToTaprootScript creates a pk script for a pay-to-taproot output key. 779 func PayToTaprootScript(taprootKey *btcec.PublicKey) ([]byte, error) { 780 return NewScriptBuilder(). 781 AddOp(OP_1). 782 AddData(schnorr.SerializePubKey(taprootKey)). 783 Script() 784 }